005-01  前へ←  ホームへ  →次へ  006-02

No.006 - 01  階層シリアライズ(複数データのファイル化)


いくつかの簡単なデータをまとめて、ひとつのファイルに入れます。


・シリアライズ
【serialize】
シリアライズ【serialize】ソフトウェア内部で扱っているデータをまとめてファイルに保存すること。


・複数のデータを1コのファイルに
GetProfileString() とか WriteProfileString() を使って ini ファイルを生成するのもいいんですが、いかんせんそれではフォローしきれないデータ型が多すぎるので、自前でセーブデータ作っちゃえってことです。ini ファイルは融通利かないんだもん。


・ディレクトリ型で保存
一個のファイルにいれるのに、タダだら〜と並べて保存すると、
保存アイテム数が増えるに従って大変になります。

読み出し側が、どれがどのデータか確実に把握しておく必要があるからです。

そこで各データに名前をつけて保存するわけです。(ハッシュ化)
1つ1つのデータに名前がついてればアプリケーションは任意に
アーカイブファイルからデータを読み出し出来ます

またここで問題がでます。
並列に保存しようとするとデータ1つ1つに
違う名前をつける必要がでてきてしまいます。、

ということでファイル内に
擬似ディレクトリ
を作り保存データの階層化を行います。
この擬似ディレクトリ下なら同名データ名が使えます。

以下のサンプルではホントのディレクトリじゃないので「フォルダ」という言葉を使うのはうまくないかな〜と思ったので「アイテム・ボックス」という言葉にしました。



・ファイルにいれるデータ型の種類
あんまりいろいろあっても大変なので
下記で扱うのは数値型(int) と、汎用データ(可変長バイナリ)だけです。

(昨今ギガバイトもだいぶ当たり前になってるので
場合によっては数値型はdouble型にしたほうがいいかもしれません。)


・ファイルの内部構造
ファイルヘッダ部分にマジック・コード全ファイル・リストを書き込み、そのとで実データを保存します。

マジックコードは異種ファイルの読込を防ぐ先頭識別コードですが、
下記では適当に決めています。
アプリケーションでなるべく同一コードにならないよう注意が必要です。
(最近はマジックコードという言い方もあまりしないようですが、
 その割に代替になる言葉もないようなので当サイトはマジックコードという言葉を使います)

ヘッダ部ファイルリスト中実データ部でのファイルオフセット値が入ります。
これにより実データ部へのランダムアクセスを可能にしています。


・フォーカス・アイテムボックス
各アイテムにアクセスするとき各階層のアイテムにどうやってアクセスするのか。
やはり一般的にカレント・ディレクトリ的な概念を作ったほうがわかり易いので、そうしました。
上記で「フォルダ」のかわりに「アイテムボックス」という名前をつかうと述べました。
ので、「カレント・ディレクトリ」も「フォ−カス・アイテムボックス」という言葉を使います。

フォ−カス・アイテムボックスの実態はただのアイテムボックス・ポインタです。
下記ソースでは各アイテムに名前指定でアクセスするとき
「フォ−カス・アイテムボックス」をカレントとして "../aaa/bbb"、や"ccc/ddd" といったパス指定もできるようになっています。


・アイテム名
各アイテムには名前をつけてファイル読込時に何のデータであるか明確にわかるようにします。
アイテム追加時、既存のアイテムと名前が重複したらどうするか、という問題があります。

下記ソースでは
まず、アイテムボックス数値アイテム汎用アイテム異なるアイテム間では同名を許可しています。
そのほうが便利かなと思ったので。(実際windowsもそうだし)

次に同一アイテムでの同名処理ですが、
アイテムボックス名前が重複したら何も処理しません
数値アイテム汎用アイテム名前が重複したら新しいデータで値を上書きしています。




・操作のおおまかな流れ
セーブ時
HIER_FILER 変数を宣言します
add_item_〜系の関数でアイテムを追加します。
セーブします。
ロード時
ロード方法は2種類用意しました。
最初にファイルリストだけを読込み、あとから指定したデータを個別に読み出していくやりかたと
一気に全データを読込んでしまうやりかたです。
前者はメモリ効率がよく、また大きなデータを扱う場合にも向いてます。
後者はメモリ効率は悪いのですが、前者より高速になります。

<やりかた1>
HIER_FILER 変数を宣言します
load_list()関数でファイルリストを読込ます。
load_data_num, load_data_any で目的データを読込ます

<やりかた2>
HIER_FILER 変数を宣言します
load_full_innner()関数でファイルを全部、内部に読込ます。
get_data_num, get_data_any で内部データからを値(またはポインタ)を取得します



load_list()関数、またはload_full_innner()を実行したあとなら
get_list_size_numなどの関数でフォ−カス・アイテムボックスのアイテム数も取得出来ます


サンプルソース解説
例によって当サイト・ライブラリplist.h使ってます。

下記 hier は hierarchy …ヒエラルキー(階層)の意味です。hier_filer でヒエラルキー・ファイラー(階層ファイラー)ってことです。


namespace HIER_FILE_ITEM
階層シリアライズ・アイテム用ネームスペースです。
階層シリアライズのクラス内でしか使わないクラスが多いので、グローバルな名前の偏在を防ぎます


EAZY_STRING
クラス
簡易文字クラスです。
NULL終端の可変長文字列
データクラスです。
copy()メンバ関数でnew演算+strcpyして、デストラクタでメモリ解放します。


BASE_ITEM
クラス
階層ファイル・クラス用のアイテム用基底クラスです。
テンプレートを使っています。
ここから数値型、汎用型へと派生させます
templateを使って実データの型を決定しています。

メンバ変数
m_self_allocate は自前メモリ確保フラグです。実データバッファのポインタが、ただのアドレス値かnew 演算したポインタかのフラグです。
int m_arc_offset ファイル・オフセット位置(読み込み用)です。階層ファイル・クラスのload_list()関数でセットされる変数です。


NUM_ITEM
クラス
階層ファイル・クラス用の数値型アイテムです。
BASE_ITEM<int> としてint 型データを保持しています


ANY_ITEM
クラス
階層ファイル・クラス用の汎用アイテムです。

メンバ
int m_data_len は実データ・バッファの長さです。

void set_data() はデータの値を設定します。自前でメモリ確保します。
void set_data_p()はデータのポインタをm_dataに代入します。サイズの大きなデータ(画像データとか)向きです。set_data()関数でクラス内にメモリを確保してしまうよりはすでに持っているメモリを有効に使おうってことです。


ITEM_BOX
クラス
アイテムボックス・クラスです。階層シリアライズ・クラス用のフォルダ構造を実現します。
INT_ITEMクラスとANY_ITEMクラス、子ディレクトリ用ITEM_BOXクラスを持ちます。

メンバ変数
ITEM_BOX *m_parent 親アイテム・ボックスへのポインタです。自身が最上位ディレクトリならNULL値になります。
PLIST<INT_ITEM> m_int_list intアイテムのリストです。
PLIST<ANY_ITEM> m_any_list 汎用アイテムのリストです。
PLIST<ITEM_BOX> m_sub_box 子アイテムボックスのリストです。

