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

data_item.C

Go to the documentation of this file.
00001 #include "std/config.H"
00002 #include "data_item.H"
00003 #include "mlib/points.H"
00004 #include "ctype.h"
00005 
00006 using mlib::Wpt;
00007 using mlib::Wvec;
00008 
00009 HASH *DATA_ITEM::_hash = 0;
00010 DATA_ITEM* (*DATA_ITEM::_decode_unknown)(STDdstream&, Cstr_ptr&, DATA_ITEM*) = 0;
00011 
00012 const str_ptr NAME_INT    ("int");
00013 const str_ptr NAME_DOUBLE ("double");
00014 const str_ptr NAME_VEC3D  ("vec3d");
00015 const str_ptr NAME_COLOR  ("color");
00016 const str_ptr NAME_POINT3D("point3d");
00017 const str_ptr NAME_STR_PTR("str_ptr");
00018 
00019 static int im=DATA_ITEM::add_decoder(NAME(0),     new TDI<int>(0), 1);
00020 static int dm=DATA_ITEM::add_decoder(NAME(0.0),   new TDI<double>(0), 1);
00021 static int vm=DATA_ITEM::add_decoder(NAME(Wvec()),new TDI<Wvec>(Wvec(0,1,0)), 1);
00022 static int pm=DATA_ITEM::add_decoder(NAME(Wpt()), new TDI<Wpt>(Wpt()), 1);
00023 static int sm=DATA_ITEM::add_decoder(NAME(str_ptr()),new TDI<str_ptr>(str_ptr()), 1);
00024 
00025 // for some odd reason, we can't inline this on the Suns because
00026 // it generates link errors when we create subclasses of DATA_ITEM...
00027 // the odd thing is it doesn't seem to effect subclasses of DATA_ITEM
00028 // that *are* able to define static_name inline...
00029 //
00030 STAT_STR_RET
00031 DATA_ITEM::static_name()
00032 { 
00033    RET_STAT_STR("DATA_ITEM"); 
00034 }
00035 
00036 DATA_ITEM::~DATA_ITEM() 
00037 {
00038 }
00039 
00040 int
00041 DATA_ITEM::add_decoder(
00042    Cstr_ptr   &name, 
00043    DATA_ITEM  *di,
00044    int         copy
00045    )
00046 {
00047    if (!_hash) 
00048       _hash = new HASH(128);
00049    _hash->add(**name, (void *) di);
00050    if (copy != -1)
00051       di->_copy = copy;
00052    return 1;
00053 }
00054  
00055 
00056 DATA_ITEM  *
00057 DATA_ITEM::Decode(
00058    STDdstream &d,
00059    int         DelayDecoding
00060    ) 
00061 {
00062    // read the keyword or class name
00063    str_ptr str; 
00064    d >> str;
00065 
00066    if (Config::get_var_bool("DEBUG_DATA_ITEM",false))
00067       cerr << "Decoding: " << str << endl;
00068 
00069    DATA_ITEM* di = lookup(str);
00070    if (di) {
00071       if (di->class_name() != str) {
00072          // DATA_ITEM only decodes classes
00073          // app may be able to decode objects
00074          // if app can't, then it's an error
00075          di = _decode_unknown(d, str, di);
00076          if (!di) {
00077             cerr << "DATA_ITEM::Decode - failure, class '"
00078             << di->class_name() << "' can't read '" << str << "'\n";
00079          }
00080       } else {
00081          if (di->_copy)
00082             di = di->dup();
00083          if (!DelayDecoding) 
00084             di->decode(d);
00085       }
00086    } else if (str) {
00087       if (_decode_unknown)
00088          di = _decode_unknown(d, str, 0);
00089 
00090       if (!di) {
00091          char *x = **str; char _buf[128], *buf = _buf;
00092          while (*x && isupper(*x)) 
00093             *buf++ = *x++;  
00094          *buf++ = '\0';  
00095 
00096          cerr << "DATA_ITEM::Decode - unknown object " << str <<endl;
00097 
00098       }
00099    }
00100 
00101    return di;
00102 }
00103 
00104 class COMMENT : public TAG {
00105    public:
00106       COMMENT(Cstr_ptr &name = str_ptr("//")) : _name(name) {}
00107       virtual ~COMMENT() {}
00108 
00109       STDdstream &format(CDATA_ITEM *, STDdstream &d) { return d; }
00110       STDdstream &decode(CDATA_ITEM *, STDdstream &d) {
00111          _delim.set_stream(&d);
00112          _delim.read_id();
00113          if (d.ascii()) {
00114             const int size = 1024;
00115             char name[size];
00116             d.istr()->getline(name, 1024);
00117          } else {
00118             str_ptr str;
00119             d >> str;
00120          }
00121          return d;
00122       }
00123       virtual Cstr_ptr &name() const { return _name; }
00124    protected:
00125       Cstr_ptr  _name;
00126       TAGformat _delim;
00127 };
00128 
00129 /* -----------------------------------------------------
00130     This decodes a DATA_ITEM record.  The format of all
00131   DATA_ITEMS is either:
00132       {
00133           name  value
00134           ...
00135           name  value
00136       }
00137 
00138    Or:
00139 
00140      {
00141         value
00142      }
00143    ----------------------------------------------------- */
00144 STDdstream &
00145 DATA_ITEM::decode(STDdstream &ds)
00146 {
00147    TAGformat d(&ds, class_name(), 1);
00148    static COMMENT comment;
00149    
00150    d.read_id();                                 // read the start delimiter
00151                                                      // if object only has
00152    if (tags().num() == 1 && tags()[0]->name() == "") // 1 unnamed tag, then
00153       tags()[0]->decode(this, *d);                   // just call its decoder
00154    else
00155       while (d) {                  // if stream hasn't hit an end delimiter
00156          str_ptr  tag_name;
00157          *d >> tag_name;                         // read tag name,
00158          int j;
00159          for (j = 0; j < tags().num(); j++)  // then find tag reader
00160             if (tags()[j]->name() == tag_name) { // corresponding to tag.
00161                tags()[j]->decode(this, *d);      // invoke tag reader.
00162                break;
00163             }
00164          if (j == tags().num()) {
00165             if (comment.name() == tag_name) {
00166                comment.decode(this, *d);
00167             } else { // skip over tag's data section
00168                int count = 0, finished = 0;
00169                while (!finished) {
00170                   str_ptr s;
00171                   *d >> s;
00172                   if (!count && s[0] != '{')  // tag is single-valued
00173                      break;
00174                   // skip over matching { }'s
00175                   for (int x=0; x < (int)s->len(); x++) {
00176                      if (s[x] == '{')   count++;
00177                      if (s[x] == '}') { count--; if (count == 0) finished=1; }
00178                   }
00179                }
00180                cerr << "DATA_ITEM::decode - unrecognized tag '" << tag_name
00181                     << "' while decoding class " << class_name() << endl;
00182             }
00183          }
00184       }
00185 
00186    d.read_end_id();                             // read the end delimiter
00187 
00188    recompute();                                 // update object from file data
00189 
00190    return *d;
00191 }
00192 
00193 STDdstream  &
00194 DATA_ITEM::format(STDdstream &ds) const 
00195 {
00196    TAGformat d(&ds, class_name(), 1);
00197 
00198    if (Config::get_var_bool("DEBUG_DATA_ITEM",false))
00199       cerr << "Formatting " << class_name() << endl;
00200 
00201    d.id();                          // write OBJECT_NAME start_delimiter
00202    for (int i=0; i<tags().num(); i++)
00203       tags()[i]->format(this, *d);  // write name value pair
00204    ds.write_newline();              // add carriage return
00205    d.end_id();                      // write end_delimiter
00206 
00207    return *d;            
00208 }

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