Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

data_item.H

Go to the documentation of this file.
00001 #ifndef JOT_DATA_ITEM_H_IS_INCLUDED
00002 #define JOT_DATA_ITEM_H_IS_INCLUDED
00003 
00004 #include "std/hash.H"
00005 #include "net/stream.H"
00006 #include "net/net_types.H"
00007 
00008 #include "rtti.H"
00009 
00010 #define DECODER_ADD(X) DATA_ITEM::add_decoder(X::static_name(), new X(), 1)
00011 
00012 #define DECLARE_NETWORK_TAGS(CLASS_NAME) \
00013 TAGlist *CLASS_NAME::_##CLASS_NAME##tags = 0; \
00014 static int CLASS_NAME##st=DECODER_ADD(CLASS_NAME);
00015 
00016 class COLOR;
00017 class mlib::Wvec;
00018 class mlib::Wpt;
00019 extern Cstr_ptr  NAME_INT;
00020 extern Cstr_ptr  NAME_DOUBLE;
00021 extern Cstr_ptr  NAME_COLOR;
00022 extern Cstr_ptr  NAME_VEC3D;
00023 extern Cstr_ptr  NAME_POINT3D;
00024 extern Cstr_ptr  NAME_STR_PTR;
00025 inline STAT_STR_RET NAME(const str_ptr    &)  { return NAME_STR_PTR;}
00026 inline STAT_STR_RET NAME(const int        &)  { return NAME_INT;    }
00027 inline STAT_STR_RET NAME(const double     &)  { return NAME_DOUBLE; }
00028 inline STAT_STR_RET NAME(const mlib::Wvec &)  { return NAME_VEC3D;  }
00029 inline STAT_STR_RET NAME(const mlib::Wpt  &)  { return NAME_POINT3D;}
00030 inline STAT_STR_RET NAME(const COLOR      &)  { return NAME_COLOR;}
00031 template <class T>
00032 inline STAT_STR_RET NAME(const T &x)       { return x.class_name(); }
00033 
00034 #define CDATA_ITEM const DATA_ITEM
00035 class DATA_ITEM;
00036 
00037 /* -----------------------------------------------------------------------
00038     TAGformat's are used to print out the name of a TAG and any delimiters
00039     necessary to distinguish the boundary of the data for the TAG.
00040     In general, TAG's with multi-valued fields will have their data 
00041     wrapped in { }'s.   However, if there is no name associated with the 
00042     TAG, then it is assumed that there is only one TAG in the object being
00043     serialized, and thus no delimiters are necessary.
00044    ---------------------------------------------------------------------- */
00045 class TAGformat {
00046   protected :
00047      str_ptr     _name;
00048      int         _multi;
00049      STDdstream *_ds;
00050   public:
00051          TAGformat(STDdstream *d, Cstr_ptr &n,int m):_name(n),_multi(m),_ds(d){}
00052          TAGformat(               Cstr_ptr &n,int m):_name(n),_multi(m),_ds(0){}
00053          TAGformat() : _multi(0), _ds(0) {}
00054      void        set_stream(STDdstream *d) { _ds = d; }
00055      STDdstream &operator*()               { return *_ds; }
00056      STDdstream &read_id()                 { if (_name != NULL_STR && _multi)
00057                                                 _ds->read_open_delim();
00058                                              return *_ds; }
00059      STDdstream &read_end_id()             { if (_name != NULL_STR && _multi)
00060                                                 _ds->read_close_delim();
00061                                              return *_ds; }
00062      STDdstream &id()                      { _ds->write_newline();
00063                                              if (_name != NULL_STR) {
00064                                                 *_ds << _name; _ds->ws("\t");
00065                                                 if (_multi)
00066                                                    _ds->write_open_delim();
00067                                              }
00068                                              return *_ds; }
00069      STDdstream &end_id()                  { if (_name != NULL_STR && _multi)
00070                                                 _ds->write_close_delim();
00071                                              return *_ds; }
00072      operator    int()                     { return !_ds->eof()&&_ds->check(); }
00073      Cstr_ptr   &name()      const         { return _name; }
00074 };
00075 
00076 
00077 /* -----------------------------------------------------------------------
00078    TAGs are the base unit for formatting a piece of data.  A TAG has a 
00079    name and a method for formatting and decoding its data.
00080    ---------------------------------------------------------------------- */
00081 class TAG {
00082    public:
00083      TAG() { }
00084      virtual ~TAG() {}
00085      virtual STDdstream &format(CDATA_ITEM *me, STDdstream &d) = 0;
00086      virtual STDdstream &decode(CDATA_ITEM *me, STDdstream &d) = 0;
00087      virtual Cstr_ptr   &name() const = 0;
00088 };
00089 typedef ARRAY<TAG *> TAGlist;
00090 #define CTAGlist const TAGlist
00091 
00092 /* -----------------------------------------------------------------------
00093    TAGmeths are TAGs that serialize the tag data by calling a pair of 
00094    methods on a DATA_ITEM derived object.    The formatting method 
00095    should call the id() function before writing any data in order to
00096    write out the TAG id and any delimiters.  Then after writing out all
00097    its data, the formatting method should call the end_id() function.
00098    The reason these functions are called explicitly by the formatting 
00099    function is to allow the formatting function not to write out *any*
00100    data.   The decoding function just needs to read its data, as the
00101    TAG name and any delimiters will be handled by TAGmeth.
00102    ---------------------------------------------------------------------- */
00103 template <class T>
00104 class TAG_meth : public TAG {
00105      typedef void (T::*infunc )(TAGformat &d);
00106      typedef void (T::*outfunc)(TAGformat &d) const;
00107      TAGformat _delim;
00108      outfunc   _format;
00109      infunc    _decode;
00110   public:
00111     TAG_meth() { }
00112     TAG_meth(Cstr_ptr &field_name, outfunc format, infunc decode, int multi=0): 
00113                                         _delim(field_name, multi),
00114                                         _format(format), _decode(decode) { }
00115     virtual ~TAG_meth() {}
00116 
00117     STDdstream &format(CDATA_ITEM *me, STDdstream &d) { _delim.set_stream(&d);
00118                                        (((T *)me)->*_format)(_delim); return d;}
00119     STDdstream &decode(CDATA_ITEM *me, STDdstream &d) 
00120                                       { _delim.set_stream(&d);
00121                                        _delim.read_id();
00122                                        (((T *)me)->*_decode)(_delim);
00123                                        _delim.read_end_id();
00124                                        return d; }
00125     Cstr_ptr   &name()     const      { return _delim.name(); }
00126 };
00127 
00128 template <class T, class V>
00129 class TAG_val : public TAG {
00130    typedef V &(T::*value)();
00131    typedef bool (T::*testval)() const;
00132    TAGformat _delim;
00133    value     _value;
00134    testval   _test;
00135  public:
00136    TAG_val() { }
00137    TAG_val(Cstr_ptr &field_name, value val, testval test=0)
00138       : _delim(field_name, 0), _value(val), _test(test) { }
00139    virtual ~TAG_val() {}
00140    STDdstream &format(CDATA_ITEM *me, STDdstream &d) {
00141       bool output;
00142       // Need to use != 0 in order to work around VC++ problem
00143       if (_test == 0) output = true;
00144       else {
00145          output = (((T *)me)->*_test)();
00146       }
00147       if (output) {
00148          _delim.set_stream(&d);
00149          _delim.id() << (((T *)me)->*_value)();
00150       }
00151       return d;
00152    }
00153    STDdstream &decode(CDATA_ITEM *me, STDdstream &d)
00154       { _delim.set_stream(&d);
00155       _delim.read_id()>>(((T *)me)->*_value)();
00156       return d; }
00157    Cstr_ptr   &name()     const      { return _delim.name(); }
00158 };
00159 
00160 #if WIN32_VCPLUSPLUS_DIDNT_HAVE_PROBLEMS
00161 // If Visual C++ didn't have problems with the following, we could use them to
00162 // avoid lots of extra typing
00163 
00164 template <class T, class V>
00165 TAG *TAGval(char *str, V &(T::*value)()) { return new TAG_val<T,V>(str, value);}
00166 
00167 // multi should default to 0, but that isn't allowed in AIX CC
00168 template <class T>
00169 TAG *TAGmeth(char *str, 
00170              void (T::*ofunc)(TAGformat &) const,
00171              void (T::*ifunc)(TAGformat &), 
00172              int multi) 
00173      { return new TAG_meth<T>(str, ofunc, ifunc, multi); }
00174 #endif
00175 
00176 
00177 /* ----------------------------------------------------------- * 
00178  *   DATA_ITEM - (marshalls objects onto and off of STDdstreams)
00179  *      virtual base class for all data stored in a hash table's
00180  *   that need to be written to and read from a STDdstream.  
00181  *   DATA_ITEM subclasses must fill in methods for :
00182  *     1) decoding themselves from a STDdstream
00183  *     2) formatting themselves onto a STDdstream as :
00184  *                OBJECT_NAME { 
00185  *                    field_name   value 
00186  *                    ... 
00187  *                    field_name   value
00188  *                }
00189  *     3) providing a unique string for a class name
00190  *     4) duplicating themselves
00191  * ----------------------------------------------------------- */
00192 class DATA_ITEM {
00193    private:
00194     static HASH *_hash;
00195     static DATA_ITEM *(*_decode_unknown)(STDdstream &, Cstr_ptr &, DATA_ITEM *);
00196    protected:
00197       int          _copy;
00198       TAGlist      _DEFINERtags;
00199 
00200    public:
00201           DATA_ITEM(int copy = 0) :_copy(copy) {}
00202  virtual ~DATA_ITEM();
00203 
00204  virtual CTAGlist    &tags()                 const { return _DEFINERtags; }
00205  virtual void         add_tags()             const { }
00206  virtual STDdstream  &format(STDdstream &d)  const;
00207  virtual STDdstream  &decode(STDdstream &d);
00208  virtual void         recompute()            { }
00209 
00210      /* -------- prototype functions overloaded by subclasses -------- */
00211  virtual STAT_STR_RET class_name ()          const = 0;
00212  virtual DATA_ITEM   *dup        ()          const = 0; 
00213  static  STAT_STR_RET static_name();
00214  virtual int          is_of_type(Cstr_ptr &t)const { return IS(t); }
00215 
00216      /* -------- Class functions -------- */
00217  static  int         add_decoder(Cstr_ptr   &d, DATA_ITEM *di, int copy= -1);
00218  static  void        set_default_decoder(DATA_ITEM *(*d)(STDdstream&, Cstr_ptr&,
00219                                                          DATA_ITEM *))
00220                                                  { _decode_unknown = d; }
00221  static  DATA_ITEM  *Decode     (STDdstream &d, int DelayDecoding = 0);
00222  static  DATA_ITEM  *lookup     (Cstr_ptr   &d) { return !_hash ? 0 : 
00223                                                 (DATA_ITEM *) _hash->find(**d);}
00224      /* -------- Static debugging functions -------- */
00225  static  HASH       *di_hash    ()              { return _hash; }
00226 };
00227 
00228 inline STDdstream &operator<<(STDdstream &s, CDATA_ITEM &d)
00229          { return d.format(s); }
00230 inline STDdstream &operator>>(STDdstream &s, DATA_ITEM *&d)
00231          { d = d->Decode(s); return s; }
00232 
00233 /* ----------------------------------------------------------- * 
00234  *  TDI -  (wraps conventional objects in a DATA_ITEM format)
00235  *     is a templated DATA_ITEM that provides a DATA_ITEM wrapper
00236  *   around objects that support :
00237  *    1) the NAME() operation
00238  *    2) the << and >> operators for STDdstreams.
00239  *    3) a copy constructor
00240  * ----------------------------------------------------------- */
00241 template <class T>
00242 class TDI : public DATA_ITEM {
00243   protected:
00244         T   _x;
00245   TAGlist   _tags;
00246          void        put_val(TAGformat &d) const { d.id() << _x; d.end_id(); }
00247          void        get_val(TAGformat &d)       { *d >> _x; }
00248   public:
00249                      TDI(const T &x): _x(x)
00250      { _tags+=new TAG_meth<TDI<T> >(NULL_STR, &TDI<T>::put_val, &TDI<T>::get_val, 1);}
00251                  T   &get()                  { return _x; }
00252          const   T   &get()            const { return _x; }
00253  virtual DATA_ITEM   *dup()            const { return new TDI<T>(_x); }
00254  virtual CTAGlist    &tags()           const { return _tags; }
00255  virtual STAT_STR_RET class_name()     const { return NAME(_x); }
00256 };
00257 
00258 /* ----------------------------------------------------------- * 
00259  *  FUNC_ITEM - (optimizes dup() and class_name() for function objects)
00260  *     is a base class for function objects.  There should only
00261  *  be one instance per "function class" so the dup() operation
00262  *  is optimized.  Alternatively, since only one instance will 
00263  *  be made for any class, we can store the class name in an
00264  *  instance variable instead of making a static method.
00265  * ----------------------------------------------------------- */
00266 class FUNC_ITEM : public DATA_ITEM {
00267  public:
00268    FUNC_ITEM(Cstr_ptr &n): _name(n) { 
00269       if (!lookup(n)) 
00270          add_decoder(n,this);
00271       _tags += new TAG_meth<FUNC_ITEM>(
00272          str_ptr(), &FUNC_ITEM::put, &FUNC_ITEM::get, 1
00273          );
00274    }
00275 
00276    CTAGlist&            tags()            const { return _tags; }
00277    virtual void         put(TAGformat &)  const = 0;
00278    virtual void         get(TAGformat &)        = 0;
00279    virtual DATA_ITEM*   dup()             const { return (DATA_ITEM *) this;}
00280    virtual STAT_STR_RET class_name()      const { return _name; }
00281 
00282  protected:
00283    str_ptr _name; // class name
00284    TAGlist _tags;
00285 };
00286 
00287 #endif // JOT_DATA_ITEM_H_IS_INCLUDED
00288 
00289 // end of file data_item.H
00290 

Generated on Mon Sep 18 11:39:29 2006 for jot by  doxygen 1.4.4