メンバ関数

// ファイル読込
load_list(FILE *fp); ファイルヘッダのリスト部分をロードします。
load_buf(FILE *fp); イテムの実データバッファをロードします。

// ファイル保存
get_save_header_size(); セーブ時のファイルヘッダ・サイズ取得します。実データ・バッファの保存位置を計算するのに使います。
save_list(FILE *fp, int *p_offset); ファイルヘッダのリスト部分をセーブします。
save_buf(FILE *fp); アイテムの実データバッファをロードします。

int get_item_order_num(char *name); 名前から数値型アイテムの番号取得します
int get_item_order_any(char *name); 名前から汎用アイテムの番号取得します
int get_item_order_box(char *name, int name_len=-1); 名前から子ボックスの番号取得します

void add_item_num (char *name, int val); 数値型アイテムを追加します。
void add_item_num_p(char *name, int *pval); 数値型アイテムをポインタ指定で追加します。
void add_item_any (char *name, char *buf, unsigned int len); 汎用アイテムを追加します。
void add_item_any_p(char *name, char *buf, unsigned int len); 汎用アイテムをポインタ指定で追加します。
void add_item_box(char *name, int name_len=-1); 子アイテムボックス追加します。(子ディレクトリ作成)

void del_item_num(int n); 数値型アイテムを削除します。(配列番号指定)
void del_item_any(int n); 汎用型アイテムを削除します。(配列番号指定)
void del_item_box(int n); 子アイテムボックスを削除します。(配列番号指定)
以上までのアイテムクラスはネームスペースDIR_SERIALIZE_ITEM内で宣言しています。


HIER_FILER
クラス
メインとなる階層ファイル・クラスです。
アプリケーションはこのクラスを宣言し、このクラスからアイテム追加・削除セーブ・ロードを行います。

HIER_FILER_ITEM::ITEM_BOX m_top; // 一番上のアイテム・ボックス
HIER_FILER_ITEM::ITEM_BOX *m_focus; // 現在のフォーカス・アイテム・ボックス
char *m_magic_code; // マジック・コード
int m_magic_code_len; // マジック・コード長
int m_loaded_list_flag; // リスト読込済み

// ファイル読込
int load_list(char *filename); ヘッダからファイルリストを読み込みます
int load_list_inline(FILE *fp); load_list関数の内部関数です。
int load_full_inner(char *filename); 全ロードです。ファイルリスト+実データ全て読み込みます
int load_data_num(char *name, int *buf); 特定の数値アイテムを引数bufに読込ます。失敗すると-1を返します。
int load_data_any_buf(char *name, char *buf); 特定の汎用アイテムの実データを引数bufに読み込みます。
int load_data_any_buflen(char *name, int *p_resln); 特定の汎用アイテムのデータ長を引数p_reslenに読み込みます。失敗すると-1を返します。
int load_data_num_inner(char *name); 特定の数値アイテムを内部変数に読み込みます。この関数の実行後ならget_data_num関数でそのアイテムの値を取得することができます。
int load_data_any_inner(char *name); 特定の汎用アイテムを内部変数に読み込みます。この関数の実行後ならget_data_any関数でそのアイテムの値を取得することができます。(データ長はget_data_any_len関数)

// ファイル保存
int save(char *filename); 一括セーブです。(…load_list()関数実行の直後に実行してはいけません。…load_list()関数は実データを読み込まないから)

int get_data_num(char *name); 数値アイテムの実データの値を返します。
char *get_data_any(char *name); 汎用アイテムの実データ(内部変数)へのポインタを返します。
int get_data_any_len(char *name); 汎用アイテムの実データ(内部変数)のデータ長を返します

int get_data_num(int n); 数値アイテムの実データの値を返します。(配列番号指定)
char *get_data_any(int n); 汎用アイテムの実データ(内部変数)へのポインタを返します。(配列番号指定)
int get_data_any_len(int n); 汎用アイテムの実データ(内部変数)のデータ長を返します。(配列番号指定)

// フォーカス・ボックス
int focus(char *path); フォーカス・アイテムボックスを移動します(文字引数)
int focus_up(); 上位アイテムボックスへ移動します
int focus_down(int n); 下位アイテムボックスへ移動します
void focus_top() 最上位のアイテム・ボックスへ移動します

int get_focus_num(); 現在のフォーカス・ボックスが親から見て何番目の子か返します

// アイテム情報取得
char* get_item_name_num(int n); 数値アイテムのデータ名を取得します
char* get_item_name_any(int n);  汎用アイテムのデータ名を取得します
char* get_item_name_box(int n);  アイテムボックスのデータ名を取得します

int get_list_size_num() 現在のフォーカス・ボックスの数値アイテム数を取得します
int get_list_size_any() 現在のフォーカス・ボックスの汎用アイテム数を取得します
int get_list_size_box() 現在のフォーカス・ボックスの子ボックス数を取得します

HIER_FILER_ITEM::ITEM_BOX *get_aim_box_by_path(char *path, int last_valid_flag, int add_mode=0);
"aaa/bbb/ccc"等のパスから目的となるアイテムボックスへのポインタを取得します。last_valid_flag引数はパス最後尾の名前をアイテムボックスとして扱うかどうかのフラグ、add_mode引数はパス途中の名前のアイテムボックスがないとき新しくアイテムボックスを追加するかどうかのフラグです。

// アイテム追加
void add_item_num (char *name, int val); 数値アイテムを追加します
void add_item_num_p(char *name, int *p); 数値アイテムを追加します(ポインタ設定)
void add_item_any (char *name, char *buf, unsigned int len); 汎用アイテムを追加します
void add_item_any_p(char *name, char *buf, unsigned int len); 汎用アイテムを追加します(ポインタ設定)
void add_item_box(char *name); 子アイテムボックスを追加します

// アイテム削除
void del_item_num(char *name); 数値アイテムを削除します
void del_item_num(int n); 数値アイテムを削除します(配列番号指定)
void del_item_any(char *name); 汎用アイテムを削除します
void del_item_any(int n); 汎用アイテムを削除します(配列番号指定)
void del_item_box(char *name); 子アイテムボックスを削除します
void del_item_box(int n); 子アイテムボックスを削除します(配列番号指定)




hier_filer_01.h



#ifndef _HIER_FILER_H_
#define _HIER_FILER_H_

#include <stdio>
#include <stdlib>
#include <string>
#include "plist.h"

