adif-parser-ts
Version:
An amateur radio log data ADIF parser in Typescript and Javascript
148 lines (145 loc) • 4.91 kB
JavaScript
/**
* A class for formatting objects into ADIF.
*/
var AdifFormatter = /** @class */ (function () {
function AdifFormatter(obj) {
this.obj = obj;
}
/**
* Format the given object into an ADIF string.
*/
AdifFormatter.formatAdi = function (obj) {
return new AdifFormatter(obj).format();
};
AdifFormatter.prototype.format = function () {
// From just a moment of research, string concatenation should have OK
// performance. Maybe do testing and reconsider.
var buffer = '';
if (this.obj.header !== undefined) {
buffer += this.obj.header.text + '\n';
var restOfHeader = this.obj.header;
delete restOfHeader.text;
buffer += AdifFormatter.formatTags(restOfHeader);
buffer += '<eoh>\n\n';
}
if (!this.obj.records) {
return AdifFormatter.prepReturn(buffer);
}
for (var _i = 0, _a = this.obj.records; _i < _a.length; _i++) {
var rec = _a[_i];
buffer += AdifFormatter.formatTags(rec);
buffer += '<eor>\n\n';
}
return AdifFormatter.prepReturn(buffer);
};
AdifFormatter.formatTags = function (obj) {
var buffer = '';
for (var _i = 0, _a = Object.entries(obj); _i < _a.length; _i++) {
var _b = _a[_i], key = _b[0], value = _b[1];
var width = new TextEncoder().encode(value).byteLength;
buffer += "<".concat(key, ":").concat(width, ">").concat(value, "\n");
}
return buffer;
};
AdifFormatter.prepReturn = function (buffer) {
buffer = buffer.trim();
if (buffer.length === 0) {
return buffer;
}
return buffer + '\n';
};
return AdifFormatter;
}());
/**
* A class for parsing ADIF data into usable data structures.
*/
var AdifParser = /** @class */ (function () {
function AdifParser(adi) {
this.adi = adi;
this.cursor = 0;
}
/**
* Parse the given ADIF data string into an object.
*/
AdifParser.parseAdi = function (adi) {
return new AdifParser(adi).parseTopLevel();
};
AdifParser.prototype.parseTopLevel = function () {
var parsed = {};
if (this.adi.length === 0) {
return parsed;
}
// Header
if (this.adi[0] !== '<') {
var header = {};
header['text'] = this.parseHeaderText();
while (this.cursor < this.adi.length) {
var endOfHeader = this.parseTagValue(header);
if (endOfHeader) {
break;
}
}
parsed.header = header;
}
// QSO Records
var records = new Array();
while (this.cursor < this.adi.length) {
var record = this.parseRecord();
if (Object.keys(record).length > 0) {
records.push(record);
}
}
if (records.length > 0) {
parsed.records = records;
}
return parsed;
};
AdifParser.prototype.parseHeaderText = function () {
var startTag = this.adi.indexOf('<', this.cursor);
this.cursor = startTag;
return this.adi.substring(0, startTag).trim();
};
AdifParser.prototype.parseRecord = function () {
var record = {};
while (this.cursor < this.adi.length) {
var endOfRecord = this.parseTagValue(record);
if (endOfRecord) {
break;
}
}
return record;
};
AdifParser.prototype.parseTagValue = function (record) {
var startTag = this.adi.indexOf('<', this.cursor);
if (startTag === -1) {
this.cursor = this.adi.length;
return true;
}
var endTag = this.adi.indexOf('>', startTag);
var tagParts = this.adi.substring(startTag + 1, endTag).split(':');
if (tagParts[0].toLowerCase() === 'eor' ||
tagParts[0].toLowerCase() === 'eoh') {
this.cursor = endTag + 1;
return true;
}
else if (tagParts.length < 2) {
if (this.adi.substring(startTag + 1, endTag) === 'APP_LoTW_EOF') {
this.cursor = endTag + 1;
return true;
}
throw new Error('Encountered field tag without enough parts near char ' +
startTag +
': ' +
this.adi.substring(startTag + 1, startTag + 80) +
'\n');
}
var fieldName = tagParts[0].toLowerCase();
var width = +tagParts[1];
record[fieldName] = this.adi.substr(endTag + 1, width);
this.cursor = endTag + 1 + width;
return false;
};
return AdifParser;
}());
export { AdifFormatter, AdifParser };
//# sourceMappingURL=adif-parser.es5.js.map