00001 #ifndef VVELIB_STORAGE_STORAGE_H
00002 #define VVELIB_STORAGE_STORAGE_H
00003
00009 #include <config.h>
00010 #include <QString>
00011 #include <cstddef>
00012 #include <string>
00013 #include <vector>
00014 #include <list>
00015 #include <map>
00016 #include <set>
00017 #include <util/unorderedmap.h>
00018
00019 #ifdef USE_HASH
00020 #include <QHash>
00021
00022 namespace std
00023 {
00024 #ifdef CXX_NEEDS_TR1
00025 namespace tr1
00026 {
00027 #endif
00028 template <>
00029 struct hash<QString>
00030 {
00031 size_t operator()(const QString& s) const
00032 {
00033 return qHash(s);
00034 }
00035 };
00036 #ifdef CXX_NEEDS_TR1
00037 }
00038 #endif
00039 }
00040 #endif
00041
00042 class Model;
00043
00179 namespace storage
00180 {
00181
00185 enum Options
00186 {
00188 TypeChecking
00189 };
00190
00194 enum TypeCheckingOption
00195 {
00197 TCO_Exact,
00204 TCO_Strict,
00211 TCO_Permissive,
00215 TCO_PermissiveNoWarning,
00220 TCO_NoCheck
00221 };
00222
00226 enum STORAGE_ERROR
00227 {
00233 NO__ERROR = 0,
00239 IO_ERROR,
00246 BAD_CONTENT,
00254 TYPE_CHECK_ERROR,
00262 TYPE_CONVERSION_ERROR,
00266 NO_FIELD_ERROR,
00273 REFERENCE_ERROR,
00279 USER_ERROR,
00283 UNKNOWN_ERROR
00284 };
00285
00286 template <typename T>
00287 struct pointer_traits;
00288
00289 template <typename T>
00290 struct pointer_traits<T*>
00291 {
00292 typedef T pointee;
00293 };
00294
00295 template <typename Ptr>
00296 Ptr create_object(Ptr const& p)
00297 {
00298 if(p != 0)
00299 delete p;
00300 typedef typename pointer_traits<Ptr>::pointee pointee;
00301 return new pointee();
00302 }
00303
00304 struct Reference
00305 {
00306 virtual ~Reference() {}
00307 Reference()
00308 : count(1)
00309 {}
00310
00311 int count;
00312 };
00313
00314 template <typename Ptr>
00315 struct RealReference : public Reference
00316 {
00317 RealReference(Ptr p=Ptr())
00318 : Reference()
00319 , value(p)
00320 { }
00321
00322 Ptr value;
00323 };
00324
00325 struct ReferencePtr
00326 {
00327 ReferencePtr(Reference* r = 0)
00328 : ptr(r)
00329 {
00330 }
00331
00332 ReferencePtr(const ReferencePtr& copy)
00333 : ptr(copy.ptr)
00334 {
00335 if(ptr)
00336 ptr->count++;
00337 }
00338
00339 void release()
00340 {
00341 if(ptr)
00342 {
00343 ptr->count--;
00344 if(ptr->count == 0)
00345 {
00346 delete ptr;
00347 ptr = 0;
00348 }
00349 }
00350 }
00351
00352 ~ReferencePtr()
00353 {
00354 release();
00355 }
00356
00357 bool operator==(const ReferencePtr& other) const
00358 {
00359 return ptr == other.ptr;
00360 }
00361
00362 ReferencePtr& operator=(const ReferencePtr& other)
00363 {
00364 if(other.ptr == ptr)
00365 return *this;
00366 release();
00367 ptr = other.ptr;
00368 if(ptr)
00369 ptr->count++;
00370 return *this;
00371 }
00372
00373 Reference *ptr;
00374 };
00375
00376 template <typename Ptr>
00377 ReferencePtr make_reference(Ptr& p)
00378 {
00379 return ReferencePtr(new RealReference<Ptr>(p));
00380 }
00381
00387 class VVEStorage
00388 {
00389 public:
00391 typedef ptrdiff_t reference_t;
00392
00393 #ifdef USE_HASH
00394 typedef std::unordered_map<size_t, ReferencePtr> ref_map;
00395 typedef std::unordered_map<QString, ref_map> ref_map_type;
00396 #else
00397 typedef std::map<size_t, ReferencePtr> ref_map;
00398 typedef std::map<QString, ref_map> ref_map_type;
00399 #endif
00400
00401 ref_map_type references;
00402
00403 VVEStorage();
00405 virtual ~VVEStorage() {}
00406
00413 virtual bool setOption(int , int ) { return false; }
00414
00421 virtual bool startCompound(const QString& name) = 0;
00425 virtual bool endCompound() = 0;
00426
00432 virtual bool ignore(const QString& ) { return true; }
00433
00448 virtual int startReference(const QString& name, const QString& ref_type, reference_t ref) = 0;
00452 virtual bool endReference() = 0;
00453
00457 virtual void clear();
00458
00462 virtual bool serialize(const QString& filename, Model* model) = 0;
00463
00467 virtual bool reader() = 0;
00471 virtual bool writer() = 0;
00472
00474
00475
00477 virtual bool field(const QString& name, bool& value) = 0;
00478 #ifndef _MSC_VER
00479
00480 virtual bool field(const QString& name, wchar_t& value) = 0;
00481 #endif
00482
00483 virtual bool field(const QString& name, char& value) = 0;
00485 virtual bool field(const QString& name, signed char& value) = 0;
00487 virtual bool field(const QString& name, short& value) = 0;
00489 virtual bool field(const QString& name, int& value) = 0;
00491 virtual bool field(const QString& name, long& value) = 0;
00493 virtual bool field(const QString& name, long long& value) = 0;
00495 virtual bool field(const QString& name, unsigned char& value) = 0;
00497 virtual bool field(const QString& name, unsigned short& value) = 0;
00499 virtual bool field(const QString& name, unsigned int& value) = 0;
00501 virtual bool field(const QString& name, unsigned long& value) = 0;
00503 virtual bool field(const QString& name, unsigned long long& value) = 0;
00505 virtual bool field(const QString& name, float& value) = 0;
00507 virtual bool field(const QString& name, double& value) = 0;
00509 virtual bool field(const QString& name, long double& value) = 0;
00511 virtual bool field(const QString& name, QString& value) = 0;
00513 virtual bool field(const QString& name, std::string& value) = 0;
00515
00525 template <typename T>
00526 bool field(const QString& name, T& value)
00527 {
00528 bool result = false;
00529 if(startCompound(name))
00530 {
00531 result = serialization(*this, value);
00532 if(!result)
00533 return false;
00534 result &= endCompound();
00535 }
00536 return result;
00537 }
00538
00549 template <typename T, typename Model>
00550 bool field(const QString& name, T& value, Model* model)
00551 {
00552 bool result = false;
00553 bool no_name = name.isEmpty();
00554 if(startCompound(name))
00555 {
00556 result = model->serialize(*this, value);
00557 result &= endCompound();
00558 }
00559 return result;
00560 }
00561
00570 template <typename Ptr>
00571 bool reference(const QString& name, const QString& type, Ptr& value)
00572 {
00573 int ref = startReference(name, type, (char*)(&*value) - (char*)0);
00574 if(ref < 0)
00575 return false;
00576 if(!find_reference(type, ref, value))
00577 {
00578 if(reader())
00579 value = create_object(value);
00580 if(!field("", *value))
00581 {
00582 return false;
00583 }
00584 references[type][ref] = make_reference(value);
00585 }
00586 return endReference();
00587 }
00588
00597 template <typename Ptr>
00598 bool reference(const QString& name, const QString& type, Ptr& value, Model* model)
00599 {
00600 int ref = startReference(name, type, (char*)(&*value) - (char*)0);
00601 if(ref < 0)
00602 return false;
00603 if(!find_reference(type, ref, value))
00604 {
00605 if(reader())
00606 value = create_object(value);
00607 if(!field("", *value, model))
00608 {
00609 return false;
00610 }
00611 references[type][ref] = make_reference(value);
00612 }
00613 return endReference();
00614 }
00615
00621 virtual bool checkNextField(const QString& name) = 0;
00622
00626 QString lastErrorString() const { return last_error_string; }
00627
00633 int lastError() const { return last_error; }
00634
00640 virtual void setLastError(int error, const QString& error_str) { if(last_error == NO__ERROR) { last_error = error; last_error_string = error_str; } }
00641
00645 virtual void clearLastError() { last_error = NO__ERROR; last_error_string = QString(); }
00646
00653 int version() const { return version_number; }
00654
00658 const QString& fileVersion() const { return file_version; }
00659
00663 virtual QString filename() const = 0;
00664
00665 protected:
00666
00667 template <typename Ptr>
00668 bool find_reference(const QString& type, int ref, Ptr& value)
00669 {
00670 ref_map_type::iterator found1 = references.find(type);
00671 if(found1 == references.end())
00672 return false;
00673 ref_map& typed_ref = found1->second;
00674 ref_map::iterator found = typed_ref.find(ref);
00675 if(found == typed_ref.end())
00676 return false;
00677 RealReference<Ptr> *r = dynamic_cast<RealReference<Ptr>*>(found->second.ptr);
00678 if(r)
00679 value = r->value;
00680 else
00681 return false;
00682 return true;
00683 }
00684
00685 QString last_error_string;
00686
00687 int last_error;
00688
00689 QString file_version;
00690
00691 int version_number;
00692 };
00693
00702 template <typename T>
00703 bool serialization(VVEStorage& storage, T& value)
00704 {
00705 return value.serialize(storage);
00706 }
00707
00730 int versionNumber(const QString& file_version);
00731 }
00732
00733 #endif // VVELIB_STORAGE_STORAGE_H
00734