00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #ifndef _DB_FIELD_H_
00038 #define _DB_FIELD_H_
00039 
00040 #include <stdio.h>
00041 
00042 #include <vector>
00043 #include <map>
00044 #include <string>
00045 #include <sstream>
00046 #include <iostream>
00047 #include <iomanip>
00048 
00049 #include <boost/format.hpp>
00050 
00051 
00052 #include <cstring>
00053 
00054 namespace database_interface {
00055 
00056 class DBClass;
00057 
00059 
00072 class DBFieldBase
00073 {
00074  private:
00076 
00077   const DBFieldBase& operator = (const DBFieldBase &rhs);
00078  public:
00083   enum Type{TEXT, BINARY};
00084  protected:
00086   Type type_;
00088   DBClass* owner_;
00090 
00093   bool write_permission_;
00095   bool read_from_database_;
00097   bool write_to_database_;
00099   std::string name_;
00101   std::string table_name_;
00103   std::string sequence_name_;
00104 
00106  DBFieldBase(DBClass *owner, const DBFieldBase *other) : 
00107   type_(other->type_), owner_(owner),
00108     write_permission_(other->write_permission_), read_from_database_(other->read_from_database_), 
00109     write_to_database_(other->write_to_database_), 
00110     name_(other->name_), table_name_(other->table_name_) {}
00111 
00112  public:
00113  DBFieldBase(Type type, DBClass* owner, std::string name, std::string table_name, bool write_permission) : 
00114     type_(type), owner_(owner),
00115     write_permission_(write_permission), read_from_database_(true), write_to_database_(true), 
00116     name_(name), table_name_(table_name) {}
00117 
00118   Type getType() const {return type_;}
00119 
00121   virtual bool fromString(const std::string &str) = 0;
00123   virtual bool toString(std::string &str) const = 0;
00124 
00126   virtual bool fromBinary(const char* binary, size_t length) = 0;
00128 
00130   virtual bool toBinary(const char* &binary, size_t &length) const = 0;
00131 
00132   DBClass* getOwner(){return owner_;}
00133   const DBClass* getOwner() const {return owner_;}
00134 
00135   bool getReadFromDatabase() const {return read_from_database_;}
00136   void setReadFromDatabase(bool sync) {read_from_database_ = sync;}
00137 
00138   bool getWriteToDatabase() const {return write_to_database_;}
00139   void setWriteToDatabase(bool sync) {write_to_database_ = sync;}
00140 
00141   bool getWritePermission() const {return write_permission_;}
00142 
00143   void setReadWrite(bool sync) 
00144   {
00145     setReadFromDatabase(sync);
00146     setWriteToDatabase(sync);
00147   }
00148 
00149   std::string getName() const {return name_;}
00150   std::string getTableName() const {return table_name_;}
00151   std::string getSequenceName() const {return sequence_name_;}
00152 
00153   void setSequenceName(std::string seq) {sequence_name_ = seq;}
00154 };
00155 
00157 template<class V>
00158 std::istream& operator >> (std::istream &iss, std::vector<V> &vec)
00159 {
00160   char c;
00161   iss >> c;
00162   if (iss.eof()) 
00163   {
00164     iss.clear();
00165     return iss;
00166   }
00167   if (iss.fail() || c != '{') 
00168   {
00169     iss.clear(std::ios::failbit);
00170     return iss;
00171   }
00172   
00173   while(1)
00174   {
00175     V val;
00176     iss >> val;
00177     if (iss.eof() || iss.fail()) 
00178     {
00179       iss.clear(std::ios::failbit);      
00180       return iss;
00181     }
00182     vec.push_back(val);
00183     
00184     iss >> c;
00185     if (iss.eof() || iss.fail()) 
00186     {
00187       iss.clear(std::ios::failbit);      
00188       return iss;
00189     }
00190     if (c == '}') break;
00191     if (c != ',') 
00192     {
00193       iss.clear(std::ios::failbit);      
00194       return iss;
00195     }
00196   }
00197   return iss;  
00198 }
00199 
00201 template <class V>
00202 std::ostream& operator << (std::ostream &str, const std::vector<V> &vec)
00203 {
00204   str << "{";
00205   for (size_t i=0; i<vec.size(); i++)
00206   {
00207     if (i!=0) str << ",";
00208     str << vec[i];
00209     if (str.fail()) return str;
00210   }
00211   str << "}";
00212   return str;
00213 }
00214 
00215 
00216 
00217 template<typename T>
00218 struct DBStreamable
00219 {
00221   static bool streamableFromString(T &data, const std::string &str)
00222   {
00223     std::istringstream iss(str);
00224     return !(iss >> data).fail();
00225   }
00226 
00228   static bool streamableToString(const T &data, std::string &str)
00229   {
00230     std::ostringstream oss;
00231     
00232     
00233     
00234     oss << std::setprecision(30) << data;
00235     if (oss.fail()) return false;
00236     str = oss.str();
00237     return true;
00238   }
00239 };
00240 
00241 template<>
00242 struct DBStreamable<double>
00243 {
00245   static bool streamableFromString(double &data, const std::string &str)
00246   {
00247     
00248     
00249     size_t point_pos = str.find('.');
00250     std::istringstream iss(str.substr(0, point_pos == std::string::npos ? point_pos : point_pos + 6));
00251     return !(iss >> data).fail();
00252   }
00253 
00255   static bool streamableToString(double data, std::string &str)
00256   {
00257     std::ostringstream oss;
00258     
00259     
00260     
00261     oss << boost::format("%.5f") % data;
00262     if (oss.fail()) return false;
00263     str = oss.str();
00264     return true;
00265   }
00266 };
00267 
00269 
00276 template <class T>
00277 class DBFieldData : public DBFieldBase
00278 {
00279  protected:
00280   T data_;
00281 
00283 
00287  DBFieldData(DBClass *owner, const DBFieldData *other) : DBFieldBase(owner, other) 
00288     {}
00289 
00290   void copy(const DBFieldData<T> *other)
00291   {
00292     if (this->type_==DBFieldBase::TEXT)
00293     {
00294       
00295       std::string copy_str;
00296       if (!other->toString(copy_str) || !this->fromString(copy_str))
00297       {
00298         std::cerr << "ERROR: database field ASCII copy failed during copy constructor of field " 
00299                   << this->name_ 
00300                   << ". This is currently an unhandled error, and will probably have serious effects.\n";
00301       }
00302       
00303     }
00304     else if (this->type_==DBFieldBase::BINARY)
00305     {
00306       
00307       const char *copy_bin; size_t length;
00308       if (!other->toBinary(copy_bin, length) || !this->fromBinary(copy_bin, length))
00309       {
00310         std::cerr << "ERROR: database field BINARY copy failed during copy constructor of field " 
00311                   << this->name_ 
00312                   << ". This is currently an unhandled error, and will probably have serious effects.\n";
00313       }
00314     }
00315   }
00316 
00317  public:
00318   DBFieldData(Type type, DBClass* owner, std::string name, std::string table_name, bool write_permission) : 
00319     DBFieldBase(type, owner, name, table_name, write_permission){}
00320 
00321   const T& get() const {return data_;}
00322 
00323   T& get() {return data_;}
00324 
00325   const T& data() const {return data_;}
00326 
00327   T& data() {return data_;}
00328 
00329   virtual bool fromString(const std::string &str)
00330   {
00331     return DBStreamable<T>::streamableFromString(this->data_, str);
00332   }
00333 
00334   virtual bool toString(std::string &str) const
00335   {
00336     return DBStreamable<T>::streamableToString(this->data_, str);
00337   }
00338 
00339   virtual bool fromBinary(const char* , size_t ) {return false;}
00340   virtual bool toBinary(const char* &, size_t &) const {return false;}
00341 };
00342 
00344 
00347 template <class T>
00348 class DBField : public DBFieldData<T>
00349 {
00350  public:
00351   DBField(DBFieldBase::Type type, DBClass *owner, std::string name, std::string table_name, bool write_permission) : 
00352     DBFieldData<T>(type, owner, name, table_name, write_permission) {}
00353 
00354  DBField(DBClass *owner, const DBField<T> *other) : DBFieldData<T>(owner, other) 
00355  {
00356    this->copy(other);
00357  }
00358 
00359 };
00360 
00362 template <>
00363 class DBField<bool> : public DBFieldData<bool>
00364 {
00365  public:
00366   DBField(Type type, DBClass *owner, std::string name, std::string table_name, bool write_permission) : 
00367     DBFieldData<bool>(type, owner, name, table_name, write_permission) {}
00368 
00369   DBField(DBClass *owner, const DBField<bool> *other) : DBFieldData<bool>(owner, other) 
00370   {
00371     this->copy(other);
00372   }
00373 
00374   virtual bool fromString(const std::string &str) 
00375   {
00376     if (str=="true" || str=="t" || str == "True" || str == "TRUE") this->data_ = true;
00377     else if (str=="false" || str=="f" || str == "False" || str == "FALSE") this->data_ = false;
00378     else return false;
00379     return true;
00380   }
00381 
00382   virtual bool toString(std::string &str) const 
00383   {
00384     if (this->data_) str="true";
00385     else str = "false";
00386     return true;
00387   }
00388 };
00389 
00390 
00392 template <>
00393 class DBField< std::vector<char> > : public DBFieldData< std::vector<char> >
00394 {
00395  public:
00396   DBField(Type type, DBClass *owner, std::string name, std::string table_name, bool write_permission) : 
00397     DBFieldData< std::vector<char> >(type, owner, name, table_name, write_permission) {}
00398 
00399  DBField(DBClass *owner, const DBField< std::vector<char> > *other) : DBFieldData< std::vector<char> >(owner, other) 
00400       {
00401         this->copy(other);
00402       }
00403   
00404   virtual bool fromBinary(const char* binary, size_t length) 
00405   {
00406     data_.resize(length);
00407     memcpy(&(data_[0]), binary, length);
00408     return true;
00409   }
00410 
00411   virtual bool toBinary(const char* &binary, size_t &length) const 
00412   {
00413     length = data_.size();
00414     if (!data_.empty())
00415     {
00416       binary = &(data_[0]);
00417     }
00418     return true;
00419   }
00420 };
00421 
00423 template <>
00424 class DBField<std::string> : public DBFieldData<std::string>
00425 {
00426  public:
00427 
00428   DBField(Type type, DBClass *owner, std::string name, std::string table_name, bool write_permission) : 
00429     DBFieldData<std::string>(type, owner, name, table_name, write_permission) {}
00430 
00431   DBField(DBClass *owner, const DBField< std::string > *other) : DBFieldData< std::string >(owner, other) 
00432       {
00433         this->copy(other);
00434       }
00435 
00436   virtual bool fromString(const std::string &str) {data_ = str; return true;}
00437   virtual bool toString(std::string &str) const {str = data_; return true;}
00438 };
00439 
00441 template <>
00442 class DBField< std::vector<std::string> > : public DBFieldData< std::vector<std::string> >
00443 {
00444  public:
00445   DBField(Type type, DBClass *owner, std::string name, std::string table_name, bool write_permission) : 
00446     DBFieldData< std::vector<std::string> >(type, owner, name, table_name, write_permission) {}
00447 
00448  DBField(DBClass *owner, const DBField< std::vector<std::string> > *other) : 
00449     DBFieldData< std::vector<std::string> >(owner, other) 
00450       {
00451         this->copy(other);
00452       }
00453 
00454   virtual bool fromString(const std::string &str) 
00455   {
00456     if (str.empty()) return true;
00457     if (str.at(0) != '{') return false;
00458 
00459     size_t pos = 1;
00460     bool done = false;
00461     while (!done)
00462     {
00463       if (pos >= str.size()) return false;
00464       size_t new_pos = str.find(',',pos);
00465       if (new_pos == std::string::npos)
00466       {
00467         new_pos = str.find('}',pos);
00468         if (new_pos == std::string::npos) return false;
00469         done = true;
00470       }
00471       if (new_pos == pos) return false;
00472       this->data_.push_back(str.substr(pos, new_pos-pos));
00473       pos = new_pos + 1;
00474     }
00475     return true;
00476   }
00477 };
00478 
00479 } 
00480 
00481 #endif
00482