logo
Литература_1 / photon_old

Простая структура данных

Давайте рассмотрим простую структуру данных:

typedef struct simp1 {

int num;

int nums_10[10];

char name[10];

short vals_5[5];

} Simp1_t;

Эту структуру можно легко запаковать, используя тип raw, поскольку она не содержит каких-либо внешних ссылок (т.е. не имеет членов-указателей). Но это не защищает транспортируемые данные от различий между источником и адресатом, заключающихся в способе передачи данных (вперёд старшим или младшим байтом). [Так, достало меня это писать! Дальше по тексту этот "способ передачи данных вперёд старшим или младшим байтом" "первожу" как эндиан. Прим. пер.] Так что даже для такой простой структуры полезно описание типа, детализирующее его эндиан-чувствительность.

Описание типа начинается с массива элементов типа init unsigned, которые описывают эндиан-чувствительность для каждого члена:

static const int unsigned Simp1Endians[] = {

Tr_ENDIAN( Simp1_t, num ),

Tr_ENDIAN_ARRAY( Simp1_t, nums_10 ),

Tr_ENDIAN_ARRAY( Simp1_t, vals_5 ),

0 /* Конец эндиан-списка */

};

Обратите внимание, что этот список должен завершаться нулевым элементом. Член name не является эндиан-чувствительным, поэтому он не включён в список.

Все типы или ссылки на типы устанавливают эндиан-параметры для своих членов на основе эндиан-массива, описанного в типе. Классификация эндиан-чувствительных членов следующая:

Tr_ENDIAN( typedef_name, member )

int, long, short, (signed или unsigned).

Например, unsigned int my_scalar.

Tr_ENDIAN_ARRAY( typedef_name, member ) - Массив из short или int элементов.

Например, short short_nums[10].

Tr_ENDIAN_REF( typedef_name, member, num ) - Ссылка на эндиан-скаляры. Например, int *nums.

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

static const PhTransportRegEntry_t Simp1TransDef = {

"simp1",

Ph_PACK_STRUCT,

sizeof( Simp1_t ),

0,

NULL,

&Simp1Endians,

NULL

};

Структура PhTransportRegEntry_t включает следующие члены:

char*type

Имя регистрируемого типа

int unsigned packing

Метод установки, который будет использоваться (один из: Ph_PACK_RAW, Ph_PACK_STRING или Ph_PACK_STRUCT)

int unsigned size

Размер типа данных в байтах

int unsigned num_fixups

Количество элементов в массиве fixups

PhTransportFixupRec_t const *fixups

Список инструкций по работе со ссылками на данные, определённые вне типа. Подробнее будет обсуждено далее

int unsigned const *endians

Завершающийся нулём массив эндиан-информации, описанный выше

int unsigned const *clear_refs

Завершающийся нулём массив членов, которые должны быть очищены (т.е. установлены в NULL), когда данные этого типа распакованы

Чтобы зарегистрировать этот впервые определённый тип, вызовите функцию PhRegisterTransportType():

PhRegisterTransportType(&Simp1, TransDef);

Этот новый тип Simp1 может теперь использоваться с любой функцией транспортировки при упаковке или распаковке данных.

Приложению-адресату нет нужды беспокоиться об эндиан-ориентации источника. Когда адресат распаковывает данные этого типа, транспортный механизм автоматически корректирует эндиан-ориентацию, используя эндиан-определение в зарегистрированном транспортном типе. Это весьма выгодно в мультиплатформенном сетевом окружении. Если транспортный механизм используется для записи двоичных конфигурационных файлов, одни и те же файлы могут использоваться приложениями независимо от эндиан-ориентации машин, на которых они выполняются.

Yandex.RTB R-A-252273-3
Yandex.RTB R-A-252273-4