006-01  前へ←  ホームへ  →次へ  006-03

No.006 - 02  簡易アーカイバ(複数ファイルの合成)


いくつかのファイルをまとめて、ひとつのファイルに入れます。


・アーカイバ
【archiver】
アーカイバ【archiver】 複数のファイルを一つのファイルにまとめたり、
逆に、まとめたファイルから元のファイルを取り出したりするプログラム。

アーカイバと言えば最近は解凍・圧縮ソフトの総称みたいに捉えられることもある言葉のようですが、
今回は本来のファイル連結が目的なので圧縮解凍はしません。


・ファイル連結
前回の階層シリアライズを拡張してファイル連結も行えるようにします。
ファイルアイテム・クラスを作り、数値アイテムや汎用アイテムと並列に位置させます。
あとは階層シリアライズと同じです。


・ファイルアイテム・クラス
ファイル情報を格納するクラスですが、いくつか考えなければならない仕様があります。

まず保存時ですが、
ファイル内のデータを全部保存してしまうかどうかのフラグです。
下記ソースではそれぞれに読込オフセット、データ長のメンバ変数をつくっています。
さらに「データ長」といっても毎回ファイルサイズをいちいち調べるのも大変なのでファイル終端まで保存するかどうかのフラグも作ります。

次にファイルのパスをセーブするかどうかです。
アプリケーションを作成するにあたって、自分のPCのディレクトリ構造を内部にいれるのは危ないと思いつつも
再編集することを考えればパスがないと一からやりなおしになってしまって大変です。
相対パスで保存することも考えましたが全部実行ファイルに対しての相対パス?というのも考え物なので、
結局、下記ソースではメンバ変数にフラグをつけて各アイテム毎にパス保存のする・しないを設定しています。

次に読込時ですが、一斉読込時に実データまでメモリを確保して読み込むかどうかです。
ファイルアイテムの場合、データサイズの大きなものもあったりするので、
あんまり大きなメモリまで確保するのはいかがな仕様かということです。
下記ソースではフラグ・メンバ変数をつくってそれぞれにメモリ上に展開するかしないかを設定し、
一斉読込時にこのフラグがfalse なら実データは読み込まないようにしています。



・2Gバイト以上は扱えません
サンプルソースは見てのとおりデータ長から、ファイルサイズ、ファイルオフセット値までみんなint型です。
当然2Gバイト以上は扱えません。

アーカイブファイルなのに2Gまでしか扱えないなんて!と思う方もいるでしょう。筆者も思います。
ですが2G以上を扱うには単に 32bit → 64bit にすりゃあいいってもんじゃありません。
それなりの対応が問われるのです。

まず大きなバイトサイズ単位の操作なら一定時間毎にOSにきちんと制御を返すようにします。
プログレスバーも表示するようにします。
書込み時は、残りディスクスペースを調べてから書き込むようにします。
FAT32システム では 2G以上のファイルを扱えないので、ファイル分割などの処理が必要です。
読込時、通常ギガバイトのメモリはないのでそれを要求されたときの処理、さらに仮想メモリの制御等。

めんどくさっ。
筆者にはこれらを実装、デバッグする元気はありません。

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

下記ソースは前回の階層シリアライズとほとんど同じなので拡張分のみの解説です。


FILE_ITEM

EAZY_STRING m_filename ファイルパスです。

int m_data_offset ファイル読込開始位置です。
char m_save_path_flag ファイルパスを保存するかどうかのフラグです。
char m_load_mode フル読込時に実データを読み込むかどうかのフラグです。
char m_all_contain_flag データ長を無視してファイル終端まで保存するかどうかのフラグです。

DWORD get_file_size() ファイルサイズを取得します。

int archive_to_other() ファイルアイテム・の中身を別のファイルに単独保存します。


HIER_FILER

void add_item_file();
ファイルアイテム追加関数です。

