Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(702)

Unified Diff: samples/buildbot/json.dart

Issue 967883004: Replace string uses with code units in Json parser. (Closed) Base URL: git@github.com:dart-lang/fletch.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | samples/buildbot/model.dart » ('j') | samples/buildbot/tests/json_test.dart » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: samples/buildbot/json.dart
diff --git a/samples/buildbot/json.dart b/samples/buildbot/json.dart
index 68b4ee4f0290f1e7158e902d1e0b8fe62a3154ec..7e69c5dfc8a1ae937c3e6df6437878dd4fee2a13 100644
--- a/samples/buildbot/json.dart
+++ b/samples/buildbot/json.dart
@@ -19,10 +19,8 @@ dynamic getJson(String host, String resource) {
}
class JsonParser {
- int _index = 0;
+ int _offset = 0;
String _json;
- String _whitespaceUnits = ' \t\n';
- String _delimiterUnits = ' \t\n,[]{}';
JsonParser(this._json);
@@ -31,37 +29,38 @@ class JsonParser {
var result = _parseValue();
_whitespace();
if (_hasCurrent) {
- throw "Parse failed to consume: ${_json.substring(_index)}";
+ throw "Parse failed to consume: ${_json.substring(_offset)}";
}
return result;
}
- int get _currentUnit => _json.codeUnitAt(_index);
- String get _current => _json[_index];
- bool get _hasCurrent => _index < _json.length;
+ bool get _hasCurrent => _offset < _json.length;
+ int get _current => _json.codeUnitAt(_offset);
+ String get _currentChar => _json[_offset];
+ void _consume() { ++_offset; }
- bool _containsCurrent(String units) {
- int length = units.length;
- int unit = _currentUnit;
- for (int i = 0; i < length; ++i) {
- if (unit == units.codeUnitAt(i)) return true;
- }
- return false;
+ void _whitespace() {
+ while (_hasCurrent && _isWhitespace(_current)) _consume();
}
- void _whitespace() {
- while (_hasCurrent && _containsCurrent(_whitespaceUnits)) ++_index;
+ bool _optional(int char) {
+ if (_current == char) {
+ _consume();
+ return true;
+ }
+ return false;
}
- void _parseToken(String token) {
- if (!_tryParseToken(token)) {
- throw "Expected $token at index $_index, found $_current";
+ void _expect(int char) {
+ if (!_optional(char)) {
+ String string = new String.fromCharCodes([char]);
+ throw "Expected $string at index $_offset, found $_currentChar";
}
}
bool _tryParseToken(String token) {
int length = token.length;
- int start = _index;
+ int start = _offset;
int end = start + length;
if (end > _json.length) return false;
for (int i = 0; i < length; ++i) {
@@ -69,49 +68,47 @@ class JsonParser {
return false;
}
}
- _index += length;
+ _offset += length;
return true;
}
- bool get _isDelimiter => _containsCurrent(_delimiterUnits);
-
String _readToken() {
- int start = _index;
- while (_hasCurrent && !_isDelimiter) ++_index;
- return _json.substring(start, _index);
+ int start = _offset;
+ while (_hasCurrent && !_isSeparator(_current)) _consume();
+ return _json.substring(start, _offset);
}
dynamic _parseValue() {
_whitespace();
- if (_tryParseToken('{')) return _parseMap();
- if (_tryParseToken('[')) return _parseList();
- if (_tryParseToken('"')) return _parseString();
- if (_tryParseToken('true')) return true;
- if (_tryParseToken('false')) return false;
- if (_tryParseToken('null')) return null;
-
- int tryIndex = _index;
+ if (_optional(_CHAR_BRACE_OPEN)) return _parseMap();
+ if (_optional(_CHAR_SQUARE_OPEN)) return _parseList();
+ if (_optional(_CHAR_DOUBLE_QUOTE)) return _parseString();
+ if (_tryParseToken(_TOKEN_TRUE)) return true;
+ if (_tryParseToken(_TOKEN_FALSE)) return false;
+ if (_tryParseToken(_TOKEN_NULL)) return null;
+
+ int start = _offset;
String token = _readToken();
bool error = false;
// TODO(zerny) floating point numbers.
int tryInt = int.parse(token, onError: (_) { error = true; return 0; });
if (!error) return tryInt;
- String context = _json.substring(tryIndex, _min(tryIndex + 10, _json.length));
- throw "Parse failed at index: $_index (context: '$context...')";
+ String context = _json.substring(start, _min(start + 10, _json.length));
+ throw "Parse failed at index: $_offset (context: '$context...')";
}
Map _parseMap() {
Map map = new Map();
_whitespace();
- while (!_tryParseToken('}')) {
+ while (!_optional(_CHAR_BRACE_CLOSE)) {
var key = _parseValue();
_whitespace();
- _parseToken(':');
+ _expect(_CHAR_COLON);
var value = _parseValue();
map[key] = value;
_whitespace();
- _tryParseToken(',');
+ _optional(_CHAR_COMMA);
_whitespace();
}
return map;
@@ -120,18 +117,56 @@ class JsonParser {
List _parseList() {
List list = new List();
_whitespace();
- while (!_tryParseToken(']')) {
+ while (!_optional(_CHAR_SQUARE_CLOSE)) {
list.add(_parseValue());
_whitespace();
- _tryParseToken(',');
+ _optional(_CHAR_COMMA);
Anders Johnsen 2015/03/05 07:35:31 Would this allow [1 2 3 4] ? (ditto above)
zerny-google 2015/03/05 08:12:31 Yes. Fortunately it does parse well-formed json :-
_whitespace();
}
return list;
}
String _parseString() {
- int start = _index;
- while (_hasCurrent && _current != '"') ++_index;
- return _json.substring(start, _index++);
+ int start = _offset;
+ while (_hasCurrent && _current != _CHAR_DOUBLE_QUOTE) {
+ if (_current == _CHAR_BACKSLASH) _consume();
+ _consume();
+ }
+ _expect(_CHAR_DOUBLE_QUOTE);
+ return _json.substring(start, _offset - 1);
}
+
+ static bool _isWhitespace(int char) =>
+ char == _CHAR_TAB ||
+ char == _CHAR_LINE_FEED ||
+ char == _CHAR_SPACE;
+
+ static bool _isSeparator(int char) =>
+ _isWhitespace(char) ||
+ char == _CHAR_PAREN_OPEN ||
+ char == _CHAR_PAREN_CLOSE ||
+ char == _CHAR_COMMA ||
+ char == _CHAR_COLON ||
+ char == _CHAR_SQUARE_OPEN ||
+ char == _CHAR_SQUARE_CLOSE ||
+ char == _CHAR_BRACE_OPEN ||
+ char == _CHAR_BRACE_CLOSE;
+
+ static const String _TOKEN_TRUE = 'true';
+ static const String _TOKEN_FALSE = 'false';
+ static const String _TOKEN_NULL = 'null';
+
+ static const int _CHAR_TAB = 9;
+ static const int _CHAR_LINE_FEED = 10;
+ static const int _CHAR_SPACE = 32;
+ static const int _CHAR_DOUBLE_QUOTE = 34;
+ static const int _CHAR_PAREN_OPEN = 40;
+ static const int _CHAR_PAREN_CLOSE = 41;
+ static const int _CHAR_COMMA = 44;
+ static const int _CHAR_COLON = 58;
+ static const int _CHAR_SQUARE_OPEN = 91;
+ static const int _CHAR_BACKSLASH = 92;
+ static const int _CHAR_SQUARE_CLOSE = 93;
+ static const int _CHAR_BRACE_OPEN = 123;
+ static const int _CHAR_BRACE_CLOSE = 125;
}
« no previous file with comments | « no previous file | samples/buildbot/model.dart » ('j') | samples/buildbot/tests/json_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698