00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_STREAM_H
00027 #define NL_STREAM_H
00028
00029 #include "nel/misc/types_nl.h"
00030 #include "nel/misc/ucstring.h"
00031 #include "nel/misc/class_registry.h"
00032 #include <utility>
00033 #include <string>
00034 #include <vector>
00035 #include <deque>
00036 #include <list>
00037 #include <set>
00038 #include <map>
00039
00040 namespace NLMISC
00041 {
00042
00043
00044 class IStream;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 # define NLMISC_BSWAP16(src) (src) = (((src)>>8)&0xFF) | (((src)&0xFF)<<8)
00055 # ifdef NL_OS_WINDOWS
00056 # define NLMISC_BSWAP32(src) _asm mov eax,(src) _asm bswap eax _asm mov (src),eax
00057 # else
00058 # define NLMISC_BSWAP32(src) (src) = (((src)>>24)&0xFF) | ((((src)>>16)&0xFF)<<8) | ((((src)>>8)&0xFF)<<16) | (((src)&0xFF)<<24)
00059 # endif
00060 # define NLMISC_BSWAP64(src) (src) = (((src)>>56)&0xFF) | ((((src)>>48)&0xFF)<<8) | ((((src)>>40)&0xFF)<<16) | ((((src)>>32)&0xFF)<<24) | ((((src)>>24)&0xFF)<<32) | ((((src)>>16)&0xFF)<<40) | ((((src)>>8)&0xFF)<<48) | (((src)&0xFF)<<56)
00061
00062
00070 struct EStream : public Exception
00071 {
00072 EStream() : Exception( "Stream Error" ) {}
00073
00074 EStream( const std::string& str ) : Exception( str ) {}
00075
00076 EStream( const IStream &f );
00077
00078 EStream( const IStream &f, const std::string& str );
00079
00080 virtual ~EStream() throw() {}
00081
00082
00083 std::string StreamName;
00084 };
00085
00086 struct EOlderStream : public EStream
00087 {
00088 EOlderStream() : EStream("The version in stream is older than the class" ) {}
00089 EOlderStream(const IStream &f) : EStream(f, "The version in stream is older than the class" ) {}
00090 };
00091
00092 struct ENewerStream : public EStream
00093 {
00094 ENewerStream() : EStream("The version in stream is newer than the class" ) {}
00095 ENewerStream(const IStream &f) : EStream(f, "The version in stream is newer than the class" ) {}
00096 };
00097
00098 struct EInvalidDataStream : public EStream
00099 {
00100 EInvalidDataStream() : EStream("Invalid data format" ) {}
00101 EInvalidDataStream(const IStream &f) : EStream(f, "Invalid data format" ) {}
00102 };
00103
00104 struct ESeekNotSupported : public EStream
00105 {
00106 ESeekNotSupported() : EStream("Seek fonctionnality is not supported" ) {}
00107 ESeekNotSupported(const IStream &f) : EStream(f, "Seek fonctionnality is not supported" ) {}
00108 };
00109
00110
00111 class IStreamable;
00112
00113
00172 class IStream
00173 {
00174 public:
00183 static void setVersionException(bool throwOnOlder, bool throwOnNewer);
00188 static void getVersionException(bool &throwOnOlder, bool &throwOnNewer);
00189
00190
00191 public:
00192
00198 explicit IStream(bool inputStream);
00199
00201 virtual ~IStream() {}
00202
00204 IStream( const IStream& other );
00205
00207 IStream& operator=( const IStream& other );
00208
00210 bool isReading() const;
00211
00212
00221 template<class T>
00222 void serial(T &obj) { obj.serial(*this); }
00223
00224
00229
00230 virtual void serial(uint8 &b) ;
00231 virtual void serial(sint8 &b) ;
00232 virtual void serial(uint16 &b) ;
00233 virtual void serial(sint16 &b) ;
00234 virtual void serial(uint32 &b) ;
00235 virtual void serial(sint32 &b) ;
00236 virtual void serial(uint64 &b) ;
00237 virtual void serial(sint64 &b) ;
00238 virtual void serial(float &b) ;
00239 virtual void serial(double &b) ;
00240 virtual void serial(bool &b) ;
00241 #ifndef NL_OS_CYGWIN
00242 virtual void serial(char &b) ;
00243 #endif
00244 virtual void serial(std::string &b) ;
00245 virtual void serial(ucstring &b) ;
00247
00248
00250 template<class T>
00251 void serialEnum(T &em)
00252 {
00253 sint32 i;
00254 if(isReading())
00255 {
00256 serial(i);
00257 em = (T)i;
00258 }
00259 else
00260 {
00261 i = em;
00262 serial(i);
00263 }
00264 }
00265
00266
00275
00276 uint8 serialBitField8(uint8 bf);
00278 uint16 serialBitField16(uint16 bf);
00280 uint32 serialBitField32(uint32 bf);
00282
00283
00288 template<class T0,class T1>
00289 void serial(T0 &a, T1 &b)
00290 { serial(a); serial(b);}
00291 template<class T0,class T1,class T2>
00292 void serial(T0 &a, T1 &b, T2 &c)
00293 { serial(a); serial(b); serial(c);}
00294 template<class T0,class T1,class T2,class T3>
00295 void serial(T0 &a, T1 &b, T2 &c, T3 &d)
00296 { serial(a); serial(b); serial(c); serial(d);}
00297 template<class T0,class T1,class T2,class T3,class T4>
00298 void serial(T0 &a, T1 &b, T2 &c, T3 &d, T4 &e)
00299 { serial(a); serial(b); serial(c); serial(d); serial(e);}
00300 template<class T0,class T1,class T2,class T3,class T4,class T5>
00301 void serial(T0 &a, T1 &b, T2 &c, T3 &d, T4 &e, T5 &f)
00302 { serial(a); serial(b); serial(c); serial(d); serial(e); serial(f);}
00304
00305
00311 template<class T>
00312 void serialCont(std::vector<T> &cont) {serialVector(cont);}
00313 template<class T>
00314 void serialCont(std::list<T> &cont) {serialSTLCont(cont);}
00315 template<class T>
00316 void serialCont(std::deque<T> &cont) {serialSTLCont(cont);}
00317 template<class T>
00318 void serialCont(std::set<T> &cont) {serialSTLCont(cont);}
00319 template<class T>
00320 void serialCont(std::multiset<T> &cont) {serialSTLCont(cont);}
00321 template<class K, class T>
00322 void serialCont(std::map<K, T> &cont) {serialMap(cont);}
00323 template<class K, class T>
00324 void serialCont(std::multimap<K, T> &cont) {serialMultimap(cont);}
00325
00326
00328 virtual void serialCont(std::vector<uint8> &cont) ;
00330 virtual void serialCont(std::vector<sint8> &cont) ;
00332 virtual void serialCont(std::vector<bool> &cont) ;
00333
00334
00341 template<class T>
00342 void serialContPtr(std::vector<T> &cont) {serialVectorPtr(cont);}
00343 template<class T>
00344 void serialContPtr(std::list<T> &cont) {serialSTLContPtr(cont);}
00345 template<class T>
00346 void serialContPtr(std::deque<T> &cont) {serialSTLContPtr(cont);}
00347 template<class T>
00348 void serialContPtr(std::set<T> &cont) {serialSTLContPtr(cont);}
00349 template<class T>
00350 void serialContPtr(std::multiset<T> &cont) {serialSTLContPtr(cont);}
00351
00352
00358 template<class T>
00359 void serialContPolyPtr(std::vector<T> &cont) {serialVectorPolyPtr(cont);}
00360 template<class T>
00361 void serialContPolyPtr(std::list<T> &cont) {serialSTLContPolyPtr(cont);}
00362 template<class T>
00363 void serialContPolyPtr(std::deque<T> &cont) {serialSTLContPolyPtr(cont);}
00364 template<class T>
00365 void serialContPolyPtr(std::set<T> &cont) {serialSTLContPolyPtr(cont);}
00366 template<class T>
00367 void serialContPolyPtr(std::multiset<T> &cont) {serialSTLContPolyPtr(cont);}
00368
00369
00377 template<class T>
00378 void serialPtr(T* &ptr)
00379 {
00380 uint64 node;
00381
00382
00383 xmlPushBegin ("PTR");
00384
00385 xmlSetAttrib ("id");
00386
00387 if(isReading())
00388 {
00389 serial(node);
00390
00391
00392 xmlPushEnd ();
00393
00394 if(node==0)
00395 ptr=NULL;
00396 else
00397 {
00398 ItIdMap it;
00399 it= _IdMap.find(node);
00400
00401
00402 if( it==_IdMap.end() )
00403 {
00404
00405 ptr= new T;
00406 if(ptr==NULL)
00407 throw EStream();
00408
00409
00410 _IdMap.insert( ValueIdMap(node, ptr) );
00411
00412
00413 serial(*ptr);
00414 }
00415 else
00416 ptr= static_cast<T*>(it->second);
00417 }
00418 }
00419 else
00420 {
00421 if(ptr==NULL)
00422 {
00423 node= 0;
00424 serial(node);
00425
00426
00427 xmlPushEnd ();
00428 }
00429 else
00430 {
00431 node= (uint64)(uint)ptr;
00432 serial(node);
00433
00434
00435 xmlPushEnd ();
00436
00437
00438
00439 if( _IdMap.insert( ValueIdMap(node, ptr) ).second==true )
00440 {
00441
00442 serial(*ptr);
00443 }
00444 }
00445 }
00446
00447
00448 xmlPop ();
00449 }
00450
00451
00459 template<class T>
00460 void serialPolyPtr(T* &ptr)
00461 { IStreamable *p=ptr; serialIStreamable(p); ptr= static_cast<T*>(p);}
00462
00463
00474 uint serialVersion(uint currentVersion) ;
00475
00476
00487 template<class T>
00488 void serialCheck(const T& value)
00489 {
00490
00491 xmlPush ("CHECK");
00492
00493 if (isReading())
00494 {
00495 T read;
00496 serial (read);
00497 if (read!=value)
00498 throw EInvalidDataStream(*this);
00499 }
00500 else
00501 {
00502 serial (const_cast<T&>(value));
00503 }
00504
00505
00506 xmlPop ();
00507 }
00508
00510
00517 enum TSeekOrigin { begin, current, end };
00518
00530 virtual bool seek (sint32 offset, TSeekOrigin origin) ;
00531
00532
00544 virtual sint32 getPos () ;
00545
00546
00550 virtual std::string getStreamName() const;
00551
00614 template<class T>
00615 void xmlSerial (T& value0, const char *nodeName)
00616 {
00617
00618 xmlPush (nodeName);
00619
00620
00621 serial (value0);
00622
00623
00624 xmlPop ();
00625 }
00626 template<class T>
00627 void xmlSerial (T& value0, T& value1, const char *nodeName)
00628 {
00629
00630 xmlPush (nodeName);
00631
00632
00633 serial (value0, value1);
00634
00635
00636 xmlPop ();
00637 }
00638 template<class T>
00639 void xmlSerial (T& value0, T& value1, T& value2, const char *nodeName)
00640 {
00641
00642 xmlPush (nodeName);
00643
00644
00645 serial (value0, value1, value2);
00646
00647
00648 xmlPop ();
00649 }
00650 template<class T>
00651 void xmlSerial (T& value0, T& value1, T& value2, T& value3, const char *nodeName)
00652 {
00653
00654 xmlPush (nodeName);
00655
00656
00657 serial (value0, value1, value2, value3);
00658
00659
00660 xmlPop ();
00661 }
00662
00669 bool xmlPush (const char *name)
00670 {
00671
00672 if (_XML)
00673 {
00674
00675 bool res=xmlPushBeginInternal (name);
00676 if (res)
00677
00678 xmlPushEndInternal ();
00679
00680 return res;
00681 }
00682
00683
00684 return true;
00685 }
00686
00693 bool xmlPushBegin (const char *name)
00694 {
00695
00696 if (_XML)
00697 {
00698 return xmlPushBeginInternal (name);
00699 }
00700
00701
00702 return true;
00703 }
00704
00710 bool xmlPushEnd ()
00711 {
00712
00713 if (_XML)
00714 {
00715 return xmlPushEndInternal ();
00716 }
00717
00718
00719 return true;
00720 }
00721
00727 bool xmlPop ()
00728 {
00729
00730 if (_XML)
00731 {
00732 return xmlPopInternal ();
00733 }
00734
00735
00736 return true;
00737 }
00738
00745 bool xmlSetAttrib (const char *name)
00746 {
00747
00748 if (_XML)
00749 {
00750 return xmlSetAttribInternal (name);
00751 }
00752
00753
00754 return true;
00755 }
00756
00762 bool xmlBreakLine ()
00763 {
00764
00765 if (_XML)
00766 {
00767 return xmlBreakLineInternal ();
00768 }
00769
00770
00771 return true;
00772 }
00773
00779 bool xmlComment ()
00780 {
00781
00782 if (_XML)
00783 {
00784 return xmlCommentInternal ();
00785 }
00786
00787
00788 return true;
00789 }
00790
00791 protected:
00792
00794
00798 void setXMLMode (bool on);
00799
00801 virtual bool xmlPushBeginInternal (const char *name) { return true; };
00802
00804 virtual bool xmlPushEndInternal () { return true; };
00805
00807 virtual bool xmlPopInternal () { return true; };
00808
00810 virtual bool xmlSetAttribInternal (const char *name) { return true; };
00811
00813 virtual bool xmlBreakLineInternal () { return true; };
00814
00816 virtual bool xmlCommentInternal () { return true; };
00817
00823 void resetPtrTable();
00824
00830 void setInOut(bool inputStream);
00831
00832
00833 public:
00835
00839 virtual void serialBuffer(uint8 *buf, uint len) =0;
00840 virtual void serialBit(bool &bit) =0;
00842
00845 virtual void serialBufferWithSize(uint8 *buf, uint32 len)
00846 {
00847 serial (len);
00848 serialBuffer (buf, len);
00849 }
00850
00851 private:
00852 bool _InputStream;
00853 static bool _ThrowOnOlder;
00854 static bool _ThrowOnNewer;
00855
00856
00857 std::map<uint64, void*> _IdMap;
00858 typedef std::map<uint64, void*>::iterator ItIdMap;
00859 typedef std::map<uint64, void*>::value_type ValueIdMap;
00860
00861
00862 void serialIStreamable(IStreamable* &ptr) ;
00863
00864
00865
00866 private:
00871 template<class T>
00872 void serialSTLContLen(T &cont, sint32 len)
00873 {
00874 typedef typename T::value_type __value_type;
00875 typedef typename T::iterator __iterator;
00876
00877 if(isReading())
00878 {
00879 for(sint i=0;i<len;i++)
00880 {
00881 xmlPush ("ELM");
00882
00883 __value_type v;
00884 serial(v);
00885 (void)cont.insert(cont.end(), v);
00886
00887 xmlPop ();
00888 }
00889 }
00890 else
00891 {
00892 __iterator it= cont.begin();
00893 for(sint i=0;i<len;i++, it++)
00894 {
00895 xmlPush ("ELM");
00896
00897 serial(const_cast<__value_type&>(*it));
00898
00899 xmlPop ();
00900 }
00901 }
00902 }
00903
00904
00921 template<class T>
00922 void serialSTLCont(T &cont)
00923 {
00924
00925 xmlPushBegin ("CONTAINER");
00926
00927
00928 xmlSetAttrib ("size");
00929
00930 sint32 len=0;
00931 if(isReading())
00932 {
00933 serial(len);
00934 cont.clear();
00935 }
00936 else
00937 {
00938 len= cont.size();
00939 serial(len);
00940 }
00941
00942
00943 xmlPushEnd ();
00944
00945 serialSTLContLen(cont, len);
00946
00947
00948 xmlPop ();
00949 }
00950
00951
00952 protected:
00953
00958 template<class T>
00959 void serialVector(T &cont)
00960 {
00961 typedef typename T::value_type __value_type;
00962 typedef typename T::iterator __iterator;
00963
00964
00965 xmlPushBegin ("VECTOR");
00966
00967
00968 xmlSetAttrib ("size");
00969
00970 sint32 len=0;
00971 if(isReading())
00972 {
00973 serial(len);
00974
00975
00976 xmlPushEnd ();
00977
00978
00979 contReset(cont);
00980 cont.resize (len);
00981
00982
00983 for(sint i=0;i<len;i++)
00984 {
00985 xmlPush ("ELM");
00986
00987 serial(cont[i]);
00988
00989 xmlPop ();
00990 }
00991 }
00992 else
00993 {
00994 len= cont.size();
00995 serial(len);
00996
00997
00998 xmlPushEnd ();
00999
01000
01001 __iterator it= cont.begin();
01002 for(sint i=0;i<len;i++, it++)
01003 {
01004 xmlPush ("ELM");
01005
01006 serial(const_cast<__value_type&>(*it));
01007
01008 xmlPop ();
01009 }
01010 }
01011
01012
01013 xmlPop ();
01014 }
01015
01016
01017 private:
01022 template<class T>
01023 void serialSTLContLenPtr(T &cont, sint32 len)
01024 {
01025 typedef typename T::value_type __value_type;
01026 typedef typename T::iterator __iterator;
01027
01028 if(isReading())
01029 {
01030 for(sint i=0;i<len;i++)
01031 {
01032 __value_type v;
01033 serialPtr(v);
01034 cont.insert(cont.end(), v);
01035 }
01036 }
01037 else
01038 {
01039 __iterator it= cont.begin();
01040 for(sint i=0;i<len;i++, it++)
01041 {
01042 serialPtr(const_cast<__value_type&>(*it));
01043 }
01044 }
01045 }
01046
01047
01052 template<class T>
01053 void serialSTLContPtr(T &cont)
01054 {
01055
01056 xmlPushBegin ("CONTAINER");
01057
01058
01059 xmlSetAttrib ("size");
01060
01061 sint32 len=0;
01062 if(isReading())
01063 {
01064 serial(len);
01065 cont.clear();
01066 }
01067 else
01068 {
01069 len= cont.size();
01070 serial(len);
01071 }
01072
01073
01074 xmlPushEnd ();
01075
01076 serialSTLContLenPtr(cont, len);
01077
01078
01079 xmlPop ();
01080 }
01081
01082
01087 template<class T>
01088 void serialVectorPtr(T &cont)
01089 {
01090 typedef typename T::value_type __value_type;
01091 typedef typename T::iterator __iterator;
01092
01093
01094 xmlPushBegin ("VECTOR");
01095
01096
01097 xmlSetAttrib ("size");
01098
01099 sint32 len=0;
01100 if(isReading())
01101 {
01102 serial(len);
01103
01104 contReset(cont);
01105 cont.reserve(len);
01106 }
01107 else
01108 {
01109 len= cont.size();
01110 serial(len);
01111 }
01112
01113
01114 xmlPushEnd ();
01115
01116 serialSTLContLenPtr(cont, len);
01117
01118
01119 xmlPop ();
01120 }
01121
01122
01123 private:
01128 template<class T>
01129 void serialSTLContLenPolyPtr(T &cont, sint32 len)
01130 {
01131 typedef typename T::value_type __value_type;
01132 typedef typename T::iterator __iterator;
01133
01134 if(isReading())
01135 {
01136 for(sint i=0;i<len;i++)
01137 {
01138 __value_type v=NULL;
01139 serialPolyPtr(v);
01140 cont.insert(cont.end(), v);
01141 }
01142 }
01143 else
01144 {
01145 __iterator it= cont.begin();
01146 for(sint i=0;i<len;i++, it++)
01147 {
01148 serialPolyPtr(const_cast<__value_type&>(*it));
01149 }
01150 }
01151 }
01152
01153
01158 template<class T>
01159 void serialSTLContPolyPtr(T &cont)
01160 {
01161 sint32 len=0;
01162 if(isReading())
01163 {
01164 serial(len);
01165 cont.clear();
01166 }
01167 else
01168 {
01169 len= cont.size();
01170 serial(len);
01171 }
01172
01173 serialSTLContLenPolyPtr(cont, len);
01174 }
01175
01176
01181 template<class T>
01182 void serialVectorPolyPtr(T &cont)
01183 {
01184 typedef typename T::value_type __value_type;
01185 typedef typename T::iterator __iterator;
01186
01187
01188 xmlPushBegin ("VECTOR");
01189
01190
01191 xmlSetAttrib ("size");
01192
01193 sint32 len=0;
01194 if(isReading())
01195 {
01196 serial(len);
01197
01198 contReset(cont);
01199 cont.reserve(len);
01200 }
01201 else
01202 {
01203 len= cont.size();
01204 serial(len);
01205 }
01206
01207
01208 xmlPushEnd ();
01209
01210 serialSTLContLenPolyPtr(cont, len);
01211
01212
01213 xmlPop ();
01214 }
01215
01216
01217
01218 private:
01219
01237 template<class T>
01238 void serialMultimap(T &cont)
01239 {
01240 typedef typename T::value_type __value_type;
01241 typedef typename T::key_type __key_type;
01242 typedef typename T::iterator __iterator;
01243
01244
01245 xmlPushBegin ("MULTIMAP");
01246
01247
01248 xmlSetAttrib ("size");
01249
01250 sint32 len;
01251 if(isReading())
01252 {
01253 cont.clear();
01254 serial(len);
01255
01256
01257 xmlPushEnd ();
01258
01259 for(sint i=0;i<len;i++)
01260 {
01261 __value_type v;
01262
01263 xmlPush ("KEY");
01264
01265 serial ( const_cast<__key_type&>(v.first) );
01266
01267 xmlPop ();
01268
01269
01270 xmlPush ("ELM");
01271
01272 serial (v.second);
01273
01274 xmlPop ();
01275
01276 cont.insert(cont.end(), v);
01277 }
01278 }
01279 else
01280 {
01281 len= cont.size();
01282 serial(len);
01283 __iterator it= cont.begin();
01284
01285
01286 xmlPushEnd ();
01287
01288 for(sint i=0;i<len;i++, it++)
01289 {
01290 xmlPush ("KEY");
01291
01292 serial( const_cast<__key_type&>((*it).first) );
01293
01294 xmlPop ();
01295
01296 xmlPush ("ELM");
01297
01298 serial((*it).second);
01299
01300 xmlPop ();
01301 }
01302 }
01303
01304
01305 xmlPop ();
01306 }
01307
01308
01326 template<class T>
01327 void serialMap(T &cont)
01328 {
01329 typedef typename T::value_type __value_type;
01330 typedef typename T::key_type __key_type;
01331 typedef typename T::iterator __iterator;
01332
01333
01334 xmlPushBegin ("MAP");
01335
01336
01337 xmlSetAttrib ("size");
01338
01339 sint32 len;
01340 if(isReading())
01341 {
01342 cont.clear();
01343 serial(len);
01344
01345
01346 xmlPushEnd ();
01347
01348 for(sint i=0;i<len;i++)
01349 {
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368 __key_type k;
01369
01370 xmlPush ("KEY");
01371 serial ( k );
01372 xmlPop ();
01373
01374
01375 xmlPush ("ELM");
01376 serial (cont[k]);
01377 xmlPop ();
01378 }
01379 }
01380 else
01381 {
01382 len= cont.size();
01383 serial(len);
01384 __iterator it= cont.begin();
01385
01386
01387 xmlPushEnd ();
01388
01389 for(sint i=0;i<len;i++, it++)
01390 {
01391 xmlPush ("KEY");
01392
01393 serial( const_cast<__key_type&>((*it).first) );
01394
01395 xmlPop ();
01396
01397 xmlPush ("ELM");
01398
01399 serial((*it).second);
01400
01401 xmlPop ();
01402 }
01403 }
01404
01405
01406 xmlPop ();
01407 }
01408
01409
01410 bool _XML;
01411 };
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01430 class IStreamable : public IClassable
01431 {
01432 public:
01433 virtual void serial(IStream &f) =0;
01434 };
01435
01436
01437 }
01438
01439
01440
01441 #include "nel/misc/stream_inline.h"
01442
01443
01444 #endif // NL_STREAM_H
01445
01446