int load_data_file() ファイルアイテム・実データを読込ます。
int load_data_file_start() ファイルアイテム・元の読込開始位置を取得します
int load_data_file_len() ファイルアイテム・データ長を読込ます。
int load_data_filename() ファイルアイテム・ファイル名を読込ます
int load_data_filename_len() ファイルアイテム・ファイル名長を読込ます
int load_data_file_flags() ファイルアイテム・フラグを取得します
これらのload_data_file〜系の関数は引数で指定したバッファに実データを読み込みます。
名前指定のものと配列番号指定の2種類あります。

int load_data_file_output() ファイルアイテム・の中身を別のファイルに単独保存します。
名前指定のものと配列番号指定の2種類あります。

char *get_data_file_filename() ファイルアイテム・ファイル名(内部メモリ)へのポインタを取得します。
int get_data_file_filename_len()  ファイルアイテム・ファイル名長を取得します。
int get_data_file_start() ファイルアイテム・元の読込開始位置を取得します。
int get_data_file_len() ファイルアイテム・データ長を取得します。
int get_data_file_flags() ファイルアイテム・フラグを取得します。
名前指定のものと配列番号指定の2種類あります。

enum { ID_SAVE_PATH=1, ID_ALL_CONTAIN=2, ID_LOAD_MODE=4 };
ファイルアイテムフラグのIDです。
ID_SAVE_PATH ファイルパスを保存するかどうかのフラグです。
ID_ALL_CONTAIN データ長を無視してファイル終端まで保存するかどうかのフラグです。
ID_LOAD_MODE フル読込時に実データを読み込むかどうかのフラグです。



hier_filer_02.h



#ifndef _HIER_FILER_H_
#define _HIER_FILER_H_

#include <stdio>
#include <stdlib>
#include <string>
#include <windows>
#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;
}
// ファイルサイズの取得
DWORD get_file_size(char *filename){
    HANDLE hfile;
    hfile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
                OPEN_EXISTING, 0, NULL);
    if (hfile==INVALID_HANDLE_VALUE ) return -1;
    DWORD dw = GetFileSize(hfile, NULL);
    CloseHandle(hfile);
    return dw;
}

// =========汎用 簡易ファイル入出力データ===================
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; m_arc_offset=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 FILE_ITEM : public BASE_ITEM<char> {
    public:
    EAZY_STRING m_filename; // ファイル名

    int m_data_offset;
    char m_save_path_flag;
    char m_load_mode;
    char m_all_contain_flag;
    FILE_ITEM(){ m_data_len=0; m_save_path_flag=0; m_load_mode=0; m_all_contain_flag=0; }
    void set_data(char *filenme, int start, int len, char save_path_flag, char load_mode);  // データ設定
    DWORD get_file_size();

    int archive_to_other(char *archive_filename, char *output_filename);
};
// ファイルアイテム・ファイルサイズの取得
DWORD FILE_ITEM::get_file_size(){
    return HIER_FILER_ITEM::get_file_size(m_filename.m_buf);
};

// ファイルアイテム・データの設定
void FILE_ITEM::set_data(char *filenme, int start, int len, char save_path_flag=0, char load_mode=0){
    m_filename.copy(filenme);
    m_data_offset = start;
    m_data_len = len;
    m_all_contain_flag = (len<0)? 1:0;
    m_save_path_flag = save_path_flag;
    m_load_mode = load_mode;
}
// アーカイブファイル→単独ファイルに取り出し保存
int FILE_ITEM::archive_to_other(char *archive_filename, char *output_filename){
    enum { TMP_BUF_SIZE = 1024 };
    char tmp[TMP_BUF_SIZE];
    EAZY_FILE archive_file, output_file;
    if (archive_file.read_open(archive_filename)<0) return -1;
    if (archive_file.seek(m_arc_offset)<0) return -1;
    if (output_file.write_open(output_filename)<0) return -1;

    int res, len = m_data_len, aim_read_byte;
    while(len>0){
        aim_read_byte = (len<TMP_BUF_SIZE)? len : TMP_BUF_SIZE;
        res = archive_file.read(tmp, aim_read_byte);
        if (res>=0) output_file.write(tmp, res);
        if (res<aim_read_byte) break;
        len -= res;
    }
    return 0;
};

