├── .gitignore ├── CMakeLists.txt ├── README.md └── src ├── testSerialization.cpp └── core └── serialization.h /.gitignore: -------------------------------------------------------------------------------- 1 | prj 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_DIR "src") 2 | 3 | include_directories ( 4 | ${SOURCE_DIR} 5 | ) 6 | 7 | set(CMAKE_CXX_FLAGS "-std=c++11") 8 | 9 | add_executable(testSerialization 10 | ${SOURCE_DIR}/testSerialization.cpp 11 | ) 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # A lite serialization solution 3 | there are several lib out there support serialization,like protobuffer,flatbuffers,capnproto. 4 | Need schema file for generating source files, which is cool between peers of different language. 5 | but that is too heavy for only local serialization. so I wrote this lite version.only support c++. 6 | If your just want to serialize & deserialize data on the same machine. I think it is a good choice. simple as it is , hack whatever u want. 7 | 8 | # Only Head file needed 9 | ```cpp 10 | src/core/serialization.h 11 | ``` 12 | that`s it!You are set to go! 13 | 14 | # support 15 | * vector 16 | * list 17 | * map 18 | * set 19 | * string 20 | * primitives(int,double,long,...) 21 | * nesting container support 22 | ```cpp 23 | Obj : implements serialize:I interface 24 | vector > 25 | vector > 26 | vector > 27 | vector 28 | vector 29 | vector 30 | ``` 31 | * endian auto conversion 32 | no need to worry about endian problem.all data is writed in little endian. 33 | 34 | 35 | use char instead bool in STL 36 | [why](http://stackoverflow.com/questions/15809157/why-is-the-size-of-stdvectorbool-16-byte) 37 | 38 | 39 | # build 40 | you can build this project by CMake. or just import **serialization.h** into your project. 41 | 42 | cmake build process: 43 | 44 | ```sh 45 | mkdir prj 46 | cd prj 47 | cmake .. 48 | ``` 49 | if it doesn`t work. set compile flags to c++11 50 | 51 | 52 | # demo 53 | check testSerialization.cpp 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/testSerialization.cpp: -------------------------------------------------------------------------------- 1 | // testSerialization.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include "core/serialization.h" 5 | #include 6 | #include 7 | #include 8 | #include "core/serialization.h" 9 | using namespace std; 10 | static const char * buffer_txt = "buffer.txt"; 11 | 12 | struct ss{ 13 | int a; 14 | int b; 15 | }; 16 | ostream& operator<< (ostream& o, ss& s) 17 | { 18 | o << s.a << " " << s.b << "\n"; 19 | return o; 20 | }; 21 | 22 | 23 | 24 | class Obj :public serialize::I 25 | { 26 | 27 | public: 28 | vector ints; 29 | vector p_objs; 30 | map string_map; 31 | int a; 32 | Obj(){} 33 | Obj(int aa) :a(aa) { 34 | ints.push_back(1); 35 | ints.push_back(2); 36 | ints.push_back(3); 37 | p_objs.push_back(new Obj()); 38 | p_objs[0]->a = 9999; 39 | 40 | string_map[1] = "hello,nesting"; 41 | string_map[2] = "hello,nesting2"; 42 | } 43 | ostream& write(ostream& s) 44 | { 45 | serialize::write(s, string_map); 46 | serialize::write(s, a); 47 | serialize::write(s, ints); 48 | serialize::write(s, p_objs); 49 | 50 | return s; 51 | } 52 | istream& read(istream& s) 53 | { 54 | serialize::read(s, string_map); 55 | serialize::read(s, a); 56 | serialize::read(s, ints); 57 | serialize::read(s, p_objs); 58 | 59 | return s; 60 | } 61 | 62 | //not complete ==,just for a demo :) 63 | bool operator==(const Obj& s) 64 | { 65 | 66 | for (int i =0;i 92 | void testVectorPrimtives(vector v) 93 | { 94 | 95 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 96 | serialize::write(file, v); 97 | file.flush(); 98 | file.close(); 99 | 100 | vector a2; 101 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 102 | serialize::read(file2, a2); 103 | for (int i=0;i passed\n"; 108 | 109 | } 110 | template 111 | void testVectorObjectsPointer(vector v) 112 | { 113 | 114 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 115 | serialize::write(file, v); 116 | file.flush(); 117 | file.close(); 118 | 119 | vector a2; 120 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 121 | serialize::read(file2, a2); 122 | for (int i=0;i v) 149 | { 150 | 151 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 152 | serialize::write(file, v); 153 | file.flush(); 154 | file.close(); 155 | 156 | map a2; 157 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 158 | serialize::read(file2, a2); 159 | for (auto& a: a2) { 160 | if(a.second) 161 | assert(*v[a.first]==*a.second); 162 | else 163 | assert(NULL==v[a.first] && NULL==a.second); 164 | } 165 | 166 | printf("map<%s, %s*> passed\n",typeid(int).name(),typeid(Obj).name()); 167 | return true; 168 | } 169 | 170 | template 171 | void testMapPrimtives(map v) 172 | { 173 | 174 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 175 | serialize::write(file, v); 176 | file.flush(); 177 | file.close(); 178 | 179 | map a2; 180 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 181 | serialize::read(file2, a2); 182 | for (auto& a: a2) { 183 | assert(v[a.first]==a.second); 184 | } 185 | printf("map<%s, %s> passed\n",typeid(K).name(),typeid(V).name()); 186 | 187 | } 188 | 189 | template 190 | void testSetPrimtives(set v) 191 | { 192 | 193 | 194 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 195 | serialize::write(file, v); 196 | file.flush(); 197 | file.close(); 198 | 199 | set a2; 200 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 201 | serialize::read(file2, a2); 202 | assert(v==a2); 203 | printf("set<%s> passed\n",typeid(K).name()); 204 | } 205 | 206 | 207 | void testVectorPointPrimtives(vector v) 208 | { 209 | 210 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 211 | serialize::write(file, v); 212 | file.flush(); 213 | file.close(); 214 | 215 | vector a2; 216 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 217 | serialize::read(file2, a2); 218 | for (int i = 0; i < a2.size(); ++i) 219 | { 220 | if(a2[i]) 221 | assert(*a2[i]==*v[i]); 222 | else 223 | assert(NULL==v[i] && NULL==a2[i]); 224 | } 225 | printf("vector<%s*> passed\n",typeid(Obj).name()); 226 | } 227 | 228 | 229 | template 230 | void testListPrimtives(list v) 231 | { 232 | 233 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 234 | serialize::write(file, v); 235 | file.flush(); 236 | file.close(); 237 | 238 | list a2; 239 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 240 | serialize::read(file2, a2); 241 | assert(v==a2); 242 | printf("list<%s> passed\n",typeid(T).name()); 243 | } 244 | 245 | template 246 | void testPointerListObjects(list v) 247 | { 248 | 249 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 250 | serialize::write(file, v); 251 | file.flush(); 252 | file.close(); 253 | 254 | list a2; 255 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 256 | serialize::read(file2, a2); 257 | 258 | printf("vector<%s*> passed\n",typeid(Obj).name()); 259 | 260 | } 261 | 262 | 263 | 264 | 265 | int main( ) 266 | { 267 | 268 | testVectorPrimtives({ false, true,false }); 269 | testVectorPrimtives({ 1,2, 3, 4 }); 270 | testVectorPrimtives({ 1.3, 2.3, 3.3, 4.3 }); 271 | testVectorPrimtives({ 1.3f, 2.3f, 3.3f, 4.3f }); 272 | testVectorPrimtives({ 'b', 'd' }); 273 | testVectorPrimtives({1111111111,222222222}); 274 | testVectorPrimtives({ 1111111111, 222222222 }); 275 | 276 | 277 | testString("hello,world"); 278 | testString("你好,世界"); 279 | 280 | { 281 | vector ints; 282 | ints.push_back(new Obj(4)); 283 | ints.push_back(new Obj(5)); 284 | ints.push_back(NULL); 285 | ints.push_back(new Obj(7)); 286 | testVectorPointPrimtives(ints); 287 | } 288 | map ms; 289 | ms[2] = new Obj(22); 290 | ms[4] = NULL; 291 | ms[3] = new Obj(33); 292 | ms[5] = NULL; 293 | ms[6] = new Obj(66); 294 | testMapObjectsPointer(ms); 295 | 296 | { 297 | map m2 = { { 1, "hello" }, { 2, "world" } }; 298 | testMapPrimtives(m2); 299 | } 300 | { 301 | map m2 = { { "ho", "hello" }, {"wd", "world" } }; 302 | testMapPrimtives(m2); 303 | } 304 | { 305 | map m2 = { { 1, 1 }, { 2, 2 } }; 306 | testMapPrimtives(m2); 307 | } 308 | 309 | { 310 | map m2 = { { 1, 1111.11 }, { 2, 1111.11 } }; 311 | testMapPrimtives(m2); 312 | } 313 | 314 | { 315 | map m2 = { { 1, 1111.11f }, { 2, 1111.11f } }; 316 | testMapPrimtives(m2); 317 | } 318 | 319 | 320 | { 321 | set sets = { 1, 2, 3, 4 }; 322 | testSetPrimtives(sets); 323 | } 324 | { 325 | set sets = { 1.111, 2, 3, }; 326 | testSetPrimtives(sets); 327 | } 328 | { 329 | set sets = { "hello","world"}; 330 | testSetPrimtives(sets); 331 | } 332 | 333 | { 334 | list lists = { 1, 2, 31, 1, 1, 0, 0, 0, 0, 1 }; 335 | testListPrimtives(lists); 336 | } 337 | { 338 | list lists = { 1, 2, 31, 1, 1, 0, 0.12321, 0, 0, 1 }; 339 | testListPrimtives(lists); 340 | } 341 | { 342 | list lists = {"hello","list" }; 343 | testListPrimtives(lists); 344 | } 345 | list ints; 346 | ints.push_back(new Obj(11)); 347 | ints.push_back(NULL); 348 | ints.push_back(new Obj(22)); 349 | ints.push_back(NULL); 350 | testPointerListObjects(ints); 351 | 352 | 353 | 354 | { 355 | vector > intss = { { { 1, new Obj(3) }, { 4, new Obj(4) } }, { { 2, new Obj(3) }, { 4, new Obj(6) } } }; 356 | testVectorObjectsPointer(intss); 357 | 358 | } 359 | 360 | { 361 | vector as; 362 | 363 | as.resize(3); 364 | as[0].string_map[1]="world"; 365 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 366 | serialize::write(file, as); 367 | file.flush(); 368 | file.close(); 369 | 370 | vector a2; 371 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 372 | serialize::read(file2, a2); 373 | assert(as[0]==a2[0]); 374 | cout<<"vector: pass\n"; 375 | 376 | } 377 | { 378 | 379 | struct AAA 380 | { 381 | public: 382 | void hello(){ 383 | printf("s"); 384 | } 385 | 386 | int a,b,c; 387 | }; 388 | 389 | AAA a={1,2,3}; 390 | ofstream file(buffer_txt, std::ios::out | std::ios::binary | std::ios::trunc); 391 | serialize::write(file, a); 392 | file.flush(); 393 | file.close(); 394 | 395 | AAA a2; 396 | ifstream file2(buffer_txt, std::ios::in | std::ios::binary); 397 | serialize::read(file2, a2); 398 | //be careful when you do this! because the memory layout is just right only if you don`t use polymorphism! So , the best practice would be: Implement serialize::I :) 399 | getchar(); 400 | } 401 | 402 | 403 | 404 | 405 | 406 | return 0; 407 | } 408 | 409 | -------------------------------------------------------------------------------- /src/core/serialization.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | // 4 | // Created by ZK on 14-7-4. 5 | // 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | 19 | 20 | class serialize 21 | { 22 | public: 23 | class I 24 | { 25 | public: 26 | 27 | virtual std::ostream& write( std::ostream& ostream_) = 0; 28 | virtual std::istream& read(std::istream& istream_) = 0; 29 | 30 | }; 31 | 32 | static inline bool LE() 33 | { 34 | 35 | const static int n = 1; 36 | const static bool le= (* (char *)&n == 1); 37 | return le; 38 | } 39 | 40 | static inline bool ReadEndian (istream &istream_) 41 | { 42 | bool littleEndian = false; 43 | istream_.read ((char*)&littleEndian, sizeof (littleEndian)); 44 | return littleEndian; 45 | } 46 | 47 | static inline void WriteEndian (ostream &ostream_) 48 | { 49 | bool littleEndian = LE(); 50 | 51 | ostream_.write ((char*)&littleEndian, sizeof (littleEndian)); 52 | } 53 | 54 | static inline istream& read_internal (istream& istream_, char* p, uint32_t size) 55 | { 56 | 57 | if (!LE()) 58 | { 59 | //read as little endian 60 | for (int i = size - 1; i >= 0; --i) 61 | { 62 | istream_.read (p+i, 1); 63 | } 64 | } 65 | else 66 | istream_.read (p, size); 67 | return istream_; 68 | } 69 | 70 | static inline ostream& write_internal (ostream& ostream_, const char* p, uint32_t size) 71 | { 72 | 73 | if (!LE()) 74 | { 75 | //if big endian .write as little endian 76 | for (int i = size-1; i>=0; --i) 77 | { 78 | ostream_.write (p + i, 1); 79 | } 80 | } 81 | else 82 | ostream_.write (p, size); 83 | return ostream_; 84 | } 85 | 86 | static inline istream& read (istream& istream_, I* t_) 87 | { 88 | return t_->read (istream_); 89 | } 90 | 91 | static inline istream& read (istream& istream_, std::string& string_) 92 | { 93 | int size = 0; 94 | read (istream_, size); 95 | string_.resize (size); 96 | read_internal (istream_, const_cast (string_.c_str()), size); 97 | return istream_; 98 | } 99 | 100 | static inline istream& read (istream& istream_, char* str) 101 | { 102 | int size = 0; 103 | read (istream_, size); 104 | read_internal (istream_, str, size); 105 | return istream_; 106 | } 107 | 108 | static inline istream& read (istream& istream_, vector&container) 109 | { 110 | if (!istream_.good() || istream_.eof())return istream_; 111 | 112 | int size; 113 | container.clear(); 114 | read (istream_, size); 115 | for (int i = 0; i < size; ++i) 116 | { 117 | bool t; 118 | read (istream_, t); 119 | container.push_back (t); 120 | } 121 | assert (istream_.good()); 122 | return istream_; 123 | } 124 | 125 | static inline ostream& write (ostream& ostream_, I* t_) 126 | { 127 | return t_->write (ostream_); 128 | } 129 | 130 | static inline ostream& write (ostream& ostream_, const std::string& string_) 131 | { 132 | uint32_t size = string_.size(); 133 | write (ostream_, size); 134 | write_internal (ostream_, string_.c_str(), string_.size()); 135 | return ostream_; 136 | } 137 | 138 | static inline ostream& write (ostream& ostream_, std::string& string_) 139 | { 140 | uint32_t size = string_.size(); 141 | write (ostream_, size); 142 | write_internal (ostream_, string_.c_str(), string_.size()); 143 | return ostream_; 144 | } 145 | 146 | static inline ostream& write (ostream& ostream_, const char* str) 147 | { 148 | uint32_t size = strlen (str); 149 | write (ostream_, size); 150 | write_internal (ostream_, str, size); 151 | return ostream_; 152 | } 153 | 154 | static inline ostream& write (ostream& ostream_, vector& container) 155 | { 156 | uint32_t size = container.size(); 157 | write (ostream_, size); 158 | 159 | for (auto ite : container) 160 | { 161 | bool c = ite; 162 | write (ostream_, c); 163 | } 164 | 165 | return ostream_; 166 | } 167 | 168 | 169 | 170 | template 171 | static inline void ZeroMem(T& t) 172 | { 173 | memset(&t, 0, sizeof (T)); 174 | } 175 | 176 | 177 | template 178 | static inline istream& read(istream& istream_, T& t_) 179 | { if(std::is_fundamental::value) 180 | { 181 | return read_internal(istream_, (char*)&t_, sizeof (t_)); 182 | }else 183 | { 184 | 185 | if(std::is_trivial::value) 186 | return read_internal(istream_, (char*)&t_, sizeof(t_)); 187 | else 188 | return read(istream_, (serialize::I*)&t_); 189 | } 190 | assert(0); 191 | return istream_; 192 | } 193 | 194 | template 195 | static inline ostream& write(ostream& ostream_, T& t_) 196 | { 197 | if(std::is_fundamental::value) 198 | { 199 | return write_internal(ostream_, (const char*)&t_, sizeof(t_)); 200 | }else 201 | { 202 | 203 | if(std::is_trivial::value) 204 | return write_internal(ostream_, (const char*)&t_, sizeof(t_)); 205 | else 206 | return write(ostream_, (serialize::I*)&t_); 207 | } 208 | 209 | 210 | } 211 | 212 | 213 | 214 | /////////////vector////////////////////////////////// 215 | template 216 | static inline ostream& write(ostream& ostream_, vector& container) 217 | { 218 | uint32_t size = container.size(); 219 | write(ostream_, size); 220 | for (auto& ite : container) 221 | { 222 | write(ostream_, ite); 223 | } 224 | return ostream_; 225 | } 226 | 227 | template 228 | static inline istream& read(istream& istream_, vector&container) 229 | { 230 | if (!istream_.good() || istream_.eof())return istream_; 231 | 232 | int size; 233 | container.clear(); 234 | read(istream_, size); 235 | for (int i = 0; i < size; ++i) 236 | { 237 | T t; 238 | read(istream_, t); 239 | container.push_back( t); 240 | } 241 | assert(istream_.good()); 242 | return istream_; 243 | } 244 | 245 | template 246 | static inline ostream& write(ostream& ostream_, vector& container) 247 | { 248 | 249 | uint32_t size = container.size(); 250 | 251 | write_internal(ostream_, (char*)&size, sizeof (uint32_t)); 252 | int index = 0; 253 | for (auto ite = container.begin(); ite != container.end(); ite++) 254 | { 255 | 256 | if ((*ite) != NULL) 257 | { 258 | bool notNULL = true; 259 | write(ostream_, notNULL); 260 | 261 | I* i = dynamic_cast(*ite); 262 | write(ostream_, i); 263 | } 264 | else 265 | { 266 | bool notNULL = false; 267 | write(ostream_, notNULL); 268 | } 269 | index++; 270 | } 271 | return ostream_; 272 | } 273 | 274 | template 275 | static inline istream& read(istream& istream_, vector& container) 276 | { 277 | if (!istream_.good() || istream_.eof())return istream_; 278 | int size; 279 | container.clear(); 280 | 281 | read(istream_, size); 282 | container.resize(size); 283 | for (int i = 0; i < size; ++i) 284 | { 285 | bool notNULL = false; 286 | read(istream_, notNULL); 287 | 288 | if (notNULL) 289 | { 290 | T* object = new T; 291 | read(istream_, dynamic_cast(object)); 292 | container[i] = object; 293 | } 294 | else 295 | { 296 | container[i] = NULL; 297 | } 298 | } 299 | return istream_; 300 | } 301 | 302 | 303 | ////////////////map///////////////////// 304 | 305 | template 306 | static inline ostream& write(ostream& ostream_, map& container) 307 | { 308 | 309 | uint32_t size = container.size(); 310 | write(ostream_, size); 311 | 312 | for (auto p : container) 313 | { 314 | write(ostream_, p.first); 315 | write(ostream_, p.second); 316 | 317 | 318 | } 319 | return ostream_; 320 | } 321 | 322 | template 323 | static inline istream& read(istream& istream_, map& container) 324 | { 325 | if (!istream_.good() || istream_.eof())return istream_; 326 | int size; 327 | container.clear(); 328 | read(istream_, size); 329 | 330 | for (int i = 0; i < size; ++i) 331 | { 332 | K key; 333 | V value; 334 | read(istream_, key); 335 | 336 | read(istream_, value); 337 | container[key] = value; 338 | 339 | } 340 | return istream_; 341 | } 342 | 343 | 344 | template 345 | static inline ostream& write(ostream& ostream_, map& container) 346 | { 347 | 348 | uint32_t size = container.size(); 349 | write(ostream_, size); 350 | int index = 0; 351 | for (auto p : container) 352 | { 353 | write(ostream_, p.first); 354 | 355 | if ((p.second) != NULL) 356 | { 357 | bool notNULL = true; 358 | write(ostream_, notNULL); 359 | I* i = dynamic_cast(p.second); 360 | write(ostream_, i); 361 | } 362 | else 363 | { 364 | bool notNULL = false; 365 | write(ostream_, notNULL); 366 | } 367 | 368 | 369 | index++; 370 | } 371 | return ostream_; 372 | } 373 | 374 | template 375 | static inline istream& read(istream& istream_, map& container) 376 | { 377 | if (!istream_.good() || istream_.eof())return istream_; 378 | int size; 379 | container.clear(); 380 | read(istream_, size); 381 | 382 | for (int i = 0; i < size; ++i) 383 | { 384 | K key; 385 | read(istream_, key); 386 | bool notNULL; 387 | read(istream_, notNULL); 388 | if (notNULL) 389 | { 390 | V* object = new V; 391 | read(istream_, dynamic_cast(object)); 392 | container[key] = (V*)object; 393 | } 394 | else 395 | { 396 | container[key] = NULL; 397 | } 398 | } 399 | return istream_; 400 | } 401 | 402 | 403 | ////////////////set///////////////////// 404 | 405 | template 406 | static inline ostream& write(ostream& ostream_, set& container) 407 | { 408 | uint32_t size = container.size(); 409 | write(ostream_, size); 410 | for (auto& ite : container) 411 | { 412 | write(ostream_, ite); 413 | } 414 | return ostream_; 415 | } 416 | 417 | template 418 | static inline istream& read(istream& istream_, set&container) 419 | { 420 | if (!istream_.good() || istream_.eof())return istream_; 421 | 422 | int size; 423 | container.clear(); 424 | read(istream_, size); 425 | for (int i = 0; i < size; ++i) 426 | { 427 | T t; 428 | read(istream_, t); 429 | container.insert(t); 430 | } 431 | assert(istream_.good()); 432 | return istream_; 433 | } 434 | 435 | template 436 | static inline ostream& write(ostream& ostream_, set& container) 437 | { 438 | 439 | uint32_t size = container.size(); 440 | write(ostream_, size); 441 | 442 | for (auto ite = container.begin(); ite != container.end(); ite++) 443 | { 444 | if ((*ite) != NULL) 445 | { 446 | bool noNULL = true; 447 | write(ostream_, noNULL); 448 | I* i = dynamic_cast(*ite); 449 | write(ostream_, i); 450 | } 451 | else 452 | { 453 | bool noNULL = false; 454 | write(ostream_, noNULL); 455 | } 456 | 457 | } 458 | return ostream_; 459 | } 460 | 461 | template 462 | static inline istream& read(istream& istream_, set& container) 463 | { 464 | if (!istream_.good() || istream_.eof())return istream_; 465 | int size; 466 | container.clear(); 467 | 468 | read(istream_, size); 469 | container.resize(size); 470 | for (int i = 0; i < size; ++i) 471 | { 472 | bool notNULL = false; 473 | read(istream_, notNULL); 474 | if (notNULL) 475 | { 476 | T* object = new T; 477 | read(istream_, dynamic_cast(object)); 478 | container.insert(object); 479 | } 480 | else 481 | { 482 | container.insert(NULL); 483 | } 484 | } 485 | return istream_; 486 | } 487 | 488 | 489 | 490 | ////////////////list///////////////////// 491 | 492 | template 493 | static inline ostream& write(ostream& ostream_, list& container) 494 | { 495 | uint32_t size = container.size(); 496 | write(ostream_, size); 497 | for (auto& ite : container) 498 | { 499 | write(ostream_, ite); 500 | } 501 | return ostream_; 502 | } 503 | 504 | template 505 | static inline istream& read(istream& istream_, list&container) 506 | { 507 | if (!istream_.good() || istream_.eof())return istream_; 508 | 509 | int size; 510 | container.clear(); 511 | read(istream_, size); 512 | for (int i = 0; i < size; ++i) 513 | { 514 | T t; 515 | read(istream_, t); 516 | container.push_back(t); 517 | } 518 | assert(istream_.good()); 519 | return istream_; 520 | } 521 | 522 | template 523 | static inline ostream& write(ostream& ostream_, list& container) 524 | { 525 | 526 | uint32_t size = container.size(); 527 | write(ostream_, size); 528 | 529 | for (auto ite = container.begin(); ite != container.end(); ite++) 530 | { 531 | if ((*ite) != NULL) 532 | { 533 | bool noNULL = true; 534 | write(ostream_, noNULL); 535 | I* i = dynamic_cast(*ite); 536 | write(ostream_, i); 537 | } 538 | else 539 | { 540 | bool noNULL = false; 541 | write(ostream_, noNULL); 542 | } 543 | 544 | } 545 | return ostream_; 546 | } 547 | 548 | 549 | 550 | template 551 | static inline istream& read(istream& istream_, list& container) 552 | { 553 | if (!istream_.good() || istream_.eof())return istream_; 554 | int size; 555 | container.clear(); 556 | 557 | read(istream_, size); 558 | 559 | for (int i = 0; i < size; ++i) 560 | { 561 | bool notNULL = false; 562 | read(istream_, notNULL); 563 | if (notNULL) 564 | { 565 | T* object = new T; 566 | read(istream_, dynamic_cast(object)); 567 | container.push_back(object); 568 | } 569 | else 570 | { 571 | container.push_back(NULL); 572 | } 573 | } 574 | return istream_; 575 | } 576 | 577 | }; 578 | --------------------------------------------------------------------------------