add TextDecoder for string to UTF32

This commit is contained in:
Jörg Breitbart
2019-01-02 22:50:15 +01:00
parent 5fd764a89d
commit dfc853aef4
3 changed files with 169 additions and 15 deletions
+87
View File
@@ -0,0 +1,87 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
/**
* StringToUtf32 - decodes UTF16 sequences into UTF32 codepoints.
* To keep the decoder in line with JS strings it handles single surrogates as UCS2.
*/
export class StringToUtf32 {
private _interim: number = 0;
/**
* Clears interim and resets decoder to clean state.
*/
public clear(): void {
this._interim = 0;
}
/**
* Decode JS string to UTF32 codepoints.
* The methods assumes stream input and will store partly transmitted
* surrogate pairs and decode them with the next data chunk.
* Note: The method does no bound checks for target, therefore make sure
* the provided input data does not exceed the size of `target`.
* Returns the number of written codepoints in `target`.
*/
decode(input: string, target: Uint32Array): number {
const length = input.length;
if (!length) {
return 0;
}
let size = 0;
let startPos = 0;
// handle leftover surrogate high
if (this._interim) {
const second = input.charCodeAt(startPos++);
if (0xDC00 <= second && second <= 0xDFFF) {
target[size++] = (this._interim - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
} else {
// illegal codepoint (USC2 handling)
target[size++] = this._interim;
target[size++] = second;
}
this._interim = 0;
}
for (let i = startPos; i < length; ++i) {
const code = input.charCodeAt(i);
// surrogate pair first
if (0xD800 <= code && code <= 0xDBFF) {
if (++i >= length) {
this._interim = code;
return size;
}
const second = input.charCodeAt(i);
if (0xDC00 <= second && second <= 0xDFFF) {
target[size++] = (code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
} else {
// illegal codepoint (USC2 handling)
target[size++] = code;
target[size++] = second;
}
continue;
}
target[size++] = code;
}
return size;
}
}
/**
* Polyfill - Convert UTF32 codepoint into JS string.
*/
export function stringFromCodePoint(codePoint: number): string {
if ((String as any).fromCodePoint) {
return (String as any).fromCodePoint(codePoint);
}
if (codePoint > 0xFFFF) {
codePoint -= 0x10000;
return String.fromCharCode((codePoint >> 10) + 0xD800) + String.fromCharCode((codePoint % 0x400) + 0xDC00);
}
return String.fromCharCode(codePoint);
}