Files
sdk/runtime/lib/integers_patch.dart
T
floitsch@google.com 8adad2eeb0 Don't throw when there is an "onError" for int.parse.
Even though the error is caught immediately we don't want "break on exception" developer tools stop at the parseInt case if there is a handler.

BUG= http://dartbug.com/12776
R=lrn@google.com

Review URL: https://codereview.chromium.org//23685004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@27005 260f80e4-7a28-3924-810f-c04153c831b5
2013-09-02 09:36:29 +00:00

137 lines
4.0 KiB
Dart

// Copyright (c) 2012, 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.
// Dart core library.
// VM implementation of int.
patch class int {
static bool _isWhitespace(int codePoint) {
return
(codePoint == 32) || // Space.
((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc.
}
static bool is64Bit() => 1 << 32 is _Smi;
static int _tryParseSmi(String str) {
if (str.isEmpty) return null;
var ix = 0;
var endIx = str.length - 1;
// Find first and last non-whitespace.
while (ix <= endIx) {
if (!_isWhitespace(str.codeUnitAt(ix))) break;
ix++;
}
if (endIx < ix) {
return null; // Empty.
}
while (endIx > ix) {
if (!_isWhitespace(str.codeUnitAt(endIx))) break;
endIx--;
}
var isNegative = false;
var c = str.codeUnitAt(ix);
// Check for leading '+' or '-'.
if ((c == 0x2b) || (c == 0x2d)) {
ix++;
isNegative = (c == 0x2d);
if (ix > endIx) {
return null; // Empty.
}
}
int smiLimit = is64Bit() ? 18 : 9;
if ((endIx - ix) >= smiLimit) {
return null; // May not fit into a Smi.
}
var result = 0;
for (int i = ix; i <= endIx; i++) {
var c = str.codeUnitAt(i) - 0x30;
if ((c > 9) || (c < 0)) {
return null;
}
result = result * 10 + c;
}
return isNegative ? -result : result;
}
static int _parse(String str) {
int res = _tryParseSmi(str);
if (res == null) {
res = _native_parse(str);
}
return res;
}
static int _native_parse(String str) native "Integer_parse";
static int _throwFormatException(String source) {
throw new FormatException(source);
}
/* patch */ static int parse(String source,
{ int radix,
int onError(String str) }) {
if (radix == null) {
int result = _parse(source);
if (result == null) {
if (onError == null) {
throw new FormatException(source);
}
return onError(source);
}
return result;
}
return _slowParse(source, radix, onError);
}
static int _slowParse(String source, int radix, int onError(String str)) {
if (source is! String) throw new ArgumentError(source);
if (radix is! int) throw new ArgumentError("Radix is not an integer");
if (radix < 2 || radix > 36) {
throw new RangeError("Radix $radix not in range 2..36");
}
if (onError == null) {
onError = _throwFormatException;
}
// Remove leading and trailing white space.
source = source.trim();
if (source.isEmpty) return onError(source);
bool negative = false;
int result = 0;
// The value 99 is used to represent a non-digit. It is too large to be
// a digit value in any of the used bases.
const NA = 99;
const List<int> digits = const <int>[
00, 01, 02, 03, 04, 05, 06, 07, 08, 09, NA, NA, NA, NA, NA, NA, // 0x30
NA, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, NA, NA, NA, NA, NA, // 0x50
NA, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x60
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, NA, NA, NA, NA, NA, // 0x70
];
int i = 0;
int code = source.codeUnitAt(i);
if (code == 0x2d || code == 0x2b) { // Starts with a plus or minus-sign.
negative = (code == 0x2d);
if (source.length == 1) return onError(source);
i = 1;
code = source.codeUnitAt(i);
}
do {
if (code < 0x30 || code > 0x7f) return onError(source);
int digit = digits[code - 0x30];
if (digit >= radix) return onError(source);
result = result * radix + digit;
i++;
if (i == source.length) break;
code = source.codeUnitAt(i);
} while (true);
return negative ? -result : result;
}
}