ucommon
ucommon/persist.h
Go to the documentation of this file.
00001 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
00002 //
00003 // This file is part of GNU uCommon C++.
00004 //
00005 // GNU uCommon C++ is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU Lesser General Public License as published
00007 // by the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // GNU uCommon C++ is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with GNU uCommon C++.  If not, see <http://www.gnu.org/licenses/>.
00017 
00023 #if defined(OLD_STDCPP) || defined(NEW_STDCPP)
00024 #if !defined(_MSC_VER) || _MSC_VER >= 1400
00025 #ifndef _UCOMMON_PERSIST_H_
00026 #define _UCOMMON_PERSIST_H_
00027 
00028 #ifndef _UCOMMON_PLATFORM_H_
00029 #include <ucommon/platform.h>
00030 #endif
00031 
00032 #include <iostream>
00033 #include <string>
00034 #include <vector>
00035 #include <deque>
00036 #include <map>
00037 
00038 namespace ucommon {
00039 
00040 // This typedef allows us to declare NewPersistObjectFunction now
00041 typedef class PersistObject* (*NewPersistObjectFunction) (void);
00042 
00043 class __EXPORT PersistException
00044 {
00045 public:
00046     PersistException(const std::string& reason);
00047     const std::string& getString() const;
00048 
00049     virtual ~PersistException() throw();
00050 
00051 protected:
00052     std::string _what;
00053 };
00054 
00063 class __EXPORT TypeManager
00064 {
00065 public:
00070     class registration
00071     {
00072     public:
00073         registration(const char* name, NewPersistObjectFunction func);
00074         virtual ~registration();
00075     private:
00076         std::string myName;
00077     };
00078 
00082     static void add(const char* name, NewPersistObjectFunction construction);
00083 
00087     static void remove(const char* name);
00088 
00094     static PersistObject* createInstanceOf(const char* name);
00095 
00096     typedef std::map<std::string,NewPersistObjectFunction> StringFunctionMap;
00097 };
00098 
00099 /*
00100  * The following defines are used to declare and define the relevant code
00101  * to allow a class to use the Persistence::Engine code.
00102  */
00103 
00104 #define DECLARE_PERSISTENCE(ClassType)                  \
00105   public:                               \
00106     friend ucommon::PersistEngine& operator>>( ucommon::PersistEngine& ar, ClassType *&ob);     \
00107     friend ucommon::PersistEngine& operator<<( ucommon::PersistEngine& ar, ClassType const &ob);    \
00108     friend ucommon::PersistObject *createNew##ClassType();                \
00109     virtual const char* getPersistenceID() const;           \
00110     static ucommon::TypeManager::Registration registrationFor##ClassType;
00111 
00112 #define IMPLEMENT_PERSISTENCE(ClassType, FullyQualifiedName)              \
00113   ucommon::PersistObject *createNew##ClassType() { return new ClassType; }              \
00114   const char* ClassType::getPersistenceID() const {return FullyQualifiedName;} \
00115   ucommon::PersistEngine& operator>>(ucommon::PersistEngine& ar, ClassType &ob)               \
00116     { ar >> (ucommon::PersistObject &) ob; return ar; }                     \
00117   ucommon::PersistEngine& operator>>(ucommon::PersistEngine& ar, ClassType *&ob)                  \
00118     { ar >> (ucommon::PersistObject *&) ob; return ar; }                    \
00119   ucommon::PersistEngine& operator<<(ucommon::PersistEngine& ar, ClassType const &ob)                 \
00120     { ar << (ucommon::PersistObject const *)&ob; return ar; }               \
00121   ucommon::TypeManager::Registration                             \
00122     ClassType::registrationFor##ClassType(FullyQualifiedName,         \
00123                           createNew##ClassType);
00124 
00125 class PersistEngine;
00126 
00146 class __EXPORT PersistObject
00147 {
00148 public:
00154     PersistObject();
00155 
00159      virtual ~PersistObject();
00160 
00164      virtual const char* getPersistenceID() const;
00165 
00171      virtual bool write(PersistEngine& archive) const;
00172 
00178      virtual bool read(PersistEngine& archive);
00179 };
00180 
00189 class __EXPORT PersistEngine
00190 {
00191 public:
00195     enum EngineMode {
00196         modeRead,
00197         modeWrite
00198     };
00199 
00205     PersistEngine(std::iostream& stream, EngineMode mode) throw(PersistException);
00206 
00207     virtual ~PersistEngine();
00208 
00209     // Write operations
00210 
00214     inline void write(const PersistObject &object) throw(PersistException)
00215         {write(&object);}
00216 
00220     void write(const PersistObject *object) throw(PersistException);
00221 
00222     // writes supported primitive types
00223   // shortcut, to make the following more readable
00224 #define CCXX_ENGINEWRITE_REF(valref) writeBinary((const uint8_t*)&valref,sizeof(valref))
00225     inline void write(int8_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00226     inline void write(uint8_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00227     inline void write(int16_t i)  throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00228     inline void write(uint16_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00229     inline void write(int32_t i)  throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00230     inline void write(uint32_t i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00231     inline void write(float i)  throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00232     inline void write(double i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00233     inline void write(bool i) throw(PersistException) { CCXX_ENGINEWRITE_REF(i); }
00234 #undef CCXX_ENGINEWRITE_REF
00235 
00236     void write(const std::string& str) throw(PersistException);
00237 
00238     // Every write operation boils down to one or more of these
00239     void writeBinary(const uint8_t* data, const uint32_t size) throw(PersistException);
00240 
00241     // Read Operations
00242 
00246     void read(PersistObject &object) throw(PersistException);
00247 
00251     void read(PersistObject *&object) throw(PersistException);
00252 
00253     // reads supported primitive types
00254   // shortcut, to make the following more readable
00255 #define CCXX_ENGINEREAD_REF(valref) readBinary((uint8_t*)&valref,sizeof(valref))
00256     inline void read(int8_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00257     inline void read(uint8_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00258     inline void read(int16_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00259     inline void read(uint16_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00260     inline void read(int32_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00261     inline void read(uint32_t& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00262     inline void read(float& i)  throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00263     inline void read(double& i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00264     inline void read(bool &i) throw(PersistException) { CCXX_ENGINEREAD_REF(i); }
00265 #undef CCXX_ENGINEREAD_REF
00266 
00267     void read(std::string& str) throw(PersistException);
00268 
00269     // Every read operation boiled down to one or more of these
00270     void readBinary(uint8_t* data, uint32_t size) throw(PersistException);
00271 
00272 private:
00277     void readObject(PersistObject* object) throw(PersistException);
00278 
00282     const std::string readClass() throw(PersistException);
00283 
00284 
00288     std::iostream& myUnderlyingStream;
00289 
00293     EngineMode myOperationalMode;
00294 
00298     typedef std::vector<PersistObject*>           ArchiveVector;
00299     typedef std::map<PersistObject const*, int32_t> ArchiveMap;
00300     typedef std::vector<std::string>                ClassVector;
00301     typedef std::map<std::string, int32_t>            ClassMap;
00302 
00303     ArchiveVector myArchiveVector;
00304     ArchiveMap myArchiveMap;
00305     ClassVector myClassVector;
00306     ClassMap myClassMap;
00307 };
00308 
00309 #define CCXX_RE(ar,ob)   ar.read(ob); return ar
00310 #define CCXX_WE(ar,ob)   ar.write(ob); return ar
00311 
00312 // Standard >> and << stream operators for PersistObject
00314 inline PersistEngine& operator >>( PersistEngine& ar, PersistObject &ob) throw(PersistException) {CCXX_RE(ar,ob);}
00316 inline PersistEngine& operator >>( PersistEngine& ar, PersistObject *&ob) throw(PersistException) {CCXX_RE(ar,ob);}
00318 inline PersistEngine& operator <<( PersistEngine& ar, PersistObject const &ob) throw(PersistException) {CCXX_WE(ar,ob);}
00320 inline PersistEngine& operator <<( PersistEngine& ar, PersistObject const *ob) throw(PersistException) {CCXX_WE(ar,ob);}
00321 
00323 inline PersistEngine& operator >>( PersistEngine& ar, int8_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00325 inline PersistEngine& operator <<( PersistEngine& ar, int8_t ob)  throw(PersistException) {CCXX_WE(ar,ob);}
00326 
00328 inline PersistEngine& operator >>( PersistEngine& ar, uint8_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00330 inline PersistEngine& operator <<( PersistEngine& ar, uint8_t ob)  throw(PersistException) {CCXX_WE(ar,ob);}
00331 
00333 inline PersistEngine& operator >>( PersistEngine& ar, int16_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00335 inline PersistEngine& operator <<( PersistEngine& ar, int16_t ob)  throw(PersistException) {CCXX_WE(ar,ob);}
00336 
00338 inline PersistEngine& operator >>( PersistEngine& ar, uint16_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00340 inline PersistEngine& operator <<( PersistEngine& ar, uint16_t ob)  throw(PersistException) {CCXX_WE(ar,ob);}
00341 
00343 inline PersistEngine& operator >>( PersistEngine& ar, int32_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00345 inline PersistEngine& operator <<( PersistEngine& ar, int32_t ob)  throw(PersistException) {CCXX_WE(ar,ob);}
00346 
00348 inline PersistEngine& operator >>( PersistEngine& ar, uint32_t& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00350 inline PersistEngine& operator <<( PersistEngine& ar, uint32_t ob)  throw(PersistException) {CCXX_WE(ar,ob);}
00351 
00353 inline PersistEngine& operator >>( PersistEngine& ar, float& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00355 inline PersistEngine& operator <<( PersistEngine& ar, float ob)  throw(PersistException) {CCXX_WE(ar,ob);}
00356 
00358 inline PersistEngine& operator >>( PersistEngine& ar, double& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00360 inline PersistEngine& operator <<( PersistEngine& ar, double ob) throw(PersistException) {CCXX_WE(ar,ob);}
00361 
00363 inline PersistEngine& operator >>( PersistEngine& ar, std::string& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00365 inline PersistEngine& operator <<( PersistEngine& ar, std::string ob) throw(PersistException) {CCXX_WE(ar,ob);}
00366 
00368 inline PersistEngine& operator >>( PersistEngine& ar, bool& ob) throw(PersistException) {CCXX_RE(ar,ob);}
00370 inline PersistEngine& operator <<( PersistEngine& ar, bool ob)  throw(PersistException) {CCXX_WE(ar,ob);}
00371 
00372 #undef CCXX_RE
00373 #undef CCXX_WE
00374 
00384 template<class T>
00385 PersistEngine& operator <<( PersistEngine& ar, typename std::vector<T> const& ob) throw(PersistException)
00386 {
00387     ar << (uint32_t)ob.size();
00388     for(unsigned int i=0; i < ob.size(); ++i)
00389         ar << ob[i];
00390     return ar;
00391 }
00392 
00398 template<class T>
00399 PersistEngine& operator >>( PersistEngine& ar, typename std::vector<T>& ob) throw(PersistException)
00400 {
00401     ob.clear();
00402     uint32_t siz;
00403     ar >> siz;
00404     ob.resize(siz);
00405     for(uint32_t i=0; i < siz; ++i)
00406         ar >> ob[i];
00407     return ar;
00408 }
00409 
00415 template<class T>
00416 PersistEngine& operator <<( PersistEngine& ar, typename std::deque<T> const& ob) throw(PersistException)
00417 {
00418     ar << (uint32_t)ob.size();
00419   for(typename std::deque<T>::const_iterator it=ob.begin(); it != ob.end(); ++it)
00420         ar << *it;
00421     return ar;
00422 }
00423 
00429 template<class T>
00430 PersistEngine& operator >>( PersistEngine& ar, typename std::deque<T>& ob) throw(PersistException)
00431 {
00432     ob.clear();
00433     uint32_t siz;
00434     ar >> siz;
00435     //ob.resize(siz);
00436     for(uint32_t i=0; i < siz; ++i) {
00437     T node;
00438     ar >> node;
00439     ob.push_back(node);
00440         //ar >> ob[i];
00441   }
00442     return ar;
00443 }
00444 
00450 template<class Key, class Value>
00451 PersistEngine& operator <<( PersistEngine& ar, typename std::map<Key,Value> const & ob) throw(PersistException)
00452 {
00453     ar << (uint32_t)ob.size();
00454     for(typename std::map<Key,Value>::const_iterator it = ob.begin();it != ob.end();++it)
00455         ar << it->first << it->second;
00456     return ar;
00457 }
00458 
00464 template<class Key, class Value>
00465 PersistEngine& operator >>( PersistEngine& ar, typename std::map<Key,Value>& ob) throw(PersistException)
00466 {
00467     ob.clear();
00468     uint32_t siz;
00469     ar >> siz;
00470     for(uint32_t i=0; i < siz; ++i) {
00471         Key a;
00472         ar >> a;
00473         ar >> ob[a];
00474     }
00475     return ar;
00476 }
00477 
00482 template<class x, class y>
00483 PersistEngine& operator <<( PersistEngine& ar, std::pair<x,y> &ob) throw(PersistException)
00484 {
00485     ar << ob.first << ob.second;
00486     return ar;
00487 }
00488 
00493 template<class x, class y>
00494 PersistEngine& operator >>(PersistEngine& ar, std::pair<x, y> &ob) throw(PersistException)
00495 {
00496     ar >> ob.first >> ob.second;
00497     return ar;
00498 }
00499 
00500 } // namespace ucommon
00501 
00502 #endif
00503 #endif
00504 #endif