volleyball-dev-frontend/node_modules/restructure/src/String.js
2025-06-02 16:42:16 +00:00

156 lines
3.7 KiB
JavaScript

import {Base} from './Base.js';
import {Number as NumberT} from './Number.js';
import * as utils from './utils.js';
class StringT extends Base {
constructor(length, encoding = 'ascii') {
super();
this.length = length;
this.encoding = encoding;
}
decode(stream, parent) {
let length, pos;
let { encoding } = this;
if (typeof encoding === 'function') {
encoding = encoding.call(parent, parent) || 'ascii';
}
let width = encodingWidth(encoding);
if (this.length != null) {
length = utils.resolveLength(this.length, stream, parent);
} else {
let buffer;
({buffer, length, pos} = stream);
while ((pos < length - width + 1) &&
(buffer[pos] !== 0x00 ||
(width === 2 && buffer[pos+1] !== 0x00)
)) {
pos += width;
}
length = pos - stream.pos;
}
const string = stream.readString(length, encoding);
if ((this.length == null) && (stream.pos < stream.length)) {
stream.pos+=width;
}
return string;
}
size(val, parent) {
// Use the defined value if no value was given
if (val === undefined || val === null) {
return utils.resolveLength(this.length, null, parent);
}
let { encoding } = this;
if (typeof encoding === 'function') {
encoding = encoding.call(parent != null ? parent.val : undefined, parent != null ? parent.val : undefined) || 'ascii';
}
if (encoding === 'utf16be') {
encoding = 'utf16le';
}
let size = byteLength(val, encoding);
if (this.length instanceof NumberT) {
size += this.length.size();
}
if ((this.length == null)) {
size += encodingWidth(encoding);
}
return size;
}
encode(stream, val, parent) {
let { encoding } = this;
if (typeof encoding === 'function') {
encoding = encoding.call(parent != null ? parent.val : undefined, parent != null ? parent.val : undefined) || 'ascii';
}
if (this.length instanceof NumberT) {
this.length.encode(stream, byteLength(val, encoding));
}
stream.writeString(val, encoding);
if ((this.length == null)) {
return encodingWidth(encoding) == 2 ?
stream.writeUInt16LE(0x0000) :
stream.writeUInt8(0x00);
}
}
}
function encodingWidth(encoding) {
switch(encoding) {
case 'ascii':
case 'utf8': // utf8 is a byte-based encoding for zero-term string
return 1;
case 'utf16le':
case 'utf16-le':
case 'utf-16be':
case 'utf-16le':
case 'utf16be':
case 'utf16-be':
case 'ucs2':
return 2;
default:
//TODO: assume all other encodings are 1-byters
//throw new Error('Unknown encoding ' + encoding);
return 1;
}
}
function byteLength(string, encoding) {
switch (encoding) {
case 'ascii':
return string.length;
case 'utf8':
let len = 0;
for (let i = 0; i < string.length; i++) {
let c = string.charCodeAt(i);
if (c >= 0xd800 && c <= 0xdbff && i < string.length - 1) {
let c2 = string.charCodeAt(++i);
if ((c2 & 0xfc00) === 0xdc00) {
c = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000;
} else {
// unmatched surrogate.
i--;
}
}
if ((c & 0xffffff80) === 0) {
len++;
} else if ((c & 0xfffff800) === 0) {
len += 2;
} else if ((c & 0xffff0000) === 0) {
len += 3;
} else if ((c & 0xffe00000) === 0) {
len += 4;
}
}
return len;
case 'utf16le':
case 'utf16-le':
case 'utf16be':
case 'utf16-be':
case 'ucs2':
return string.length * 2;
default:
throw new Error('Unknown encoding ' + encoding);
}
}
export {StringT as String};