Skip to content

Commit 33b3728

Browse files
Merge pull request #10 from danini-the-panini/performance
Use codeUnits instead of runes
2 parents 0e2cb9c + bff9f04 commit 33b3728

File tree

5 files changed

+28
-113
lines changed

5 files changed

+28
-113
lines changed

lib/src/document.dart

+9-9
Original file line numberDiff line numberDiff line change
@@ -488,11 +488,11 @@ class _StringDumper {
488488
String dump() {
489489
if (_isBareIdentifier()) return _string;
490490

491-
return "\"${_string.runes.map(_escape).join('')}\"";
491+
return "\"${_string.codeUnits.map(_escape).join('')}\"";
492492
}
493493

494-
String _escape(int rune) {
495-
switch (rune) {
494+
String _escape(int code) {
495+
switch (code) {
496496
case 10:
497497
return "\\n";
498498
case 13:
@@ -508,15 +508,15 @@ class _StringDumper {
508508
case 12:
509509
return "\\f";
510510
default:
511-
return String.fromCharCode(rune);
511+
return String.fromCharCode(code);
512512
}
513513
}
514514

515515
static final forbidden = [
516-
...KdlTokenizer.symbols.keys.map((e) => e.runes.single),
517-
...KdlTokenizer.whitespace.map((e) => e.runes.single),
518-
...KdlTokenizer.newlines.map((e) => e.runes.single),
519-
..."()[]/\\\"#".runes,
516+
...KdlTokenizer.symbols.keys.map((e) => e.codeUnits.single),
517+
...KdlTokenizer.whitespace.map((e) => e.codeUnits.single),
518+
...KdlTokenizer.newlines.map((e) => e.codeUnits.single),
519+
..."()[]/\\\"#".codeUnits,
520520
...List.generate(0x20, (e) => e),
521521
];
522522

@@ -540,6 +540,6 @@ class _StringDumper {
540540
return false;
541541
}
542542

543-
return !_string.runes.any((c) => forbidden.contains(c));
543+
return !_string.codeUnits.any((c) => forbidden.contains(c));
544544
}
545545
}

lib/src/tokenizer.dart

+9-9
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ class KdlTokenizer {
302302
String nl = _expectNewline(_index + 3);
303303
_context = _KdlTokenizerContext.multiLineString;
304304
_buffer = '';
305-
_traverse(3 + nl.runes.length);
305+
_traverse(3 + nl.length);
306306
} else {
307307
_context = _KdlTokenizerContext.string;
308308
_buffer = '';
@@ -315,7 +315,7 @@ class KdlTokenizer {
315315
_context = _KdlTokenizerContext.multiLineRawstring;
316316
_rawstringHashes = 1;
317317
_buffer = '';
318-
_traverse(4 + nl.runes.length);
318+
_traverse(4 + nl.length);
319319
continue;
320320
} else {
321321
_context = _KdlTokenizerContext.rawstring;
@@ -336,7 +336,7 @@ class KdlTokenizer {
336336
String nl = _expectNewline(i + 3);
337337
_context = _KdlTokenizerContext.multiLineRawstring;
338338
_buffer = '';
339-
_traverse(_rawstringHashes + 3 + nl.runes.length);
339+
_traverse(_rawstringHashes + 3 + nl.length);
340340
continue;
341341
} else {
342342
_context = _KdlTokenizerContext.rawstring;
@@ -408,7 +408,7 @@ class KdlTokenizer {
408408
return KdlToken(symbols[c]!, c);
409409
} else if (c == "\r" || newlines.contains(c)) {
410410
String nl = _expectNewline(_index);
411-
_traverse(nl.runes.length);
411+
_traverse(nl.length);
412412
return _token(KdlTerm.newline, nl);
413413
} else if (c == "/") {
414414
var n = _char(_index + 1);
@@ -710,10 +710,10 @@ class KdlTokenizer {
710710
}
711711

712712
_char(int i) {
713-
if (i < 0 || i >= _str.runes.length) {
713+
if (i < 0 || i >= _str.length) {
714714
return null;
715715
}
716-
var char = String.fromCharCode(_str.runes.elementAt(i));
716+
var char = _str.substring(i, i+1);
717717
if (_forbidden.contains(char)) {
718718
_fail("Forbidden character: $char");
719719
}
@@ -787,8 +787,8 @@ class KdlTokenizer {
787787
return _token(KdlTerm.integer, _parseInteger(_munchUnderscores(s), 10));
788788
} catch (e) {
789789
if (_nonInitialIdentifierChars
790-
.contains(String.fromCharCode(s.runes.first)) ||
791-
s.runes.skip(1).any(
790+
.contains(String.fromCharCode(s.codeUnitAt(0))) ||
791+
s.codeUnits.skip(1).any(
792792
(c) => _nonIdentifierChars.contains(String.fromCharCode(c)))) {
793793
rethrow;
794794
}
@@ -1081,7 +1081,7 @@ class KdlV1Tokenizer extends KdlTokenizer {
10811081
return _token(_symbols[c]!, c);
10821082
} else if (c == "\r" || _newlines.contains(c)) {
10831083
String nl = _expectNewline(_index);
1084-
_traverse(nl.runes.length);
1084+
_traverse(nl.length);
10851085
return _token(KdlTerm.newline, nl);
10861086
} else if (c == "/") {
10871087
var n = _char(_index + 1);

lib/src/types/email.dart

+3-3
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,11 @@ class _EmailTokenizer {
167167

168168
String _substring(int start, [int? end]) {
169169
return String.fromCharCodes(
170-
_string.runes.toList().sublist(start, end ?? _length(_string)));
170+
_string.codeUnits.sublist(start, end ?? _length(_string)));
171171
}
172172

173173
int _length(String str) {
174-
return str.runes.length;
174+
return str.length;
175175
}
176176

177177
_EmailToken nextToken() {
@@ -246,5 +246,5 @@ class _EmailTokenizer {
246246

247247
RegExp _localPartChars() => _idn ? _localPartIdn : _localPartAscii;
248248

249-
String _charAt(int i) => String.fromCharCode(_string.runes.elementAt(i));
249+
String _charAt(int i) => String.fromCharCode(_string.codeUnitAt(i));
250250
}

lib/src/types/irl/parser.dart

+6-91
Original file line numberDiff line numberDiff line change
@@ -36,95 +36,10 @@ class IrlParser {
3636
r"^(?:(?:([a-z][a-z0-9+.\-]+)):\/\/([^@]+@)?([^\/?#]+)?)?(\/?[^?#]*)?(?:\?([^#]*))?(?:#(.*))?$",
3737
caseSensitive: false);
3838

39-
static const _reservedUrlChars = [
40-
'!',
41-
'#',
42-
'&',
43-
"'",
44-
'(',
45-
')',
46-
'*',
47-
'+',
48-
',',
49-
'/',
50-
':',
51-
';',
52-
'=',
53-
'?',
54-
'@',
55-
'[',
56-
']',
57-
'%'
58-
];
59-
static const _unreservedUrlChars = [
60-
'A',
61-
'B',
62-
'C',
63-
'D',
64-
'E',
65-
'F',
66-
'G',
67-
'H',
68-
'I',
69-
'J',
70-
'K',
71-
'L',
72-
'M',
73-
'N',
74-
'O',
75-
'P',
76-
'Q',
77-
'R',
78-
'S',
79-
'T',
80-
'U',
81-
'V',
82-
'W',
83-
'X',
84-
'Y',
85-
'Z',
86-
'a',
87-
'b',
88-
'c',
89-
'd',
90-
'e',
91-
'f',
92-
'g',
93-
'h',
94-
'i',
95-
'j',
96-
'k',
97-
'l',
98-
'm',
99-
'n',
100-
'o',
101-
'p',
102-
'q',
103-
'r',
104-
's',
105-
't',
106-
'u',
107-
'v',
108-
'w',
109-
'x',
110-
'y',
111-
'z',
112-
'0',
113-
'1',
114-
'2',
115-
'3',
116-
'4',
117-
'5',
118-
'6',
119-
'7',
120-
'8',
121-
'9',
122-
'-',
123-
'_',
124-
'.',
125-
'~'
126-
];
127-
static final _urlChars = _reservedUrlChars + _unreservedUrlChars;
39+
static const _reservedUrlChars = "!#&'()*+,/:;=?@[]%";
40+
static const _unreservedUrlChars =
41+
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~';
42+
static final _urlChars = (_reservedUrlChars + _unreservedUrlChars).codeUnits;
12843

12944
final String _string;
13045
final bool _isReference;
@@ -199,8 +114,8 @@ class IrlParser {
199114
static bool _isValidUrlPart(String? string) {
200115
if (string == null) return true;
201116

202-
return !string.runes.any((rune) =>
203-
rune <= 127 && !_urlChars.contains(String.fromCharCode(rune)));
117+
return !string.codeUnits
118+
.any((code) => code <= 127 && !_urlChars.contains(code));
204119
}
205120

206121
static String? _encode(String? string) {

test/tokenizer_test.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ smile "😁"
241241
tokenizer.nextToken(), equals(KdlToken(KdlTerm.whitespace, ' ', 1, 6)));
242242
expect(tokenizer.nextToken(), equals(KdlToken(KdlTerm.string, '😁', 1, 7)));
243243
expect(
244-
tokenizer.nextToken(), equals(KdlToken(KdlTerm.newline, "\n", 1, 10)));
244+
tokenizer.nextToken(), equals(KdlToken(KdlTerm.newline, "\n", 1, 11)));
245245
expect(tokenizer.nextToken(), equals(KdlToken(KdlTerm.ident, 'ノード', 2, 1)));
246246
expect(
247247
tokenizer.nextToken(), equals(KdlToken(KdlTerm.whitespace, ' ', 2, 4)));

0 commit comments

Comments
 (0)