// 階層シリアライズ用アイテムのためのネームスペース
namespace HIER_FILER_ITEM {

// =========簡便用関数===================
// 全角判定(シフトJIS)
is_zenkaku(char *s){
    unsigned char c = s[0];
    if ( (c>=0x81 && c<=0x9f) || (c>=0xe0 && c<=0xfc)){ // 全角の第1バイト
        c=s[1];
        if (c>=0x40 && c<=0xfc) return 1;   // 全角の第2バイト
        else return -1;
    }
    return 0;
}
// ファーストパス長取得
int get_first_path_len(char *path){
    int len=0;
    while(1){
        if (is_zenkaku(path+len)){
            len+=2;
            continue;
        }
        if (path[len]=='/' || path[len]=='\\') break;
        if (path[len]=='\0') return -1;
        len++;
    }
    return len;
}
// ラストパス・ポインタ取得
char *get_last_name(char *path){
    for(int i=strlen(path)-1;i>=0;i--){
        if (path[i]=='/' || path[i]=='\\') {
            if (i>=1 && is_zenkaku(path+i-1)) continue;
            return path+i+1;
        }
    }

    return path;
}

// =========汎用 簡易ファイル入出力データ===================
class EAZY_FILE {
    FILE *m_fp;
    public:
    int read_open(char *filename){
        m_fp = fopen(filename, "rb");
        return (m_fp)? 0 : -1;
    }
    int write_open(char *filename){
        m_fp = fopen(filename, "wb");
        return (m_fp)? 0 : -1;
    }
    void close(){   if (m_fp) fclose(m_fp); }
    int tell(){ return (m_fp)? ftell(m_fp) : 0; }   // ファイル位置取得
    int seek(int pos){                              // ファイル位置移動
        int res = fseek(m_fp, pos, SEEK_SET);
        return (res)? -1 : 0;
    }
    int read(void *buf, int len){   return fread(buf, 1, len, m_fp);    }   // ファイル読込
    int write(void *buf, int len){  return fwrite(buf, 1, len, m_fp);   }   // ファイル書込

    EAZY_FILE(){ m_fp = NULL; };
    ~EAZY_FILE(){ close(); };
};
// =========汎用 簡易文字列データ===================
class EAZY_STRING {
    public:
    char *m_buf;
    int m_buf_len;
    EAZY_STRING(){ m_buf = NULL; m_buf_len=0; };    // コンストラクタ
    ~EAZY_STRING(){ if (m_buf) delete[] m_buf; }    // デストラクタ
    void del(){ if (m_buf) delete[] m_buf; m_buf=NULL; }    // 削除
    void copy(char *s, int slen=-1);
    void read(EAZY_FILE *p_read_file, int len);
};
// 文字列読込(メモリ確保付)
void EAZY_STRING::read(EAZY_FILE *p_read_file, int len){
    del();
    if (len<0) return;
    m_buf = new char [len+1];
    p_read_file->read(m_buf, len);
    m_buf[len] = '\0';
};

// 文字列コピー
void EAZY_STRING::copy(char *s, int slen){
    del();
    if (!s) return;
    int len = (slen<0)? strlen(s) : slen;
    if (len<0) return;
    m_buf = new char [len+1]; strncpy(m_buf, s, len);
    m_buf[len] = '\0';
};
// =========基底アイテム===================
template <class T> class BASE_ITEM {
    char m_self_allocate;   // 自前メモリ確保フラグ
    public:
    T *m_data;    // 実データ
    int m_data_len;     // 実データ長
    EAZY_STRING m_name; // アイテム名

    // 読み込み用
    int m_arc_offset;   // ファイル・オフセット位置(読み込み用)

    BASE_ITEM(){ m_data = NULL; m_self_allocate = 0; }
    ~BASE_ITEM(){ self_free(); }
    void set_name(char *s, int slen=-1){ m_name.copy(s, slen); }
    void self_free(){
        if (m_data && m_self_allocate) delete[] m_data;
        m_self_allocate = 0;
        m_data = NULL;
    }
    // メモリの自前確保
    int self_alloc(int n){
        self_free();
        if (!m_data || !m_self_allocate) m_data = new T[n];
        m_self_allocate = 1;
    }
    int read_buf(EAZY_FILE *p_read_file, T *buf){
        p_read_file->seek(m_arc_offset);
        if (buf) return p_read_file->read(buf, m_data_len*sizeof(T));
        else {
            self_alloc(m_data_len);
            return p_read_file->read(m_data, m_data_len*sizeof(T));
        }
    }
};


// =========数値アイテム===================
class NUM_ITEM : public BASE_ITEM<int> {
    public:

    NUM_ITEM(){ m_data_len=1; }
    void set_data(int n);       // データの代入
    void set_data_p(int *p);    // データのポインタ設定
};
// 数値アイテム・データの代入
void NUM_ITEM::set_data(int n){
    self_alloc(1);
    *m_data = n;
}
// 数値アイテム・データのポインタ設定
void NUM_ITEM::set_data_p(int *p){
    self_free();
    m_data = p;
}

// =========汎用アイテム===================
class ANY_ITEM : public BASE_ITEM<char> {
    public:
    ANY_ITEM(){ m_data_len = 0; }   // コンストラクタ
    void set_data(char *buf, int len);   // データの代入
    void set_data_p(char *buf, int len);     // データのポインタ設定
};
// 汎用アイテム・データの代入
void ANY_ITEM::set_data(char *buf, int len){
    if (!len) return;
    self_alloc(len);
    for(int i=0;i<len;i++) m_data[i] = buf[i];
    m_data_len = len;
}
// 汎用アイテム・データのポインタ設定
void ANY_ITEM::set_data_p(char *buf, int len){
    self_free();
    m_data = buf;
    m_data_len = len;
}

// =========アイテム・ボックス===================
class ITEM_BOX {
    public:
    EAZY_STRING m_name; // アイテム・ボックス名
    ITEM_BOX *m_parent; // 親アイテム・ボックス
    PLIST<NUM_ITEM> m_num_list;     // intアイテム リスト
    PLIST<ANY_ITEM> m_any_list;     // 汎用アイテム リスト
    PLIST<ITEM_BOX> m_box_list;     // 子アイテムボックス リスト

    ITEM_BOX(){ m_parent=NULL; };
    void set_name(char *s, int slen){ m_name.copy(s, slen); }

    // ファイル読込
    load_list(HIER_FILER_ITEM::EAZY_FILE *p_read_file); // リスト読込
    load_buf_inner(HIER_FILER_ITEM::EAZY_FILE *p_read_file);    // 実データ読込

    // ファイル保存
    int get_save_header_size();                 // ヘッダサイズ取得
    void save_list(HIER_FILER_ITEM::EAZY_FILE *p_write_file, int *p_offset);    // リスト・セーブ
    void save_buf(HIER_FILER_ITEM::EAZY_FILE *p_write_file);                    // 実データ・セーブ

    int get_item_order_num(char *name); // アイテム番号取得(数値)
    int get_item_order_any(char *name); // アイテム番号取得(汎用)
    int get_item_order_box(char *name, int name_len=-1); // アイテム番号取得(ボックス)

    void add_item_num  (char *name, int val);   // アイテム追加(int)
    void add_item_num_p(char *name, int *pval);    // アイテム追加(int ポインタ指定)
    void add_item_any  (char *name, char *buf, int len);    // アイテム追加(汎用)
    void add_item_any_p(char *name, char *buf, int len);    // 汎用アイテム追加(ポインタ指定)
    void add_item_box(char *name, int name_len=-1);     // 子アイテムボックス追加

