Поэтому, для улучшения параметров скорости/экономичности сериализации объектов необходимо для каждого сериализуемого объекта сократить к минимуму количество сериализуемых полей (атрибутов). Одним из способов является использование опциональных полей.
Опциональным полем является атрибут объекта, которому можно назначить значение по-умолчанию, использующееся в подавляющем большинстве случаев. Если при сериализации проверить, что поле содержит такое значение, то поле можно не сериализовать. Достаточно указать в двоичном представлении, что поле имеет значение по-умолчанию. При десериализации можно определить, что поле не было сериализовано и назначить ему значение по-умолчанию сразу после десериализации всего объекта.
Пример. Пусть есть некое сообщение handshake, в котором требуется передать параметры коммуникационной сессии. Среди прочих параметров в нем содержатся: параметры использования подписи передаваемых данных и параметры компрессии передаваемых данных. При этом, в большинстве случаев в качестве подписи будет использоваться алгоритм md5. Компрессия по умолчанию не используется, но если используется, то обычно применяется gzip со средней степенью сжатия. Представить это на DDL можно следующим образом:
|| Параметры компрессии. {type compression_t || Алгоритм копрессии. {attr m_algorithm {of std::string} {default || По-умолчанию в C++ значение задается константой gzip. {c++ compression_t::gzip} || Сериализовать атрибут необходимо только, если || значение отличается от gzip. {present_if {c++ m_algorithm != compression_t::gzip}} } } || Степень сжатия. {attr m_level {of oess_1::uint_t}} } || Описание параметров для коммуникационной сессии. {type handshake_t || Остальные атрибуты опущены за ненадобностью. || Алгоритм подписи данных. {attr m_signature {of std::string} {default || По-умолчанию в C++ значение задается константой md5. {c++ handshake_t::signature_md5} || Сериализовать атрибут необходимо только, если || значение отличается от md5. {present_if {c++ handshake_t::signature_md5 != m_signature} } } } || Признак необходимости использования компрессии данных. {attr m_is_compression {of oess_1::uchar_t}} || Параметры компрессии. {attr m_compression {of compression_t} {default || По-умолчанию должен использоваться конструктор || класса compression_t. {c++ compression_t() } || Сериализовать атрибут нужно только, если флаг || m_is_compression отличен от 0. {present_if {c++ m_is_compression}} } } }
if()
, укажет, должен ли атрибут быть сериализован. Атрибут сериализуется только, если данный предикат производит значение true. Выражением может быть любое корректное C++ выражение, приводящееся к булевому результату.
{attr m_algorithm {of std::string} {default {c++ \"md5\"} {present_if {c++ m_algorithm != \"md5\"}} } }
{attr m_compression {of std::string} {default {c++ \"gzip\"} {present_if {c++ m_compression != \"gzip\" || m_compression != \"zip\"}} } }
{attr m_compression {of std::string} {default {c++ \"gzip\"} {present_if {c++ m_compression != \"gzip\" \|\| m_compression != \"zip\"}} } }
В версии 1.2.0 для приведенного выше DDL описания методы oess_present_if, oess_set_default будут иметь вид:
bool compression_t::oess_present_if( const std::string & a ) const { if( a == "m_algorithm" ) return ( m_algorithm != compression_t::gzip ); return false; } void compression_t::oess_set_default( const std::string & a ) { if( a == "m_algorithm" ) m_algorithm = compression_t::gzip ; } bool handshake_t::oess_present_if( const std::string & a ) const { if( a == "m_signature" ) return ( handshake_t::signature_md5 != m_signature ); if( a == "m_compression" ) return ( m_is_compression ); return false; } void handshake_t::oess_set_default( const std::string & a ) { if( a == "m_signature" ) m_signature = handshake_t::signature_md5 ; if( a == "m_compression" ) m_compression = compression_t() ; }