// =========アイテム・ボックス===================
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<FILE_ITEM> m_file_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_file(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_file(char *name, char *filenme, int start, int len, char save_path_flag, char load_mode); // ファイルアイテム追加
    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_file(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_file_list.a_push();

    for(i=0;i<m_file_list.size();i++){
        p_read_file->read(&num, sizeof(int));
        m_file_list[i]->m_name.read(p_read_file, num);  // データ名
        p_read_file->read(&m_file_list[i]->m_save_path_flag, sizeof(char)); // セーブパスフラグ
        if (m_file_list[i]->m_save_path_flag){
            p_read_file->read(&num, sizeof(int));
            m_file_list[i]->m_filename.read(p_read_file, num);  // ファイル名
        }
        p_read_file->read(&m_file_list[i]->m_data_offset, sizeof(int)); // データ自体のオフセット
        p_read_file->read(&m_file_list[i]->m_data_len, sizeof(int));    // データ長 
        p_read_file->read(&m_file_list[i]->m_all_contain_flag, sizeof(char));   // ファイル中身全部フラグ
        p_read_file->read(&m_file_list[i]->m_load_mode, sizeof(char));  // ロードモード
        p_read_file->read(&m_file_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_file_list.size();i++) {
        if (m_file_list[i]->m_load_mode) m_file_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)*4;  // m_num_list + m_any_list + m_file_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_file_list.size();i++){
        total += sizeof(int);   // データ名長
        ps = m_file_list[i]->m_name.m_buf;
        total += strlen(ps);    // データ名分
        total += sizeof(char);  // セーブパスフラグ分
        if (m_file_list[i]->m_save_path_flag){
            total += sizeof(int);   // ファイル名長分
            ps = m_file_list[i]->m_filename.m_buf;
            total += strlen(ps);    // ファイル名分
        }
        total += sizeof(int);   // データ自体のオフセット
        total += sizeof(char);  // ファイル中身全部フラグ
        total += sizeof(char);  // ロードモード分
        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)); // オフセット位置 情報分
        m_num_list[i]->m_arc_offset = *p_offset;
        (*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)); // オフセット位置 情報分
        m_any_list[i]->m_arc_offset = *p_offset;
        (*p_offset) += num;
    }
    // ファイルアイテム
    num = m_file_list.size(); p_write_file->write(&num, sizeof(int));
    for(i=0;i<m_file_list.size();i++){
        ps = m_file_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(&m_file_list[i]->m_save_path_flag, sizeof(char)); // セーブパスフラグ
        if (m_file_list[i]->m_save_path_flag){
            ps = m_file_list[i]->m_filename.m_buf;
            num = strlen(ps); 
            p_write_file->write(&num, sizeof(int)); // ファイル名長
            p_write_file->write(ps, num); // ファイル名
        }
        num = m_file_list[i]->m_data_offset;
        p_write_file->write(&num, sizeof(int));     // データ自体のオフセット
        if (m_file_list[i]->m_all_contain_flag) m_file_list[i]->m_data_len = m_file_list[i]->get_file_size();
        num = m_file_list[i]->m_data_len;
        p_write_file->write(&num, sizeof(int));     // データ長

        p_write_file->write(&m_file_list[i]->m_all_contain_flag, sizeof(char)); // ファイル中身全部フラグ
        p_write_file->write(&m_file_list[i]->m_load_mode, sizeof(char));    // ロードモード分
        p_write_file->write(p_offset, sizeof(int)); // オフセット位置 情報分
        m_file_list[i]->m_arc_offset = *p_offset;
        (*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;
    int len;
    char c;
    EAZY_FILE m_item_file;
    // 数値アイテム
    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 {
            c = 0;
            for(ai=0;ai<m_any_list[i]->m_data_len;ai++) p_write_file->write(&c, 1);
        }
    }
    // ファイルアイテム
    for(i=0;i<m_file_list.size();i++){
        if (m_item_file.read_open(m_file_list[i]->m_filename.m_buf)<0){
            c = 0;
            for(ai=0;ai<m_file_list[i]->m_data_len;ai++) p_write_file->write(&c, 1);
        }
        else {
            len = m_file_list[i]->m_data_len;
            for(ai=0;(len<0 || ai<len);ai++) {
                if (m_item_file.read(&c, 1)<1) break;
                p_write_file->write(&c, 1);
            }
            c = 0;
            if (len<0) m_file_list[i]->m_data_len = ai;
            num = m_file_list[i]->m_data_len - ai;
            for(ai=0;ai<num;ai++) p_write_file->write(&c, 1);
        }
        m_item_file.close();
    }
    // 子ボックス
    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_file(char *name){
    for(int i=0;i<m_file_list.size();i++) if (!strcmp(m_file_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_file(char *name, char *filenme, int start, int len, char save_path_flag, char load_mode){
    int n = get_item_order_file(name);
    HIER_FILER_ITEM::FILE_ITEM *pitem = (!m_file_list[n])? m_file_list.a_push() : m_file_list[n];
    pitem->set_name(name);
    pitem->set_data(filenme, start, len, save_path_flag, load_mode);
};
// 子ボックス追加
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_file(int n){ m_file_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_file_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_file(char *name, char *buf);  // ファイルアイテム・実データ読込(名前指定)
    int load_data_file_start(char *name, int *p_reslen);    // ファイルアイテム・元の読込開始位置取得
    int load_data_file_len(char *name, int *p_reslen);  // ファイルアイテム・データ長読込(名前指定)
    int load_data_filename(char *name, char *buf);  // ファイルアイテム・ファイル名読込(名前指定)
    int load_data_filename_len(char *name, int *p_reslen);  // ファイルアイテム・ファイル名長読込(名前指定)
    int load_data_file_flags(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_file(int n, char *buf);   // ファイルアイテム・実データ読込(配列番号指定)
    int load_data_file_start(int n, int *p_reslen); // ファイルアイテム・元の読込開始位置取得(配列番号指定)
    int load_data_file_len(int n, int *p_reslen);   // ファイルアイテム・データ長読込(配列番号指定)
    int load_data_filename(int n, char *buf);   // ファイルアイテム・ファイル名読込(配列番号指定)
    int load_data_filename_len(int n, int *p_reslen);   // ファイルアイテム・ファイル名長読込(配列番号指定)
    int load_data_file_flags(int n, int *p_reslen); // ファイルアイテム・フラグ取得(配列番号指定)


    int load_data_file_output(char *name, char *putout_name);   // ファイルアイテム・単独ファイル出力
    int load_data_file_output(int n, char *putout_name);        // ファイルアイテム・単独ファイル出力(配列番号指定)


    int load_data_num_inner(char *name);        // 数値アイテム読込(内部)
    int load_data_any_inner(char *name);        // 汎用アイテム読込(内部)
    int load_data_file_inner(char *name);       // ファイルアイテム読込(内部)

    int load_data_num_inner(int n);             // 数値アイテム読込(内部)(配列番号指定)
    int load_data_any_inner(int n);             // 汎用アイテム読込(内部)(配列番号指定)
    int load_data_file_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_file_lepto_member(HIER_FILER_ITEM::FILE_ITEM* pitem, int *buf);


    enum { ID_SAVE_PATH=1, ID_ALL_CONTAIN=2, ID_LOAD_MODE=4 };

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

    char *get_data_file_filename(char *name);   // ファイルアイテム・ファイル名取得
    int get_data_file_filename_len(char *name); // ファイルアイテム・ファイル名長取得
    int get_data_file_start(char *name);    // ファイルアイテム・元の読込開始位置取得
    int get_data_file_len(char *name);  // ファイルアイテム・データ長取得
    int get_data_file_flags(char *name);    // ファイルアイテム・フラグ取得


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

    char *get_data_file_filename(int n);    // ファイルアイテム・ファイル名取得
    int get_data_file_filename_len(int n);  // ファイルアイテム・ファイル名長取得
    int get_data_file_start(int n); // ファイルアイテム・元の読込開始位置取得
    int get_data_file_len(int n);   // ファイルアイテム・データ長取得
    int get_data_file_flags(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();    // フォーカス・ボックスが親から見て何番目の子か
    int get_child_num(HIER_FILER_ITEM::ITEM_BOX *p_box);    // 引数ボックスが親から見て何番目の子か

    // アイテム情報取得
    char* get_item_name_num(int n); // アイテム名取得(数値)
    char* get_item_name_any(int n); // アイテム名取得(汎用)
    char* get_item_name_file(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_file(){ return m_focus->m_file_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);   // 汎用アイテムポインタ取得
    inline HIER_FILER_ITEM::FILE_ITEM* get_file_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_file(char *name, char *filenme, int start=0, int len=-1, char save_path_flag=0, char load_mode=0);
    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_file(char *name); // アイテム削除(ファイル)
    void del_item_file(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::FILE_ITEM* HIER_FILER::get_file_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_file(p);
    return tmp_box->m_file_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::get_file_lepto_member(HIER_FILER_ITEM::FILE_ITEM* pitem, int *buf){
    if (!pitem || !buf) return -1;
    *buf=0;
    *buf |= (pitem->m_save_path_flag)? ID_SAVE_PATH : 0;
    *buf |= (pitem->m_all_contain_flag)? ID_ALL_CONTAIN : 0;
    *buf |= (pitem->m_load_mode)? ID_LOAD_MODE : 0;
    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_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_file(char *name, char *buf){
    return load_data_one<char>(buf, get_file_ptr_inline(name));
};
// ファイルアイテム・データ長読込(名前指定)
int HIER_FILER::load_data_file_len(char *name, int *p_reslen){
    return load_data_one_len<char>(p_reslen, get_file_ptr_inline(name));
};
// ファイルアイテム・元の読込開始位置取得
int HIER_FILER::load_data_file_start(char *name, int *p_reslen){
    if (!p_reslen || !m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::FILE_ITEM* pitem = get_file_ptr_inline(name);
    if (!pitem) return -1;
    *p_reslen = pitem->m_data_offset;
    return 0;
};
// ファイルアイテム・ファイル名読込(名前指定)
int HIER_FILER::load_data_filename(char *name, char *buf){
    if (!buf || !m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::FILE_ITEM* pitem = get_file_ptr_inline(name);
    if (!pitem) return -1;
    strcpy(buf, pitem->m_filename.m_buf);
    return 0;
};
// ファイルアイテム・ファイル名長読込(名前指定)
int HIER_FILER::load_data_filename_len(char *name, int *p_reslen){
    if (!p_reslen || !m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::FILE_ITEM* pitem = get_file_ptr_inline(name);
    char *ps = (pitem)? pitem->m_filename.m_buf : NULL;
    if (!ps) return -1;
    *p_reslen = strlen(ps);
    return 0;
};
// ファイルアイテム・フラグ取得(名前指定)
int HIER_FILER::load_data_file_flags(char *name, int *p_reslen){
    if (!p_reslen || !m_loaded_list_flag) return -1;
    if (get_file_lepto_member(get_file_ptr_inline(name), p_reslen)<0) return -1;
    return 0;
};


// 数値アイテム読込(配列番号指定)
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(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_file(int n, char *buf){
    return load_data_one<char>(buf, m_focus->m_file_list[n]);
}
// ファイルアイテム・データ長読込(配列番号指定)
int HIER_FILER::load_data_file_len(int n, int *p_reslen){
    return load_data_one_len<char>(p_reslen, m_focus->m_file_list[n]);
};
// ファイルアイテム・元の読込開始位置取得(配列番号指定)
int HIER_FILER::load_data_file_start(int n, int *p_reslen){
    if (!p_reslen || !m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::FILE_ITEM* pitem = m_focus->m_file_list[n];
    if (!pitem) return -1;
    *p_reslen = pitem->m_data_offset;
    return 0;
};
// ファイルアイテム・ファイル名読込(配列番号指定)
int HIER_FILER::load_data_filename(int n, char *buf){
    if (!buf || !m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::FILE_ITEM* pitem = m_focus->m_file_list[n];
    if (!pitem) return -1;
    strcpy(buf, pitem->m_filename.m_buf);
    return 0;
};
// ファイルアイテム・ファイル名長読込(配列番号指定)
int HIER_FILER::load_data_filename_len(int n, int *p_reslen){
    if (!p_reslen || !m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::FILE_ITEM* pitem = m_focus->m_file_list[n];
    char *ps = (pitem)? pitem->m_filename.m_buf : NULL;
    if (!ps) return -1;
    *p_reslen = strlen(ps);
    return 0;
};
// ファイルアイテム・フラグ取得(配列番号指定)
int HIER_FILER::load_data_file_flags(int n, int *p_reslen){
    if (!p_reslen || !m_loaded_list_flag) return -1;
    if (get_file_lepto_member(m_focus->m_file_list[n], p_reslen)<0) return -1;
    return 0;
};

// アイテム読込(内部変数に読み込みます)
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_file_inner(int n){ return load_data_file(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::load_data_file_inner(char *name){ return load_data_file(name, NULL); }  // ファイルアイテム読込(内部)

// -------- ファイルアイテム読出保存 --------------------------------------

// ファイルアイテム・単独ファイル出力
int HIER_FILER::load_data_file_output(char *name, char *putout_name){
    if (!m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::FILE_ITEM* pitem = get_file_ptr_inline(name);
    if (!pitem) return -1;

    // アーカイブファイル→単独ファイルに取り出し保存
    return pitem->archive_to_other(m_filename.m_buf, putout_name);
};

// ファイルアイテム・単独ファイル出力(配列番号指定)
int HIER_FILER::load_data_file_output(int n, char *putout_name){
    if (!m_loaded_list_flag) return -1;
    HIER_FILER_ITEM::FILE_ITEM* pitem = m_focus->m_file_list[n];
    if (!pitem) return -1;

    // アーカイブファイル→単独ファイルに取り出し保存
    return pitem->archive_to_other(m_filename.m_buf, putout_name);
};
// -------- 保存 --------------------------------------
// セーブ
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::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_focus_num(){
    return get_child_num(m_focus);
}
// 引数ボックスが親から見て何番目の子か
int HIER_FILER::get_child_num(HIER_FILER_ITEM::ITEM_BOX *p_box){
    if (!p_box->m_parent) return -1;    // 最上位ボックス
    HIER_FILER_ITEM::ITEM_BOX *tmp_parent = p_box->m_parent;
    for(int i=0;i<tmp_parent->m_box_list.size();i++) if (tmp_parent->m_box_list[i]==p_box) return i;
    return -1;  // エラー
}
// -------- 内部アイテムデータ取得 --------------------------------------
// 数値アイテム
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_file_filename(int n){
    if (!m_focus->m_file_list[n]) return 0;
    return m_focus->m_file_list[n]->m_filename.m_buf;
};
// ファイルアイテム・ファイル名取得
int HIER_FILER::get_data_file_filename_len(int n){
    char *ps = get_data_file_filename(n);
    return (ps)? strlen(ps) : -1;
};
// ファイルアイテム・元の読込開始位置取得
int   HIER_FILER::get_data_file_start(int n){
    if (!m_focus->m_file_list[n]) return 0;
    return m_focus->m_file_list[n]->m_data_offset;
};
// ファイルアイテム・データ長取得
int   HIER_FILER::get_data_file_len(int n){
    if (!m_focus->m_file_list[n]) return 0;
    return m_focus->m_file_list[n]->m_data_len;
};
// ファイルアイテム・フラグ取得
int   HIER_FILER::get_data_file_flags(int n){
    int res;
    if (get_file_lepto_member(m_focus->m_file_list[n], &res)<0) return -1;
    return res;
};



// 数値アイテム
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;
};
// 汎用アイテム・実データ取得
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_data_file_filename(char *name){
    HIER_FILER_ITEM::FILE_ITEM* pitem = get_file_ptr_inline(name);
    return (pitem)? pitem->m_filename.m_buf : NULL;
};
// ファイルアイテム・ファイル名長取得
int HIER_FILER::get_data_file_filename_len(char *name){
    char *ps = get_data_file_filename(name);
    return (ps)? strlen(ps) : -1;
};
// ファイルアイテム・元の読込開始位置取得
int HIER_FILER::get_data_file_start(char *name){
    HIER_FILER_ITEM::FILE_ITEM* pitem = get_file_ptr_inline(name);
    return (pitem)? pitem->m_data_offset : -1;
};
// ファイルアイテム・データ長取得
int HIER_FILER::get_data_file_len(char *name){
    HIER_FILER_ITEM::FILE_ITEM* pitem = get_file_ptr_inline(name);
    return (pitem)? pitem->m_data_len : NULL;
};
// ファイルアイテム・フラグ取得
int HIER_FILER::get_data_file_flags(char *name){
    int res;
    if (get_file_lepto_member(get_file_ptr_inline(name), &res)<0) return -1;
    return res;
};


// アイテム名取得(数値)
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_file(int n){
    return (m_focus->m_file_list[n])? m_focus->m_file_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_file(char *name, char *filenme, int start, int len, char save_path_flag, char load_mode){
    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_file(p, filenme, start, len, save_path_flag, load_mode);
};
// 子ボックス追加
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_file(int n){ m_focus->del_item_file(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_file(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_file(name);
    if (n>=0) tmp_box->del_item_file(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_






サンプルです。

hier_filer_02.cpp



#include "hier_filer_02.h"

main(){
    int res;
    HIER_FILER hier_ser;    // 宣言
    hier_ser.add_item_file("CPPソース", __FILE__); // CPPソース という名前のファイルアイテムを追加している
    hier_ser.add_item_file("ヘッダファイル", "../hier_filer.h"); // ヘッダファイル という名前のファイルアイテムを追加している

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

    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_file_output(0, "bbb.txt");
    if (res<0) return 0;    // エラー
    printf("0番目のファイルアイテムを bbb.txt というファイル名で保存しました\n");
    printf("0番目のファイルアイテム : %s\n", hier_ser.get_item_name_file(0));
    printf("   〃        ファイルサイズ : %d バイト\n\n", hier_ser.get_data_file_len(0));

    res = hier_ser.load_data_file_output(1, "ccc.txt");
    if (res<0) return 0;    // エラー
    printf("1番目のファイルアイテムを ccc.txt というファイル名で保存しました\n");
    printf("「ヘッダファイル」のファイルアイテム : %s\n", hier_ser.get_data_file_filename("ヘッダファイル"));
    printf("   〃        ファイルサイズ : %d バイト\n\n", hier_ser.get_data_file_len("ヘッダファイル"));


    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_file());
    printf("m_focus ボックスの子ボックス数   : %d\n", hier_ser.get_list_size_box());
    printf("\n\n");
}





 006-01  前へ←  ホームへ  →次へ  006-03