cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
158 lines (134 loc) • 5.59 kB
JavaScript
import defaultValue from './defaultValue.js';
import defined from './defined.js';
import DeveloperError from './DeveloperError.js';
import RuntimeError from './RuntimeError.js';
/**
* @private
*/
function getStringFromTypedArray(uint8Array, byteOffset, byteLength) {
//>>includeStart('debug', pragmas.debug);
if (!defined(uint8Array)) {
throw new DeveloperError('uint8Array is required.');
}
if (byteOffset < 0) {
throw new DeveloperError('byteOffset cannot be negative.');
}
if (byteLength < 0) {
throw new DeveloperError('byteLength cannot be negative.');
}
if ((byteOffset + byteLength) > uint8Array.byteLength) {
throw new DeveloperError('sub-region exceeds array bounds.');
}
//>>includeEnd('debug');
byteOffset = defaultValue(byteOffset, 0);
byteLength = defaultValue(byteLength, uint8Array.byteLength - byteOffset);
uint8Array = uint8Array.subarray(byteOffset, byteOffset + byteLength);
return getStringFromTypedArray.decode(uint8Array);
}
// Exposed functions for testing
getStringFromTypedArray.decodeWithTextDecoder = function(view) {
var decoder = new TextDecoder('utf-8');
return decoder.decode(view);
};
getStringFromTypedArray.decodeWithFromCharCode = function(view) {
var result = '';
var codePoints = utf8Handler(view);
var length = codePoints.length;
for (var i = 0; i < length; ++i) {
var cp = codePoints[i];
if (cp <= 0xFFFF) {
result += String.fromCharCode(cp);
} else {
cp -= 0x10000;
result += String.fromCharCode((cp >> 10) + 0xD800,
(cp & 0x3FF) + 0xDC00);
}
}
return result;
};
function inRange(a, min, max) {
return min <= a && a <= max;
}
// This code is inspired by public domain code found here: https://github.com/inexorabletash/text-encoding
function utf8Handler(utfBytes) {
var codePoint = 0;
var bytesSeen = 0;
var bytesNeeded = 0;
var lowerBoundary = 0x80;
var upperBoundary = 0xBF;
var codePoints = [];
var length = utfBytes.length;
for (var i = 0; i < length; ++i) {
var currentByte = utfBytes[i];
// If bytesNeeded = 0, then we are starting a new character
if (bytesNeeded === 0) {
// 1 Byte Ascii character
if (inRange(currentByte, 0x00, 0x7F)) {
// Return a code point whose value is byte.
codePoints.push(currentByte);
continue;
}
// 2 Byte character
if (inRange(currentByte, 0xC2, 0xDF)) {
bytesNeeded = 1;
codePoint = currentByte & 0x1F;
continue;
}
// 3 Byte character
if (inRange(currentByte, 0xE0, 0xEF)) {
// If byte is 0xE0, set utf-8 lower boundary to 0xA0.
if (currentByte === 0xE0) {
lowerBoundary = 0xA0;
}
// If byte is 0xED, set utf-8 upper boundary to 0x9F.
if (currentByte === 0xED) {
upperBoundary = 0x9F;
}
bytesNeeded = 2;
codePoint = currentByte & 0xF;
continue;
}
// 4 Byte character
if (inRange(currentByte, 0xF0, 0xF4)) {
// If byte is 0xF0, set utf-8 lower boundary to 0x90.
if (currentByte === 0xF0) {
lowerBoundary = 0x90;
}
// If byte is 0xF4, set utf-8 upper boundary to 0x8F.
if (currentByte === 0xF4) {
upperBoundary = 0x8F;
}
bytesNeeded = 3;
codePoint = currentByte & 0x7;
continue;
}
throw new RuntimeError('String decoding failed.');
}
// Out of range, so ignore the first part(s) of the character and continue with this byte on its own
if (!inRange(currentByte, lowerBoundary, upperBoundary)) {
codePoint = bytesNeeded = bytesSeen = 0;
lowerBoundary = 0x80;
upperBoundary = 0xBF;
--i;
continue;
}
// Set appropriate boundaries, since we've now checked byte 2 of a potential longer character
lowerBoundary = 0x80;
upperBoundary = 0xBF;
// Add byte to code point
codePoint = (codePoint << 6) | (currentByte & 0x3F);
// We have the correct number of bytes, so push and reset for next character
++bytesSeen;
if (bytesSeen === bytesNeeded) {
codePoints.push(codePoint);
codePoint = bytesNeeded = bytesSeen = 0;
}
}
return codePoints;
}
if (typeof TextDecoder !== 'undefined') {
getStringFromTypedArray.decode = getStringFromTypedArray.decodeWithTextDecoder;
} else {
getStringFromTypedArray.decode = getStringFromTypedArray.decodeWithFromCharCode;
}
export default getStringFromTypedArray;