GME
13
|
00001 00002 #ifndef MGA_COREBINFILE_H 00003 #define MGA_COREBINFILE_H 00004 00005 #include "CoreDictionaryAttributeValue.h" 00006 00007 #include <fstream>//fstream.h 00008 #include <list>//slist 00009 #include <map> 00010 #include <vector> 00011 #include <algorithm> 00012 #include <memory> 00013 00014 #include "windows.h" 00015 class membuf 00016 { 00017 public: 00018 membuf() : 00019 begin(0), end(0), hFile(INVALID_HANDLE_VALUE), hFileMappingObject(INVALID_HANDLE_VALUE) 00020 { } 00021 00022 int open(const wchar_t* filename) { 00023 ASSERT(hFile == INVALID_HANDLE_VALUE); 00024 hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 00025 if (hFile == INVALID_HANDLE_VALUE) { 00026 return 1; 00027 } 00028 DWORD filesize = GetFileSize(hFile, NULL); 00029 if (filesize == INVALID_FILE_SIZE || filesize == 0) { 00030 return 1; 00031 } 00032 hFileMappingObject = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 00033 if (hFileMappingObject == INVALID_HANDLE_VALUE) { 00034 return 1; 00035 } 00036 begin = (char*)MapViewOfFile(hFileMappingObject, FILE_MAP_READ, 0, 0, 0); 00037 if (begin == NULL) { 00038 return 1; 00039 } 00040 end = begin + filesize; 00041 return 0; 00042 } 00043 00044 ~membuf() { 00045 if (begin) 00046 UnmapViewOfFile(begin); 00047 if (hFileMappingObject != INVALID_HANDLE_VALUE) 00048 CloseHandle(hFileMappingObject); 00049 if (hFile != INVALID_HANDLE_VALUE) 00050 CloseHandle(hFile); 00051 } 00052 00053 char* getBegin() const { 00054 return begin; 00055 } 00056 char* getEnd() const { 00057 return end; 00058 } 00059 00060 private: 00061 membuf(const membuf&); 00062 membuf& operator=(const membuf&); 00063 00064 HANDLE hFile,hFileMappingObject; 00065 char* begin, * end; 00066 }; 00067 00068 class CCoreBinFile; 00069 class BinAttrUnion; 00070 00071 // --------------------------- BinAttr 00072 class __declspec(novtable) BinAttrBase 00073 { 00074 public: 00075 BinAttrBase() : attrid(ATTRID_NONE) { } 00076 BinAttrBase(attrid_type attrid) : attrid(attrid) { } 00077 virtual ~BinAttrBase() { } 00078 00079 attrid_type attrid; 00080 00081 static BinAttrBase *Create(BinAttrBase& attr, valtype_type valtype); 00082 00083 virtual valtype_type GetValType() const NOTHROW = 0; 00084 virtual void Set(CCoreBinFile *binfile, VARIANT p) = 0; 00085 virtual void Get(CCoreBinFile *binfile, VARIANT *p) = 0; 00086 virtual void Write(CCoreBinFile *binfile) = 0; 00087 virtual void Read(CCoreBinFile *binfile) = 0; 00088 // virtual move constructor 00089 virtual void move(BinAttrUnion&& dest) = 0; 00090 }; 00091 00092 class __declspec(novtable) BinAttrUnion : public BinAttrBase 00093 { 00094 public: 00095 BinAttrUnion() { } 00096 explicit BinAttrUnion(attrid_type attrid) : BinAttrBase(attrid) { } 00097 virtual ~BinAttrUnion() { } 00098 00099 virtual valtype_type GetValType() const NOTHROW { DebugBreak(); return 0; } 00100 virtual void Set(CCoreBinFile *binfile, VARIANT p) { DebugBreak(); } 00101 virtual void Get(CCoreBinFile *binfile, VARIANT *p) { DebugBreak(); } 00102 virtual void Write(CCoreBinFile *binfile) { DebugBreak(); } 00103 virtual void Read(CCoreBinFile *binfile) { DebugBreak(); } 00104 virtual void move(BinAttrUnion&& dest) { DebugBreak(); } 00105 00106 // that is a subtype of BinAttrUnion 00107 // that must not be BinAttrUnion because of __declspec(novtable) 00108 BinAttrUnion(BinAttrUnion&& that) { 00109 // volatile to read the vtable of that 00110 BinAttrUnion* volatile that_ = &that; 00111 that_->move(std::move(*this)); 00112 } 00113 00114 BinAttrUnion& operator=(BinAttrUnion&& that) { 00115 BinAttrUnion* volatile that_ = &that; 00116 that_->move(std::move(*this)); 00117 return *this; 00118 } 00119 BinAttrUnion(const BinAttrUnion& that) { 00120 // FIXME 00121 } 00122 // BinAttrUnion is guaranteed to have enough space to contain any BinAttr<*> 00123 // (Ideally we'd do union { char [sizeof(BinAttrBase) - sizeof(BinAttr<*>) }, but that requires method definitions for BinAttr<*>::* to be separated from the declaration) 00124 #ifdef _DEBUG 00125 char pad[12 + 2 * sizeof(void*)]; 00126 #else 00127 char pad[4 + sizeof(void*)]; 00128 #endif 00129 }; 00130 00131 typedef std::vector<BinAttrUnion> binattrs_type; 00132 typedef binattrs_type::iterator binattrs_iterator; 00133 00134 template<valtype_enum VALTYPE> 00135 class BinAttr; 00136 00137 00138 // --------------------------- BinObject 00139 00140 class BinObject 00141 { 00142 public: 00143 ~BinObject() { DestroyAttributes(); } 00144 00145 // binattrs actually contains elements of type BinAttr<*> 00146 binattrs_type binattrs; 00147 bool deleted; 00148 00149 void HasGuidAndStatAttributes(GUID& guid, bool* p_statusFound, bool* p_oldRegFound); 00150 void CreateGuidAttributes( CCoreBinFile* p_bf); 00151 void CreateStatusAttribute( CCoreBinFile* p_bf); 00152 void UpgradeRegistryIfNecessary(CCoreBinFile* binFile); 00153 00154 BinAttrBase *Find(attrid_type attrid) 00155 { 00156 binattrs_iterator i = binattrs.begin(); 00157 binattrs_iterator e = binattrs.end(); 00158 while( i != e && (i)->attrid != attrid ) 00159 ++i; 00160 00161 if( i == e ) 00162 HR_THROW(E_BINFILE); 00163 00164 return &*i; 00165 } 00166 00167 void CreateAttributes(ICoreMetaObject *metaobject); 00168 void DestroyAttributes(); 00169 void Read(CCoreBinFile *binfile); 00170 void Write(CCoreBinFile *binfile); 00171 00172 bool HasEmptyPointers() const; 00173 }; 00174 00175 typedef stdext::hash_map< metaobjidpair_type 00176 , BinObject 00177 , metaobjid2pair_hashfunc 00178 > objects_type; 00179 typedef objects_type::iterator objects_iterator; 00180 00181 00182 // --------------------------- CCoreBinFile 00183 00184 class ATL_NO_VTABLE CCoreBinFile : 00185 public CComObjectRootEx<CComSingleThreadModel>, 00186 public IDispatchImpl<ICoreStorage, &__uuidof(ICoreStorage), &__uuidof(__MGACoreLib)>, 00187 public ISupportErrorInfoImpl<&__uuidof(ICoreStorage)>, 00188 public CComCoClass<CCoreBinFile, &__uuidof(CoreBinFile)> 00189 { 00190 public: 00191 CCoreBinFile(); 00192 ~CCoreBinFile(); 00193 00194 BEGIN_COM_MAP(CCoreBinFile) 00195 COM_INTERFACE_ENTRY(ICoreStorage) 00196 COM_INTERFACE_ENTRY(IDispatch) 00197 COM_INTERFACE_ENTRY(ISupportErrorInfo) 00198 END_COM_MAP() 00199 00200 DECLARE_REGISTRY_RESOURCEID(IDR_COREBINFILE) 00201 00202 // ------- MetaProject 00203 00204 public: 00205 CComObjPtr<ICoreMetaProject> metaproject; 00206 bindata metaprojectid; 00207 00208 STDMETHODIMP get_MetaProject(ICoreMetaProject **p); 00209 STDMETHODIMP put_MetaProject(ICoreMetaProject *p); 00210 00211 void OpenMetaProject(); 00212 void CloseMetaProject() NOTHROW; 00213 00214 // ------- MetaObject 00215 00216 public: 00217 CComObjPtr<ICoreMetaObject> metaobject; 00218 metaid_type metaid; 00219 00220 STDMETHODIMP get_MetaObject(ICoreMetaObject **p); 00221 STDMETHODIMP put_MetaObject(ICoreMetaObject *p); 00222 00223 STDMETHODIMP get_MetaID(metaid_type *p); 00224 STDMETHODIMP put_MetaID(metaid_type p); 00225 00226 void OpenMetaObject(); 00227 void CloseMetaObject() NOTHROW; 00228 00229 // ------- MetaAttribute 00230 00231 public: 00232 CComObjPtr<ICoreMetaAttribute> metaattribute; 00233 attrid_type attrid; 00234 00235 STDMETHODIMP get_MetaAttribute(ICoreMetaAttribute **p); 00236 STDMETHODIMP put_MetaAttribute(ICoreMetaAttribute *p); 00237 00238 STDMETHODIMP get_AttrID(attrid_type *p); 00239 STDMETHODIMP put_AttrID(attrid_type p); 00240 00241 void OpenMetaAttribute(); 00242 void CloseMetaAttribute() NOTHROW; 00243 00244 // ------- Ios 00245 00246 public: 00247 char* cifs; 00248 char* cifs_eof; 00249 00250 std::ofstream ofs; 00251 00252 public: 00253 #define CoreBinFile_read(a, size) if (size > cifs_eof - cifs) HR_THROW(E_FILEOPEN); memcpy(&a, cifs, size); cifs += size; 00254 void read(unsigned char &a) { CoreBinFile_read(a, sizeof(unsigned char)); } 00255 void read(short &a) { CoreBinFile_read(a, sizeof(short)); } 00256 void read(int &a) { CoreBinFile_read(a, sizeof(int)); } 00257 void read(long &a) { CoreBinFile_read(a, sizeof(long)); } 00258 void read(double &a) { CoreBinFile_read(a, sizeof(double)); } 00259 void read(CComBstrObj &a); 00260 void read(CComBstrObj &ss, char*& cifs); 00261 void read(bindata &a); 00262 void read(unsigned char*& b, int& len); 00263 void readstring(char*& pos); 00264 00265 void write(unsigned char a) { ofs.write((const char*)&a, sizeof(unsigned char)); } 00266 void write(short a) { ofs.write((const char*)&a, sizeof(short)); } 00267 void write(int a) { ofs.write((const char*)&a, sizeof(int)); } 00268 void write(long a) { ofs.write((const char*)&a, sizeof(long)); } 00269 void write(double a) { ofs.write((const char*)&a, sizeof(double)); } 00270 void write(const CComBstrObj &a); 00271 void write(const bindata &a); 00272 void write(const unsigned char* a, int len); 00273 void write(const wchar_t* a, int len) { 00274 write((const unsigned char*)a, len * sizeof(wchar_t)); 00275 } 00276 void writestring(const char* pos); 00277 // ------- Attribute 00278 00279 public: 00280 typedef std::map<BinAttrBase*, CComVariant> undos_type; 00281 typedef undos_type::iterator undos_iterator; 00282 00283 undos_type undos; 00284 00285 STDMETHODIMP get_AttributeValue(VARIANT *p); 00286 STDMETHODIMP put_AttributeValue(VARIANT p); 00287 00288 // ------- Object 00289 00290 public: 00291 objects_type objects; 00292 objects_iterator opened_object; 00293 bool isEmpty; 00294 00295 typedef core::hash_map<metaid_type, objid_type> maxobjids_type; 00296 typedef maxobjids_type::iterator maxobjids_iterator; 00297 00298 maxobjids_type maxobjids; 00299 core::forward_list<objects_iterator> deleted_objects; 00300 core::forward_list<objects_iterator> created_objects; 00301 00302 struct resolve_type 00303 { 00304 objects_iterator obj; 00305 attrid_type attrid; 00306 metaobjidpair_type idpair; 00307 }; 00308 00309 typedef core::forward_list<resolve_type> resolvelist_type; 00310 resolvelist_type resolvelist; 00311 00312 void InitMaxObjIDs(); 00313 00314 public: 00315 STDMETHODIMP OpenObject(objid_type objid); 00316 STDMETHODIMP CreateObject(objid_type *objid); 00317 STDMETHODIMP CloseObject() NOTHROW; 00318 00319 STDMETHODIMP DeleteObject(); 00320 STDMETHODIMP LockObject(); 00321 00322 // ------- Project 00323 00324 public: 00325 std::wstring filename; 00326 bool read_only; 00327 bool intrans; 00328 bool modified; 00329 00330 membuf file_buffer; 00331 bool IsOpened() const { return !filename.empty(); } 00332 bool InTransaction() const { return intrans; } 00333 00334 void CancelProject() NOTHROW; 00335 void SaveProject(const std::wstring& origfname, bool keepoldname); 00336 void LoadProject(); 00337 00338 public: 00339 STDMETHODIMP OpenProject(BSTR connection, VARIANT_BOOL *ro_mode); 00340 STDMETHODIMP CreateProject(BSTR connection); 00341 STDMETHODIMP CloseProject( VARIANT_BOOL abort = VARIANT_FALSE) NOTHROW; 00342 STDMETHODIMP SaveProject(BSTR connection, VARIANT_BOOL keepoldname); 00343 STDMETHODIMP DeleteProject() { return E_NOTIMPL; } 00344 00345 STDMETHODIMP BeginTransaction(); 00346 STDMETHODIMP CommitTransaction(); 00347 STDMETHODIMP AbortTransaction(); 00348 00349 STDMETHODIMP get_StorageType(long *p); 00350 }; 00351 00352 // --------------------------- BinAttr<VALTYPE_LONG> 00353 00354 template<> 00355 class BinAttr<VALTYPE_LONG> : public BinAttrBase 00356 { 00357 public: 00358 BinAttr() : a(0) { } 00359 00360 long a; 00361 00362 virtual valtype_type GetValType() const NOTHROW { return VALTYPE_LONG; } 00363 virtual void Set(CCoreBinFile *binfile, VARIANT p) 00364 { ASSERT( binfile != NULL ); binfile->modified = true; CopyTo(p, a); } 00365 00366 virtual void Get(CCoreBinFile *binfile, VARIANT *p) { CopyTo(a, p); } 00367 virtual void Write(CCoreBinFile *binfile) { binfile->write(a); } 00368 virtual void Read(CCoreBinFile *binfile) { binfile->read(a); } 00369 00370 BinAttr(BinAttr<VALTYPE_LONG>&& that) : BinAttrBase(that.attrid), a(that.a) { } 00371 virtual void move(BinAttrUnion&& dest) { 00372 new (&dest) BinAttr<VALTYPE_LONG>(std::move(*this)); 00373 } 00374 }; 00375 00376 // --------------------------- BinAttr<VALTYPE_REAL> 00377 00378 template<> 00379 class BinAttr<VALTYPE_REAL> : public BinAttrBase 00380 { 00381 public: 00382 BinAttr() : a(0) { } 00383 00384 double a; 00385 00386 virtual valtype_type GetValType() const NOTHROW { return VALTYPE_REAL; } 00387 virtual void Set(CCoreBinFile *binfile, VARIANT p) 00388 { ASSERT( binfile != NULL ); binfile->modified = true; CopyTo(p, a); } 00389 00390 virtual void Get(CCoreBinFile *binfile, VARIANT *p) { CopyTo(a, p); } 00391 virtual void Write(CCoreBinFile *binfile) { binfile->write(a); } 00392 virtual void Read(CCoreBinFile *binfile) { binfile->read(a); } 00393 BinAttr(BinAttr<VALTYPE_REAL>&& that) : BinAttrBase(that.attrid), a(that.a) { } 00394 virtual void move(BinAttrUnion&& dest) { 00395 new (&dest) BinAttr<VALTYPE_REAL>(std::move(*this)); 00396 } 00397 }; 00398 00399 // --------------------------- BinAttr<VALTYPE_STRING> 00400 00401 template<> 00402 class BinAttr<VALTYPE_STRING> : public BinAttrBase 00403 { 00404 public: 00405 BinAttr() : pos(NULL) { } 00406 00407 CComBstrObj a; 00408 // Lazy read: if pos is non-null, a is invalid and 00409 // pos points to the pascal-style UTF-8 string in the memory-mapped mga file 00410 char* pos; 00411 00412 virtual valtype_type GetValType() const NOTHROW { return VALTYPE_STRING; } 00413 virtual void Set(CCoreBinFile *binfile, VARIANT p) 00414 { 00415 ASSERT( binfile != NULL ); 00416 binfile->modified = true; 00417 CopyTo(p, a); 00418 pos = NULL; 00419 } 00420 00421 virtual void Get(CCoreBinFile *binfile, VARIANT *p) { 00422 if (pos != NULL) { 00423 binfile->read(this->a, this->pos); 00424 this->pos = NULL; 00425 } 00426 CopyTo(a, p); 00427 } 00428 virtual void Write(CCoreBinFile *binfile) { 00429 if (pos != NULL) { 00430 binfile->read(this->a, this->pos); 00431 this->pos = NULL; 00432 } 00433 binfile->write(a); 00434 } 00435 virtual void Read(CCoreBinFile *binfile) { 00436 binfile->readstring(pos); 00437 // to disable lazy read: 00438 //binfile->read(a, pos); 00439 //pos = NULL; 00440 } 00441 BinAttr(BinAttr<VALTYPE_STRING>&& that) : BinAttrBase(that.attrid), a(std::move(that.a)), pos(that.pos) { } 00442 virtual void move(BinAttrUnion&& dest) { 00443 new (&dest) BinAttr<VALTYPE_STRING>(std::move(*this)); 00444 } 00445 }; 00446 00447 // --------------------------- BinAttr<VALTYPE_BINARY> 00448 00449 template<class Type> 00450 struct free_deleter { 00451 void operator()(Type* p) { free(p); } 00452 }; 00453 00454 template<> 00455 class BinAttr<VALTYPE_BINARY> : public BinAttrBase 00456 { 00457 public: 00458 BinAttr() : data(0), need_free(false) { } 00459 virtual ~BinAttr() { if (need_free) free(data); } 00460 00461 unsigned char* data; 00462 // memcpy: if lazy read, data is not guaranteed to be properly aligned for int* 00463 int get_len() const { int ret; memcpy(&ret, data, sizeof(int)); return ret; } 00464 void put_len(int len) { memcpy(data, &len, sizeof(len)); } 00465 __declspec(property(get=get_len, put=put_len)) int len; 00466 unsigned char* get_value() const { return (data + sizeof(len)); } 00467 __declspec(property(get=get_value)) unsigned char* value; 00468 bool need_free; 00469 00470 virtual valtype_type GetValType() const NOTHROW { return VALTYPE_BINARY; } 00471 virtual void Set(CCoreBinFile *binfile, VARIANT v) 00472 { 00473 ASSERT( binfile != NULL ); 00474 binfile->modified = true; 00475 if( v.vt == (VT_I4 | VT_ARRAY) ) 00476 { 00477 if (need_free) free(data); 00478 data = (unsigned char*)malloc(sizeof(len) + sizeof(long) * GetArrayLength(v)); 00479 need_free = true; 00480 len = sizeof(long) * GetArrayLength(v); 00481 CopyTo(v, (long*)(value), (long*)(value) + len/sizeof(long)); 00482 } 00483 else 00484 { 00485 if (GetArrayLength(v)==0) 00486 { 00487 if (need_free) free(data); 00488 data = 0; 00489 } 00490 else 00491 { 00492 int len = GetArrayLength(v); 00493 if (need_free) free(data); 00494 data = (unsigned char*) malloc(sizeof(this->len) + len); 00495 need_free = true; 00496 this->len = len; 00497 CopyTo(v, value, value + len); 00498 } 00499 } 00500 } 00501 00502 virtual void Get(CCoreBinFile *binfile, VARIANT *p) { 00503 if (data == 0) { 00504 unsigned char* pnull=NULL; 00505 CopyTo(pnull, pnull, p); 00506 } else 00507 CopyTo(value, value + len, p); 00508 } 00509 virtual void Write(CCoreBinFile *binfile) { 00510 if (data) 00511 { 00512 if (!need_free) 00513 { 00514 // need to get data off the disk; the file is going away 00515 unsigned char* olddata = this->data; 00516 int len = this->len; 00517 this->data = (unsigned char*)malloc(sizeof(len) + len); 00518 this->need_free = true; 00519 this->len = len; 00520 memcpy(value, olddata+sizeof(len), len); 00521 } 00522 binfile->write(value, len); 00523 } 00524 else 00525 binfile->write((unsigned char*)NULL, 0); 00526 } 00527 virtual void Read(CCoreBinFile *binfile) { 00528 data = (unsigned char*)binfile->cifs; 00529 int len = this->len; 00530 // to test without lazy read: 00531 //data = (unsigned char*)malloc(sizeof(len) + len); 00532 //need_free = true; 00533 //this->len = len; 00534 //memcpy(value, binfile->cifs+sizeof(len), len); 00535 binfile->cifs += sizeof(len) + len; 00536 } 00537 BinAttr(BinAttr<VALTYPE_BINARY>&& that) : BinAttrBase(that.attrid), data(that.data), need_free(that.need_free) { that.need_free = false; } 00538 virtual void move(BinAttrUnion&& dest) { 00539 new (&dest) BinAttr<VALTYPE_BINARY>(std::move(*this)); 00540 } 00541 }; 00542 00543 // --------------------------- BinAttr<VALTYPE_DICT> 00544 00545 template<> 00546 class BinAttr<VALTYPE_DICT> : public BinAttrBase 00547 { 00548 public: 00549 BinAttr() : data(0) { 00550 CCoreDictionaryAttributeValue *val = NULL; 00551 typedef CComObject< CCoreDictionaryAttributeValue > COMTYPE; 00552 HRESULT hr = COMTYPE::CreateInstance((COMTYPE **)&val); 00553 COMTHROW(hr); 00554 dict = val; 00555 } 00556 virtual ~BinAttr() { } 00557 00558 char* data; 00559 // memcpy: if lazy read, data is not guaranteed to be properly aligned for int* 00560 int read_len(char*& offset) const { int ret; memcpy(&ret, offset, sizeof(int)); offset += sizeof(int); return ret; } 00561 00562 CComPtr<ICoreDictionaryAttributeValue> dict; 00563 00564 virtual valtype_type GetValType() const NOTHROW { return VALTYPE_DICT; } 00565 virtual void Set(CCoreBinFile *binfile, VARIANT v) 00566 { 00567 ASSERT( binfile != NULL ); 00568 ASSERT(v.vt == VT_DISPATCH); 00569 binfile->modified = true; 00570 dict = 0; 00571 v.pdispVal->QueryInterface(&dict); 00572 } 00573 00574 virtual void Get(CCoreBinFile *binfile, VARIANT *p) { 00575 if (dict == 0) { 00576 // lazy read 00577 CCoreDictionaryAttributeValue* val = NULL; 00578 typedef CComObject< CCoreDictionaryAttributeValue > COMTYPE; 00579 HRESULT hr = COMTYPE::CreateInstance((COMTYPE **)&val); 00580 COMTHROW(hr); 00581 00582 char* data = this->data; 00583 int size = read_len(data); 00584 while (data < this->data + size) 00585 { 00586 int keysize = read_len(data); 00587 CComBSTR key(keysize / sizeof(wchar_t)); 00588 memcpy(key.m_str, data, keysize); 00589 data += keysize; 00590 int valuesize = read_len(data); 00591 CComBSTR value(valuesize / sizeof(wchar_t)); 00592 memcpy(value.m_str, data, valuesize); 00593 data += valuesize; 00594 val->m_dict.emplace( 00595 std::unordered_map<CComBSTR, CComBSTR, CComBSTR_Length>::value_type(std::move(key), std::move(value))); 00596 } 00597 00598 this->dict = val; 00599 this->data = 0; 00600 } 00601 CComVariant ret = dict; 00602 COMTHROW(ret.Detach(p)); 00603 } 00604 virtual void Write(CCoreBinFile *binfile) { 00605 int size = 0; 00606 00607 if (dict == NULL) 00608 { 00609 // need to read before write, since the file is going away 00610 CComVariant p; 00611 Get(binfile, &p); 00612 } 00613 00614 const CCoreDictionaryAttributeValue* cdict = (const CCoreDictionaryAttributeValue*)(const ICoreDictionaryAttributeValue*)dict; 00615 for (auto it = cdict->m_dict.begin(); it != cdict->m_dict.end(); it++) { 00616 size += sizeof(int); 00617 size += it->first.Length() * sizeof(wchar_t); 00618 size += sizeof(int); 00619 size += it->second.Length() * sizeof(wchar_t); 00620 } 00621 binfile->write(size); 00622 00623 for (auto it = cdict->m_dict.begin(); it != cdict->m_dict.end(); it++) { 00624 // binfile->write((int)it->first.Length()); 00625 binfile->write(it->first, it->first.Length()); 00626 // binfile->write((int)it->second.Length()); 00627 binfile->write(it->second, it->second.Length()); 00628 } 00629 } 00630 virtual void Read(CCoreBinFile *binfile) { 00631 dict = 0; 00632 data = (char*)binfile->cifs; 00633 int len = read_len(binfile->cifs); 00634 binfile->cifs += len; 00635 } 00636 BinAttr(BinAttr<VALTYPE_DICT>&& that) : BinAttrBase(that.attrid), data(that.data), dict(std::move(that.dict)) { } 00637 virtual void move(BinAttrUnion&& dest) { 00638 new (&dest) BinAttr<VALTYPE_DICT>(std::move(*this)); 00639 } 00640 }; 00641 00642 // --------------------------- BinAttr<VALTYPE_LOCK> 00643 00644 template<> 00645 class BinAttr<VALTYPE_LOCK> : public BinAttrBase 00646 { 00647 public: 00648 BinAttr() : a(0) { } 00649 00650 lockval_type a; 00651 00652 virtual valtype_type GetValType() const NOTHROW { return VALTYPE_LOCK; } 00653 virtual void Set(CCoreBinFile *binfile, VARIANT p) { CopyTo(p, a); } 00654 virtual void Get(CCoreBinFile *binfile, VARIANT *p) { CopyTo(a, p); } 00655 virtual void Write(CCoreBinFile *binfile) { } 00656 virtual void Read(CCoreBinFile *binfile) { a = 0; } 00657 BinAttr(BinAttr<VALTYPE_LOCK>&& that) : BinAttrBase(that.attrid), a(that.a) { } 00658 virtual void move(BinAttrUnion&& dest) { 00659 new (&dest) BinAttr<VALTYPE_LOCK>(std::move(*this)); 00660 } 00661 }; 00662 // --------------------------- BinAttr<VALTYPE_COLLECTION> 00663 00664 template<> 00665 class BinAttr<VALTYPE_COLLECTION> : public BinAttrBase 00666 { 00667 public: 00668 std::unique_ptr<std::vector<objects_iterator>> backing; 00669 std::vector<objects_iterator>& getbacking() const { return *backing.get(); } 00670 __declspec(property(get = getbacking )) std::vector<objects_iterator>& a; 00671 00672 BinAttr() : backing(new std::vector<objects_iterator>()) { } 00673 virtual valtype_type GetValType() const NOTHROW { return VALTYPE_COLLECTION; } 00674 virtual void Set(CCoreBinFile *binfile, VARIANT p) { ASSERT(false); } 00675 virtual void Get(CCoreBinFile *binfile, VARIANT *p) 00676 { 00677 ASSERT( p != NULL && p->vt == VT_EMPTY ); 00678 00679 std::vector<metaobjidpair_type> idpairs; 00680 00681 std::vector<objects_iterator>::const_iterator i = a.begin(); 00682 std::vector<objects_iterator>::const_iterator e = a.end(); 00683 while( i != e ) 00684 { 00685 idpairs.push_back( (*i)->first ); 00686 00687 ++i; 00688 } 00689 00690 CopyTo(idpairs, p); 00691 } 00692 virtual void Write(CCoreBinFile *binfile) { } 00693 virtual void Read(CCoreBinFile *binfile) { } 00694 BinAttr(BinAttr<VALTYPE_COLLECTION>&& that) : BinAttrBase(that.attrid), backing(std::move(that.backing)) { } 00695 virtual void move(BinAttrUnion&& dest) { 00696 new (&dest) BinAttr<VALTYPE_COLLECTION>(std::move(*this)); 00697 } 00698 }; 00699 00700 // --------------------------- BinAttr<VALTYPE_POINTER> 00701 00702 template<> 00703 class BinAttr<VALTYPE_POINTER> : public BinAttrBase 00704 { 00705 public: 00706 BinAttr() : isEmpty(true) { } 00707 00708 objects_iterator a; 00709 bool isEmpty; 00710 00711 virtual valtype_type GetValType() const NOTHROW { return VALTYPE_POINTER; } 00712 00713 void Set(CCoreBinFile *binfile, objects_iterator b) 00714 { 00715 ASSERT( binfile != NULL ); 00716 ASSERT( isEmpty ); 00717 ASSERT( b != binfile->objects.end()); 00718 00719 binfile->modified = true; 00720 00721 a = b; 00722 isEmpty = false; 00723 00724 ASSERT( binfile->opened_object->second.Find(attrid) == this ); 00725 00726 BinAttrBase *base = a->second.Find(attrid + ATTRID_COLLECTION); 00727 ASSERT( base != NULL ); 00728 00729 ASSERT( base->GetValType() == VALTYPE_COLLECTION ); 00730 std::vector<objects_iterator> &objs = ((BinAttr<VALTYPE_COLLECTION>*)base)->a; 00731 00732 #ifdef DEBUG_CONTAINERS 00733 std::vector<objects_iterator>::iterator i = find(objs.begin(), objs.end(), a); 00734 ASSERT( i == objs.end() ); 00735 #endif 00736 00737 objs.push_back(binfile->opened_object); 00738 } 00739 00740 virtual void Set(CCoreBinFile *binfile, VARIANT p) 00741 { 00742 if( !isEmpty ) 00743 { 00744 BinAttrBase *base = a->second.Find(attrid + ATTRID_COLLECTION); 00745 ASSERT( base != NULL ); 00746 00747 ASSERT( base->GetValType() == VALTYPE_COLLECTION ); 00748 std::vector<objects_iterator> &objs = ((BinAttr<VALTYPE_COLLECTION>*)base)->a; 00749 00750 ASSERT( binfile->opened_object->second.Find(attrid) == this ); 00751 00752 std::vector<objects_iterator>::iterator i = std::find(objs.begin(), objs.end(), binfile->opened_object); 00753 ASSERT( i != objs.end() ); 00754 00755 objs.erase(i); 00756 } 00757 00758 isEmpty = true; 00759 00760 metaobjidpair_type idpair; 00761 CopyTo(p, idpair); 00762 00763 if( idpair.metaid == METAID_NONE ) 00764 { 00765 ASSERT( idpair.objid == OBJID_NONE ); 00766 } 00767 else 00768 { 00769 ASSERT( idpair.objid != OBJID_NONE ); 00770 00771 Set(binfile, binfile->objects.find(idpair)); 00772 } 00773 } 00774 virtual void Get(CCoreBinFile *binfile, VARIANT *p) 00775 { 00776 if( isEmpty ) 00777 { 00778 metaobjidpair_type idpair; 00779 idpair.metaid = METAID_NONE; 00780 idpair.objid = OBJID_NONE; 00781 CopyTo(idpair, p); 00782 } 00783 else 00784 CopyTo(a->first, p); 00785 } 00786 00787 virtual void Write(CCoreBinFile *binfile) 00788 { 00789 if( isEmpty ) 00790 { 00791 binfile->write((metaid_type)METAID_NONE); 00792 } 00793 else 00794 { 00795 ASSERT( a->first.metaid != METAID_NONE ); 00796 ASSERT( a->first.objid != OBJID_NONE ); 00797 00798 binfile->write((metaid_type)a->first.metaid); 00799 binfile->write((objid_type)a->first.objid); 00800 } 00801 } 00802 00803 virtual void Read(CCoreBinFile *binfile) 00804 { 00805 ASSERT( isEmpty ); 00806 00807 metaid_type metaid; 00808 binfile->read(metaid); 00809 00810 if( metaid != METAID_NONE ) 00811 { 00812 objid_type objid; 00813 binfile->read(objid); 00814 00815 ASSERT( objid != OBJID_NONE ); 00816 00817 binfile->resolvelist.push_front(CCoreBinFile::resolve_type()); 00818 CCoreBinFile::resolve_type &b = binfile->resolvelist.front(); 00819 00820 ASSERT( !binfile->isEmpty ); 00821 00822 b.obj = binfile->opened_object; 00823 b.attrid = attrid; 00824 b.idpair.metaid = metaid; 00825 b.idpair.objid = objid; 00826 } 00827 } 00828 BinAttr(BinAttr<VALTYPE_POINTER>&& that) : BinAttrBase(that.attrid), a(std::move(that.a)), isEmpty(that.isEmpty) { } 00829 virtual void move(BinAttrUnion&& dest) { 00830 new (&dest) BinAttr<VALTYPE_POINTER>(std::move(*this)); 00831 } 00832 }; 00833 00834 00835 static_assert(sizeof(BinAttr<VALTYPE_LONG>) <= sizeof(BinAttrUnion), "BinAttrUnion is too small."); 00836 static_assert(sizeof(BinAttr<VALTYPE_REAL>) <= sizeof(BinAttrUnion), "BinAttrUnion is too small."); 00837 static_assert(sizeof(BinAttr<VALTYPE_STRING>) <= sizeof(BinAttrUnion), "BinAttrUnion is too small."); 00838 static_assert(sizeof(BinAttr<VALTYPE_POINTER>) <= sizeof(BinAttrUnion), "BinAttrUnion is too small."); 00839 static_assert(sizeof(BinAttr<VALTYPE_BINARY>) <= sizeof(BinAttrUnion), "BinAttrUnion is too small."); 00840 static_assert(sizeof(BinAttr<VALTYPE_COLLECTION>) <= sizeof(BinAttrUnion), "BinAttrUnion is too small."); 00841 00842 00843 #endif//MGA_COREBINFILE_H