    void del_item_num(int n);       // アイテム削除(数値 配列番号指定)
    void del_item_any(int n);       // アイテム削除(汎用 配列番号指定)
    void del_item_box(int n);       // 子アイテムボックス削除(配列番号指定)
};
// リスト読込
int ITEM_BOX::load_list(HIER_FILER_ITEM::EAZY_FILE *p_read_file){
    int num;
    int i;

    // 数値アイテム
    p_read_file->read(&num, sizeof(int)); for(i=0;i<num;i++) m_num_list.a_push();

    for(i=0;i<m_num_list.size();i++){
        p_read_file->read(&num, sizeof(int));
        m_num_list[i]->m_name.read(p_read_file, num);   // データ名
        p_read_file->read(&m_num_list[i]->m_arc_offset, sizeof(int));   // オフセット位置
    }

    // 汎用アイテム
    p_read_file->read(&num, sizeof(int)); for(i=0;i<num;i++) m_any_list.a_push();

    for(i=0;i<m_any_list.size();i++){
        p_read_file->read(&num, sizeof(int));
        m_any_list[i]->m_name.read(p_read_file, num);   // データ名
        p_read_file->read(&m_any_list[i]->m_data_len, sizeof(int)); // データ長 
        p_read_file->read(&m_any_list[i]->m_arc_offset, sizeof(int));   // オフセット位置
    }

    // 子ボックス
    p_read_file->read(&num, sizeof(int)); for(i=0;i<num;i++) m_box_list.a_push();

    for(i=0;i<m_box_list.size();i++){
        p_read_file->read(&num, sizeof(int));
        m_box_list[i]->m_name.read(p_read_file, num);   // データ名
        m_box_list[i]->load_list(p_read_file);
    }
};
// 実データ読込
int ITEM_BOX::load_buf_inner(HIER_FILER_ITEM::EAZY_FILE *p_read_file){
    int i;
    for(i=0;i<m_num_list.size();i++) m_num_list[i]->read_buf(p_read_file, NULL);    // 実データ読込(数値)
    for(i=0;i<m_any_list.size();i++) m_any_list[i]->read_buf(p_read_file, NULL);    // 実データ読込(汎用)

    for(i=0;i<m_box_list.size();i++) m_box_list[i]->load_buf_inner(p_read_file);
}

// ヘッダサイズ取得
int ITEM_BOX::get_save_header_size(){
    int total=0, i;
    char *ps;
    total = sizeof(int)*3;  // m_num_list + m_any_list + m_box_list の数

    // 数値アイテム
    for(i=0;i<m_num_list.size();i++){
        total += sizeof(int);   // データ名長
        ps = m_num_list[i]->m_name.m_buf;
        total += strlen(ps);
        total += sizeof(int);   // オフセット位置 情報分
    }
    // 汎用アイテム
    for(i=0;i<m_any_list.size();i++){
        total += sizeof(int);   // データ名長
        ps = m_any_list[i]->m_name.m_buf;
        total += strlen(ps);
        total += sizeof(int);   // データ長 情報分
        total += sizeof(int);   // オフセット位置 情報分
    }
    // 子ボックス
    for(i=0;i<m_box_list.size();i++){
        total += sizeof(int);   // データ名長
        ps = m_box_list[i]->m_name.m_buf;
        total += strlen(ps);
        total += m_box_list[i]->get_save_header_size();
    }
    return total;
}
// リスト・セーブ
void ITEM_BOX::save_list(HIER_FILER_ITEM::EAZY_FILE *p_write_file, int *p_offset){
    char *ps;
    int num;
    int i;
    // 数値アイテム
    num = m_num_list.size(); p_write_file->write(&num, sizeof(int));
    for(i=0;i<m_num_list.size();i++){
        ps = m_num_list[i]->m_name.m_buf;
        num = strlen(ps); 
        p_write_file->write(&num, sizeof(int));
        p_write_file->write(ps, num); // データ名
        p_write_file->write(p_offset, sizeof(int)); // オフセット位置 情報分
        (*p_offset) += sizeof(int);
    }
    // 汎用アイテム
    num = m_any_list.size(); p_write_file->write(&num, sizeof(int));
    for(i=0;i<m_any_list.size();i++){
        ps = m_any_list[i]->m_name.m_buf;
        num = strlen(ps); 
        p_write_file->write(&num, sizeof(int));
        p_write_file->write(ps, num); // データ名
        num = m_any_list[i]->m_data_len; 
        p_write_file->write(&num, sizeof(int));
        p_write_file->write(p_offset, sizeof(int)); // オフセット位置 情報分
        (*p_offset) += num;
    }

    // 子ボックス
    num = m_box_list.size(); 
    p_write_file->write(&num, sizeof(int));
    for(i=0;i<m_box_list.size();i++){
        ps = m_box_list[i]->m_name.m_buf;
        num = strlen(ps); 
        p_write_file->write(&num, sizeof(int));
        p_write_file->write(ps, num); // データ名
        m_box_list[i]->save_list(p_write_file, p_offset);
    }
};
// 実データ・セーブ
void ITEM_BOX::save_buf(HIER_FILER_ITEM::EAZY_FILE *p_write_file){
    int i, num=0, ai;
    // 数値アイテム
    for(i=0;i<m_num_list.size();i++){
        num = (m_num_list[i]->m_data)? *m_num_list[i]->m_data : num;
        p_write_file->write(&num, sizeof(int));
    }
    // 汎用アイテム
    for(i=0;i<m_any_list.size();i++){
        if (m_any_list[i]->m_data)
            p_write_file->write(m_any_list[i]->m_data, m_any_list[i]->m_data_len);
        else {
            for(ai=0;ai<m_any_list[i]->m_data_len;ai++) p_write_file->write(&num, 1);
        }
    }
    // 子ボックス
    for(i=0;i<m_box_list.size();i++){
        m_box_list[i]->save_buf(p_write_file);
    }
}

// アイテム番号取得(数値)
int ITEM_BOX::get_item_order_num(char *name){
    for(int i=0;i<m_num_list.size();i++) if (!strcmp(m_num_list[i]->m_name.m_buf, name)) return i;
    return -1;
};
// アイテム番号取得(汎用)
int ITEM_BOX::get_item_order_any(char *name){
    for(int i=0;i<m_any_list.size();i++) if (!strcmp(m_any_list[i]->m_name.m_buf, name)) return i;
    return -1;
};
// アイテム番号取得(ボックス)
int ITEM_BOX::get_item_order_box(char *name, int name_len){
    if (name_len<0) name_len = strlen(name);
    for(int i=0;i<m_box_list.size();i++) if (!strncmp(m_box_list[i]->m_name.m_buf, name, name_len)) return i;
    return -1;
};
// 数値 追加
void ITEM_BOX::add_item_num(char *name, int val){
    int n = get_item_order_num(name);
    HIER_FILER_ITEM::NUM_ITEM *pitem = (!m_num_list[n])? m_num_list.a_push() : m_num_list[n];
    pitem->set_name(name);
    pitem->set_data(val);
};
// 数値 追加(ポインタ指定)
void ITEM_BOX::add_item_num_p(char *name, int *pval){
    int n = get_item_order_num(name);
    HIER_FILER_ITEM::NUM_ITEM *pitem = (!m_num_list[n])? m_num_list.a_push() : m_num_list[n];
    pitem->set_name(name);
    pitem->set_data_p(pval);
};
// アイテム追加(汎用)
void ITEM_BOX::add_item_any(char *name, char *buf, int len){
    int n = get_item_order_any(name);
    HIER_FILER_ITEM::ANY_ITEM *pitem = (!m_any_list[n])? m_any_list.a_push() : m_any_list[n];
    pitem->set_name(name);
    pitem->set_data(buf, len);
};
// アイテム追加(汎用)(ポインタ指定)
void ITEM_BOX::add_item_any_p(char *name, char *buf, int len){
    int n = get_item_order_any(name);
    HIER_FILER_ITEM::ANY_ITEM *pitem = (!m_any_list[n])? m_any_list.a_push() : m_any_list[n];
    pitem->set_name(name);
    pitem->set_data_p(buf, len);
};
// 子ボックス追加
void ITEM_BOX::add_item_box(char *name, int name_len){
    int n = get_item_order_box(name, name_len);
    HIER_FILER_ITEM::ITEM_BOX *pitem = (!m_box_list[n])? m_box_list.a_push() : m_box_list[n];
    pitem->set_name(name, name_len);
    pitem->m_parent = this;
};

// アイテム削除
void ITEM_BOX::del_item_num(int n){ m_num_list.pop(n); }    // 数値 削除(配列番号指定)
void ITEM_BOX::del_item_any(int n){ m_any_list.pop(n); }    // 汎用 削除(配列番号指定)
void ITEM_BOX::del_item_box(int n){ m_box_list.pop(n); };   // 子ボックス削除(配列番号指定)


};  // namespace HIER_FILER_ITEM


