メインページ | ネームスペース一覧 | クラス階層 | 構成 | Directories | ファイル一覧 | ネームスペースメンバ | 構成メンバ | ファイルメンバ | 関連ページ

FITypeDesc.h

00001 #ifndef FITYPEDESC_H
00002 #define FITYPEDESC_H
00003 
00004 #include "FIIterator.h"
00005 #include <Base/BaseUtility.h>
00006 #include <WinBasis/WBUtility.h>
00007 #include <set>
00008 #include <map>
00009 #include <algorithm>
00010 
00011 /** @page FITypeDesc ドキュメントオブジェクトと型記述
00012     C++の構造体からデータを書き出す場合など,構造体やデータには,
00013     変数名や変数の型と言った情報はない.
00014     そこで,型記述型オブジェクト(FITypeDesc)を使って記述しておく.
00015 
00016     データを書き出す際には,バイナリデータから
00017     ドキュメントオブジェクトのプロパティを作る.
00018     この際,型記述を見てプロパティ名やプロパティ型を記入する.
00019 
00020     データを読み出す際には,型記述を見ながら,バイナリデータから
00021     構造体を構築する.
00022 
00023     これを実現するためのインタフェースとして,
00024     - 読み出しコンテキストの作成        FIContext* ReadContext();
00025     - 書き込みコンテキストの作成        FIContext* WriteContext();
00026     - コンテキストの開放                void ReleaseContext(FIContext*);
00027     - 次のフィールドを読み出す関数      bool Read(void* ctx, void* ptr, int sz)
00028     - 次のフィールドのデータを書き込む  void Write(void* ctx, void* ptr, int sz, FIString fn)
00029     - フィールドのグループに入る        void EnterGroup(FIString fn);
00030     - グループから抜ける.              void ExitGroup();
00031     を用意する.
00032 */
00033 
00034 namespace Spr {;
00035 
00036 /** FIVVectorの基本クラス.
00037     ベクタへのロードとセーブのサポートに必要な仮想関数を用意    */
00038 class FIVVectorBase{
00039 public:
00040     virtual size_t VItemSize() = 0;
00041     virtual size_t VSize() = 0;
00042     virtual void VResize(size_t s) = 0;
00043     virtual char* VBegin() = 0;
00044     virtual char* VEnd() = 0;
00045     virtual void VInsert(int pos, void* v) = 0;
00046     virtual void VPushBack(void* v) = 0;
00047     virtual void VPushBack() = 0;
00048     virtual void VPopBack() = 0;
00049 };
00050 /** FITypeDesc が理解できるstd::vector
00051     ベクタへのロードとセーブのサポートに必要な仮想関数が実装される.
00052     FITypeDesc は普通のvector を含むクラスはサポートしない.*/
00053 template <class T>
00054 class FIVVector: public FIVVectorBase, public std::vector<T>{
00055     virtual size_t VItemSize(){ return sizeof(T); }
00056     virtual size_t VSize(){ return size(); }
00057     virtual void VResize(size_t s){ resize(s); }
00058     virtual char* VBegin(){ return (char*)&*begin(); }
00059     virtual char* VEnd(){ return (char*) &*end(); }
00060     virtual void VInsert(int pos, void* v){ insert(begin()+pos, *(T*)v); }
00061     virtual void VPushBack(void* v){ push_back(*(T*)v); }
00062     virtual void VPushBack(){ push_back(T()); }
00063     virtual void VPopBack(){ pop_back(); }
00064 public:
00065     FIVVector(){}
00066     FIVVector(const std::vector<T>& v):std::vector<T>(v){}
00067     FIVVector& operator=(const std::vector<T>& v){ *(std::vector<T>*)this = v; return *this; }
00068 };
00069 
00070 class FIDocNodeBase;
00071 class FIDocNodePos;
00072 
00073 class FITypeDescDb;
00074 /// 型を表す
00075 class SPR_DLL FITypeDesc:public UTRefCount{
00076 public:
00077     /// レコードのフィールドを表す
00078     class SPR_DLL Field{
00079     public:
00080         Field(): length(1), lengthFieldOffset(0), lengthFieldSize(0), bReference(false), bVector(false){}
00081         ~Field();
00082         /// メンバ名
00083         UTString name;
00084         /// 型
00085         UTRef<FITypeDesc> type;
00086         /// 配列の要素数.
00087         int length;
00088         /// 要素数を別のフィールドからとる場合のフィールド名
00089         UTString lengthFieldName;
00090         /// 要素数を別のフィールドからとる場合のオフセット
00091         int lengthFieldOffset;
00092         /// 要素数を別のフィールドからとる場合サイズ
00093         int lengthFieldSize;
00094         /// vectorかどうか
00095         int bVector;
00096         /// 参照かどうか
00097         bool bReference;
00098         /// データのサイズ
00099         size_t Size();
00100         ///
00101         void Print(std::ostream& os) const;
00102         /// ノードから,構造体のフィールドを読み出す
00103         bool Read(char*& to, size_t align, FIDocNodeBase* node, FIIterator& ctx);
00104         /// ノードに構造体のフィールドを書き出す.
00105         void Write(FIDocNodeBase* node, FIIterator& ctx, const char*& from);
00106     };
00107     /// 組み立て型をあらわす場合に使う
00108     class SPR_DLL Composit: public std::vector<Field>{
00109     public:
00110         /// データのサイズを返す
00111         int Size(){ return Size(""); }
00112         /// データのサイズを返す
00113         int Size(FIString id);
00114         ///
00115         void Print(std::ostream& os) const;
00116         /// ノードから,構造体を読み出す
00117         bool Read(char*& to, size_t align, FIDocNodeBase* node, FIIterator& ctx);
00118         /// ノードに構造体を書き出す.
00119         void Write(FIDocNodeBase* node, FIIterator& ctx, const char*& from);
00120     };
00121 protected:
00122     /// 型名
00123     UTString typeName;
00124     /// データの長さ
00125     size_t size;
00126     /// 組み立て型の中身の記述.単純型の場合は,size() == 0
00127     Composit composit;
00128 
00129     friend class FITypeDescDb;
00130 public:
00131     /// 型のGUID
00132     WBGuid guid;
00133     /// コンストラクタ
00134     FITypeDesc():size(0){}
00135     /// コンストラクタ
00136     FITypeDesc(UTString tn, int sz=0): typeName(tn), size(sz){}
00137     /// 
00138     ~FITypeDesc(){}
00139     /// C++言語のクラス定義部の文字列から,その型を表すオブジェクトを構築する.
00140     bool Init(const char* clsDef, FITypeDescDb& db);
00141     ///
00142     void Print(std::ostream& os) const;
00143     /// ノードから,構造体を読み出す
00144     int Read(void* to, FIDocNodeBase* node, FIString id);
00145     int Read(void* to, FIDocNodeBase* node){ return Read(to, node, ""); }
00146     /// 属性から構造体を読み出す
00147     bool Read(char*& to, size_t align, FIDocNodeBase* node, FIIterator& ctx);
00148     /// ノードへ,構造体を書き出す
00149     int Write(FIDocNodeBase* node, const void* from);
00150     /// 属性へ,構造体を書き出す
00151     void Write(FIDocNodeBase* node, FIIterator& ctx, const char*& from, UTString id);
00152     /// 型名
00153     UTString GetTypeName() const { return typeName; }
00154     /// GUID
00155     const GUID& GetGuid() const { return guid; };
00156     /// 型のサイズ
00157     size_t Size() { return size; }
00158     /// 組み立て型の要素
00159     Composit& GetComposit(){ return composit; }
00160 };
00161 inline bool operator < (const FITypeDesc& d1, const FITypeDesc& d2){
00162     return d1.GetTypeName().compare(d2.GetTypeName()) < 0;
00163 }
00164 /// 型のデータベース
00165 class SPR_DLL FITypeDescDb: public UTRefCount{
00166 public:
00167     /// コンテナの型
00168     typedef std::set< UTRef<FITypeDesc>, UTContentsLess< UTRef<FITypeDesc> > > Db;
00169     struct ProtoDesc{
00170         FIString fileType;
00171         UTRef<FITypeDesc> desc;
00172     };
00173     typedef std::vector<ProtoDesc> ProtoDescs;
00174 protected:
00175     FIString prefix;            ///<    名前のうちプレフィックスの部分
00176     Db db;                      ///<    FITypeDesc を入れておくコンテナ
00177     static ProtoDescs protoDescs;
00178 public:
00179     /// 
00180     ~FITypeDescDb();
00181     static const ProtoDescs& GetProtoDescs(){ return protoDescs; }
00182     /** 型情報をデータベースに登録.    */
00183     void RegisterDesc(FITypeDesc* n){
00184         if (prefix.length() && n->typeName.compare(0, prefix.length(), prefix) == 0){
00185             n->typeName = n->typeName.substr(prefix.length());
00186         }
00187         db.insert(n);
00188     }
00189     /** 型情報をプロトタイプリストに登録    */
00190     void RegisterProto(FITypeDesc* n);
00191     /** REG_RECORDマクロが使用する関数.型名と構造体の定義部分の文字列
00192         から型情報を生成し,データベースに登録.    */
00193     void Register(const char* type, const char* def, bool bProto=false){
00194         UTRef<FITypeDesc> desc = new FITypeDesc(type);
00195         desc->Init(def, *this);
00196         RegisterDesc(desc);
00197         if(bProto) RegisterProto(desc);
00198     }
00199     /** 型名のPrefix を設定.
00200         型名をFindで検索する際に,検索キーにPrefixをつけたキーでも型名を検索する.  */
00201     void SetPrefix(FIString p);
00202     /** 型情報を名前から検索する.
00203         @param tn   型名.prefix は省略してよい.   */
00204     FITypeDesc* Find(UTString tn);
00205     /// DB内の型情報の表示
00206     void Print(std::ostream& os) const ;
00207 };
00208 
00209 /// FIVVectorのサイズ指定.x にはフィールド名(メンバ変数名)を指定する.
00210 #define VSIZE(x)
00211 
00212 /// 単純型を登録する.
00213 #define REG_FIELD(type) RegisterDesc( new FITypeDesc(#type, sizeof(type)) )
00214 /** ドキュメントからロード可能なクラスの定義.
00215     クラスが基本クラスを持つ場合    */
00216 #define DEF_RECORDBASE(Type, Base, Def)                 \
00217     struct Type: public Base Def;                       \
00218     static const char* classNameOf##Type = #Type;       \
00219     static const char* classDefOf##Type = #Def;         \
00220 
00221 /** ドキュメントからロード可能なクラスの定義.
00222     基本クラスが無い場合    */
00223 #define DEF_RECORD(Type, Def)                           \
00224     struct Type Def;                                    \
00225     static const char* classNameOf##Type = #Type;       \
00226     static const char* classDefOf##Type = #Def;         \
00227 
00228 /** DER_RECORD で定義した型を登録する.*/
00229 #define REG_RECORD(Type)    \
00230     Register(classNameOf##Type, classDefOf##Type)
00231 
00232 /** DER_RECORD で定義した型をプロトタイプとしても登録する.*/
00233 #define REG_RECORD_PROTO(Type)  \
00234     Register(classNameOf##Type, classDefOf##Type, true)
00235 
00236 /** @page TypeDesc 型説明クラス
00237 C++の構造体宣言を文字列として受け取り,型を解析する.
00238 使い方:ヘッダファイルで,定義
00239 DEF_RECORD( Test, {
00240     int x;
00241     char y;
00242 }
00243 )
00244 
00245 を書いて,クラスの定義を行い,
00246 .cppファイルの何かの関数の中で
00247     REG_RECORD(Test);
00248 を書いて登録します.
00249 */
00250 }
00251 #endif

Springheadに対してSun Apr 16 01:57:52 2006に生成されました。  doxygen 1.4.1