From b7079f60b3b37f551682fbf3c35d043eb8e85c58 Mon Sep 17 00:00:00 2001 From: AugustePop Date: Mon, 17 Jul 2017 16:38:34 +0800 Subject: [PATCH] add BinaryStringC encoding for IE compatibility --- src/Common/CompressionCommon.ts | 8 ++++ src/Encoding/BinaryStringC.ts | 95 +++++++++++++++++++++++++++++++++++++++++ src/Exports/Exports.ts | 10 ++++- 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/Encoding/BinaryStringC.ts diff --git a/src/Common/CompressionCommon.ts b/src/Common/CompressionCommon.ts index 6edea5f..d2c3c38 100644 --- a/src/Common/CompressionCommon.ts +++ b/src/Common/CompressionCommon.ts @@ -33,6 +33,8 @@ namespace LZUTF8 { return encodeBase64(compressedBytes); case "BinaryString": return encodeBinaryString(compressedBytes); + case "BinaryStringC": + return encodeBinaryStringC(compressedBytes); default: throw new TypeError("encodeCompressedBytes: invalid output encoding requested"); } @@ -62,6 +64,12 @@ namespace LZUTF8 { return decodeBinaryString(compressedData); + case "BinaryStringC": + if (typeof compressedData !== "string") + throw new TypeError("decodeCompressedData: 'BinaryStringC' input type was specified but input is not a string"); + + return decodeBinaryStringC(compressedData); + default: throw new TypeError(`decodeCompressedData: invalid input encoding requested: '${inputEncoding}'`); } diff --git a/src/Encoding/BinaryStringC.ts b/src/Encoding/BinaryStringC.ts new file mode 100644 index 0000000..914ff06 --- /dev/null +++ b/src/Encoding/BinaryStringC.ts @@ -0,0 +1,95 @@ +namespace LZUTF8 { + export namespace Encoding { + export namespace BinaryStringC { + export const encode = function (input: Uint8Array): string { + if (input == null) + throw new TypeError("BinaryStringC.encode: undefined or null input received"); + + if (input.length === 0) + return ""; + + const inputLength = input.length; + + const outputStringBuilder = new StringBuilder(); + + let remainder = 0; + let state = 1; + + for (let i = 0; i < inputLength; i += 2) { + let value: number; + + if (i == inputLength - 1) + value = (input[i] << 8); + else + value = (input[i] << 8) | input[i + 1]; + + outputStringBuilder.appendCharCode(((remainder << (16 - state)) | value >>> state) + 1); + remainder = value & ((1 << state) - 1); + + if (state === 15) { + outputStringBuilder.appendCharCode(remainder + 1); + remainder = 0; + state = 1; + } + else { + state += 1; + } + + if (i >= inputLength - 2) + outputStringBuilder.appendCharCode((remainder << (16 - state)) + 1); + } + + outputStringBuilder.appendCharCode(32770 | (inputLength % 2)); + + return outputStringBuilder.getOutputString(); + } + + export const decode = function (input: string): Uint8Array { + if (typeof input !== "string") + throw new TypeError("BinaryStringC.decode: invalid input type"); + + if (input == "") + return new Uint8Array(0); + + const output = new Uint8Array(input.length * 3); + let outputPosition = 0; + + const appendToOutput = (value: number) => { + output[outputPosition++] = value >>> 8; + output[outputPosition++] = value & 255; + }; + + let remainder = 0; + let state = 0; + + for (let i = 0; i < input.length; i++) { + let value = input.charCodeAt(i) - 1; + + if (value >= 32770 - 1) { + if (value == (32770 | 1) - 1) + outputPosition--; + + state = 0; + continue; + } + + // + if (state == 0) { + remainder = value; + } + else { + appendToOutput((remainder << state) | (value >>> (15 - state))); + remainder = value & ((1 << (15 - state)) - 1); + } + + if (state == 15) + state = 0; + else + state += 1; + } + + return output.subarray(0, outputPosition); + } + } + } +} diff --git a/src/Exports/Exports.ts b/src/Exports/Exports.ts index ffa377c..8e2abd3 100644 --- a/src/Exports/Exports.ts +++ b/src/Exports/Exports.ts @@ -1,6 +1,6 @@ namespace LZUTF8 { export type UncompressedEncoding = "String" | "ByteArray"; - export type CompressedEncoding = "ByteArray" | "Buffer" | "Base64" | "BinaryString"; + export type CompressedEncoding = "ByteArray" | "Buffer" | "Base64" | "BinaryString" | "BinaryStringC"; export type DecompressedEncoding = "String" | "ByteArray" | "Buffer"; export type CompressionOptions = { @@ -137,4 +137,12 @@ namespace LZUTF8 { export function decodeBinaryString(str: string): Uint8Array { return Encoding.BinaryString.decode(str); } + + export function encodeBinaryStringC(input: Uint8Array): string { + return Encoding.BinaryStringC.encode(input); + } + + export function decodeBinaryStringC(str: string): Uint8Array { + return Encoding.BinaryStringC.decode(str); + } } -- 2.13.1