UNPKG

beth-parser

Version:

Parser library for Bethesda's Creation Engine data files

123 lines 4.63 kB
"use strict"; exports.__esModule = true; var zlib = require("zlib"); var ModfileDefs_1 = require("../ModfileDefs"); var utils_1 = require("../../utils"); /** * Basic types used by the parser. */ var _a = utils_1.defineTypeTags("GRUP", "OFST", "XXXX"), GRUP = _a.GRUP, OFST = _a.OFST, XXXX = _a.XXXX; /** * Simple parser for Bethesda's ESM/ESP modfiles. * Parser reads provided data source and processes entries via provided entry handler. */ var ModfileParser = /** @class */ (function () { function ModfileParser(source) { this.source = source; } /** * Start modfile parsing with the given handler. * @param handler Top-level modfile handler. */ ModfileParser.prototype.parse = function (handler) { while (this.parseNext(handler)) { /* no-op */ } }; /** * Parse next entry and return its size in bytes. * @param handler Current modfile handler. * @param assert Whether to signal error when there is no content. * @returns Number of processed bytes or zero for EOF. */ ModfileParser.prototype.parseNext = function (handler, assert) { if (assert === void 0) { assert = false; } var buffer = this.source.read(24); var type = buffer.length === 24 ? buffer.readUInt32LE(0) : null; if (assert && !type) { throw new Error("Unexpected end of source reached."); } else if (type === GRUP) { return this.parseGroup(buffer, handler); } else if (type !== null) { return this.parseRecord(type, buffer, handler) + 24; } return 0; // EOF }; /** * Parse group based entry and return its size (including header). * @param buffer Buffer with group header. * @param handler Modfile handler to use. */ ModfileParser.prototype.parseGroup = function (buffer, handler) { var _this = this; var size = buffer.readUInt32LE(4); var label = buffer.readUInt32LE(8); var type = buffer.readInt32LE(12); var skip = size - 24; handler.handleGroup(type, skip, label, function (handler) { while (skip > 0) { skip -= _this.parseNext(handler, true); } }); this.source.skip(skip); return size; }; /** * Parse record based entry and return size of its data. * @param type Record type. * @param buffer Buffer with record header. * @param handler Modfile handler to use. * @returns Number of processed bytes. */ ModfileParser.prototype.parseRecord = function (type, buffer, handler) { var _this = this; var size = buffer.readUInt32LE(4); var flags = buffer.readUInt32LE(8); var formId = buffer.readUInt32LE(12); var skip = size; handler.handleRecord(type, size, flags, formId, function (handler) { var buffer = _this.source.read(size); if (flags & ModfileDefs_1.RecordFlag.ZLIB_COMPRESSED) { buffer = zlib.inflateSync(buffer.subarray(4)); } _this.parseFields(buffer, handler); skip = 0; }); this.source.skip(skip); return size; }; /** * Parse field based entries. * @param buffer Byffer with field header. * @param handler Modfile handler to use. * @returns Number of processed bytes. */ ModfileParser.prototype.parseFields = function (buffer, handler) { var offset = 0; while (offset < buffer.length) { offset += this.parseField(buffer, offset, buffer.readUInt16LE(offset + 4), handler); } return buffer.length; }; /** * Parse field at the specified offset. * @param buffer Data buffer all the field data. * @param offset Offset of field data in the buffer. * @param size Size of field data. * @param handler Modfile handler to use. */ ModfileParser.prototype.parseField = function (buffer, offset, size, handler) { var type = buffer.readUInt32LE(offset); if (type === OFST) { return buffer.length - offset; } else if (type === XXXX) { return size + 6 + this.parseField(buffer, offset + 10, buffer.readUInt32LE(offset + 6), handler); } handler(type, size, buffer, offset + 6); return size + 6; }; return ModfileParser; }()); exports["default"] = ModfileParser; //# sourceMappingURL=ModfileParser.js.map