Дан дамп некоторого количества пакетов, определённых Си-структурой (порядок байт LE):
typedef struct udpPackage_t {
char protocolID[4]; // Всегда одинаковое значение
uint32_t uid;
int64_t timestamp;
float data32[ DATA32_ARRAY_SIZE ];
} udpPackage_t;
Задача: распарсить дамп со raw-data на пакеты на JS.
Решение на Си простО до безобразия:
udpPackage_t *p;
p = [адрес начального байта пакета];
p->[имя поля]; // получаем значение пакета.
Тут может возникнуть проблема с порядком байт, если этот код будет компилироваться под BE, но это поравлятся одним макросом.
В javascript объект
fields = {
protocolID : '',
uid : null,
timestamp : null,
data32 : new Array(DATA_ARRAY_SIZE)
};
сам по себе не упакуется. Каждому из полей нужно добавить(привязать) констанстанту LENGTH и OFFSET.
Вот что у меня
получилось:
/** class Packet constructor */
function Packet(data) {
/** Parsed fields */
this.fields = {
protocolID : '',
uid : null,
timestamp : null,
data32 : new Array(Packet.DATA_ARRAY_SIZE)
};
this.parseAllFields(data);
}
/** Packet fields constants */
Packet.PROTOCOL_ID_OFFSET = 0;
Packet.PROTOCOL_ID_LEN = 4;
Packet.UID_OFFSET = Packet.PROTOCOL_ID_OFFSET + Packet.PROTOCOL_ID_LEN;
Packet.UID_LEN = 4;
Packet.TS_OFFSET = Packet.UID_OFFSET + Packet.UID_LEN;
Packet.TS_LEN = 8;
Packet.DATA32_OFFSET = Packet.TS_OFFSET + Packet.TS_LEN;
Packet.DATA32_LEN = 4;
Packet.DATA_ARRAY_SIZE = 250;
Packet.TOTAL_LEN = Packet.PROTOCOL_ID_LEN +
Packet.UID_LEN +
Packet.TS_LEN +
Packet.DATA32_LEN * Packet.DATA_ARRAY_SIZE;
/** Parses all packet fields from this.data */
Packet.prototype.parseAllFields = function (data) {
this.fields.protocolID = '';
for (var i=0; i<Packet.PROTOCOL_ID_LEN; i++) {
this.fields.protocolID += String.fromCharCode(data[Packet.PROTOCOL_NAME_OFFSET + i]);
}
this.fields.uid = assembleLittleEndianFromBytesArray(data, Packet.UID_OFFSET, Packet.UID_LEN);
this.fields.timestamp = assembleLittleEndianFromBytesArray(data, Packet.TS_OFFSET, Packet.TS_LEN);
for (var i=0, len = this.fields.data32.length; i<len; i++) {
var temp = assembleLittleEndianFromBytesArray(this.data, Packet.DATA32_OFFSET+i, Packet.DATA32_LEN);
this.fields.data32[i] = parseHexFloat(temp);
}
};
/** Возвращает Number собраный в порядке LE из массива bytes */
function assembleLittleEndianFromBytesArray(bytes, begin, length){};
/** Принимает 32-битное float число IEEE 754 или строку - массив байт. Возвращает js number
function parseHexFloat(str);
Код громоздкий. Особенно по сравнению с Си. Хотелось бы как-то причесать, структурировать. Например, константы упаковать к полям, чтобы обращаться так:
this.fields.uid.offset; this.fields.data32.len
Если записать их в конструкторе:
/** Parsed fields */
this.fields = {
protocolID : {
value: '',
offset: 0,
len: 4
},
... и т.д.
};
, но тогда в каждом экземпляре объекте будут соранятся эти "константы". Не годится.
Подскажите как
оптимизировать код.