mirror of
https://github.com/dart-lang/sdk
synced 2024-07-03 08:19:13 +00:00
Add boolean parse
Closes https://github.com/dart-lang/sdk/pull/51026 Co-authored-by: Renato Burton <renatoburton96@gmail.com> GitOrigin-RevId: e85a56ce338476b38eac890fac2b8ca193ca42e8 Change-Id: I60f92c594830ef0438ecd92b4c83cec609054326 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279746 Reviewed-by: Lasse Nielsen <lrn@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com> Commit-Queue: Lasse Nielsen <lrn@google.com>
This commit is contained in:
parent
e0fedb81a1
commit
c974c70f31
|
@ -29,6 +29,7 @@
|
|||
* `StringConversionSink`
|
||||
|
||||
#### `dart:core`
|
||||
- Added `bool.parse` and `bool.tryParse` static methods.
|
||||
|
||||
- **Breaking change** [#49529][]:
|
||||
- Removed the deprecated `List` constructor, as it wasn't null safe.
|
||||
|
|
|
@ -34,7 +34,9 @@ abstract class String implements Comparable<String> {
|
|||
List<int> get codeUnits;
|
||||
}
|
||||
|
||||
class bool extends Object {}
|
||||
class bool extends Object {
|
||||
static bool parse(String source, {bool caseSensitive = false}) => false;
|
||||
}
|
||||
|
||||
abstract class num implements Comparable<num> {
|
||||
bool operator <(num other);
|
||||
|
|
|
@ -703,6 +703,16 @@ class bool {
|
|||
'bool.hasEnvironment can only be used as a const constructor');
|
||||
}
|
||||
|
||||
@patch
|
||||
static bool parse(String source, {bool caseSensitive = true}) =>
|
||||
Primitives.parseBool(source, caseSensitive) ??
|
||||
(throw FormatException("Invalid boolean", source));
|
||||
|
||||
@patch
|
||||
static bool? tryParse(String source, {bool caseSensitive = true}) {
|
||||
return Primitives.parseBool(source, caseSensitive);
|
||||
}
|
||||
|
||||
@patch
|
||||
int get hashCode => super.hashCode;
|
||||
|
||||
|
|
|
@ -159,6 +159,31 @@ class Primitives {
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool? parseBool(
|
||||
@nullCheck String source, @nullCheck bool caseSensitive) {
|
||||
if (caseSensitive) {
|
||||
return JS('bool', r'# == "true" || # != "false" && null', source, source);
|
||||
}
|
||||
return _compareIgnoreCase(source, "true")
|
||||
? true
|
||||
: _compareIgnoreCase(source, "false")
|
||||
? false
|
||||
: null;
|
||||
}
|
||||
|
||||
/// Compares a string against an ASCII lower-case letter-only string.
|
||||
///
|
||||
/// Returns `true` if the [input] has the same length and same letters
|
||||
/// as [lowerCaseTarget], `false` if not.
|
||||
static bool _compareIgnoreCase(String input, String lowerCaseTarget) {
|
||||
if (input.length != lowerCaseTarget.length) return false;
|
||||
var delta = 0x20;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
delta |= input.codeUnitAt(i) ^ lowerCaseTarget.codeUnitAt(i);
|
||||
}
|
||||
return delta == 0x20;
|
||||
}
|
||||
|
||||
/** `r"$".codeUnitAt(0)` */
|
||||
static const int DOLLAR_CHAR_VALUE = 36;
|
||||
|
||||
|
|
|
@ -580,6 +580,16 @@ class String {
|
|||
class bool {
|
||||
@patch
|
||||
int get hashCode => super.hashCode;
|
||||
|
||||
@patch
|
||||
static bool parse(String source, {bool caseSensitive = true}) =>
|
||||
tryParse(source, caseSensitive: caseSensitive) ??
|
||||
(throw FormatException("Invalid boolean", source));
|
||||
|
||||
@patch
|
||||
static bool? tryParse(String source, {bool caseSensitive = true}) {
|
||||
return Primitives.parseBool(source, caseSensitive);
|
||||
}
|
||||
}
|
||||
|
||||
@patch
|
||||
|
|
|
@ -388,7 +388,6 @@ class Primitives {
|
|||
static bool? parseBool(String source, bool caseSensitive) {
|
||||
checkNotNullable(source, "source");
|
||||
checkNotNullable(caseSensitive, "caseSensitive");
|
||||
// The caseSensitive defaults to true.
|
||||
if (caseSensitive) {
|
||||
return source == "true"
|
||||
? true
|
||||
|
@ -396,7 +395,6 @@ class Primitives {
|
|||
? false
|
||||
: null;
|
||||
}
|
||||
// Compare case-sensitive when caseSensitive is false.
|
||||
return _compareIgnoreCase(source, "true")
|
||||
? true
|
||||
: _compareIgnoreCase(source, "false")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "dart:_internal" show patch;
|
||||
import "dart:_internal" show patch, checkNotNullable;
|
||||
|
||||
@patch
|
||||
@pragma("vm:entry-point")
|
||||
|
@ -20,4 +20,50 @@ class bool {
|
|||
int get hashCode => this ? 1231 : 1237;
|
||||
|
||||
int get _identityHashCode => this ? 1231 : 1237;
|
||||
|
||||
@patch
|
||||
static bool parse(String source, {bool caseSensitive = true}) {
|
||||
checkNotNullable(source, "source");
|
||||
checkNotNullable(caseSensitive, "caseSensitive");
|
||||
if (caseSensitive) {
|
||||
return source == "true" ||
|
||||
source != "false" &&
|
||||
(throw FormatException("Invalid boolean", source));
|
||||
}
|
||||
// Ignore case-sensitive when `caseSensitive` is false.
|
||||
return _compareIgnoreCase(source, "true") ||
|
||||
!_compareIgnoreCase(source, "false") &&
|
||||
(throw FormatException("Invalid boolean", source));
|
||||
}
|
||||
|
||||
@patch
|
||||
static bool? tryParse(String source, {bool caseSensitive = true}) {
|
||||
checkNotNullable(source, "source");
|
||||
checkNotNullable(caseSensitive, "caseSensitive");
|
||||
if (caseSensitive) {
|
||||
return source == "true"
|
||||
? true
|
||||
: source == "false"
|
||||
? false
|
||||
: null;
|
||||
}
|
||||
return _compareIgnoreCase(source, "true")
|
||||
? true
|
||||
: _compareIgnoreCase(source, "false")
|
||||
? false
|
||||
: null;
|
||||
}
|
||||
|
||||
/// Compares a string against an ASCII lower-case letter-only string.
|
||||
///
|
||||
/// Returns `true` if the [input] has the same length and same letters
|
||||
/// as [lowerCaseTarget], `false` if not.
|
||||
static bool _compareIgnoreCase(String input, String lowerCaseTarget) {
|
||||
if (input.length != lowerCaseTarget.length) return false;
|
||||
var delta = 0x20;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
delta |= input.codeUnitAt(i) ^ lowerCaseTarget.codeUnitAt(i);
|
||||
}
|
||||
return delta == 0x20;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,68 @@ final class bool {
|
|||
//ignore: const_factory
|
||||
external const factory bool.hasEnvironment(String name);
|
||||
|
||||
/// Parses [source] as an, optionally case-insensitive, boolean literal.
|
||||
///
|
||||
/// If [caseSensitive] is `true`, which is the default,
|
||||
/// the only accepted inputs are the strings `"true"` and `"false"`,
|
||||
/// which returns the results `true` and `false` respectively.
|
||||
///
|
||||
/// If [caseSensitive] is `false`, any combination of upper and lower case
|
||||
/// ASCII letters in the words `"true"` and `"false"` are accepted,
|
||||
/// as if the input was first lower-cased.
|
||||
///
|
||||
/// Throws a [FormatException] if the [source] string does not contain
|
||||
/// a valid boolean literal.
|
||||
///
|
||||
/// Rather than throwing and immediately catching the [FormatException],
|
||||
/// instead use [tryParse] to handle a potential parsing error.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// print(bool.tryParse('true')); // true
|
||||
/// print(bool.tryParse('false')); // false
|
||||
/// print(bool.tryParse('TRUE')); // throws FormatException
|
||||
/// print(bool.tryParse('TRUE', caseSensitive: false)); // true
|
||||
/// print(bool.tryParse('FALSE', caseSensitive: false)); // false
|
||||
/// print(bool.tryParse('NO')); // throws FormatException
|
||||
/// print(bool.tryParse('YES')); // throws FormatException
|
||||
/// print(bool.tryParse('0')); // throws FormatException
|
||||
/// print(bool.tryParse('1')); // throws FormatException
|
||||
/// ```
|
||||
@Since("3.0")
|
||||
external static bool parse(String source, {bool caseSensitive = true});
|
||||
|
||||
/// Parses [source] as an, optionally case-insensitive, boolean literal.
|
||||
///
|
||||
/// If [caseSensitive] is `true`, which is the default,
|
||||
/// the only accepted inputs are the strings `"true"` and `"false"`,
|
||||
/// which returns the results `true` and `false` respectively.
|
||||
///
|
||||
/// If [caseSensitive] is `false`, any combination of upper and lower case
|
||||
/// ASCII letters in the words `"true"` and `"false"` are accepted,
|
||||
/// as if the input was first lower-cased.
|
||||
///
|
||||
/// Returns `null` if the [source] string does not contain a valid
|
||||
/// boolean literal.
|
||||
///
|
||||
/// If the input can be assumed to be valid, use [bool.parse] to avoid
|
||||
/// having to deal with a possible `null` result.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// print(bool.tryParse('true')); // true
|
||||
/// print(bool.tryParse('false')); // false
|
||||
/// print(bool.tryParse('TRUE')); // null
|
||||
/// print(bool.tryParse('TRUE', caseSensitive: false)); // true
|
||||
/// print(bool.tryParse('FALSE', caseSensitive: false)); // false
|
||||
/// print(bool.tryParse('NO')); // null
|
||||
/// print(bool.tryParse('YES')); // null
|
||||
/// print(bool.tryParse('0')); // null
|
||||
/// print(bool.tryParse('1')); // null
|
||||
/// ```
|
||||
@Since("3.0")
|
||||
external static bool? tryParse(String source, {bool caseSensitive = true});
|
||||
|
||||
external int get hashCode;
|
||||
|
||||
/// The logical conjunction ("and") of this and [other].
|
||||
|
|
23
tests/corelib/bool_parse_test.dart
Normal file
23
tests/corelib/bool_parse_test.dart
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// SharedOptions=-Da=true -Db=false -Dc=NOTBOOL -Dd=True
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.isTrue(bool.parse('true'));
|
||||
Expect.isFalse(bool.parse('false'));
|
||||
Expect.isTrue(bool.parse('TRUE', caseSensitive: false));
|
||||
Expect.isFalse(bool.parse('FALSE', caseSensitive: false));
|
||||
Expect.isTrue(bool.parse('true', caseSensitive: true));
|
||||
Expect.isFalse(bool.parse('false', caseSensitive: true));
|
||||
Expect.throws(() => bool.parse('True'));
|
||||
Expect.throws(() => bool.parse('False'));
|
||||
Expect.throws(() => bool.parse('y'));
|
||||
Expect.throws(() => bool.parse('n'));
|
||||
Expect.throws(() => bool.parse('0'));
|
||||
Expect.throws(() => bool.parse('1'));
|
||||
Expect.throws(() => bool.parse('TRUE', caseSensitive: true));
|
||||
Expect.throws(() => bool.parse('FALSE', caseSensitive: true));
|
||||
}
|
21
tests/corelib/bool_try_parse_test.dart
Normal file
21
tests/corelib/bool_try_parse_test.dart
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// SharedOptions=-Da=true -Db=false -Dc=NOTBOOL -Dd=True
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.isTrue(bool.tryParse('true'));
|
||||
Expect.isFalse(bool.tryParse('false'));
|
||||
Expect.isTrue(bool.tryParse('TRUE', caseSensitive: false));
|
||||
Expect.isFalse(bool.tryParse('FALSE', caseSensitive: false));
|
||||
Expect.isNull(bool.tryParse('TRUE'));
|
||||
Expect.isNull(bool.tryParse('FALSE'));
|
||||
Expect.isNull(bool.tryParse('y'));
|
||||
Expect.isNull(bool.tryParse('n'));
|
||||
Expect.isNull(bool.tryParse(' true ', caseSensitive: false));
|
||||
Expect.isNull(bool.tryParse(' false ', caseSensitive: false));
|
||||
Expect.isNull(bool.tryParse('0', caseSensitive: true));
|
||||
Expect.isNull(bool.tryParse('1', caseSensitive: true));
|
||||
}
|
Loading…
Reference in New Issue
Block a user