| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #library("unicode_core"); | 5 #library("unicode_core"); |
| 6 | 6 |
| 7 /* | 7 /* |
| 8 * Test for presence of bug related to the use of UTF-16 code units for | 8 * Test for presence of bug related to the use of UTF-16 code units for |
| 9 * Dart compiled to JS. | 9 * Dart compiled to JS. |
| 10 */ | 10 */ |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 throw new IllegalArgumentException("length"); | 54 throw new IllegalArgumentException("length"); |
| 55 } | 55 } |
| 56 | 56 |
| 57 int end = length != null ? | 57 int end = length != null ? |
| 58 Math.min(codepoints.length, offset + length) : | 58 Math.min(codepoints.length, offset + length) : |
| 59 codepoints.length; | 59 codepoints.length; |
| 60 | 60 |
| 61 int encodedLength = 0; | 61 int encodedLength = 0; |
| 62 for (int i = offset; i < end; i++) { | 62 for (int i = offset; i < end; i++) { |
| 63 int value = codepoints[i]; | 63 int value = codepoints[i]; |
| 64 if ((value >= 0 && value < UNICODE_UTF16_RESERVED_LO) || | 64 if ((value >= 0 && value < UNICODE_UTF16_RESERVED_LO) || |
| 65 (value > UNICODE_UTF16_RESERVED_HI && value <= UNICODE_PLANE_ONE_MAX)) { | 65 (value > UNICODE_UTF16_RESERVED_HI && value <= UNICODE_PLANE_ONE_MAX)) { |
| 66 encodedLength++; | 66 encodedLength++; |
| 67 } else if (value > UNICODE_PLANE_ONE_MAX && | 67 } else if (value > UNICODE_PLANE_ONE_MAX && |
| 68 value <= UNICODE_VALID_RANGE_MAX) { | 68 value <= UNICODE_VALID_RANGE_MAX) { |
| 69 encodedLength += 2; | 69 encodedLength += 2; |
| 70 } else { | 70 } else { |
| 71 encodedLength++; | 71 encodedLength++; |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 | 74 |
| 75 void addReplacementCodepoint(List<int> codepointBuffer, int offset, | 75 void addReplacementCodepoint(List<int> codepointBuffer, int offset, |
| 76 int replacementCodepoint) { | 76 int replacementCodepoint) { |
| 77 if(replacementCodepoint != null) { | 77 if (replacementCodepoint != null) { |
| 78 codepointBuffer[offset] = replacementCodepoint; | 78 codepointBuffer[offset] = replacementCodepoint; |
| 79 } else { | 79 } else { |
| 80 throw new IllegalArgumentException("Invalid encoding"); | 80 throw new IllegalArgumentException("Invalid encoding"); |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 |
| 83 List<int> codeUnitsBuffer = new List<int>(encodedLength); | 84 List<int> codeUnitsBuffer = new List<int>(encodedLength); |
| 84 int j = 0; | 85 int j = 0; |
| 85 for (int i = offset; i < end; i++) { | 86 for (int i = offset; i < end; i++) { |
| 86 int value = codepoints[i]; | 87 int value = codepoints[i]; |
| 87 if ((value >= 0 && value < UNICODE_UTF16_RESERVED_LO) || | 88 if ((value >= 0 && value < UNICODE_UTF16_RESERVED_LO) || |
| 88 (value > UNICODE_UTF16_RESERVED_HI && value <= UNICODE_PLANE_ONE_MAX)) { | 89 (value > UNICODE_UTF16_RESERVED_HI && value <= UNICODE_PLANE_ONE_MAX)) { |
| 89 codeUnitsBuffer[j++] = value; | 90 codeUnitsBuffer[j++] = value; |
| 90 } else if (value > UNICODE_PLANE_ONE_MAX && | 91 } else if (value > UNICODE_PLANE_ONE_MAX && |
| 91 value <= UNICODE_VALID_RANGE_MAX) { | 92 value <= UNICODE_VALID_RANGE_MAX) { |
| 92 int base = value - UNICODE_UTF16_OFFSET; | 93 int base = value - UNICODE_UTF16_OFFSET; |
| 93 codeUnitsBuffer[j++] = UNICODE_UTF16_SURROGATE_UNIT_0_BASE + | 94 codeUnitsBuffer[j++] = UNICODE_UTF16_SURROGATE_UNIT_0_BASE + |
| 94 ((base & UNICODE_UTF16_HI_MASK) >> 10); | 95 ((base & UNICODE_UTF16_HI_MASK) >> 10); |
| 95 codeUnitsBuffer[j++] = UNICODE_UTF16_SURROGATE_UNIT_1_BASE + | 96 codeUnitsBuffer[j++] = UNICODE_UTF16_SURROGATE_UNIT_1_BASE + |
| 96 (base & UNICODE_UTF16_LO_MASK); | 97 (base & UNICODE_UTF16_LO_MASK); |
| 97 } else { | 98 } else { |
| 98 addReplacementCodepoint(codeUnitsBuffer, j++, replacementCodepoint); | 99 addReplacementCodepoint(codeUnitsBuffer, j++, replacementCodepoint); |
| 99 } | 100 } |
| 100 } | 101 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 112 } | 113 } |
| 113 | 114 |
| 114 if (!(length == null || length >= 0)) { | 115 if (!(length == null || length >= 0)) { |
| 115 throw new IllegalArgumentException("length"); | 116 throw new IllegalArgumentException("length"); |
| 116 } | 117 } |
| 117 | 118 |
| 118 int end = length != null ? | 119 int end = length != null ? |
| 119 Math.min(utf16CodeUnits.length, offset + length) : | 120 Math.min(utf16CodeUnits.length, offset + length) : |
| 120 utf16CodeUnits.length; | 121 utf16CodeUnits.length; |
| 121 | 122 |
| 122 void addReplacementCodepoint(void f(int v), int replacementCodepoint) { | 123 void decode(void f(int v)) { |
| 123 if(replacementCodepoint != null) { | |
| 124 f(replacementCodepoint); | |
| 125 } else { | |
| 126 throw new IllegalArgumentException("Invalid encoding"); | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 void apply(void f(int v)) { | |
| 131 int i = offset; | 124 int i = offset; |
| 132 // skip the first entry if it is a BOM. | 125 // skip the first entry if it is a BOM. |
| 133 if (end > 0 && utf16CodeUnits[0] == UNICODE_BOM) { | 126 if (end > 0 && utf16CodeUnits[0] == UNICODE_BOM) { |
| 134 i++; | 127 i++; |
| 135 } | 128 } |
| 136 while (i < end) { | 129 while (i < end) { |
| 137 int value = utf16CodeUnits[i++]; | 130 int value = utf16CodeUnits[i++]; |
| 138 if (value < 0) { | 131 if (value < 0) { |
| 139 addReplacementCodepoint(f, replacementCodepoint); | 132 f(null); |
| 140 continue; | 133 continue; |
| 141 } | 134 } |
| 142 if (value < UNICODE_UTF16_RESERVED_LO || | 135 if (value < UNICODE_UTF16_RESERVED_LO || |
| 143 (value > UNICODE_UTF16_RESERVED_HI && | 136 (value > UNICODE_UTF16_RESERVED_HI && |
| 144 value <= UNICODE_PLANE_ONE_MAX)) { | 137 value <= UNICODE_PLANE_ONE_MAX)) { |
| 145 // transfer directly | 138 // transfer directly |
| 146 f(value); | 139 f(value); |
| 147 } else if (value < UNICODE_UTF16_SURROGATE_UNIT_1_BASE && i < end) { | 140 } else if (value < UNICODE_UTF16_SURROGATE_UNIT_1_BASE && i < end) { |
| 148 // merge surrogate pair | 141 // merge surrogate pair |
| 149 int nextValue = utf16CodeUnits[i++]; | 142 int nextValue = utf16CodeUnits[i++]; |
| 150 if (nextValue >= UNICODE_UTF16_SURROGATE_UNIT_1_BASE && | 143 if (nextValue >= UNICODE_UTF16_SURROGATE_UNIT_1_BASE && |
| 151 nextValue <= UNICODE_UTF16_RESERVED_HI) { | 144 nextValue <= UNICODE_UTF16_RESERVED_HI) { |
| 152 value = (value - UNICODE_UTF16_SURROGATE_UNIT_0_BASE) << 10; | 145 value = (value - UNICODE_UTF16_SURROGATE_UNIT_0_BASE) << 10; |
| 153 value += UNICODE_UTF16_OFFSET + | 146 value += UNICODE_UTF16_OFFSET + |
| 154 (nextValue - UNICODE_UTF16_SURROGATE_UNIT_1_BASE); | 147 (nextValue - UNICODE_UTF16_SURROGATE_UNIT_1_BASE); |
| 155 f(value); | 148 f(value); |
| 156 } else { | 149 } else { |
| 157 if (nextValue >= UNICODE_UTF16_SURROGATE_UNIT_0_BASE && | 150 if (nextValue >= UNICODE_UTF16_SURROGATE_UNIT_0_BASE && |
| 158 nextValue < UNICODE_UTF16_SURROGATE_UNIT_1_BASE) { | 151 nextValue < UNICODE_UTF16_SURROGATE_UNIT_1_BASE) { |
| 159 i--; | 152 i--; |
| 160 } | 153 } |
| 161 addReplacementCodepoint(f, replacementCodepoint); | 154 f(null); |
| 162 continue; | 155 continue; |
| 163 } | 156 } |
| 164 } else { | 157 } else { |
| 165 addReplacementCodepoint(f, replacementCodepoint); | 158 f(null); |
| 166 continue; | 159 continue; |
| 167 } | 160 } |
| 168 } | 161 } |
| 169 } | 162 } |
| 163 |
| 164 // First pass through data to 1) size the output buffer and 2) check for |
| 165 // special case optimization where A) the length stays the same and B) |
| 166 // no special replacement characters are used. If these criteria are met |
| 167 // we can just copy input to the output. |
| 170 int codepointBufferLength = 0; | 168 int codepointBufferLength = 0; |
| 171 apply(void _(int value) { | 169 bool hasReplacements = false; |
| 170 decode(void _(int value) { |
| 172 codepointBufferLength++; | 171 codepointBufferLength++; |
| 172 if (value == null) { |
| 173 hasReplacements = true; |
| 174 } |
| 173 }); | 175 }); |
| 174 | 176 |
| 177 // If the string calls for replacements, but when the method is called |
| 178 // with replacementCodepoint explicitly set to null, then throw an exception. |
| 179 if (hasReplacements && replacementCodepoint == null) { |
| 180 throw new IllegalArgumentException("Invalid encoding"); |
| 181 } |
| 182 |
| 183 int _length = end - offset; |
| 175 List<int> codepointBuffer = new List<int>(codepointBufferLength); | 184 List<int> codepointBuffer = new List<int>(codepointBufferLength); |
| 176 int i = 0; | 185 if (_length == codepointBufferLength && !hasReplacements) { |
| 177 apply(void _(int value) { | 186 codepointBuffer.setRange(0, _length, utf16CodeUnits, offset); |
| 178 codepointBuffer[i++] = value; | 187 } else { |
| 179 }); | 188 int i = 0; |
| 189 decode( |
| 190 void _(int value) { |
| 191 if (value != null) { |
| 192 codepointBuffer[i++] = value; |
| 193 } else { |
| 194 codepointBuffer[i++] = replacementCodepoint; |
| 195 } |
| 196 } |
| 197 ); |
| 198 } |
| 180 return codepointBuffer; | 199 return codepointBuffer; |
| 181 } | 200 } |
| OLD | NEW |