いけむランド

はてダからやってきました

eet 入門 (1)

eet の簡単な使い方をまとめてみた。

It is a tiny library designed to write an arbitary set of chunks of data to a file and optionally compress each chunk (very much like a zip file) and allow fast random-access reading of the file later on.


さっそく サンプルコンパイルしてみるが、なんか警告はでるわ、exe はセグるわでちゃんと動いてくれない。

% gcc eet_org.c -leet -o eet_org.exe
eet_org.c: In function `main':
eet_org.c:13: 警告: 互換性のないポインタ型からの初期化です
eet_org.c:14: 警告: スカラー初期化子内の要素が多すぎます
eet_org.c:14: 警告: (`entries' の初期化は不完全です)
eet_org.c:16: 警告: スカラー初期化子内の要素が多すぎます
eet_org.c:16: 警告: (`entries' の初期化は不完全です)
% ./eet_org.exe 
Segmentation fault (core dumped)
%


初期化の書き方がまずかったらしく、それを書き直すと、きちんと動いた。

  char     *entries[3] =
    {
      "Entry 1",
      "Big text string here compared to others",
      "Eet is cool"
    };


処理の流れは以下のようによくあるパターンから構成される。

  1. eet_init (初期化)
  2. eet_open (ファイルのオープン)
  3. eet_read/write (読み書き)
  4. eet_close (ファイルのクローズ)
  5. eet_shutdown (後始末)


eet ではハッシュテーブルのようにキーと値を対応付けて、データを保存できるが、すべての値を取り出す場合は

  1. eet_list ですべてのキーを取得する
  2. そのキーごとに eet_read する

というのが一般的なやり方のようである。

/*
 * gcc -std=c99 gcc4-def.c -leet -o gcc4-def.exe
 */
#include <stdio.h>
#include <string.h>

#include <Eet.h>

#define EET_FILE_NAME "gcc4-def.eet"

typedef struct {
  char* key;
  char* value;
} Entry;

int main(int argc, char **argv)
{
  Eet_File *ef;
  char    **list;
  int       num, size;
  Entry     entries[] = {
#include "gcc4-def.h"
  };
  int nEntries = sizeof(entries) / sizeof(Entry);

  if (argc != 2) {
    printf("usage: %s <shell wildcard pattern>\n", argv[0]);
    return 1;
  }

  eet_init();

  ef = eet_open(EET_FILE_NAME, EET_FILE_MODE_WRITE);
  for (int i = 0; i < nEntries; i++) {
    eet_write(ef, entries[i].key, entries[i].value,
              strlen(entries[i].value) + 1, 0);
  }
  eet_close(ef);

  ef = eet_open(EET_FILE_NAME, EET_FILE_MODE_READ);
  list = eet_list(ef, argv[1], &num);
  if (list) {
    for (int i = 0; i < num; i++) {
      printf("\"%s\" = \"%s\"\n", list[i], (char*)eet_read(ef, list[i], &size));
    }
  }

  eet_close(ef);

  eet_shutdown();

  return 0;
}


キーと値の組み合わせのサンプルとして、gcc4-def.h を用意してみる。
このファイルは gcc4 であらかじめ定義されたマクロを struct の初期化子に合わせて整形したもので、以下のコマンドで生成した。(gcc4 にした意味は特にない。)

% echo | /opt/gcc4/bin/gcc -E -dM - | & sed -e 's/^#define /{"/' -e 's/ /", "/' -e 's/$/"},/' | sort


eet_list からリストとして返してもらうキーの条件はシェルの ワイルドカードパターン で指定できる。よって、"*" を渡せば、すべてのキーを入手できる。

% ./gcc4-def.exe '*'
"__DBL_MAX__" = "1.7976931348623157e+308"
"__DEC128_MAX_EXP__" = "6144"
"__REGISTER_PREFIX__" = ""
"__DBL_HAS_QUIET_NAN__" = "1"
:
: (snip)
:
"__DEC32_DEN__" = "0.000001E-95DF"
"__PTRDIFF_TYPE__" = "int"
"__LDBL_HAS_DENORM__" = "1"
"__i386" = "1"
"__VERSION__" = "4.2.0"
%


正規表現ではないことに注意する。
ちなみにシェルのワイルドカードパターンによる検索には fnmatch を使っている。*1

% ./gcc4-def.exe '*[a-z]*'
"_cdecl" = "__attribute__((__cdecl__))"
"unix" = "1"
"_stdcall" = "__attribute__((__stdcall__))"
"__unix" = "1"
"_fastcall" = "__attribute__((__fastcall__))"
"i386" = "1"
"__i386__" = "1"
"__cdecl" = "__attribute__((__cdecl__))"
"__declspec(x)" = "__attribute__((x))"
"__fastcall" = "__attribute__((__fastcall__))"
"__stdcall" = "__attribute__((__stdcall__))"
"__unix__" = "1"
"__i386" = "1"
%
% ./gcc4-def.exe '__LDBL_???__'
"__LDBL_DIG__" = "18"
"__LDBL_MIN__" = "3.36210314311209350626e-4932L"
"__LDBL_MAX__" = "1.18973149535723176502e+4932L"
%


他にも構造体の直列化関数の定義のやり方とかを調べてみる必要があるので、次回はそれについて書く予定にしておく。