Какой эффективный и простой способ хранения структуры данных? - PullRequest
4 голосов
/ 09 августа 2010

Я хочу написать анализатор для структур NBT (именованные двоичные теги). Формат представлен так:

TAG_Compound("hello world"): 1 entries
{
    TAG_String("name"): Bananrama
}

И в памяти (или в файле, в котором он хранится) в шестнадцатеричном виде:

0000000: 0a 00 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64 08 00  ...hello world..
0000010: 04 6e 61 6d 65 00 09 42 61 6e 61 6e 72 61 6d 61  .name..Bananrama
0000020: 00                                               .
  • 0x0a = TAG_Compound
    • 0x00 0x0b = имя длиной 11 символов
    • "Привет, мир"
  • 0x08 = TAG_String
    • 0x00 0x04 = длина имени 4 символа
    • "имя"
    • 0x00 0x09 = полезная нагрузка составляет 9 символов
    • "Bananarama"
  • 0x00 = TAG_End

С усложнением TAG_Compound, например древовидной структурой, все становится сложнее.

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

Я знаю, что не могу достичь такой степени легкости, как

tags["hello world"]["name"] = "Bananrama"

Но каков наилучший способ сохранить его, оставляя его простым в использовании? Я подумал о структуре nbt_compound (потому что каждое дерево NBT имеет по крайней мере одно корневое соединение), чтобы оно сохраняло количество дочерних элементов и содержало массив структур nbt_value, которые будут хранить тип и содержимое этого значения. Это хорошая идея?

Редактировать: полную спецификацию можно увидеть здесь

1 Ответ

1 голос
/ 09 августа 2010

Я уверен, что этот код не работает, но идея в том, что я пытаюсь донести. Я думаю, что я бы использовал объект Tag, как

struct TagHeader
{
  TagType type;  // Enum of COMPOUND, STRING, etc
  char *name;
}

struct TagCompound
{
  TagHeader header;
  int nelems;
  void *children;
}

struct TagString
{
  TagHeader hearder;
  char *value;
}

С такой функцией, как

void *get_value(void *root, char *name)
{
  int i;
  if (! root) return NULL;

  if (((TagHeader *) root)->type == COMPOUND)
  {
    TagCompound *c = (TagCompound *)root;
    for (i = 0; i < c->nelems; i++)
    {
      if (strcmp(((TagHeader *) c->values[i])->name, name) == 0)
      {
        return c->values[i];
      }
    }
    return NULL;
  } else if ( /* handle other tag Types */ ) {
  }
  return NULL;
}

Затем получите к нему доступ:

get_value(get_value(root, "Hello World"), "name");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...