// =========階層ファイル・クラス===================
class HIER_FILER {
    HIER_FILER_ITEM::EAZY_STRING m_filename;
    public:
    HIER_FILER_ITEM::ITEM_BOX m_top;    // 一番上のアイテム・ボックス
    HIER_FILER_ITEM::ITEM_BOX *m_focus; // 現在のフォーカス・アイテム・ボックス
    char *m_magic_code;     // マジック・コード
    int m_magic_code_len;   // マジック・コード長
    int m_loaded_list_flag; // リスト読込済み

    HIER_FILER(){   // コンストラクタ
        m_magic_code =NULL;
        m_magic_code_len = 0;
        m_focus = &m_top;
        m_loaded_list_flag = 0;

        char s[10];
        s[0]=0x89; s[1]='H'; s[2]='R'; s[3]='F';
        s[4]='I'; s[5]='L'; s[6]='E'; s[7]=0x1A; s[8]=0x00;
        set_magic_code(s, 9);
    };
    void set_magic_code(char *s, int len){
        if (m_magic_code) delete[] m_magic_code;
        m_magic_code_len = len;
        m_magic_code =  new char [m_magic_code_len];
        memcpy(m_magic_code, s, len);
    };
    clear(){
        m_top.m_num_list.del_all();
        m_top.m_any_list.del_all();
        m_top.m_box_list.del_all();
        m_focus = &m_top;
    }

    // ファイル保存
    int save(char *filename);

    // ファイル読込
    int load_list(char *filename);              // リスト読込
    int load_list_inline(HIER_FILER_ITEM::EAZY_FILE *p_read_file);          // リスト読込インライン
    int load_full_inner(char *filename);        // 全ロード
    int load_data_num(char *name, int *buf);            // 数値アイテム読込
    int load_data_any(char *name, char *buf);       // 汎用アイテム・実データ読込
    int load_data_any_len(char *name, int *p_reslen); // 汎用アイテム・データ長読込

    int load_data_num(int n, int *buf);             // 数値アイテム読込(配列番号指定)
    int load_data_any(int n, char *buf);            // 汎用アイテム・実データ読込(配列番号指定)
    int load_data_any_len(int n, int *p_reslen);    // 汎用アイテム・データ長読込(配列番号指定)

    int load_data_num_inner(char *name);                // 数値アイテム読込(内部)
    int load_data_any_inner(char *name);                // 汎用アイテム読込(内部)
    int load_data_num_inner(int n);             // 数値アイテム読込(内部)(配列番号指定)
    int load_data_any_inner(int n);             // 汎用アイテム読込(内部)(配列番号指定)

    // アイテム読込テンプレート
    template <class T> int load_data_one(T *buf, HIER_FILER_ITEM::BASE_ITEM<T>* pitem);

    // アイテムデータ長読込テンプレート
    template <class T> int load_data_one_len(int *p_reslen, HIER_FILER_ITEM::BASE_ITEM<T>* pitem);

    // ファイル全読込後のデータ取得(…保存時も取得可能)
    int get_data_num(char *name);       // 数値アイテム取得
    char *get_data_any(char *name);     // 汎用アイテム・実データポインタ取得
    int get_data_any_len(char *name);   // 汎用アイテム・データ長取得

    int get_data_num(int n);        // 数値アイテム取得(配列番号指定)
    char *get_data_any(int n);      // 汎用アイテム・実データポインタ取得(配列番号指定)
    int get_data_any_len(int n);    // 汎用アイテム・データ長取得(配列番号指定)

    // フォーカス・ボックス
    int focus(char *path);  // フォーカス・アイテムボックスの移動(文字引数) 
    int focus_up();        // 上位アイテムボックスへの移動
    int focus_down(int n);  // 下位アイテムボックスへの移動
    void focus_top(){ m_focus = &m_top; }   // 一番上のアイテム・ボックスへ

    int get_focus_num();    // フォーカス・ボックスが親から見て何番目の子か

    // アイテム情報取得
    char* get_item_name_num(int n); // アイテム名取得(数値)
    char* get_item_name_any(int n); // アイテム名取得(汎用)
    char* get_item_name_box(int n); // アイテム名取得(ボックス)
    char* get_focus_name(); // フォーカスボックス名取得

    int get_list_size_num(){ return m_focus->m_num_list.size(); } // アイテム数取得(数値) 
    int get_list_size_any(){ return m_focus->m_any_list.size(); } // アイテム数取得(汎用)
    int get_list_size_box(){ return m_focus->m_box_list.size(); } // アイテム数取得(ボックス)

    // パスから目的ボックス取得
    HIER_FILER_ITEM::ITEM_BOX *get_aim_box_by_path(char *path, int last_valid_flag, int add_mode=0);

