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