Skip to content

Commit e85a56c

Browse files
authored
Merge d2ecd64 into ad706a9
2 parents ad706a9 + d2ecd64 commit e85a56c

File tree

8 files changed

+179
-2
lines changed

8 files changed

+179
-2
lines changed

pkg/analyzer_cli/test/data/sky_engine/lib/core.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ abstract class String implements Comparable<String> {
3434
List<int> get codeUnits;
3535
}
3636

37-
class bool extends Object {}
37+
class bool extends Object {
38+
static bool parse(String source, {bool caseSensitive = false}) => false;
39+
}
3840

3941
abstract class num implements Comparable<num> {
4042
bool operator <(num other);

sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,16 @@ class bool {
721721
'bool.hasEnvironment can only be used as a const constructor');
722722
}
723723

724+
@patch
725+
static bool parse(String source, {bool caseSensitive = true}) =>
726+
Primitives.parseBool(source, caseSensitive) ??
727+
(throw FormatException("Not valid boolean", source));
728+
729+
@patch
730+
static bool? tryParse(String source, {bool caseSensitive = true}) {
731+
return Primitives.parseBool(source, caseSensitive);
732+
}
733+
724734
@patch
725735
int get hashCode => super.hashCode;
726736

sdk/lib/_internal/js_runtime/lib/core_patch.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,16 @@ class String {
582582
class bool {
583583
@patch
584584
int get hashCode => super.hashCode;
585+
586+
@patch
587+
static bool parse(String source, {bool caseSensitive = true}) =>
588+
tryParse(source, caseSensitive: caseSensitive) ??
589+
(throw FormatException("Not a valid boolean", source));
590+
591+
@patch
592+
static bool? tryParse(String source, {bool caseSensitive = true}) {
593+
return Primitives.parseBool(source, caseSensitive);
594+
}
585595
}
586596

587597
@patch

sdk/lib/_internal/js_runtime/lib/js_helper.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import 'dart:_interceptors';
5050
import 'dart:_internal' as _symbol_dev;
5151
import 'dart:_internal'
5252
show
53+
checkNotNullable,
5354
EfficientLengthIterable,
5455
MappedIterable,
5556
IterableElementError,
@@ -381,6 +382,35 @@ class Primitives {
381382
return result;
382383
}
383384

385+
static bool? parseBool(String source, bool caseSensitive) {
386+
checkNotNullable(source, "source");
387+
checkNotNullable(caseSensitive, "caseSensitive");
388+
// The caseSensitive defaults to true.
389+
if (caseSensitive) {
390+
return source == "true"
391+
? true
392+
: source == "false"
393+
? false
394+
: null;
395+
}
396+
// Compare case-sensitive when caseSensitive is false.
397+
return _compareIgnoreCase(source, "true")
398+
? true
399+
: _compareIgnoreCase(source, "false")
400+
? false
401+
: null;
402+
}
403+
404+
static bool _compareIgnoreCase(String input, String lowerCaseTarget) {
405+
if (input.length != lowerCaseTarget.length) return false;
406+
for (var i = 0; i < input.length; i++) {
407+
if (input.codeUnitAt(i) | 0x20 != lowerCaseTarget.codeUnitAt(i)) {
408+
return false;
409+
}
410+
}
411+
return true;
412+
}
413+
384414
/// [: r"$".codeUnitAt(0) :]
385415
static const int DOLLAR_CHAR_VALUE = 36;
386416

sdk/lib/_internal/vm_shared/lib/bool_patch.dart

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import "dart:_internal" show patch;
5+
import "dart:_internal" show patch, checkNotNullable;
66

77
@patch
88
@pragma("vm:entry-point")
@@ -20,4 +20,48 @@ class bool {
2020
int get hashCode => this ? 1231 : 1237;
2121

2222
int get _identityHashCode => this ? 1231 : 1237;
23+
24+
@patch
25+
static bool parse(String source, {bool caseSensitive = true}) {
26+
checkNotNullable(source, "source");
27+
// The caseSensitive defaults to true.
28+
if (caseSensitive == null || caseSensitive) {
29+
return source == "true" ||
30+
source != "false" &&
31+
(throw FormatException("Not a valid boolean", source));
32+
}
33+
// Ignore case-sensitive when caseSensitive is false.
34+
return _compareIgnoreCase(source, "true") ||
35+
!_compareIgnoreCase(source, "false") &&
36+
(throw FormatException("Not a valid boolean", source));
37+
}
38+
39+
@patch
40+
static bool? tryParse(String source, {bool? caseSensitive}) {
41+
checkNotNullable(source, "source");
42+
// The caseSensitive defaults to true.
43+
if (caseSensitive == null || caseSensitive) {
44+
return source == "true"
45+
? true
46+
: source == "false"
47+
? false
48+
: null;
49+
}
50+
// Ignore case-sensitive when caseSensitive is false.
51+
return _compareIgnoreCase(source, "true")
52+
? true
53+
: _compareIgnoreCase(source, "false")
54+
? false
55+
: null;
56+
}
57+
58+
static bool _compareIgnoreCase(String input, String lowerCaseTarget) {
59+
if (input.length != lowerCaseTarget.length) return false;
60+
for (var i = 0; i < input.length; i++) {
61+
if (input.codeUnitAt(i) | 0x20 != lowerCaseTarget.codeUnitAt(i)) {
62+
return false;
63+
}
64+
}
65+
return true;
66+
}
2367
}

sdk/lib/core/bool.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,43 @@ class bool {
9494
//ignore: const_factory
9595
external const factory bool.hasEnvironment(String name);
9696

97+
/// Parse [source] as an, optionally case-insensitive, boolean literal.
98+
///
99+
/// If [caseSensitive] is `true`, which is the default,
100+
/// the only accepted inputs are the strings `"true"` and `"false"`.
101+
///
102+
/// If [caseSensitive] is `false`, any combination of upper and lower case
103+
/// ASCII letters in the words `"true"` and `"false"` are accepted, as if the
104+
/// input was first lower-cased.
105+
///
106+
/// If the [source] string does not contain a valid boolean literal
107+
/// a [FormatException] is thrown.
108+
///
109+
/// Rather than throwing and immediately catching the [FormatException],
110+
/// instead use [tryParse] to handle a potential parsing error.
111+
@Since("3.0")
112+
external static bool parse(String source, {bool caseSensitive = true});
113+
114+
/// Parse [source] as an, optionally case-insensitive, boolean literal.
115+
///
116+
/// Like [parse] except that this function returns `null` where a
117+
/// similar call to [parse] would throw a [FormatException].
118+
///
119+
/// Example:
120+
/// ```dart
121+
/// print(bool.tryParse('true')); // true
122+
/// print(bool.tryParse('false')); // false
123+
/// print(bool.tryParse('TRUE')); // null
124+
/// print(bool.tryParse('TRUE', caseSensitive: false)); // true
125+
/// print(bool.tryParse('FALSE', caseSensitive: false)); // false
126+
/// print(bool.tryParse('NO')); // null
127+
/// print(bool.tryParse('YES')); // null
128+
/// print(bool.tryParse('0')); // null
129+
/// print(bool.tryParse('1')); // null
130+
/// ```
131+
@Since("3.0")
132+
external static bool? tryParse(String source, {bool caseSensitive = true});
133+
97134
external int get hashCode;
98135

99136
/// The logical conjunction ("and") of this and [other].

tests/corelib/bool_parse_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
// SharedOptions=-Da=true -Db=false -Dc=NOTBOOL -Dd=True
5+
6+
import "package:expect/expect.dart";
7+
8+
main() {
9+
Expect.isTrue(bool.parse('true'));
10+
Expect.isFalse(bool.parse('false'));
11+
Expect.isTrue(bool.parse('TRUE', caseSensitive: false));
12+
Expect.isFalse(bool.parse('FALSE', caseSensitive: false));
13+
Expect.isTrue(bool.parse('true', caseSensitive: true));
14+
Expect.isFalse(bool.parse('false', caseSensitive: true));
15+
Expect.throws(()=> bool.parse('True'));
16+
Expect.throws(()=> bool.parse('False'));
17+
Expect.throws(()=> bool.parse('y'));
18+
Expect.throws(()=> bool.parse('n'));
19+
Expect.throws(()=> bool.parse('0'));
20+
Expect.throws(()=> bool.parse('1'));
21+
Expect.throws(()=> bool.parse('TRUE', caseSensitive: true));
22+
Expect.throws(()=> bool.parse('FALSE', caseSensitive: true));
23+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
// SharedOptions=-Da=true -Db=false -Dc=NOTBOOL -Dd=True
5+
6+
import "package:expect/expect.dart";
7+
8+
main() {
9+
Expect.isTrue(bool.tryParse('true'));
10+
Expect.isFalse(bool.tryParse('false'));
11+
Expect.isTrue(bool.tryParse('TRUE', caseSensitive: false));
12+
Expect.isFalse(bool.tryParse('FALSE', caseSensitive: false));
13+
Expect.isNull(bool.tryParse('TRUE'));
14+
Expect.isNull(bool.tryParse('FALSE'));
15+
Expect.isNull(bool.tryParse('y'));
16+
Expect.isNull(bool.tryParse('n'));
17+
Expect.isNull(bool.tryParse(' true ', caseSensitive: false));
18+
Expect.isNull(bool.tryParse(' false ', caseSensitive: false));
19+
Expect.isNull(bool.tryParse('0', caseSensitive: true));
20+
Expect.isNull(bool.tryParse('1', caseSensitive: true));
21+
}

0 commit comments

Comments
 (0)