s2-tools
Version:
A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.
128 lines • 4.21 kB
JavaScript
import { toReader } from '..';
/** A DBF data class to parse the data from a DBF */
export class DataBaseFile {
reader;
#header;
#rows;
/**
* @param input - the input data structure to parse
* @param encoding - the encoding of the raw data. defaults to 'utf-8'
*/
constructor(input, encoding) {
this.reader = toReader(input);
if (encoding !== undefined)
this.reader.setStringEncoding(encoding);
this.#parseHeader();
this.#rows = this.#parseRowHeader();
}
/**
* Create a copy of the header data
* @returns - a copy of the header
*/
getHeader() {
return { ...this.#header };
}
/**
* Get the properties for the given index
* @param index - the index of the properties data we want
* @returns - the properties for the given index
*/
getProperties(index) {
const { records, recLen } = this.#header;
if (index > records)
return undefined;
const offset = ((this.#rows.length + 1) << 5) + 2 + index * recLen;
return this.#parseProperties(offset);
}
/**
* Get all the properties in the DBF
* @returns - an array of Properties
*/
getAllProperties() {
const { records } = this.#header;
const res = [];
for (let i = 0; i < records; i++) {
const properties = this.getProperties(i);
if (properties !== undefined)
res.push(properties);
}
return res;
}
/**
* Parse the header and store it in the class
*/
#parseHeader() {
const { reader } = this;
this.#header = {
lastUpdated: new Date(reader.getUint8(1) + 1900, reader.getUint8(2), reader.getUint8(3)),
records: reader.getUint32(4, true),
headerLen: reader.getUint16(8, true),
recLen: reader.getUint16(10, true),
};
}
/**
* Parses the row header and builds an array of keys that each property may have
* @returns - an array of Rows that describe keys in each property
*/
#parseRowHeader() {
const { reader } = this;
const { headerLen } = this.#header;
const len = headerLen - 1;
const res = [];
let offset = 32;
while (offset < len) {
res.push({
name: reader.parseString(offset, 11),
dataType: String.fromCharCode(reader.getUint8(offset + 11)),
len: reader.getUint8(offset + 16),
decimal: reader.getUint8(offset + 17),
});
if (reader.getUint8(offset + 32) === 13) {
break;
}
else {
offset += 32;
}
}
return res;
}
/**
* Parse the properties starting from the given offset
* @param offset - offset of the row
* @returns - a Properties object
*/
#parseProperties(offset) {
const properties = {};
for (const header of this.#rows) {
const value = this.#parseValue(offset, header.len, header.dataType);
offset += header.len;
if (typeof value !== 'undefined')
properties[header.name] = value;
}
return properties;
}
/**
* Parse the value at the given offset
* @param offset - offset of the value
* @param len - length of the value
* @param type - the type of the value
* @returns - the value as a string, number or boolean
*/
#parseValue(offset, len, type) {
const { reader } = this;
const textData = reader.parseString(offset, len);
switch (type) {
case 'N':
case 'F':
case 'O':
return parseFloat(textData);
case 'D':
return new Date(parseFloat(textData.slice(0, 4)), parseInt(textData.slice(4, 6)) - 1, parseFloat(textData.slice(6, 8))).getUTCDate();
case 'L':
return textData.toLowerCase() === 'y' || textData.toLowerCase() === 't';
default:
return textData;
}
}
}
//# sourceMappingURL=dbf.js.map