Поэтому, для улучшения параметров скорости/экономичности сериализации объектов необходимо для каждого сериализуемого объекта сократить к минимуму количество сериализуемых полей (атрибутов). Одним из способов является использование опциональных полей.
Опциональным полем является атрибут объекта, которому можно назначить значение по-умолчанию, использующееся в подавляющем большинстве случаев. Если при сериализации проверить, что поле содержит такое значение, то поле можно не сериализовать. Достаточно указать в двоичном представлении, что поле имеет значение по-умолчанию. При десериализации можно определить, что поле не было сериализовано и назначить ему значение по-умолчанию сразу после десериализации всего объекта.
Пример. Пусть есть некое сообщение 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() ; }
1.4.7