Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 18.10.2014, 16:43
kyb kyb вне форума
Новичок на форуме
Отправить личное сообщение для kyb Посмотреть профиль Найти все сообщения от kyb
 
Регистрация: 09.10.2014
Сообщений: 8

Си-подобные структуры. Парсинг пакета, массива байт
Дан дамп некоторого количества пакетов, определённых Си-структурой (порядок байт 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
                },
		... и т.д.
	 };
, но тогда в каждом экземпляре объекте будут соранятся эти "константы". Не годится.
Подскажите как оптимизировать код.
Ответить с цитированием
  #2 (permalink)  
Старый 18.10.2014, 20:50
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,492

Для работы с raw на js рекомендую смотреть в сторону TypedArray и ArrayBuffer(если не нужна поддердка древних браузеров), с ними удобней.

А конкретно по вопросу - увы не понял что именно нужно.
Покажи какая результирующая структура имеется сейчас и какую ты хочешь получить в итоге.
__________________
29375, 35
Ответить с цитированием
  #3 (permalink)  
Старый 18.10.2014, 22:20
kyb kyb вне форума
Новичок на форуме
Отправить личное сообщение для kyb Посмотреть профиль Найти все сообщения от kyb
 
Регистрация: 09.10.2014
Сообщений: 8

Сообщение от Aetae Посмотреть сообщение
увы не понял что именно нужно.
Покажи какая результирующая структура имеется сейчас и какую ты хочешь получить в итоге.
Сообщение от kyb Посмотреть сообщение
, чтобы обращаться так:
this.fields.uid.offset; 
this.fields.data32.len
Но при этом хранить константы на уровне класса, а не в каждом экземпляре.
Сообщение от Aetae Посмотреть сообщение
смотреть в сторону TypedArray и ArrayBuffer
Тема. Это должно решить все вопросы. Переделаю всё на них. Благодарю.
Ответить с цитированием
  #4 (permalink)  
Старый 18.10.2014, 22:56
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,492

Если эти offset и len уникальны для каждого экземпляра, то зачем их хранить на уровне класса, а если они общие, то в чём смысл выдавать их таким образом?
Проще всего не заворачиваться и добавить отдельно в прототип:
Packet.prototype.params = {
        protocolID : {
                      offset: 0,
                      len:     4
                },
        ... и т.д.
     };

Но можно и по извращаться конечно.)
__________________
29375, 35

Последний раз редактировалось Aetae, 18.10.2014 в 23:09.
Ответить с цитированием
  #5 (permalink)  
Старый 19.10.2014, 10:06
kyb kyb вне форума
Новичок на форуме
Отправить личное сообщение для kyb Посмотреть профиль Найти все сообщения от kyb
 
Регистрация: 09.10.2014
Сообщений: 8

Сообщение от Aetae Посмотреть сообщение
добавить отдельно в прототип
Тогда каждый экземпляр будет хранить в памяти общие для класса константы. И при большом количестве экземпляров будет перерасход памяти. Так?
Ответить с цитированием
  #6 (permalink)  
Старый 19.10.2014, 16:58
Аватар для Erolast
Профессор
Отправить личное сообщение для Erolast Посмотреть профиль Найти все сообщения от Erolast
 
Регистрация: 24.09.2013
Сообщений: 1,436

Нет. Каждый экземпляр будет хранить ссылку на общий объект-прототип.
Ответить с цитированием
  #7 (permalink)  
Старый 20.10.2014, 00:25
kyb kyb вне форума
Новичок на форуме
Отправить личное сообщение для kyb Посмотреть профиль Найти все сообщения от kyb
 
Регистрация: 09.10.2014
Сообщений: 8

Отлично. Erolast, благодарю.

Можно ли определить в объекте поля OFFSET и LEN константами? Не просто "договориться" что мы это не меняем, а как в Java кл. слово final. Ключевое слово const сюда не вписать.
Ответить с цитированием
  #8 (permalink)  
Старый 20.10.2014, 01:54
Кандидат Javascript-наук
Посмотреть профиль Найти все сообщения от terminator-101
 
Регистрация: 14.10.2014
Сообщений: 117

Сообщение от kyb
Можно ли определить в объекте поля OFFSET и LEN константами? Не просто "договориться" что мы это не меняем,
Есть такая штука:
Object.defineProperty(the_object, property, {...options...})

возможно Вам подойдет что-то вроде:
set=function(source, target){
var d=Object.defineProperty
for(var i in source) {
if(source.hasOwnProperty(i)){
d(target, i, {value: source[i], writable: false})
}
}
}

O=function(){}
set({a:1, b:2, c:3}, O.prototype)
o=new O

alert([o.a, o.b, o.c]) //  1 2 3
o.a=10
o.b=20
o.c=30
alert([o.a, o.b, o.c]) //  1 2 3
Ответить с цитированием
  #9 (permalink)  
Старый 20.10.2014, 05:06
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,492

terminator-101, парниша, используй табуляцию, мерзко же выглядит.

kyb, ответ выше, однако в js константы особого смысла не имеют, только лишние заморочки.
__________________
29375, 35
Ответить с цитированием
  #10 (permalink)  
Старый 21.10.2014, 23:33
kyb kyb вне форума
Новичок на форуме
Отправить личное сообщение для kyb Посмотреть профиль Найти все сообщения от kyb
 
Регистрация: 09.10.2014
Сообщений: 8

terminator-101, спасибо. Интересно. Поковырял.
Aetae, теперь согласен. Не стоят константы таких кодовыкрутасов.
Однако сишно-джавистская привычка к константам не дает покоя. С другой стороны и ежу понятно что константа. Поменял - сам дурак )

Теперь по теме. Нашел отличный фреймворк для Node node-ctype и просто js-ctypes (c ней не разбирался). Работатет на ура. То что нужно.

Последний раз редактировалось kyb, 21.10.2014 в 23:38.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Парсинг XML файла и создание массива fAmOus AJAX и COMET 23 22.03.2014 18:11
Парсинг JSON массива со скобками [ ] lightdesign jQuery 1 24.04.2011 15:35