devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
133 lines (122 loc) • 3.95 kB
JavaScript
// jshint strict:implied, -W098, -W117
function parseDBF(stream, errors) {
var timeStart, timeEnd, header, parseData, records;
try {
timeStart = new Date();
header = parseDataBaseFileHeader(stream, errors);
parseData = prepareDataBaseFileRecordParseData(header, errors);
records = parseDataBaseFileRecords(stream, header.numberOfRecords, header.recordLength, parseData, errors);
timeEnd = new Date();
} catch (e) {
errors.push("dbf: parsing error: " + e.message + " / " + e.description);
} finally {
return { records: records, errors: errors, time: timeEnd - timeStart };
}
}
function parseDataBaseFileHeader(stream, errors) {
var i,
header = {
versionNumber: stream.ui8(),
lastUpdate: new Date(1900 + stream.ui8(), stream.ui8() - 1, stream.ui8()),
numberOfRecords: stream.ui32LE(),
headerLength: stream.ui16LE(),
recordLength: stream.ui16LE(),
fields: []
},
term;
stream.skip(20);
for (i = (header.headerLength - stream.pos() - 1) / 32; i > 0; --i) {
header.fields.push(parseFieldDescriptor(stream));
}
term = stream.ui8();
if (term !== 13) {
errors.push("dbf: header terminator: " + term + " / expected: 13");
}
return header;
}
var _fromCharCode = String.fromCharCode;
function getAsciiString(stream, length) {
return _fromCharCode.apply(null, stream.ui8arr(length));
}
function parseFieldDescriptor(stream) {
var desc = {
name: getAsciiString(stream, 11).replace(/\0*$/gi, ''),
type: _fromCharCode(stream.ui8()),
length: stream.skip(4).ui8(),
count: stream.ui8()
};
stream.skip(14);
return desc;
}
var DBF_FIELD_PARSERS = {
"C": function C(stream, length) {
var str = getAsciiString(stream, length);
try {
str = decodeURIComponent(escape(str)); // T522922
} catch (e) {}
return str.trim();
},
"N": function N(stream, length) {
var str = getAsciiString(stream, length);
return parseFloat(str, 10);
},
"D": function D(stream, length) {
var str = getAsciiString(stream, length);
return new Date(str.substring(0, 4), str.substring(4, 6) - 1, str.substring(6, 8));
}
};
function DBF_FIELD_PARSER_DEFAULT(stream, length) {
stream.skip(length);
return null;
}
function prepareDataBaseFileRecordParseData(header, errors) {
var list = [],
i = 0,
ii = header.fields.length,
item,
field,
totalLength = 0;
for (i = 0; i < ii; ++i) {
field = header.fields[i];
item = {
name: field.name,
parser: DBF_FIELD_PARSERS[field.type],
length: field.length
};
if (!item.parser) {
item.parser = DBF_FIELD_PARSER_DEFAULT;
errors.push("dbf: field " + field.name + " type: " + field.type + " / unknown");
}
totalLength += field.length;
list.push(item);
}
if (totalLength + 1 !== header.recordLength) {
errors.push("dbf: record length: " + header.recordLength + " / actual: " + (totalLength + 1));
}
return list;
}
function parseDataBaseFileRecords(stream, recordCount, recordLength, parseData, errors) {
var i,
j,
jj = parseData.length,
pos,
records = [],
record,
pd;
for (i = 0; i < recordCount; ++i) {
record = {};
pos = stream.pos();
stream.skip(1);
for (j = 0; j < jj; ++j) {
pd = parseData[j];
record[pd.name] = pd.parser(stream, pd.length);
}
pos = stream.pos() - pos;
if (pos !== recordLength) {
errors.push("dbf: record #" + (i + 1) + " length: " + recordLength + " / actual: " + pos);
}
records.push(record);
}
return records;
}
;