Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> разбор набора данных полученного по сети, из файла, поэтапное считывание vs каст на стуктуру 
:(
    Опции темы
semibug
Дата 12.12.2011, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



Как будет лучше (правильнее, надежнее, логичнее и т.п.) разобрать набор данных, представленный куском памяти - читать из него кусочками или кастовать в указатель на структуру?
Кастовать - поменьше кода получается, читать по байтово и формировать значения нужной разрядности - более ресурсоемко (увеличение размера кода + замедление работы программы).
Сделал и так и так, не знаю на чем остановиться.
Вопрос больше академический, понимаю, что описанные недостатки второго варианта не существенны для современных машин.

PM   Вверх
newbee
Дата 12.12.2011, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 3
Всего: 19



Кастовать область памяти в указатель на какой-нибудь тип нельзя, если не хочешь в будущем поиметь множество сюрпризов, особенно во время портирования на другие архитектуры. Можно сделать memcpy память -> структура. Вариант с ручным разбором более гибкий в том плане, что не любые данные "ровно" ложатся в структуру, для них требуется предварительная обработка. Например массивы заранее неизвестной длины, взаимосвязи между разными структурами и т.д.


--------------------
You're face to face
With man who sold the world
PM   Вверх
rumit7
Дата 13.12.2011, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(semibug @ 12.12.2011,  23:05)
Как будет лучше (правильнее, надежнее, логичнее и т.п.) разобрать набор данных, представленный куском памяти - читать из него кусочками или кастовать в указатель на структуру?
...

Я сейчас тоже думаю над похожей задачей. Соглашусь с newbee в том, что кастовать нельзя, т.к. в этом случае в ход могут вмешаться множество факторов, как например порядок байтов, выравнивание и т.д.

А вот с 
Цитата

Можно сделать memcpy память -> структура.


мне как-то не совсем понятно, как в этом случае быть с big endian? 


PM MAIL   Вверх
semibug
Дата 13.12.2011, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



newbee, спасибо за ответ
Не совсем понял на счет проблем при касте в указатель на структуру, если подразумевается, как пишет 
rumit7, порядок байт и выравнивание, то как memcpy решает проблему? (присоединяюсь к вопросу 
rumit7)
PM   Вверх
newbee
Дата 13.12.2011, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бревно
**


Профиль
Группа: Участник
Сообщений: 703
Регистрация: 24.8.2011

Репутация: 3
Всего: 19



Господа, если у вас намечаются проблемы с порядком байт, достаточно просто перевернуть необходимые слова внутри структуры (т.к. между словами байты не перетасуются, только в рамках слова). Если ваша система будет обмениваться информацией между собой одновременно на разных системах, конечно нужен договор о порядке байт: при отправке данных они кодируются в сетевой порядок, во время приема декодируются в хостовый.

Я писала совсем о другом: в общем случае нельзя кастовать некий буфер данных в свои переменные. Пример проблемы. Чтобы в будущем не нажить проблем? лучше сразу приучить себя всегда использовать memcpy для копирования сырых данных в свои пользовательские.


--------------------
You're face to face
With man who sold the world
PM   Вверх
mes
Дата 13.12.2011, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



подход зависит от того что представляет из себя поток данных.. т. е. важно согласование обеих сторон, и если не известно в каком виде отправляется, непонятно как это принимать..




--------------------
PM MAIL WWW   Вверх
rumit7
Дата 13.12.2011, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(mes @ 13.12.2011,  09:52)
подход зависит от того что представляет из себя поток данных.. т. е. важно согласование обеих сторон, и если не известно в каком виде отправляется, непонятно как это принимать..

А если предположить, что формат задан по спецификации и построен по следующим принципам:
  •  первый байт является тэгом сообщения, т.е. определяет его тип;
  •  следующие 2 байта определяют общую длину данного сообщения;
  •  далее идет содержимое сообщения. Здесь могут находится вложенные сообщения, идентифицирующиеся также по тегу или просто содержимое какой-то структуры.

Тэги всех сообщений заданы. Формат их задан. Единственно что: многие сообщения являются опциональными, т.е. их присутствие не гарантируется. 

Так вот, в таком случае: как мог бы выглядеть парсер? Интересует правильный дизайн парсера с точки зрения читабельности полученного кода и эффективности реализации. 

Я ниже приведу свои мысли, а если кто-то подскажет что-то - буду очень признателен!


Имеется буфер содержащий целое количество сообщений (т.е. дочитывать еще данные нет необходимости).

Код

// код упрощен для наглядности
while( !finished )
{
    uint8_t * buffer;
    size_t     length;

    // считываем буффер
    if( (buffer = receive_buffer( &length )) != 0 )
    {
        parse_buffer(buffer, length);
        free_buffer(buffer);
    }
  }
 

Дальше буфер нужно парсить. Использовать внутри "parse_buffer" целую кучу switch, if-ов в стиле процедурного программирования не выход, особенно если спецификация на формат достаточно обширная. Здесь бы воспользоваться преимуществами с++, но как правильно это сделать?! Есть ли идеи?

PM MAIL   Вверх
semibug
Дата 14.12.2011, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 27.3.2009

Репутация: нет
Всего: нет



Цитата(rumit7 @  13.12.2011,  10:49 Найти цитируемый пост)
Использовать внутри "parse_buffer" целую кучу switch, if-ов в стиле процедурного программирования не выход, особенно если спецификация на формат достаточно обширная.

Думаю в любом случае, получив тэг (число) надо будет выбрать обработчик, т.е. сопоставить значение с исполнителем, тут либо switch либо через табличку (switch, как правило, компилятор реализует табличкой).

PM   Вверх
rumit7
Дата 14.12.2011, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(semibug @ 14.12.2011,  12:26)
Думаю в любом случае, получив тэг (число) надо будет выбрать обработчик, т.е. сопоставить значение с исполнителем, тут либо switch либо через табличку (switch, как правило, компилятор реализует табличкой).

Да, конечно не без этого, но хотелось бы найти решение. Пока крутится в голове что-то в этом роде:

Код

void parse_buffer(uint8_t * buffer, size_t length)
{
    ss7::stream stream(buffer, length);
    
    // здесь мы знаем точно, что буффер содержит
    // данные с уровня M3UA, далее возможно SCCP, TCAP, Camel
    // хотя наличие именно последних 3 необязательно
    //
    ss7::m3ua    m3ua;
    ss7::sccp    sccp;
    ss7::tcap    tcap;
    ss7::camel    camel;
    
    stream >> m3ua >> sccp >> tcap >> camel;    // здесь каждый из уровней вызывает
                                                // оператор >> для своих подуровней
    
    // предположим нам нужны следующие данные:
    //        - из M3UA: OPC, DPC, SI;
    //        - из SCCP: UnitData
    //        - из Camel: Service Key.
    //
    if(camel)
    {
        // если уровень Camel успешно сформирован,
        // это значит что и предыдущие уровни сформированы
        //
        cout << m3ua.opc;
        cout << m3ua.dpc;
        cout << m3ua.si;
        
        cout << sccp.unit_data;
        
        cout << camel.service_key;
    }
    
}

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0484 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.