(_bytes, onError)
| 65 | }); |
| 66 | // http://stackoverflow.com/questions/13356493/decode-utf-8-with-javascript#13691499 |
| 67 | function getUtf8CodePoints(_bytes, onError) { |
| 68 | if (onError == null) { |
| 69 | onError = Utf8ErrorFuncs.error; |
| 70 | } |
| 71 | const bytes = getBytes(_bytes, "bytes"); |
| 72 | const result = []; |
| 73 | let i = 0; |
| 74 | // Invalid bytes are ignored |
| 75 | while (i < bytes.length) { |
| 76 | const c = bytes[i++]; |
| 77 | // 0xxx xxxx |
| 78 | if (c >> 7 === 0) { |
| 79 | result.push(c); |
| 80 | continue; |
| 81 | } |
| 82 | // Multibyte; how many bytes left for this character? |
| 83 | let extraLength = null; |
| 84 | let overlongMask = null; |
| 85 | // 110x xxxx 10xx xxxx |
| 86 | if ((c & 0xe0) === 0xc0) { |
| 87 | extraLength = 1; |
| 88 | overlongMask = 0x7f; |
| 89 | // 1110 xxxx 10xx xxxx 10xx xxxx |
| 90 | } |
| 91 | else if ((c & 0xf0) === 0xe0) { |
| 92 | extraLength = 2; |
| 93 | overlongMask = 0x7ff; |
| 94 | // 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx |
| 95 | } |
| 96 | else if ((c & 0xf8) === 0xf0) { |
| 97 | extraLength = 3; |
| 98 | overlongMask = 0xffff; |
| 99 | } |
| 100 | else { |
| 101 | if ((c & 0xc0) === 0x80) { |
| 102 | i += onError("UNEXPECTED_CONTINUE", i - 1, bytes, result); |
| 103 | } |
| 104 | else { |
| 105 | i += onError("BAD_PREFIX", i - 1, bytes, result); |
| 106 | } |
| 107 | continue; |
| 108 | } |
| 109 | // Do we have enough bytes in our data? |
| 110 | if (i - 1 + extraLength >= bytes.length) { |
| 111 | i += onError("OVERRUN", i - 1, bytes, result); |
| 112 | continue; |
| 113 | } |
| 114 | // Remove the length prefix from the char |
| 115 | let res = c & ((1 << (8 - extraLength - 1)) - 1); |
| 116 | for (let j = 0; j < extraLength; j++) { |
| 117 | let nextChar = bytes[i]; |
| 118 | // Invalid continuation byte |
| 119 | if ((nextChar & 0xc0) != 0x80) { |
| 120 | i += onError("MISSING_CONTINUE", i, bytes, result); |
| 121 | res = null; |
| 122 | break; |
| 123 | } |
| 124 | ; |
no test coverage detected