| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #library("unicode_core"); |
| 6 |
| 7 /* |
| 8 * Test for presence of bug related to the use of UTF-16 code units for |
| 9 * Dart compiled to JS. |
| 10 */ |
| 11 bool _test16BitCodeUnit = null; |
| 12 // TODO is16BitCodeUnit() is used to work around a bug with frog/dartc |
| 13 // (http://code.google.com/p/dart/issues/detail?id=1357). Consider |
| 14 // removing after this issue is resolved. |
| 15 bool is16BitCodeUnit() { |
| 16 if (_test16BitCodeUnit == null) { |
| 17 _test16BitCodeUnit = (new String.fromCharCodes([0x1D11E])) == |
| 18 (new String.fromCharCodes([0xD11E])); |
| 19 } |
| 20 return _test16BitCodeUnit; |
| 21 } |
| 22 |
| 23 /** |
| 24 * Invalid codepoints or encodings may be substituted with the value U+fffd. |
| 25 */ |
| 26 final int UNICODE_REPLACEMENT_CHARACTER_CODEPOINT = 0xfffd; |
| 27 final int UNICODE_BOM = 0xfeff; |
| 28 final int UNICODE_UTF_BOM_LO = 0xff; |
| 29 final int UNICODE_UTF_BOM_HI = 0xfe; |
| 30 |
| 31 final int UNICODE_BYTE_ZERO_MASK = 0xff; |
| 32 final int UNICODE_BYTE_ONE_MASK = 0xff00; |
| 33 final int UNICODE_VALID_RANGE_MAX = 0x10ffff; |
| 34 final int UNICODE_PLANE_ONE_MAX = 0xffff; |
| 35 final int UNICODE_UTF16_RESERVED_LO = 0xd800; |
| 36 final int UNICODE_UTF16_RESERVED_HI = 0xdfff; |
| 37 final int UNICODE_UTF16_OFFSET = 0x10000; |
| 38 final int UNICODE_UTF16_SURROGATE_UNIT_0_BASE = 0xd800; |
| 39 final int UNICODE_UTF16_SURROGATE_UNIT_1_BASE = 0xdc00; |
| 40 final int UNICODE_UTF16_HI_MASK = 0xffc00; |
| 41 final int UNICODE_UTF16_LO_MASK = 0x3ff; |
| 42 |
| 43 /** |
| 44 * Encode code points as UTF16 code units. |
| 45 */ |
| 46 List<int> codepointsToUtf16CodeUnits( |
| 47 List<int> codepoints, [int offset = 0, int length, |
| 48 int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { |
| 49 if (!(offset >= 0)) { |
| 50 throw new IllegalArgumentException("offset"); |
| 51 } |
| 52 |
| 53 if (!(length == null || length >= 0)) { |
| 54 throw new IllegalArgumentException("length"); |
| 55 } |
| 56 |
| 57 int end = length != null ? |
| 58 Math.min(codepoints.length, offset + length) : |
| 59 codepoints.length; |
| 60 |
| 61 int encodedLength = 0; |
| 62 for (int i = offset; i < end; i++) { |
| 63 int value = codepoints[i]; |
| 64 if ((value >= 0 && value < UNICODE_UTF16_RESERVED_LO) || |
| 65 (value > UNICODE_UTF16_RESERVED_HI && value <= UNICODE_PLANE_ONE_MAX)) { |
| 66 encodedLength++; |
| 67 } else if (value > UNICODE_PLANE_ONE_MAX && |
| 68 value <= UNICODE_VALID_RANGE_MAX) { |
| 69 encodedLength += 2; |
| 70 } else { |
| 71 encodedLength++; |
| 72 } |
| 73 } |
| 74 |
| 75 void addReplacementCodepoint(List<int> codepointBuffer, int offset, |
| 76 int replacementCodepoint) { |
| 77 if(replacementCodepoint != null) { |
| 78 codepointBuffer[offset] = replacementCodepoint; |
| 79 } else { |
| 80 throw new IllegalArgumentException("Invalid encoding"); |
| 81 } |
| 82 } |
| 83 List<int> codeUnitsBuffer = new List<int>(encodedLength); |
| 84 int j = 0; |
| 85 for (int i = offset; i < end; i++) { |
| 86 int value = codepoints[i]; |
| 87 if ((value >= 0 && value < UNICODE_UTF16_RESERVED_LO) || |
| 88 (value > UNICODE_UTF16_RESERVED_HI && value <= UNICODE_PLANE_ONE_MAX)) { |
| 89 codeUnitsBuffer[j++] = value; |
| 90 } else if (value > UNICODE_PLANE_ONE_MAX && |
| 91 value <= UNICODE_VALID_RANGE_MAX) { |
| 92 int base = value - UNICODE_UTF16_OFFSET; |
| 93 codeUnitsBuffer[j++] = UNICODE_UTF16_SURROGATE_UNIT_0_BASE + |
| 94 ((base & UNICODE_UTF16_HI_MASK) >> 10); |
| 95 codeUnitsBuffer[j++] = UNICODE_UTF16_SURROGATE_UNIT_1_BASE + |
| 96 (base & UNICODE_UTF16_LO_MASK); |
| 97 } else { |
| 98 addReplacementCodepoint(codeUnitsBuffer, j++, replacementCodepoint); |
| 99 } |
| 100 } |
| 101 return codeUnitsBuffer; |
| 102 } |
| 103 |
| 104 /** |
| 105 * Decodes the utf16 codeunits to codepoints. |
| 106 */ |
| 107 List<int> utf16CodeUnitsToCodepoints( |
| 108 List<int> utf16CodeUnits, [int offset = 0, int length, |
| 109 int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { |
| 110 if (!(offset >= 0)) { |
| 111 throw new IllegalArgumentException("offset"); |
| 112 } |
| 113 |
| 114 if (!(length == null || length >= 0)) { |
| 115 throw new IllegalArgumentException("length"); |
| 116 } |
| 117 |
| 118 int end = length != null ? |
| 119 Math.min(utf16CodeUnits.length, offset + length) : |
| 120 utf16CodeUnits.length; |
| 121 |
| 122 void addReplacementCodepoint(void f(int v), int replacementCodepoint) { |
| 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; |
| 132 // skip the first entry if it is a BOM. |
| 133 if (end > 0 && utf16CodeUnits[0] == UNICODE_BOM) { |
| 134 i++; |
| 135 } |
| 136 while (i < end) { |
| 137 int value = utf16CodeUnits[i++]; |
| 138 if (value < 0) { |
| 139 addReplacementCodepoint(f, replacementCodepoint); |
| 140 continue; |
| 141 } |
| 142 if (value < UNICODE_UTF16_RESERVED_LO || |
| 143 (value > UNICODE_UTF16_RESERVED_HI && |
| 144 value <= UNICODE_PLANE_ONE_MAX)) { |
| 145 // transfer directly |
| 146 f(value); |
| 147 } else if (value < UNICODE_UTF16_SURROGATE_UNIT_1_BASE && i < end) { |
| 148 // merge surrogate pair |
| 149 int nextValue = utf16CodeUnits[i++]; |
| 150 if (nextValue >= UNICODE_UTF16_SURROGATE_UNIT_1_BASE && |
| 151 nextValue <= UNICODE_UTF16_RESERVED_HI) { |
| 152 value = (value - UNICODE_UTF16_SURROGATE_UNIT_0_BASE) << 10; |
| 153 value += UNICODE_UTF16_OFFSET + |
| 154 (nextValue - UNICODE_UTF16_SURROGATE_UNIT_1_BASE); |
| 155 f(value); |
| 156 } else { |
| 157 if (nextValue >= UNICODE_UTF16_SURROGATE_UNIT_0_BASE && |
| 158 nextValue < UNICODE_UTF16_SURROGATE_UNIT_1_BASE) { |
| 159 i--; |
| 160 } |
| 161 addReplacementCodepoint(f, replacementCodepoint); |
| 162 continue; |
| 163 } |
| 164 } else { |
| 165 addReplacementCodepoint(f, replacementCodepoint); |
| 166 continue; |
| 167 } |
| 168 } |
| 169 } |
| 170 int codepointBufferLength = 0; |
| 171 apply(void _(int value) { |
| 172 codepointBufferLength++; |
| 173 }); |
| 174 |
| 175 List<int> codepointBuffer = new List<int>(codepointBufferLength); |
| 176 int i = 0; |
| 177 apply(void _(int value) { |
| 178 codepointBuffer[i++] = value; |
| 179 }); |
| 180 return codepointBuffer; |
| 181 } |
| OLD | NEW |