From be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 04:57:58 +0200 Subject: Adding upstream version 1.44.3. Signed-off-by: Daniel Baumann --- .../h2o/libh2o/misc/oktavia/src/binary-util.jsx | 597 +++++++++++++++++++++ 1 file changed, 597 insertions(+) create mode 100644 web/server/h2o/libh2o/misc/oktavia/src/binary-util.jsx (limited to 'web/server/h2o/libh2o/misc/oktavia/src/binary-util.jsx') diff --git a/web/server/h2o/libh2o/misc/oktavia/src/binary-util.jsx b/web/server/h2o/libh2o/misc/oktavia/src/binary-util.jsx new file mode 100644 index 00000000..06d5e758 --- /dev/null +++ b/web/server/h2o/libh2o/misc/oktavia/src/binary-util.jsx @@ -0,0 +1,597 @@ +class Binary +{ + static function dump32bitNumber (num : number) : string + { + var result = [String.fromCharCode(Math.floor(num / 65536))]; + result.push(String.fromCharCode(num % 65536)); + return result.join(""); + } + + static function load32bitNumber (buffer : string, offset : int) : number + { + var result = buffer.charCodeAt(offset) * 65536 + buffer.charCodeAt(offset + 1); + return result; + } + + static function dump16bitNumber (num : int) : string + { + return String.fromCharCode(num % 65536); + } + + static function load16bitNumber (buffer : string, offset : int) : int + { + return buffer.charCodeAt(offset); + } + + static function dumpString (str : string) : string + { + return Binary.dumpString(str, null); + } + + static function dumpString (str : string, report : Nullable.) : string + { + if (str.length > 32768) + { + str = str.slice(0, 32768); + } + var length = str.length; + var compress = true; + var charCodes = [] : int[]; + for (var i = 0; i < length; i++) + { + var charCode = str.charCodeAt(i); + if (charCode > 255) + { + compress = false; + break; + } + charCodes.push(charCode); + } + if (compress) + { + var result = [Binary.dump16bitNumber(length + 32768)]; + for (var i = 0; i < length; i += 2) + { + var bytes = charCodes[i]; + if (i != length - 1) + { + bytes += charCodes[i + 1] << 8; + } + result.push(Binary.dump16bitNumber(bytes)); + } + if (report) + { + report.add(length, Math.ceil(length / 2)); + } + } + else + { + var result = [Binary.dump16bitNumber(length), str]; + if (report) + { + report.add(length, length); + } + } + return result.join(''); + } + + static function loadString (buffer : string, offset : int) : LoadedStringResult + { + return new LoadedStringResult(buffer, offset); + } + + static function dumpStringList (strList : string[]) : string + { + return Binary.dumpStringList(strList, null); + } + + static function dumpStringList (strList : string[], report : Nullable.) : string + { + var result = [Binary.dump32bitNumber(strList.length)]; + for (var i = 0; i < strList.length; i++) + { + result.push(Binary.dumpString(strList[i], report)); + } + return result.join(''); + } + + static function loadStringList (buffer : string, offset : int) : LoadedStringListResult + { + return new LoadedStringListResult(buffer, offset); + } + + static function dumpStringListMap (strMap : Map.) : string + { + return Binary.dumpStringListMap(strMap, null); + } + + static function dumpStringListMap (strMap : Map., report : Nullable.) : string + { + var result = [] : string[]; + var counter = 0; + for (var key in strMap) + { + result.push(Binary.dumpString(key, report)); + result.push(Binary.dumpStringList(strMap[key], report)); + counter++; + } + return Binary.dump32bitNumber(counter) + result.join(''); + } + + static function loadStringListMap (buffer : string, offset : int) : LoadedStringListMapResult + { + return new LoadedStringListMapResult(buffer, offset); + } + + static function dump32bitNumberList (array : number[]) : string + { + return Binary.dump32bitNumberList(array, null); + } + + static function dump32bitNumberList (array : number[], report : Nullable.) : string + { + var result = [Binary.dump32bitNumber(array.length)] : string[]; + var index = 0; + var inputLength = array.length; + while (index < inputLength) + { + if (array[index] == 0) + { + var length = Binary._countZero(array, index); + result.push(Binary._zeroBlock(length)); + index += length; + } + else if (Binary._shouldZebraCode(array, index)) + { + result.push(Binary._createZebraCode(array, index)); + index = Math.min(array.length, index + 15); + } + else + { + var length = Binary._searchDoubleZero(array, index); + result.push(Binary._nonZeroBlock(array, index, length)); + if (length == 0) + { + throw new Error(''); + } + index += length; + } + } + var resultString = result.join(''); + if (report) + { + report.add(array.length * 2 + 2, resultString.length); + } + return resultString; + } + + static function load32bitNumberList (buffer :string, offset : int) : LoadedNumberListResult + { + return new LoadedNumberListResult(buffer, offset); + } + + static function _countZero (array : number[], offset : int) : int + { + for (var i = offset; i < array.length; i++) + { + if (array[i] != 0) + { + return i - offset; + } + } + return array.length - offset; + } + + static function _zeroBlock (length : int) : string + { + var result = [] : string[]; + while (length > 0) + { + if (length > 16384) + { + result.push(Binary.dump16bitNumber(16384 - 1)); + length -= 16384; + } + else + { + result.push(Binary.dump16bitNumber(length - 1)); + length = 0; + } + } + return result.join(''); + } + + static function _shouldZebraCode(array : number[], offset : int) : boolean + { + if (array.length - offset < 16) + { + return true; + } + var change = 0; + var isLastZero = false; + for (var i = offset; i < offset + 15; i++) + { + if (array[i] == 0) + { + if (!isLastZero) + { + isLastZero = true; + change++; + } + } + else + { + if (isLastZero) + { + isLastZero = false; + change++; + } + } + } + return change > 2; + } + + static function _searchDoubleZero (array : number[], offset : int) : int + { + var isLastZero = false; + for (var i = offset; i < array.length; i++) + { + if (array[i] == 0) + { + if (isLastZero) + { + return i - offset - 1; + } + isLastZero = true; + } + else + { + isLastZero = false; + } + } + return array.length - offset; + } + + static function _nonZeroBlock (array : number[], offset : int, length : int) : string + { + var result = [] : string[]; + while (length > 0) + { + var blockLength : int; + if (length > 16384) + { + blockLength = 16384; + length -= 16384; + } + else + { + blockLength = length; + length = 0; + } + result.push(Binary.dump16bitNumber((blockLength - 1) + 0x4000)); + for (var i = offset; i < offset + blockLength; i++) + { + result.push(Binary.dump32bitNumber(array[i])); + } + offset += blockLength; + } + return result.join(''); + } + + static function _createZebraCode (array : number[], offset : int) : string + { + var last = Math.min(offset + 15, array.length); + var code = 0x8000; + var result = [] : string[]; + for (var i = offset; i < last; i++) + { + if (array[i] != 0) + { + result.push(Binary.dump32bitNumber(array[i])); + code = code + (0x1 << (i - offset)); + } + } + return String.fromCharCode(code) + result.join(''); + } + + /* These base64 functions are based on http://www.onicos.com/staff/iz/amuse/javascript/expert/base64.txt + * original license: + * Copyright (C) 1999 Masanao Izumo + * Version: 1.0 + * LastModified: Dec 25 1999 + * This library is free. You can redistribute it and/or modify it. + */ + static const _base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + static function base64encode (str : string) : string + { + var out = [] : string[]; + var source = [] : int[]; + for (var i = 0; i < str.length; i++) + { + var code = str.charCodeAt(i); + source.push(code & 0x00ff, code >>> 8); + } + var len = str.length * 2; + var i = 0; + while (i < len) + { + var c1 = source[i++] & 0xff; + if (i == len) + { + out.push(Binary._base64EncodeChars.charAt(c1 >> 2)); + out.push(Binary._base64EncodeChars.charAt((c1 & 0x3) << 4)); + out.push("=="); + break; + } + var c2 = source[i++]; + if (i == len) + { + out.push(Binary._base64EncodeChars.charAt(c1 >> 2)); + out.push(Binary._base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4))); + out.push(Binary._base64EncodeChars.charAt((c2 & 0xF) << 2)); + out.push("="); + break; + } + var c3 = source[i++]; + out.push(Binary._base64EncodeChars.charAt(c1 >> 2)); + out.push(Binary._base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4))); + out.push(Binary._base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6))); + out.push(Binary._base64EncodeChars.charAt(c3 & 0x3F)); + } + return out.join(''); + } + + static const _base64DecodeChars = [ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1]; + + static function _mergeCharCode (source : int[]) : string + { + var result = [] : string[]; + for (var i = 0; i < source.length; i += 2) + { + result.push(String.fromCharCode(source[i] + (source[i + 1] << 8))); + } + return result.join(''); + } + + static function base64decode (str : string) : string + { + var len = str.length; + var i = 0; + var out = [] : int[]; + + while (i < len) + { + var c1, c2, c3, c4 : int; + + /* c1 */ + do { + c1 = Binary._base64DecodeChars[str.charCodeAt(i++) & 0xff]; + } while(i < len && c1 == -1); + if (c1 == -1) + { + break; + } + /* c2 */ + do { + c2 = Binary._base64DecodeChars[str.charCodeAt(i++) & 0xff]; + } while(i < len && c2 == -1); + if (c2 == -1) + { + break; + } + out.push((c1 << 2) | ((c2 & 0x30) >> 4)); + /* c3 */ + do { + c3 = str.charCodeAt(i++) & 0xff; + if (c3 == 61) + { + return Binary._mergeCharCode(out); + } + c3 = Binary._base64DecodeChars[c3]; + } while(i < len && c3 == -1); + if (c3 == -1) + { + break; + } + out.push(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); + + /* c4 */ + do { + c4 = str.charCodeAt(i++) & 0xff; + if (c4 == 61) + { + return Binary._mergeCharCode(out); + } + c4 = Binary._base64DecodeChars[c4]; + } while(i < len && c4 == -1); + if (c4 == -1) + { + break; + } + out.push(((c3 & 0x03) << 6) | c4); + } + return Binary._mergeCharCode(out); + } +} + +class LoadedStringResult +{ + var result : string; + var offset : int; + + function constructor (data : string, offset : int) + { + var strLength = Binary.load16bitNumber(data, offset++); + if (strLength > 32767) + { + strLength = strLength - 32768; + var bytes = [] : string[]; + + for (var i = 0; i < strLength; i += 2) + { + var code = data.charCodeAt(offset); + bytes.push(String.fromCharCode(code & 0x00ff)); + if (i != strLength - 1) + { + bytes.push(String.fromCharCode(code >>> 8)); + } + offset++; + } + this.result = bytes.join(''); + this.offset = offset; + } + else + { + this.result = data.slice(offset, offset + strLength); + this.offset = offset + strLength; + } + } +} + +class LoadedStringListResult +{ + var result : string[]; + var offset : int; + + function constructor (data : string, offset : int) + { + this.result = [] : string[]; + + var length = Binary.load32bitNumber(data, offset); + offset += 2; + for (var i = 0; i < length; i++) + { + var strLength = Binary.load16bitNumber(data, offset++); + var resultStr : string; + if (strLength > 32767) + { + var strLength = strLength - 32768; + var bytes = [] : string[]; + for (var j = 0; j < strLength; j += 2) + { + var code = data.charCodeAt(offset); + bytes.push(String.fromCharCode(code & 0x00ff)); + if (j != strLength - 1) + { + bytes.push(String.fromCharCode(code >>> 8)); + } + offset++; + } + resultStr = bytes.join(''); + } + else + { + resultStr = data.slice(offset, offset + strLength); + offset = offset + strLength; + } + this.result.push(resultStr); + } + this.offset = offset; + } +} + +class LoadedStringListMapResult +{ + var result : Map.; + var offset : int; + + function constructor (data : string, offset : int) + { + this.result = {} : Map.; + + var length = Binary.load32bitNumber(data, offset); + offset += 2; + for (var i = 0; i < length; i++) + { + var keyResult = Binary.loadString(data, offset); + var valueResult = Binary.loadStringList(data, keyResult.offset); + this.result[keyResult.result] = valueResult.result; + offset = valueResult.offset; + } + this.offset = offset; + } +} + +class LoadedNumberListResult +{ + var result : number[]; + var offset : int; + + function constructor(data : string, offset : int) + { + var resultLength = Binary.load32bitNumber(data, offset); + var originalOffset = offset; + offset += 2; + var result = [] : number[]; + while (result.length < resultLength) + { + var tag = data.charCodeAt(offset++); + if ((tag >>> 15) == 1) // zebra + { + var length = Math.min(resultLength - result.length, 15); + for (var i = 0; i < length; i++) + { + if ((tag >>> i) & 0x1) + { + result.push(Binary.load32bitNumber(data, offset)); + offset += 2; + } + else + { + result.push(0); + } + } + } + else if ((tag >>> 14) == 1) // non-zero + { + var length = tag - 0x4000 + 1; + for (var i = 0; i < length; i++) + { + result.push(Binary.load32bitNumber(data, offset)); + offset += 2; + } + } + else // zero + { + var length = tag + 1; + for (var i = 0; i < length; i++) + { + result.push(0); + } + } + } + this.result = result; + this.offset = offset; + } +} + +class CompressionReport +{ + var source : int; + var result : int; + function constructor () + { + this.source = 0; + this.result = 0; + } + + function add (source : int, result : int) : void + { + this.source += source; + this.result += result; + } + + function rate () : int + { + return Math.round(this.result * 100.0 / this.source); + } +} -- cgit v1.2.3