qvdjs 2.0.1 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +192 -100
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +191 -99
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5,7 +5,7 @@ var path2 = require('path');
|
|
|
5
5
|
var assert3 = require('assert');
|
|
6
6
|
var crypto2 = require('crypto');
|
|
7
7
|
var promises = require('timers/promises');
|
|
8
|
-
var
|
|
8
|
+
var xml = require('xml2js');
|
|
9
9
|
var os = require('os');
|
|
10
10
|
var v8 = require('v8');
|
|
11
11
|
var util = require('util');
|
|
@@ -16,7 +16,7 @@ var fs2__default = /*#__PURE__*/_interopDefault(fs2);
|
|
|
16
16
|
var path2__default = /*#__PURE__*/_interopDefault(path2);
|
|
17
17
|
var assert3__default = /*#__PURE__*/_interopDefault(assert3);
|
|
18
18
|
var crypto2__default = /*#__PURE__*/_interopDefault(crypto2);
|
|
19
|
-
var
|
|
19
|
+
var xml__default = /*#__PURE__*/_interopDefault(xml);
|
|
20
20
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
21
21
|
var v8__default = /*#__PURE__*/_interopDefault(v8);
|
|
22
22
|
|
|
@@ -1802,7 +1802,7 @@ var init_QvdFileWriter = __esm({
|
|
|
1802
1802
|
});
|
|
1803
1803
|
}
|
|
1804
1804
|
}
|
|
1805
|
-
const builder = new
|
|
1805
|
+
const builder = new xml__default.default.Builder({
|
|
1806
1806
|
renderOpts: {
|
|
1807
1807
|
pretty: true,
|
|
1808
1808
|
newline: "\r\n",
|
|
@@ -2364,6 +2364,13 @@ var init_memoryUtils = __esm({
|
|
|
2364
2364
|
});
|
|
2365
2365
|
|
|
2366
2366
|
// src/util/validationUtils.js
|
|
2367
|
+
function headerInteger(value) {
|
|
2368
|
+
if (typeof value !== "string" || !/^\s*-?\d+\s*$/.test(value)) {
|
|
2369
|
+
return NaN;
|
|
2370
|
+
}
|
|
2371
|
+
const number = Number(value);
|
|
2372
|
+
return number === 0 ? 0 : number;
|
|
2373
|
+
}
|
|
2367
2374
|
function validateHeaderStructure(headerObj, filePath, stage) {
|
|
2368
2375
|
const tableHeader = headerObj?.["QvdTableHeader"];
|
|
2369
2376
|
if (tableHeader === null || typeof tableHeader !== "object" || Array.isArray(tableHeader)) {
|
|
@@ -2373,7 +2380,7 @@ function validateHeaderStructure(headerObj, filePath, stage) {
|
|
|
2373
2380
|
stage
|
|
2374
2381
|
});
|
|
2375
2382
|
}
|
|
2376
|
-
const symbolTableLength =
|
|
2383
|
+
const symbolTableLength = headerInteger(tableHeader["Offset"]);
|
|
2377
2384
|
if (isNaN(symbolTableLength) || !Number.isSafeInteger(symbolTableLength) || symbolTableLength < 0) {
|
|
2378
2385
|
throw new exports.QvdCorruptedError("Invalid symbol table offset", {
|
|
2379
2386
|
offset: tableHeader["Offset"],
|
|
@@ -2381,6 +2388,47 @@ function validateHeaderStructure(headerObj, filePath, stage) {
|
|
|
2381
2388
|
stage
|
|
2382
2389
|
});
|
|
2383
2390
|
}
|
|
2391
|
+
const fields = tableHeader["Fields"]?.["QvdFieldHeader"];
|
|
2392
|
+
const fieldList = fields === void 0 || fields === null ? [] : Array.isArray(fields) ? fields : [fields];
|
|
2393
|
+
if (fieldList.length === 0) {
|
|
2394
|
+
throw new exports.QvdCorruptedError("The QVD file header declares no fields", {
|
|
2395
|
+
file: filePath,
|
|
2396
|
+
stage
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
const malformedIndex = fieldList.findIndex(
|
|
2400
|
+
(field) => field === null || typeof field !== "object" || Array.isArray(field)
|
|
2401
|
+
);
|
|
2402
|
+
if (malformedIndex !== -1) {
|
|
2403
|
+
throw new exports.QvdCorruptedError("The QVD file header declares a field with no properties", {
|
|
2404
|
+
fieldIndex: malformedIndex,
|
|
2405
|
+
fieldCount: fieldList.length,
|
|
2406
|
+
file: filePath,
|
|
2407
|
+
stage
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2411
|
+
fieldList.forEach((field, fieldIndex) => {
|
|
2412
|
+
const name = field["FieldName"];
|
|
2413
|
+
if (typeof name !== "string" || name === "") {
|
|
2414
|
+
throw new exports.QvdCorruptedError("The QVD file header declares a field with no usable name", {
|
|
2415
|
+
fieldIndex,
|
|
2416
|
+
fieldName: name,
|
|
2417
|
+
file: filePath,
|
|
2418
|
+
stage
|
|
2419
|
+
});
|
|
2420
|
+
}
|
|
2421
|
+
if (seen.has(name)) {
|
|
2422
|
+
throw new exports.QvdCorruptedError("The QVD file header declares two fields with the same name", {
|
|
2423
|
+
field: name,
|
|
2424
|
+
fieldIndexes: [seen.get(name), fieldIndex],
|
|
2425
|
+
file: filePath,
|
|
2426
|
+
stage
|
|
2427
|
+
});
|
|
2428
|
+
}
|
|
2429
|
+
seen.set(name, fieldIndex);
|
|
2430
|
+
});
|
|
2431
|
+
return fieldList;
|
|
2384
2432
|
}
|
|
2385
2433
|
function validateSymbolTableSizeEarly(symbolTableLength, filePath) {
|
|
2386
2434
|
const heapLimit = getHeapLimit();
|
|
@@ -2426,8 +2474,8 @@ function validateSymbolTableSize(symbolTableLength, filePath, totalRows) {
|
|
|
2426
2474
|
}
|
|
2427
2475
|
}
|
|
2428
2476
|
function validateFieldMetadata(field, symbolBufferLength, filePath) {
|
|
2429
|
-
const symbolsOffset =
|
|
2430
|
-
const symbolsLength =
|
|
2477
|
+
const symbolsOffset = headerInteger(field["Offset"]);
|
|
2478
|
+
const symbolsLength = headerInteger(field["Length"]);
|
|
2431
2479
|
if (isNaN(symbolsOffset) || !Number.isSafeInteger(symbolsOffset) || symbolsOffset < 0) {
|
|
2432
2480
|
throw new exports.QvdCorruptedError("Invalid symbol offset", {
|
|
2433
2481
|
field: field["FieldName"],
|
|
@@ -2455,6 +2503,63 @@ function validateFieldMetadata(field, symbolBufferLength, filePath) {
|
|
|
2455
2503
|
});
|
|
2456
2504
|
}
|
|
2457
2505
|
}
|
|
2506
|
+
function firstOverlap(ranges) {
|
|
2507
|
+
const claimed = ranges.filter((range) => range.length > 0).sort((a, b) => a.start - b.start);
|
|
2508
|
+
let furthest = null;
|
|
2509
|
+
for (const range of claimed) {
|
|
2510
|
+
if (furthest !== null && range.start < furthest.start + furthest.length) {
|
|
2511
|
+
return [furthest, range];
|
|
2512
|
+
}
|
|
2513
|
+
if (furthest === null || range.start + range.length > furthest.start + furthest.length) {
|
|
2514
|
+
furthest = range;
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
return null;
|
|
2518
|
+
}
|
|
2519
|
+
function validateSymbolAreas(fields, filePath) {
|
|
2520
|
+
const overlap = firstOverlap(
|
|
2521
|
+
fields.map((field) => ({
|
|
2522
|
+
field: field["FieldName"],
|
|
2523
|
+
start: headerInteger(field["Offset"]),
|
|
2524
|
+
length: headerInteger(field["Length"])
|
|
2525
|
+
}))
|
|
2526
|
+
);
|
|
2527
|
+
if (overlap !== null) {
|
|
2528
|
+
const [first, second] = overlap;
|
|
2529
|
+
throw new exports.QvdCorruptedError("Symbol areas overlap", {
|
|
2530
|
+
field: second.field,
|
|
2531
|
+
offset: second.start,
|
|
2532
|
+
length: second.length,
|
|
2533
|
+
overlaps: first.field,
|
|
2534
|
+
overlapsOffset: first.start,
|
|
2535
|
+
overlapsLength: first.length,
|
|
2536
|
+
file: filePath,
|
|
2537
|
+
stage: "parseSymbolTable"
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
function validateBitFields(fields, filePath) {
|
|
2542
|
+
const overlap = firstOverlap(
|
|
2543
|
+
fields.map((field) => ({
|
|
2544
|
+
field: field["FieldName"],
|
|
2545
|
+
start: headerInteger(field["BitOffset"]),
|
|
2546
|
+
length: headerInteger(field["BitWidth"])
|
|
2547
|
+
}))
|
|
2548
|
+
);
|
|
2549
|
+
if (overlap !== null) {
|
|
2550
|
+
const [first, second] = overlap;
|
|
2551
|
+
throw new exports.QvdCorruptedError("Bit fields overlap", {
|
|
2552
|
+
field: second.field,
|
|
2553
|
+
bitOffset: second.start,
|
|
2554
|
+
bitWidth: second.length,
|
|
2555
|
+
overlaps: first.field,
|
|
2556
|
+
overlapsBitOffset: first.start,
|
|
2557
|
+
overlapsBitWidth: first.length,
|
|
2558
|
+
file: filePath,
|
|
2559
|
+
stage: "parseIndexTable"
|
|
2560
|
+
});
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2458
2563
|
function validateRecordCount(totalRows, filePath, stage = "parseIndexTable") {
|
|
2459
2564
|
if (isNaN(totalRows) || !Number.isSafeInteger(totalRows) || totalRows < 0) {
|
|
2460
2565
|
throw new exports.QvdCorruptedError("Invalid number of records", {
|
|
@@ -2464,14 +2569,17 @@ function validateRecordCount(totalRows, filePath, stage = "parseIndexTable") {
|
|
|
2464
2569
|
});
|
|
2465
2570
|
}
|
|
2466
2571
|
}
|
|
2467
|
-
function
|
|
2572
|
+
function validateRecordSize(recordSize, filePath, stage = "parseIndexTable") {
|
|
2468
2573
|
if (isNaN(recordSize) || !Number.isSafeInteger(recordSize) || recordSize < 0) {
|
|
2469
2574
|
throw new exports.QvdCorruptedError("Invalid record byte size", {
|
|
2470
2575
|
recordSize,
|
|
2471
2576
|
file: filePath,
|
|
2472
|
-
stage
|
|
2577
|
+
stage
|
|
2473
2578
|
});
|
|
2474
2579
|
}
|
|
2580
|
+
}
|
|
2581
|
+
function validateIndexTableMetadata(recordSize, totalRows, indexTableLength, indexTableOffset, bufferLength, rowsToLoad, filePath, fileSize = null, windowFirstRow = 0, bufferFirstRow = 0) {
|
|
2582
|
+
validateRecordSize(recordSize, filePath);
|
|
2475
2583
|
validateRecordCount(totalRows, filePath);
|
|
2476
2584
|
if (recordSize === 0 && totalRows > 0) {
|
|
2477
2585
|
throw new exports.QvdCorruptedError("Record byte size cannot be zero when records exist", {
|
|
@@ -2555,8 +2663,8 @@ function validateIndexTableMetadata(recordSize, totalRows, indexTableLength, ind
|
|
|
2555
2663
|
}
|
|
2556
2664
|
}
|
|
2557
2665
|
function validateFieldBitMetadata(field, recordSize, filePath) {
|
|
2558
|
-
const bitOffset =
|
|
2559
|
-
const bitWidth =
|
|
2666
|
+
const bitOffset = headerInteger(field["BitOffset"]);
|
|
2667
|
+
const bitWidth = headerInteger(field["BitWidth"]);
|
|
2560
2668
|
if (isNaN(bitOffset) || !Number.isSafeInteger(bitOffset) || bitOffset < 0) {
|
|
2561
2669
|
throw new exports.QvdCorruptedError("Invalid bit offset", {
|
|
2562
2670
|
field: field["FieldName"],
|
|
@@ -2573,7 +2681,7 @@ function validateFieldBitMetadata(field, recordSize, filePath) {
|
|
|
2573
2681
|
stage: "parseIndexTable"
|
|
2574
2682
|
});
|
|
2575
2683
|
}
|
|
2576
|
-
const bias =
|
|
2684
|
+
const bias = headerInteger(field["Bias"]);
|
|
2577
2685
|
if (isNaN(bias) || !Number.isSafeInteger(bias)) {
|
|
2578
2686
|
throw new exports.QvdCorruptedError("Invalid bias", {
|
|
2579
2687
|
field: field["FieldName"],
|
|
@@ -2600,6 +2708,14 @@ function validateFieldBitMetadata(field, recordSize, filePath) {
|
|
|
2600
2708
|
stage: "parseIndexTable"
|
|
2601
2709
|
});
|
|
2602
2710
|
}
|
|
2711
|
+
if (bias !== 0 && bias !== -2) {
|
|
2712
|
+
throw new exports.QvdCorruptedError("Bias is neither 0 nor -2", {
|
|
2713
|
+
field: field["FieldName"],
|
|
2714
|
+
bias,
|
|
2715
|
+
file: filePath,
|
|
2716
|
+
stage: "parseIndexTable"
|
|
2717
|
+
});
|
|
2718
|
+
}
|
|
2603
2719
|
const recordSizeInBits = recordSize * 8;
|
|
2604
2720
|
if (bitOffset + bitWidth > recordSizeInBits) {
|
|
2605
2721
|
throw new exports.QvdCorruptedError("Bit field extends beyond record size", {
|
|
@@ -2617,11 +2733,16 @@ var init_validationUtils = __esm({
|
|
|
2617
2733
|
init_QvdErrors();
|
|
2618
2734
|
init_memoryUtils();
|
|
2619
2735
|
init_bitUtils();
|
|
2736
|
+
__name(headerInteger, "headerInteger");
|
|
2620
2737
|
__name(validateHeaderStructure, "validateHeaderStructure");
|
|
2621
2738
|
__name(validateSymbolTableSizeEarly, "validateSymbolTableSizeEarly");
|
|
2622
2739
|
__name(validateSymbolTableSize, "validateSymbolTableSize");
|
|
2623
2740
|
__name(validateFieldMetadata, "validateFieldMetadata");
|
|
2741
|
+
__name(firstOverlap, "firstOverlap");
|
|
2742
|
+
__name(validateSymbolAreas, "validateSymbolAreas");
|
|
2743
|
+
__name(validateBitFields, "validateBitFields");
|
|
2624
2744
|
__name(validateRecordCount, "validateRecordCount");
|
|
2745
|
+
__name(validateRecordSize, "validateRecordSize");
|
|
2625
2746
|
__name(validateIndexTableMetadata, "validateIndexTableMetadata");
|
|
2626
2747
|
__name(validateFieldBitMetadata, "validateFieldBitMetadata");
|
|
2627
2748
|
}
|
|
@@ -3253,6 +3374,31 @@ async function* chunksFrom(handle, chunkSize, failed) {
|
|
|
3253
3374
|
position += bytesRead;
|
|
3254
3375
|
}
|
|
3255
3376
|
}
|
|
3377
|
+
async function parseHeaderXml(text, file, stage) {
|
|
3378
|
+
let parsed;
|
|
3379
|
+
try {
|
|
3380
|
+
parsed = await xml__default.default.parseStringPromise(text, { explicitArray: false });
|
|
3381
|
+
} catch (error) {
|
|
3382
|
+
throw new exports.QvdParseError(
|
|
3383
|
+
"The XML header could not be parsed.",
|
|
3384
|
+
{
|
|
3385
|
+
// The first line of the parser's message. The rest is the line and column it stopped at, which
|
|
3386
|
+
// stay on `cause`.
|
|
3387
|
+
reason: String(
|
|
3388
|
+
/** @type {any} */
|
|
3389
|
+
error?.message ?? error
|
|
3390
|
+
).split("\n")[0],
|
|
3391
|
+
file,
|
|
3392
|
+
stage
|
|
3393
|
+
},
|
|
3394
|
+
{ cause: error }
|
|
3395
|
+
);
|
|
3396
|
+
}
|
|
3397
|
+
if (!parsed) {
|
|
3398
|
+
throw new exports.QvdParseError("The XML header could not be parsed.", { file, stage });
|
|
3399
|
+
}
|
|
3400
|
+
return parsed;
|
|
3401
|
+
}
|
|
3256
3402
|
var MAX_HEADER_SIZE, READ_CHUNK_SIZE, ANALYSIS_SLICE_ROWS, COUNT_SYMBOLS_PAST; exports.QvdFileReader = void 0;
|
|
3257
3403
|
var init_QvdFileReader = __esm({
|
|
3258
3404
|
"src/QvdFileReader.js"() {
|
|
@@ -3273,6 +3419,7 @@ var init_QvdFileReader = __esm({
|
|
|
3273
3419
|
ANALYSIS_SLICE_ROWS = 65536;
|
|
3274
3420
|
COUNT_SYMBOLS_PAST = 65536;
|
|
3275
3421
|
__name(chunksFrom, "chunksFrom");
|
|
3422
|
+
__name(parseHeaderXml, "parseHeaderXml");
|
|
3276
3423
|
exports.QvdFileReader = class {
|
|
3277
3424
|
static {
|
|
3278
3425
|
__name(this, "QvdFileReader");
|
|
@@ -3508,29 +3655,19 @@ var init_QvdFileReader = __esm({
|
|
|
3508
3655
|
const headerBuffer = Buffer.concat(headerChunks);
|
|
3509
3656
|
const headerEndIndex = headerDelimiterIndex + HEADER_DELIMITER.length;
|
|
3510
3657
|
const headerXml = headerBuffer.subarray(0, headerEndIndex).toString();
|
|
3511
|
-
const headerObj = await
|
|
3512
|
-
|
|
3513
|
-
throw new exports.QvdParseError("The XML header could not be parsed.", {
|
|
3514
|
-
file: this._path,
|
|
3515
|
-
stage: "readData"
|
|
3516
|
-
});
|
|
3517
|
-
}
|
|
3518
|
-
validateHeaderStructure(headerObj, this._path, "readData");
|
|
3658
|
+
const headerObj = await parseHeaderXml(headerXml, this._path, "readData");
|
|
3659
|
+
const headerFields = validateHeaderStructure(headerObj, this._path, "readData");
|
|
3519
3660
|
const symbolTableOffset = headerEndIndex;
|
|
3520
|
-
const symbolTableLength =
|
|
3661
|
+
const symbolTableLength = headerInteger(headerObj["QvdTableHeader"]["Offset"]);
|
|
3521
3662
|
const indexTableOffset = symbolTableOffset + symbolTableLength;
|
|
3522
|
-
const recordSize =
|
|
3523
|
-
const totalRows =
|
|
3663
|
+
const recordSize = headerInteger(headerObj["QvdTableHeader"]["RecordByteSize"]);
|
|
3664
|
+
const totalRows = headerInteger(headerObj["QvdTableHeader"]["NoOfRecords"]);
|
|
3524
3665
|
if (headerOnly) {
|
|
3525
3666
|
this._buffer = headerBuffer.subarray(0, headerEndIndex);
|
|
3526
3667
|
this._emitProgress("read", 1, 1);
|
|
3527
3668
|
return;
|
|
3528
3669
|
}
|
|
3529
|
-
|
|
3530
|
-
if (headerFields && !Array.isArray(headerFields)) {
|
|
3531
|
-
headerFields = [headerFields];
|
|
3532
|
-
}
|
|
3533
|
-
const columnCount = Array.isArray(headerFields) ? selectFields(headerFields, this._requestedFields, this._path).length : 0;
|
|
3670
|
+
const columnCount = selectFields(headerFields, this._requestedFields, this._path).length;
|
|
3534
3671
|
const headerNumbersUsable = [symbolTableLength, recordSize, totalRows].every(
|
|
3535
3672
|
(value) => Number.isSafeInteger(value) && value >= 0
|
|
3536
3673
|
);
|
|
@@ -3562,20 +3699,8 @@ var init_QvdFileReader = __esm({
|
|
|
3562
3699
|
}
|
|
3563
3700
|
const rowsToLoad = windowRows;
|
|
3564
3701
|
validateSymbolTableSizeEarly(symbolTableLength, this._path);
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
["RecordByteSize", recordSize],
|
|
3568
|
-
["NoOfRecords", totalRows]
|
|
3569
|
-
]) {
|
|
3570
|
-
if (!Number.isSafeInteger(value) || Number(value) < 0) {
|
|
3571
|
-
throw new exports.QvdCorruptedError(`Invalid header value: ${name}`, {
|
|
3572
|
-
name,
|
|
3573
|
-
value,
|
|
3574
|
-
file: this._path,
|
|
3575
|
-
stage: "readData"
|
|
3576
|
-
});
|
|
3577
|
-
}
|
|
3578
|
-
}
|
|
3702
|
+
validateRecordSize(recordSize, this._path, "readData");
|
|
3703
|
+
validateRecordCount(totalRows, this._path, "readData");
|
|
3579
3704
|
const skippedIndexBytes = resolved.offset * recordSize;
|
|
3580
3705
|
const indexTableBytesToRead = rowsToLoad * recordSize;
|
|
3581
3706
|
const totalBytesToRead = indexTableOffset + indexTableBytesToRead;
|
|
@@ -3674,36 +3799,11 @@ var init_QvdFileReader = __esm({
|
|
|
3674
3799
|
const headerEndIndex = headerDelimiterIndex + HEADER_DELIMITER.length;
|
|
3675
3800
|
const headerBuffer = this._buffer.subarray(headerBeginIndex, headerEndIndex);
|
|
3676
3801
|
this._fieldBitMetadataValidated = false;
|
|
3677
|
-
this._header = await
|
|
3678
|
-
|
|
3679
|
-
throw new exports.QvdParseError("The XML header could not be parsed.", {
|
|
3680
|
-
file: this._path,
|
|
3681
|
-
stage: "parseHeader"
|
|
3682
|
-
});
|
|
3683
|
-
}
|
|
3684
|
-
validateHeaderStructure(this._header, this._path, "parseHeader");
|
|
3685
|
-
const fields = this._header["QvdTableHeader"]?.["Fields"]?.["QvdFieldHeader"];
|
|
3686
|
-
const fieldList = fields === void 0 || fields === null ? [] : Array.isArray(fields) ? fields : [fields];
|
|
3687
|
-
if (fieldList.length === 0) {
|
|
3688
|
-
throw new exports.QvdCorruptedError("The QVD file header declares no fields", {
|
|
3689
|
-
file: this._path,
|
|
3690
|
-
stage: "parseHeader"
|
|
3691
|
-
});
|
|
3692
|
-
}
|
|
3693
|
-
const malformedIndex = fieldList.findIndex(
|
|
3694
|
-
(field) => field === null || typeof field !== "object" || Array.isArray(field)
|
|
3695
|
-
);
|
|
3696
|
-
if (malformedIndex !== -1) {
|
|
3697
|
-
throw new exports.QvdCorruptedError("The QVD file header declares a field with no properties", {
|
|
3698
|
-
fieldIndex: malformedIndex,
|
|
3699
|
-
fieldCount: fieldList.length,
|
|
3700
|
-
file: this._path,
|
|
3701
|
-
stage: "parseHeader"
|
|
3702
|
-
});
|
|
3703
|
-
}
|
|
3802
|
+
this._header = await parseHeaderXml(headerBuffer.toString(), this._path, "parseHeader");
|
|
3803
|
+
const fieldList = validateHeaderStructure(this._header, this._path, "parseHeader");
|
|
3704
3804
|
this._headerOffset = headerBeginIndex;
|
|
3705
3805
|
this._symbolTableOffset = headerEndIndex;
|
|
3706
|
-
this._indexTableOffset = this._symbolTableOffset +
|
|
3806
|
+
this._indexTableOffset = this._symbolTableOffset + headerInteger(this._header["QvdTableHeader"]["Offset"]);
|
|
3707
3807
|
this._allFields = fieldList;
|
|
3708
3808
|
this._selectedFields = selectFields(this._allFields, this._requestedFields, this._path);
|
|
3709
3809
|
}
|
|
@@ -3735,9 +3835,9 @@ var init_QvdFileReader = __esm({
|
|
|
3735
3835
|
}
|
|
3736
3836
|
const allFields = this._allFields;
|
|
3737
3837
|
const fields = this._selectedFields;
|
|
3738
|
-
const recordSize =
|
|
3739
|
-
const totalRows =
|
|
3740
|
-
const indexTableLength =
|
|
3838
|
+
const recordSize = headerInteger(this._header["QvdTableHeader"]["RecordByteSize"]);
|
|
3839
|
+
const totalRows = headerInteger(this._header["QvdTableHeader"]["NoOfRecords"]);
|
|
3840
|
+
const indexTableLength = headerInteger(this._header["QvdTableHeader"]["Length"]);
|
|
3741
3841
|
const { offset: firstRow, limit: rowsToLoad } = resolveWindow(window, totalRows);
|
|
3742
3842
|
validateIndexTableMetadata(
|
|
3743
3843
|
recordSize,
|
|
@@ -3760,6 +3860,7 @@ var init_QvdFileReader = __esm({
|
|
|
3760
3860
|
for (const field of allFields) {
|
|
3761
3861
|
validateFieldBitMetadata(field, recordSize, this._path);
|
|
3762
3862
|
}
|
|
3863
|
+
validateBitFields(allFields, this._path);
|
|
3763
3864
|
this._fieldBitMetadataValidated = true;
|
|
3764
3865
|
}
|
|
3765
3866
|
assert3__default.default(
|
|
@@ -3790,10 +3891,10 @@ var init_QvdFileReader = __esm({
|
|
|
3790
3891
|
this._throwIfAborted();
|
|
3791
3892
|
const needed = /* @__PURE__ */ new Set();
|
|
3792
3893
|
symbolUsage[position] = needed;
|
|
3793
|
-
const bitOffset =
|
|
3794
|
-
const bitWidth =
|
|
3795
|
-
const bias =
|
|
3796
|
-
const length =
|
|
3894
|
+
const bitOffset = headerInteger(field["BitOffset"]);
|
|
3895
|
+
const bitWidth = headerInteger(field["BitWidth"]);
|
|
3896
|
+
const bias = headerInteger(field["Bias"]);
|
|
3897
|
+
const length = headerInteger(field["Length"]);
|
|
3797
3898
|
let indexLimit = Number.isSafeInteger(length) && length >= 0 ? Math.ceil(length / 2) : Infinity;
|
|
3798
3899
|
let counted = false;
|
|
3799
3900
|
for (let first = 0; first < rowsToLoad; first += sliceRows) {
|
|
@@ -3846,11 +3947,11 @@ var init_QvdFileReader = __esm({
|
|
|
3846
3947
|
);
|
|
3847
3948
|
const symbolBuffer = this._buffer.subarray(this._symbolTableOffset, this._indexTableOffset);
|
|
3848
3949
|
validateFieldMetadata(field, symbolBuffer.length, this._path);
|
|
3849
|
-
const offset =
|
|
3950
|
+
const offset = headerInteger(field["Offset"]);
|
|
3850
3951
|
return countFieldSymbols(
|
|
3851
3952
|
symbolBuffer,
|
|
3852
3953
|
offset,
|
|
3853
|
-
offset +
|
|
3954
|
+
offset + headerInteger(field["Length"]),
|
|
3854
3955
|
field["FieldName"],
|
|
3855
3956
|
this._path
|
|
3856
3957
|
);
|
|
@@ -3885,7 +3986,7 @@ var init_QvdFileReader = __esm({
|
|
|
3885
3986
|
const fields = this._selectedFields;
|
|
3886
3987
|
const symbolBuffer = this._buffer.subarray(this._symbolTableOffset, this._indexTableOffset);
|
|
3887
3988
|
const symbolTableSize = symbolBuffer.length;
|
|
3888
|
-
const totalRows =
|
|
3989
|
+
const totalRows = headerInteger(this._header["QvdTableHeader"]["NoOfRecords"]);
|
|
3889
3990
|
validateSymbolTableSize(symbolTableSize, this._path, totalRows);
|
|
3890
3991
|
if (this._headerMatchesFile) {
|
|
3891
3992
|
validateMemoryAvailability(
|
|
@@ -3903,10 +4004,11 @@ var init_QvdFileReader = __esm({
|
|
|
3903
4004
|
for (const field of allFields) {
|
|
3904
4005
|
validateFieldMetadata(field, symbolBuffer.length, this._path);
|
|
3905
4006
|
}
|
|
4007
|
+
validateSymbolAreas(allFields, this._path);
|
|
3906
4008
|
this._symbolTable = fields.map((field, position) => {
|
|
3907
4009
|
this._throwIfAborted();
|
|
3908
|
-
const symbolsOffset =
|
|
3909
|
-
const symbolsLength =
|
|
4010
|
+
const symbolsOffset = headerInteger(field["Offset"]);
|
|
4011
|
+
const symbolsLength = headerInteger(field["Length"]);
|
|
3910
4012
|
const symbols = parseFieldSymbols(
|
|
3911
4013
|
symbolBuffer,
|
|
3912
4014
|
symbolsOffset,
|
|
@@ -3958,9 +4060,9 @@ var init_QvdFileReader = __esm({
|
|
|
3958
4060
|
indexBuffer,
|
|
3959
4061
|
recordSize,
|
|
3960
4062
|
rowsToLoad,
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
4063
|
+
headerInteger(field["BitOffset"]),
|
|
4064
|
+
headerInteger(field["BitWidth"]),
|
|
4065
|
+
headerInteger(field["Bias"]),
|
|
3964
4066
|
new Int32Array(rowsToLoad),
|
|
3965
4067
|
{ symbolCount: symbolTable[position].numbers.length, field: field["FieldName"], file: this._path, firstRow }
|
|
3966
4068
|
);
|
|
@@ -3990,23 +4092,13 @@ var init_QvdFileReader = __esm({
|
|
|
3990
4092
|
await this._parseHeader();
|
|
3991
4093
|
this._emitProgress("header", 1, 1);
|
|
3992
4094
|
this._throwIfAborted();
|
|
3993
|
-
assert3__default.default(this._header, "The QVD file header has not been parsed.");
|
|
4095
|
+
assert3__default.default(this._header && this._allFields, "The QVD file header has not been parsed.");
|
|
3994
4096
|
const header = this._header["QvdTableHeader"];
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
fields = [fields];
|
|
3998
|
-
}
|
|
3999
|
-
if (fields.length === 0) {
|
|
4000
|
-
throw new exports.QvdCorruptedError("The QVD file header declares no fields", {
|
|
4001
|
-
file: this._path,
|
|
4002
|
-
stage: "readMetadata"
|
|
4003
|
-
});
|
|
4004
|
-
}
|
|
4005
|
-
const columns = fields.map((field) => field["FieldName"]);
|
|
4006
|
-
const rowCount = parseInt(header["NoOfRecords"], 10);
|
|
4097
|
+
const columns = this._allFields.map((field) => field["FieldName"]);
|
|
4098
|
+
const rowCount = headerInteger(header["NoOfRecords"]);
|
|
4007
4099
|
validateRecordCount(rowCount, this._path, "readMetadata");
|
|
4008
4100
|
const shape = new exports.QvdDataFrame([], columns, header, {
|
|
4009
|
-
symbolTableBytes:
|
|
4101
|
+
symbolTableBytes: headerInteger(header["Offset"]),
|
|
4010
4102
|
totalRows: rowCount,
|
|
4011
4103
|
rowsLoaded: 0,
|
|
4012
4104
|
symbolFiltering: false,
|
|
@@ -4171,8 +4263,8 @@ var init_QvdFileReader = __esm({
|
|
|
4171
4263
|
this._emitProgress("header", 1, 1);
|
|
4172
4264
|
this._throwIfAborted();
|
|
4173
4265
|
assert3__default.default(this._header, "The QVD file header has not been parsed.");
|
|
4174
|
-
const totalRows =
|
|
4175
|
-
const symbolTableLength =
|
|
4266
|
+
const totalRows = headerInteger(this._header["QvdTableHeader"]["NoOfRecords"]);
|
|
4267
|
+
const symbolTableLength = headerInteger(this._header["QvdTableHeader"]["Offset"]);
|
|
4176
4268
|
const resolved = resolveWindow(window, totalRows);
|
|
4177
4269
|
const rowsAvailable = resolved.limit;
|
|
4178
4270
|
let symbolsToKeep = null;
|