    inline HIER_FILER_ITEM::NUM_ITEM* get_num_ptr_inline(char *name);   // 数値アイテムポインタ取得
    inline HIER_FILER_ITEM::ANY_ITEM* get_any_ptr_inline(char *name);   // 汎用アイテムポインタ取得

    // アイテム追加
    void add_item_num  (char *name, int val);   // アイテム追加(数値)
    void add_item_num_p(char *name, int *p);    // アイテム追加(数値 ポインタ指定)
    void add_item_any  (char *name, char *buf, int len);    // アイテム追加(汎用)
    void add_item_any_p(char *name, char *buf, int len);    // 汎用アイテム追加(ポインタ指定)
    void add_item_box(char *name);      // 子アイテムボックス追加

    // アイテム削除
    void del_item_num(char *name);  // アイテム削除(数値)
    void del_item_num(int n);       // アイテム削除(数値 配列番号指定)
    void del_item_any(char *name);  // アイテム削除(汎用)
    void del_item_any(int n);       // アイテム削除(汎用 配列番号指定)
    void del_item_box(char *name);  // 子アイテムボックス削除 
    void del_item_box(int n);       // 子アイテムボックス削除(配列番号指定)

};
// -------- アイテムポインタ取得 -------------------------------
// 数値アイテムポインタ取得
HIER_FILER_ITEM::NUM_ITEM* HIER_FILER::get_num_ptr_inline(char *name){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0);
    char *p=HIER_FILER_ITEM::get_last_name(name);
    if (!tmp_box) return NULL;
    int n = tmp_box->get_item_order_num(p);
    return tmp_box->m_num_list[n];
}
// 汎用アイテムポインタ取得
HIER_FILER_ITEM::ANY_ITEM* HIER_FILER::get_any_ptr_inline(char *name){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0);
    char *p=HIER_FILER_ITEM::get_last_name(name);
    if (!tmp_box) return NULL;
    int n = tmp_box->get_item_order_any(p);
    return tmp_box->m_any_list[n];
}
// パスから目的ボックス取得
HIER_FILER_ITEM::ITEM_BOX *
HIER_FILER::get_aim_box_by_path(char *path, int last_valid_flag, int add_mode){
    if (!path) return NULL;
    int slen, box_num, cmplen;
    char *sub_name = path;
    HIER_FILER_ITEM::ITEM_BOX* p_box = m_focus;
    while(1){
        slen = HIER_FILER_ITEM::get_first_path_len(sub_name);
        if (!last_valid_flag && slen<=0) break;
        cmplen = (slen<0)? strlen(sub_name) : slen;
        if (!strncmp(sub_name, "..", cmplen)) {
            box_num = 0;
            if (!p_box->m_parent) return NULL;
            p_box = p_box->m_parent;
        }
        else {
            box_num = p_box->get_item_order_box(sub_name, cmplen);
            if (box_num>=0) p_box = p_box->m_box_list[box_num];
        }
        if (box_num<0) {
            if (!add_mode) return NULL;
            p_box->add_item_box(sub_name, slen);
            p_box = p_box->m_box_list.last();
        }
        if (slen<=0) break;
        sub_name += slen+1;
    }
    return p_box;
}
// -------- リスト読込・全読込 --------------------------------------
// リスト読込
int HIER_FILER::load_list(char *filename){
    clear();
    HIER_FILER_ITEM::EAZY_FILE read_file;
    if (read_file.read_open(filename)<0) return -1;

    int res = load_list_inline(&read_file);
    m_filename.copy(filename);
    return res;
};
// フル読込
int HIER_FILER::load_full_inner(char *filename){
    clear();
    HIER_FILER_ITEM::EAZY_FILE read_file;
    if (read_file.read_open(filename)<0) return -1;

    int res = load_list_inline(&read_file);
    if (res>=0) m_top.load_buf_inner(&read_file);
    m_filename.copy(filename);
    return res;
};
// リスト読込インライン
int HIER_FILER::load_list_inline(HIER_FILER_ITEM::EAZY_FILE *p_read_file){
    char *tmp_magic_code=new char [m_magic_code_len];
    if (m_magic_code_len>(p_read_file->read(tmp_magic_code, m_magic_code_len))) {
        delete[] tmp_magic_code;
        return -1;
    }
    int res = memcmp(m_magic_code, tmp_magic_code, m_magic_code_len);
    delete[] tmp_magic_code;
    if (res) return -1;

    m_top.load_list(p_read_file);
    m_loaded_list_flag=1;
    return 0;
}
// -------- アイテム読込 --------------------------------------

