mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-19 23:07:33 +09:00
133 lines
2.8 KiB
JavaScript
133 lines
2.8 KiB
JavaScript
/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
/* jshint esnext: true, moz: true */
|
|
|
|
'use strict';
|
|
|
|
this.EXPORTED_SYMBOLS = ['DataReader'];
|
|
|
|
class DataReader {
|
|
// `data` is `Uint8Array`
|
|
constructor(data, startByte = 0) {
|
|
this._data = data;
|
|
this._cursor = startByte;
|
|
}
|
|
|
|
get buffer() {
|
|
return this._data.buffer;
|
|
}
|
|
|
|
get data() {
|
|
return this._data;
|
|
}
|
|
|
|
get eof() {
|
|
return this._cursor >= this._data.length;
|
|
}
|
|
|
|
getBytes(length = 1) {
|
|
if (!length) {
|
|
return new Uint8Array();
|
|
}
|
|
|
|
let end = this._cursor + length;
|
|
if (end > this._data.length) {
|
|
return new Uint8Array();
|
|
}
|
|
|
|
let uint8Array = new Uint8Array(this.buffer.slice(this._cursor, end));
|
|
this._cursor += length;
|
|
|
|
return uint8Array;
|
|
}
|
|
|
|
getString(length) {
|
|
let uint8Array = this.getBytes(length);
|
|
return _uint8ArrayToString(uint8Array);
|
|
}
|
|
|
|
getValue(length) {
|
|
let uint8Array = this.getBytes(length);
|
|
return _uint8ArrayToValue(uint8Array);
|
|
}
|
|
|
|
getLabel(decompressData) {
|
|
let parts = [];
|
|
let partLength;
|
|
|
|
while ((partLength = this.getValue(1))) {
|
|
// If a length has been specified instead of a pointer,
|
|
// read the string of the specified length.
|
|
if (partLength !== 0xc0) {
|
|
parts.push(this.getString(partLength));
|
|
continue;
|
|
}
|
|
|
|
// TODO: Handle case where we have a pointer to the label
|
|
parts.push(String.fromCharCode(0xc0) + this.getString(1));
|
|
break;
|
|
}
|
|
|
|
let label = parts.join('.');
|
|
|
|
return _decompressLabel(label, decompressData || this._data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
function _uint8ArrayToValue(uint8Array) {
|
|
let length = uint8Array.length;
|
|
if (length === 0) {
|
|
return null;
|
|
}
|
|
|
|
let value = 0;
|
|
for (let i = 0; i < length; i++) {
|
|
value = value << 8;
|
|
value += uint8Array[i];
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
function _uint8ArrayToString(uint8Array) {
|
|
let length = uint8Array.length;
|
|
if (length === 0) {
|
|
return '';
|
|
}
|
|
|
|
let results = [];
|
|
for (let i = 0; i < length; i += 1024) {
|
|
results.push(String.fromCharCode.apply(null, uint8Array.subarray(i, i + 1024)));
|
|
}
|
|
|
|
return results.join('');
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
function _decompressLabel(label, decompressData) {
|
|
let result = '';
|
|
|
|
for (let i = 0, length = label.length; i < length; i++) {
|
|
if (label.charCodeAt(i) !== 0xc0) {
|
|
result += label.charAt(i);
|
|
continue;
|
|
}
|
|
|
|
i++;
|
|
|
|
let reader = new DataReader(decompressData, label.charCodeAt(i));
|
|
result += _decompressLabel(reader.getLabel(), decompressData);
|
|
}
|
|
|
|
return result;
|
|
}
|