Если вы хотите избежать экранирования строк, вы можете посмотреть, как работает ASN.1. Это излишне для ваших заявленных требований: строк, основных типов и массивов этих вещей, но принцип заключается в том, что поток содержит однозначную информацию о длине. Поэтому ничего не нужно избегать.
Для очень простого эквивалента вы можете вывести uint32_t
как "ui4", за которым следуют 4 байта данных, int8_t
как "si1", за которым следует 1 байт данных, IEEE с плавающей точкой как "f4", IEEE удваивается как "f8" и так далее. Используйте некоторый дополнительный модификатор для массивов: «a134ui4», за которым следуют 536 байтов данных. Обратите внимание, что произвольные длины должны быть завершены, тогда как ограниченные длины, такие как число байтов в следующем целом числе, могут быть фиксированного размера (одна из причин, по которой ASN.1 больше, чем вам нужно, заключается в том, что он использует произвольные длины для всего). Строка может быть либо a<len>ui1
, либо сокращением, например s<len>:
. Читатель действительно очень прост.
Это имеет очевидные недостатки: размер и представление типов должны быть независимыми от платформы, а выходные данные не читаются человеком и не сжимаются.
Вы можете сделать его в основном читабельным для человека, хотя с ASCII вместо двоичного представления арифметических типов (осторожно с массивами: вы можете вычислить длину всего массива перед выводом любого из него, или вы можете использовать разделитель и терминатор, поскольку нет необходимости в экранировании символов), и, при необходимости, добавляя большой жирный видимый человеком разделитель, который десериализатор игнорирует. Например, s16:hello, worlds12:||s12:hello, world
значительно легче читать, чем s16:hello, worlds12:s12:hello, world
. Просто будьте внимательны, читая, что то, что выглядит как последовательность разделителя, может на самом деле не быть единым, и вам следует избегать попадания в ловушки, например, если предположить, что s5:hello||
в середине кода означает, что строка длиной 5 символов: она может быть частью s15:hello||s5:hello||
.
Если у вас нет очень жестких ограничений на размер кода, вероятно, проще использовать универсальный сериализатор с полки, чем писать специализированный. Чтение простого XML с SAX не сложно. Тем не менее, каждый и его собака написали «наконец, сериализатор / парсер / что угодно, что спасет нас от ручного кодирования сериализатора / парсера / что угодно когда-либо еще», с большим или меньшим успехом.