// アイテム読込テンプレート
template <class T>
int HIER_FILER::load_data_one(T *buf, HIER_FILER_ITEM::BASE_ITEM<T>* pitem){
    if (!m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::EAZY_FILE read_file;
    if (read_file.read_open(m_filename.m_buf)<0) return -1;

    if (!pitem) return -1;
    return pitem->read_buf(&read_file, buf);
};
// アイテムデータ長読込テンプレート
template <class T>
int HIER_FILER::load_data_one_len(int *p_reslen, HIER_FILER_ITEM::BASE_ITEM<T>* pitem){
    if (!m_loaded_list_flag || !p_reslen || !pitem) return -1;
    *p_reslen = pitem->m_data_len;
    return 0;
};

// 数値アイテム読込
int HIER_FILER::load_data_num(char *name, int *buf){
    return load_data_one<int>(buf, get_num_ptr_inline(name));
};
// 数値アイテム読込(配列番号指定)
int HIER_FILER::load_data_num(int n, int *buf){
    return load_data_one<int>(buf, m_focus->m_num_list[n]);
}
// 汎用アイテム・実データ読込
int HIER_FILER::load_data_any(char *name, char *buf){
    return load_data_one<char>(buf, get_any_ptr_inline(name));
};
// 汎用アイテム・データ長読込
int HIER_FILER::load_data_any_len(char *name, int *p_reslen){
    return load_data_one_len<char>(p_reslen, get_any_ptr_inline(name));
};
// 汎用アイテム・実データ読込(配列番号指定)
int HIER_FILER::load_data_any(int n, char *buf){
    return load_data_one<char>(buf, m_focus->m_any_list[n]);
}
// 汎用アイテム・データ長読込(配列番号指定)
int HIER_FILER::load_data_any_len(int n, int *p_reslen){
    return load_data_one_len<char>(p_reslen, m_focus->m_any_list[n]);
}

// アイテム読込(内部変数に読み込みます)
int HIER_FILER::load_data_num_inner(int n){ return load_data_num(n, NULL); }// 数値アイテム(配列番号指定)
int HIER_FILER::load_data_any_inner(int n){ return load_data_any(n, NULL); }// 汎用アイテム・実データ(配列番号指定)
int HIER_FILER::load_data_num_inner(char *name){ return load_data_num(name, NULL); };// 数値アイテム(名前指定)
int HIER_FILER::load_data_any_inner(char *name){ return load_data_any(name, NULL); };// 汎用アイテム・実データ(名前指定)

// -------- 保存 --------------------------------------
// セーブ
int HIER_FILER::save(char *filename){
    HIER_FILER_ITEM::EAZY_FILE write_file;
    if (write_file.write_open(filename)<0) return -1;

    write_file.write(m_magic_code, m_magic_code_len);
    int header_size = m_top.get_save_header_size() + write_file.tell();
    m_top.save_list(&write_file, &header_size);
    m_top.save_buf(&write_file);
    return 0;
};

// -------- フォーカス --------------------------------------
// フォーカス・ボックスが親から見て何番目の子か
int HIER_FILER::get_focus_num(){
    if (!m_focus->m_parent) return -1;  // 最上位ボックス
    HIER_FILER_ITEM::ITEM_BOX *tmp_parent = m_focus->m_parent;
    for(int i=0;i<tmp_parent->m_box_list.size();i++) if (tmp_parent->m_box_list[i]==m_focus) return i;
    return -1;  // エラー
}
// フォーカス・アイテムボックスの移動(文字引数)
int HIER_FILER::focus(char *path){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(path, 1);
    if (!tmp_box) return -1;
    m_focus = tmp_box;
    return 0;
};
// 上位アイテムボックスへの移動
int HIER_FILER::focus_up(){
    if (!m_focus->m_parent) return -1;
    m_focus = m_focus->m_parent;
    return 0;
}
// 下位アイテムボックスへの移動
int HIER_FILER::focus_down(int n){
    if (!m_focus->m_box_list[n]) return -1;
    m_focus = m_focus->m_box_list[n];
    return 0;
}

// -------- 内部アイテムデータ取得 --------------------------------------
// 数値アイテム
int HIER_FILER::get_data_num(char *name){
    HIER_FILER_ITEM::NUM_ITEM* pitem = get_num_ptr_inline(name);
    return (pitem)? *(pitem->m_data) : 0;
};
// 数値アイテム
int HIER_FILER::get_data_num(int n){
    if (!m_focus->m_num_list[n]) return 0;
    return *(m_focus->m_num_list[n]->m_data);
};
// 汎用アイテム
char *HIER_FILER::get_data_any(int n){
    if (!m_focus->m_any_list[n]) return NULL;
    return m_focus->m_any_list[n]->m_data;
};
// 汎用アイテムデータ長
int HIER_FILER::get_data_any_len(int n){
    if (!m_focus->m_any_list[n]) return 0;
    return m_focus->m_any_list[n]->m_data_len;
};
// 汎用アイテム・実データ取得
char *HIER_FILER::get_data_any(char *name){
    HIER_FILER_ITEM::ANY_ITEM* pitem = get_any_ptr_inline(name);
    return (pitem)? pitem->m_data : NULL;
}
// 汎用アイテム・データ長取得
int HIER_FILER::get_data_any_len(char *name){
    HIER_FILER_ITEM::ANY_ITEM* pitem = get_any_ptr_inline(name);
    return (pitem)? pitem->m_data_len : -1;
};

// アイテム名取得(数値)
char* HIER_FILER::get_item_name_num(int n){
    return (m_focus->m_num_list[n])? m_focus->m_num_list[n]->m_name.m_buf : NULL;
}
// アイテム名取得(汎用)
char* HIER_FILER::get_item_name_any(int n){
    return (m_focus->m_any_list[n])? m_focus->m_any_list[n]->m_name.m_buf : NULL;
}
// アイテム名取得(ボックス)
char* HIER_FILER::get_item_name_box(int n){
    return (m_focus->m_box_list[n])? m_focus->m_box_list[n]->m_name.m_buf : NULL;
};
// フォーカスボックス名取得
char* HIER_FILER::get_focus_name(){
    return m_focus->m_name.m_buf;
};

// -------- アイテム追加 --------------------------------------
// 数値 追加
void HIER_FILER::add_item_num(char *name, int val){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0, 1);
    if (!tmp_box) return;
    char *p=HIER_FILER_ITEM::get_last_name(name);
    tmp_box->add_item_num(p, val);
};
// 数値 追加(ポインタ指定)
void HIER_FILER::add_item_num_p(char *name, int *pval){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0, 1);
    if (!tmp_box) return;
    char *p=HIER_FILER_ITEM::get_last_name(name);
    tmp_box->add_item_num_p(p, pval);
};
// アイテム追加(汎用)
void HIER_FILER::add_item_any(char *name, char *buf, int len){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0, 1);
    if (!tmp_box) return;
    char *p=HIER_FILER_ITEM::get_last_name(name);
    tmp_box->add_item_any(p, buf, len);
};
// アイテム追加(汎用)(ポインタ指定)
void HIER_FILER::add_item_any_p(char *name, char *buf, int len){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0, 1);
    if (!tmp_box) return;
    char *p=HIER_FILER_ITEM::get_last_name(name);
    tmp_box->add_item_any_p(p, buf, len);
};
// 子ボックス追加
void HIER_FILER::add_item_box(char *name){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0, 1);
    if (!tmp_box) return;
    char *p=HIER_FILER_ITEM::get_last_name(name);
    tmp_box->add_item_box(p);
};
// -------- アイテム削除 --------------------------------------
// アイテム削除
void HIER_FILER::del_item_num(int n){ m_focus->del_item_num(n); }   // 数値 削除(配列番号指定)
void HIER_FILER::del_item_any(int n){ m_focus->del_item_any(n); }   // 汎用 削除(配列番号指定)
void HIER_FILER::del_item_box(int n){ m_focus->del_item_box(n); };  // 子ボックス削除(配列番号指定)

// 数値 削除
void HIER_FILER::del_item_num(char *name){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0);
    if (!tmp_box) return;
    char *p=HIER_FILER_ITEM::get_last_name(name);
    int n = tmp_box->get_item_order_num(p);
    if (n>=0) tmp_box->del_item_num(n);
};
// アイテム削除(汎用)
void HIER_FILER::del_item_any(char *name){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0);
    if (!tmp_box) return;
    char *p=HIER_FILER_ITEM::get_last_name(name);
    int n = tmp_box->get_item_order_any(name);
    if (n>=0) tmp_box->del_item_any(n);
};
// 子ボックス削除
void HIER_FILER::del_item_box(char *name){
    HIER_FILER_ITEM::ITEM_BOX* tmp_box= get_aim_box_by_path(name, 0);
    if (!tmp_box) return;
    char *p=HIER_FILER_ITEM::get_last_name(name);
    int n = tmp_box->get_item_order_box(p);
    if (n>=0) tmp_box->del_item_box(n);
};

#endif  // _HIER_FILER_H_










以下サンプルcppファイルです。

サンプル1ではファイルリスト読込→各データ読込

サンプル2では全データを内部に読込→各データを内部より取得しています




サンプル1

サンプル1
hier_filer_01_1.cpp


#include "hier_filer_01.h"

