Как сериализовать древовидную структуру в C ++? - PullRequest
6 голосов
/ 23 октября 2011

Я пытаюсь сериализовать / десериализовать игровую сцену для отправки / получения по сети и сохранения / загрузки с / на диск.

Мой игровой движок использует узлы и компоненты, и, таким образом, это единственные объекты, которыенужна сериализация.Сцена может выглядеть так:

Root Node
  - Node
    - SpecializedComponent
    - SpecializedComponent
    - Node 
      - Node
  - Node
    - Node
    - Node
      - Node
        - Node
          - SpecializedComponent
  - Node

Узел в основном такой:

class Node {
    map<String, Node> mChildren;
    map<String, Component> mComponents;
    uuid_t mId;
    Node* mParent;
};

Специализированный компонент в основном такой:

class SpecializedComponent : public Component {
    uuid_t mId;
    Node* mNode;
};

Я бы хотеллибо использовать YAML или JSON для моего текстового представления этого.У меня есть Qt, Boost и любая другая библиотека, которая мне нужна, поэтому зависимости не являются проблемой.На самом деле, узлы уже Q_OBJECTS, поэтому у меня есть рефлексия.

Несмотря на рефлексию, десериализация этого корректно обратно в древовидную структуру C ++ кажется проблемой.

Оптимально, я бы хотел элегантныйи эффективное решение для сериализации / десериализации подобной структуры в двоичном или текстовом формате.

Ответы [ 4 ]

3 голосов
/ 23 октября 2011

Рекурсивный анализатор спуска, как правило, это более простая и достаточно мощная опция для обработки части восстановления.Я мог бы попытаться настроить некоторый код, чтобы показать в конкретном случае, в псевдокоде что-то вроде этого:

 Node *parse(stream s) {
  content = new Node;
  s >> content >> nsons;
  for (int c = 0; c < nsons; ++c)
   content->addChild(parse(s));
  return content; 
 }

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

2 голосов
/ 23 октября 2011

Я предлагаю вам использовать библиотеку буферов протокола для этого.Поскольку вы сериализуете данные C ++ для отправки по сети, вы будете очень полезны для того, что может предложить эта библиотека.

1 голос
/ 23 октября 2011

Полагаю, вы можете сделать это с помощью Boost Serialization .Он поддерживает сериализацию всех контейнеров STL, включая std::map.

1 голос
/ 23 октября 2011

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

Чтобы сериализовать компонент, вы должны присвоить Id (или int, или строку) каждому типу компонента (чтобы вы могли определить, как десериализоватьконкретный компонент, относящийся к типу hs) Сериализация количества дочерних узлов Сериализация дочерних узлов (рекурсивный вызов той же функции)

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

Если вы используете Qt, QTextStream / QDataStream являются простейшими опциями.Бинарный формат должен быть хорошо известен во время десериализации, поэтому вы должны поместить номер версии или Id в начало вашего сериализованного контента, чтобы вы могли добавлять или изменять вещи позже.

Также, если вам нужно быть совместимым с другими языками (например, Java), имейте в виду, что Qt не использует те же нормы для типов, что и строка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...