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

Side by Side Diff: utils/string_encoding/Utf8_impl.dart

Issue 9233041: String encoding utility methods and tests for Unicode, UTF-8, -16 and -32. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: updates from initial review. Created 8 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011, 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
5 /**
6 * Produce a sequence of UTF8 encoded bytes from the provided string.
7 */
8 List<int> encodeAsUtf8(String str) =>
9 _codepointsToUtf8(stringToCodepoints(str));
10
11 /**
12 * Produce a String from a sequence of UTF8 encoded bytes.
13 */
14 String decodeFromUtf8(List<int> bytes) =>
15 codepointsToString(_utf8ToCodepoints(bytes, 0, bytes.length));
16
17 int _addToEncoding(int start, int bytes, int value, List<int> buffer) {
18 while(bytes > 0) {
19 buffer[start + bytes] = 0x80 + (value & 0x3f);
20 value = value >> 6;
21 bytes--;
22 }
23 return value;
24 }
25
26 /**
27 * Encode code points as UTF8 code units.
28 */
29 List<int> _codepointsToUtf8(List<int> codepoints,
30 [int start = 0, int length = -1]) {
31
32 List<int> encoded = <int>[];
33 int end = length >= 0 ? Math.min(codepoints.length, start + length) :
34 codepoints.length;
35 int i = start;
36 while (i < end) {
37 int value = codepoints[i++];
38 int insertAt = encoded.length;
39 if (value < 0 || value > 0x7fffffff) {
40 encoded.addAll([0xef, 0xbf, 0xbd]);
41 } else if (value <= 0x7f) {
42 encoded.add(value);
43 } else if (value <= 0x7ff) {
44 encoded.insertRange(encoded.length, 2, 99);
45 encoded[insertAt] = 0xc0 |
46 (0x1f & _addToEncoding(insertAt, 1, value, encoded));
47 } else if (value <= 0xffff) {
48 encoded.insertRange(encoded.length, 3, 99);
49 encoded[insertAt] = 0xe0 |
50 (0xf & _addToEncoding(insertAt, 2, value, encoded));
51 } else if (value <= 0x1fffff) {
52 encoded.insertRange(encoded.length, 4, 0);
53 encoded[insertAt] = 0xf0 |
54 (0x7 & _addToEncoding(insertAt, 3, value, encoded));
55 } else if (value <= 0x3ffffff) {
56 encoded.insertRange(encoded.length, 5, 0);
57 encoded[insertAt] = 0xf8 |
58 (0x3 & _addToEncoding(insertAt, 4, value, encoded));
59 } else if (value <= 0x7fffffff) {
60 encoded.insertRange(encoded.length, 6, 0);
61 encoded[insertAt] = 0xfc |
62 (0x1 & _addToEncoding(insertAt, 5, value, encoded));
63 }
64 }
65 return encoded;
66 }
67
68 /**
69 * UTF-8 bytes are utf8 code units, so we can go directly from
70 * encoded bytes to code points.
71 */
72 List<int> _utf8ToCodepoints(List<int> utf8EncodedBytes, [int start = 0,
73 int length = -1]) {
74 List<int> codepointBuffer = <int>[];
75 int end = length >= 0 ? Math.min(utf8EncodedBytes.length, start + length) :
76 utf8EncodedBytes.length;
77 int i = start;
78 while (i < end) {
79 int value = utf8EncodedBytes[i++];
80 if (value >= 0x0) {
81 if (value < 0x80) {
82 codepointBuffer.add(value);
83 } else if (value < 0xc0) {
84 codepointBuffer.add(REPLACEMENT_CHARACTER_CODEPOINT);
85 continue;
86 } else {
87 int additionalBytes = 0;
88 if (value < 0xe0) {
89 value -= 0xc0;
90 additionalBytes = 1;
91 } else if (value < 0xf0) {
92 value -= 0xe0;
93 additionalBytes = 2;
94 } else if (value < 0xf8) {
95 value -= 0xf0;
96 additionalBytes = 3;
97 } else if (value < 0xfc) {
98 value -= 0xf8;
99 additionalBytes = 4;
100 } else if (value < 0xfe) {
101 value -= 0xfc;
102 additionalBytes = 5;
103 } else {
104 codepointBuffer.add(REPLACEMENT_CHARACTER_CODEPOINT);
105 continue;
106 }
jat 2012/01/31 15:19:22 Do you want to reject over-long encodings? They c
dcarlson 2012/01/31 22:11:38 :) I do. See the tests for checks on overlong enco
107 int j = 0;
108 while (j < additionalBytes && i < end) {
109 int nextValue = utf8EncodedBytes[i++];
110 if (nextValue >= 0x80 && nextValue < 0xc0) {
111 // equiv to (value << 6) | (nextValue & 0x3f)
112 value = (value * 0x40) + (nextValue - 0x80);
113 } else {
114 // if sequence-starting code unit, reposition cursor to start here
115 if (nextValue >= 0xc0) i--;
116 break;
117 }
118 j++;
119 }
120 if (j == additionalBytes &&
121 (value < 0xd800 || value > 0xdfff)) {
122 if(additionalBytes == 1 && value > 0x7f) {
123 codepointBuffer.add(value);
124 } else if(additionalBytes == 2 && value > 0x7ff) {
125 codepointBuffer.add(value);
126 } else if(additionalBytes == 3 && value > 0xffff) {
127 codepointBuffer.add(value);
128 } else if(additionalBytes == 4 && value > 0x1fffff) {
129 codepointBuffer.add(value);
130 } else if(additionalBytes == 5 && value > 0x3ffffff) {
131 codepointBuffer.add(value);
132 } else {
133 codepointBuffer.add(REPLACEMENT_CHARACTER_CODEPOINT);
134 }
135 } else {
136 codepointBuffer.add(REPLACEMENT_CHARACTER_CODEPOINT);
137 continue;
138 }
139 }
140 } else {
141 codepointBuffer.add(REPLACEMENT_CHARACTER_CODEPOINT);
142 continue;
143 }
144 }
145 return codepointBuffer;
146 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698