main(){
    int res;
    HIER_FILER hier_ser;    // 宣言
    hier_ser.add_item_num("abc", 20);   // abc という名前の数値データ「20」を追加している
    hier_ser.add_item_num("def", 1024); // def という名前の数値データ「1024」を追加している
    hier_ser.add_item_any("ggg", "あいう\0", 7);    // ggg という名前の汎用データ「"あいう\0" 7バイト」を追加している
    hier_ser.add_item_any("hijklmn", "かき\0", 5);  // hijklmn という名前の汎用データ「"かき\0" 5バイト」を追加している
    hier_ser.add_item_any("ポット", "お湯\0", 5);   // ポット という名前の汎用データ「"お湯\0" 5バイト」を追加している
    // 汎用データは完全バイナリなデータを想定しているので文字列の場合'\0'を末尾につけてやる必要があります。

    hier_ser.add_item_box("NFL");   // NFLという名前のアイテムボックスを作る

    // アイテムボックス「NFL」の中に「カンザスシティ」という名前の汎用データ「"チーフス\0" 9バイト」を追加する
    // ロードするときは"NFL/カンザスシティ"という名前を呼ぶと"チーフス"というデータが得られる
    hier_ser.add_item_any("NFL/カンザスシティ", "チーフス\0", 9);

    // アイテムボックス「NFL」の中に「カンザスシティ」という名前のボックスを追加しながらダンテホール
    // という名前の数値データ82を追加する
    // (同名アイテムは、アイテムの種類が違えばOKな仕様です)
    hier_ser.add_item_num("NFL/カンザスシティ/ダンテホール", 82);

    hier_ser.save("aaa");   // 上記でhier_serに追加されたアイテムを"aaa"というファイル名で一括保存する
    printf("セーブしました\n");
    printf("\n\n");



    // "aaa"というファイルからファイルリストを読み込む(実データは読み込まない)
    res = hier_ser.load_list("aaa");
    if (res<0) return 0;    // エラー
    printf("ファイルリストを読み込みました\n");
    int num1, num2;

    // ファイルリストを読み込んだだけの状態はまた個別に実データを読み込む必要があります
    char s[20];
    res = hier_ser.load_data_num(0, &num1); // m_focus ボックスの 0番目の数値アイテムを num1 に読み出している
    if (res<0) return 0;    // エラー

    res = hier_ser.load_data_num("def", &num2); // m_focus ボックスの def という名前の数値データを num2 に読み出している
    if (res<0) return 0;    // エラー
    printf("0番目の数値アイテム : %d\ndef : %d\n", num1, num2);

    res = hier_ser.load_data_any("ggg", s); // m_focus ボックスの ggg という名前の汎用データを s に読み出している
    res = hier_ser.load_data_any_len("ggg", &num1); //     〃   のデータ長を num1 に読み出している
    if (res<0) return 0;    // エラー
    printf("ggg : %s   …データ長 %d\n", s, num1);


        // NFL/カンザスシティ という名前の汎用データを s に読み出している
        // (NFLという子ボックス下のカンザスシティという名前の汎用データ)
    res = hier_ser.load_data_any("NFL/カンザスシティ", s);
    res = hier_ser.load_data_any_len("NFL/カンザスシティ", &num1);  //   〃   のデータ長を num1 に読み出している
    if (res<0) return 0;    // エラー
    printf("NFL/カンザスシティ : %s  …データ長 %d\n", s, num1);

    hier_ser.focus("NFL");
    printf("m_focus ボックスを 「NFL」に移動\n");
    res = hier_ser.load_data_any("カンザスシティ", s);
    printf("カンザスシティ : %s\n", s);
    printf("\n");

    printf("m_focus ボックスの数値アイテム数 : %d\n", hier_ser.get_list_size_num());
    printf("m_focus ボックスの汎用アイテム数 : %d\n", hier_ser.get_list_size_any());
    printf("m_focus ボックスの子ボックス数   : %d\n", hier_ser.get_list_size_box());
    printf("\n\n");
}




サンプル2

サンプル2
hier_filer_01_2.cpp


#include "hier_filer_01.h"

main(){
    int res;
    HIER_FILER hier_ser;    // 宣言
    hier_ser.add_item_num("abc", 20);   // abc という名前の数値データ「20」を追加している
    hier_ser.add_item_num("def", 1024); // def という名前の数値データ「1024」を追加している
    hier_ser.add_item_any("ggg", "あいう\0", 7);    // ggg という名前の汎用データ「"あいう\0" 7バイト」を追加している
    hier_ser.add_item_any("hijklmn", "かき\0", 5);  // hijklmn という名前の汎用データ「"かき\0" 5バイト」を追加している
    hier_ser.add_item_any("ポット", "お湯\0", 5);   // ポット という名前の汎用データ「"お湯\0" 5バイト」を追加している
    // 汎用データは完全バイナリなデータを想定しているので文字列の場合'\0'を末尾につけてやる必要があります。

    hier_ser.add_item_box("NFL");   // NFLという名前のアイテムボックスを作る

    // アイテムボックス「NFL」の中に「ミネソタ」という名前の汎用データ「"バイキングス\0" 13バイト」を追加する
    // ロードするときは"NFL/ミネソタ"という名前を呼ぶと"バイキングス"というデータが得られる
    hier_ser.add_item_any("NFL/ミネソタ", "バイキングス\0", 13);

    hier_ser.save("aaa");   // 上記でhier_serに追加されたアイテムを"aaa"というファイル名で一括保存する
    printf("セーブしました\n");
    printf("\n\n");



    // "aaa"というファイルからファイルリストを含め全データを読み込む
    res = hier_ser.load_full_inner("aaa");
    if (res<0) return 0;    // エラー
    printf("全データを読み込みました\n\n");

    // load_full_inner 関数は内部にデータを読み込んでしまうので
    // アプリケーション側はそれらを呼び出すことで値を取得出来ます
    printf("abc : %d\n", hier_ser.get_data_num("abc"));
    printf("1番目の数値アイテム : %d\n", hier_ser.get_data_num(1));
    printf("0番目の汎用アイテム : %s\n", hier_ser.get_data_any(0));
    printf("1番目の汎用アイテム : %s\n", hier_ser.get_data_any(1));
    printf("NFL/ミネソタ : %s\n", hier_ser.get_data_any("NFL/ミネソタ"));
    printf("\n");

    res = hier_ser.focus_down(0);
    if (res<0) return 0;    // エラー
    printf("focus_down(0); …m_focus ボックスを 0番目の子ボックスに移動\n");
    printf("0番目の汎用アイテム名 : %s\n", hier_ser.get_item_name_any(0));
    printf("0番目の汎用アイテム   : %s\n", hier_ser.get_data_any(0));
    printf("\n");

    printf("m_focus ボックスの数値アイテム数   : %d\n", hier_ser.get_list_size_num());
    printf("m_focus ボックスの汎用アイテム数   : %d\n", hier_ser.get_list_size_any());
    printf("m_focus ボックスの子ボックス数   : %d\n", hier_ser.get_list_size_box());
    printf("\n");
}




 005-01  前へ←  ホームへ  →次へ  006-02