UNPKG

@deepkit/bson

Version:
132 lines (128 loc) 4.95 kB
"use strict"; /* * Deepkit Framework * Copyright (C) 2021 Deepkit UG, Marc J. Schmidt * * This program is free software: you can redistribute it and/or modify * it under the terms of the MIT License. * * You should have received a copy of the MIT License along with this program. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.buildStringDecoder = exports.decodeUTF8Short = exports.decodeUTF8 = void 0; const core_1 = require("@deepkit/core"); const model_1 = require("./model"); const decoder = new TextDecoder("utf-8"); function decodeUTF8(buffer, off = 0, end) { if (end - off > 512) { return decoder.decode(buffer.slice(off, end)); } else { return decodeUTF8Short(buffer, off, end); } } exports.decodeUTF8 = decodeUTF8; function decodeUTF8Short(buffer, off = 0, end) { let s = ''; while (off < end) { let c = buffer[off++]; if (c > 127) { if (c > 191 && c < 224) { if (off >= end) throw new model_1.BSONError('UTF-8 decode: incomplete 2-byte sequence'); c = (c & 31) << 6 | buffer[off++] & 63; } else if (c > 223 && c < 240) { if (off + 1 >= end) throw new model_1.BSONError('UTF-8 decode: incomplete 3-byte sequence'); c = (c & 15) << 12 | (buffer[off++] & 63) << 6 | buffer[off++] & 63; } else if (c > 239 && c < 248) { if (off + 2 >= end) throw new model_1.BSONError('UTF-8 decode: incomplete 4-byte sequence'); c = (c & 7) << 18 | (buffer[off++] & 63) << 12 | (buffer[off++] & 63) << 6 | buffer[off++] & 63; } else throw new model_1.BSONError('UTF-8 decode: unknown multibyte start 0x' + c.toString(16) + ' at index ' + (off - 1)); if (c <= 0xffff) { s += String.fromCharCode(c); } else if (c <= 0x10ffff) { c -= 0x10000; s += String.fromCharCode(c >> 10 | 0xd800, c & 0x3FF | 0xdc00); } else throw new model_1.BSONError('UTF-8 decode: code point 0x' + c.toString(16) + ' exceeds UTF-16 reach'); } else { if (c === 0) { return s; } s += String.fromCharCode(c); } } return s; } exports.decodeUTF8Short = decodeUTF8Short; function buildStringDecoder(specializations = 10) { const compiler = new core_1.CompilerContext(); // const midDecoding: string[] = []; const endDecoding = []; function fromCharCode(number) { const codes = []; for (let i = 0; i < number; i++) { codes.push(`codes[${i}]`); } return `fromCharCode(${codes.join(', ')})`; } const fns = []; for (let i = 1; i <= specializations; i++) { const fn = new Function('fromCharCode', 'return function(codes) { return ' + fromCharCode(i) + '}')(String.fromCharCode); compiler.context.set('decodeCodes' + i, fn); fns.push(fn); } for (let i = 0; i < specializations; i++) { // midDecoding.push(`if (codesOffset === ${i + 1}) s += decodeCodes${i + 1}(codes);`) endDecoding.push(`if (codesOffset === ${i + 1}) return s + decodeCodes${i + 1}(codes);`); } compiler.context.set('codes', new Uint16Array(specializations)); compiler.context.set('fns', fns); compiler.context.set('fromCharCode', String.fromCharCode); const functionCode = ` let codesOffset = 0; let s = ''; while (off < end) { let c = buffer[off++]; if (c > 127) { if (c > 191 && c < 224) { c = (c & 31) << 6 | buffer[off++] & 63; } else if (c > 223 && c < 240) { c = (c & 15) << 12 | (buffer[off++] & 63) << 6 | buffer[off++] & 63; } else if (c > 239 && c < 248) { c = (c & 7) << 18 | (buffer[off++] & 63) << 12 | (buffer[off++] & 63) << 6 | buffer[off++] & 63; } if (c <= 0xffff) { codes[codesOffset++] = c; } else if (c <= 0x10ffff) { c -= 0x10000; codes[codesOffset++] = c >> 10 | 0xd800; codes[codesOffset++] = c & 0x3FF | 0xdc00; } } else { if (c === 0) { return codesOffset ? s + fns[codesOffset - 1](codes) : s; } codes[codesOffset++] = c; } if (codesOffset >= ${specializations}) { s += decodeCodes${specializations}(codes); codesOffset = 0; } } if (codesOffset === 0) return s; return s + fns[codesOffset - 1](codes); `; return compiler.build(functionCode, 'buffer', 'off', 'end'); } exports.buildStringDecoder = buildStringDecoder; //# sourceMappingURL=strings.js.map