/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2016, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Teigha(R) software pursuant to a license // agreement with Open Design Alliance. // Teigha(R) Copyright (C) 2002-2016 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef __OdGsFilerV100Impl_H__ #define __OdGsFilerV100Impl_H__ #include "TD_PackPush.h" #include "Ge/GeMatrix3d.h" #include "Ge/GeExtents3d.h" #include "DbBaseDatabase.h" #include "GsFiler.h" #include "OdStack.h" #include "RxObjectImpl.h" // Database linker class OdGsFilerDbLinker : public OdRxObject { public: OdGsFilerDbLinker() { } virtual ~OdGsFilerDbLinker() { } public: // Get database hash virtual OdBinaryData getDbHash(const OdDbBaseDatabase *pDb) const; // Transform database handle virtual OdUInt64 stubToDbHandle(OdDbStub *pStub) const = 0; virtual OdDbStub *handleToDbStub(OdUInt64 nHandle) const = 0; // Util methods virtual OdDbBaseDatabase *getDatabase() const = 0; virtual OdDbBaseDatabase *getDatabase(OdDbStub *pStub) const = 0; }; typedef OdSmartPtr OdGsFilerDbLinkerPtr; #define STL_USING_MAP #define STL_USING_SET #include "OdaSTL.h" // Implement substitutor struct GS_TOOLKIT_EXPORT OdGsFiler_SubstitutorImpl : public OdRxObject, public OdGsFiler::Substitutor { template struct DataTyp { OdUInt8 m_data[nBytes]; static int compare(const DataTyp &t1, const DataTyp &t2) { for (OdUInt32 nb = 0; nb < nBytes; nb++) { if (t1.m_data[nb] != t2.m_data[nb]) return int(t1.m_data[nb]) - int(t2.m_data[nb]); } return 0; } bool operator ==(const DataTyp &t2) const { return compare(*this, t2) == 0; } bool operator !=(const DataTyp &t2) const { return compare(*this, t2) != 0; } bool operator <(const DataTyp &t2) const { return compare(*this, t2) < 0; } bool operator <=(const DataTyp &t2) const { return compare(*this, t2) <= 0; } bool operator >(const DataTyp &t2) const { return compare(*this, t2) > 0; } bool operator >=(const DataTyp &t2) const { return compare(*this, t2) >= 0; } operator const void*() const { return this; } }; struct VoidsSet { void *m_pVoid; OdGsFiler::SubstitutionActuator *m_pAct; }; struct VoidArry : public VoidsSet { OdInt32 m_nVoids; VoidArry() : m_nVoids(0) { m_pVoid = NULL; m_pAct = NULL; } ~VoidArry() { clear(); } VoidsSet *getSet() { return (VoidsSet*)m_pVoid; } VoidsSet *at(OdInt32 n) { if (m_nVoids == 1) return this; return getSet() + n; } bool contains(void *pVoid); void add(void *pVoid, OdGsFiler::SubstitutionActuator *pAct); void kill(void *pVoid); void clear(); }; struct AbstractTyp { void *m_pContainer; AbstractTyp() : m_pContainer(NULL) { } }; typedef std::map RegsMap; typedef std::map SubstsMap; RegsMap m_regs; SubstsMap m_substs; template struct Procs { typedef OdGsFiler_SubstitutorImpl::DataTyp ProcTyp; typedef std::map RegMap; typedef std::map SubstMap; static void makeSubst(void *pPlace, const void *pSubstitution) { *(ProcTyp*)(pPlace) = *(const ProcTyp*)(pSubstitution); } static void runSubst(void *pPlace, const void *pSubstitution, OdGsFiler::SubstitutionActuator *pActuator) { ODA_ASSERT(pActuator); pActuator->applySubstitution(pPlace, pSubstitution, makeSubst); } static void subst(OdGsFiler_SubstitutorImpl &impl, const void *pValue, void *pPlace, OdGsFiler::SubstitutionActuator *pAct, const void *pSubstitution, bool bClear) { if (pPlace && pSubstitution) { runSubst(pPlace, pSubstitution, pAct); return; } if (pValue) { if (pPlace) { RegMap *pRegMap = (RegMap*)impl.m_regs[nBytes].m_pContainer; OD_TYPENAME RegMap::iterator itReg = pRegMap->find(*(const ProcTyp*)pValue); if (itReg != pRegMap->end()) { runSubst(pPlace, itReg->second, pAct); if (bClear) pRegMap->erase(itReg); } } else if (pSubstitution) { SubstMap *pSubMap = (SubstMap*)impl.m_substs[nBytes].m_pContainer; OD_TYPENAME SubstMap::iterator itSub = pSubMap->find(*(const ProcTyp*)pValue); if (itSub != pSubMap->end()) { for (OdInt32 n = 0; n < itSub->second.m_nVoids; n++) runSubst(itSub->second.at(n)->m_pVoid, pSubstitution, itSub->second.at(n)->m_pAct); if (bClear) pSubMap->erase(itSub); } } else { RegMap *pRegMap = (RegMap*)impl.m_regs[nBytes].m_pContainer; SubstMap *pSubMap = (SubstMap*)impl.m_substs[nBytes].m_pContainer; if (pRegMap && pSubMap) { OD_TYPENAME RegMap::iterator itReg = pRegMap->find(*(const ProcTyp*)pValue); OD_TYPENAME SubstMap::iterator itSub = pSubMap->find(*(const ProcTyp*)pValue); if ((itReg != pRegMap->end()) && (itSub != pSubMap->end())) { for (OdInt32 n = 0; n < itSub->second.m_nVoids; n++) runSubst(itSub->second.at(n)->m_pVoid, itReg->second, itSub->second.at(n)->m_pAct); } if (bClear) { if (itReg != pRegMap->end()) pRegMap->erase(itReg); if (itSub != pSubMap->end()) pSubMap->erase(itSub); } } else if (bClear) { if (pRegMap) { OD_TYPENAME RegMap::iterator itReg = pRegMap->find(*(const ProcTyp*)pValue); if (itReg != pRegMap->end()) pRegMap->erase(itReg); } if (pSubMap) { OD_TYPENAME SubstMap::iterator itSub = pSubMap->find(*(const ProcTyp*)pValue); if (itSub != pSubMap->end()) pSubMap->erase(itSub); } } } return; } RegMap *pRegMap = (RegMap*)impl.m_regs[nBytes].m_pContainer; SubstMap *pSubMap = (SubstMap*)impl.m_substs[nBytes].m_pContainer; if (pRegMap && pSubMap) { OD_TYPENAME RegMap::iterator itReg = pRegMap->begin(); while (itReg != pRegMap->end()) { OD_TYPENAME SubstMap::iterator itSub = pSubMap->find(itReg->first); if (itSub != pSubMap->end()) { for (OdInt32 n = 0; n < itSub->second.m_nVoids; n++) runSubst(itSub->second.at(n)->m_pVoid, itReg->second, itSub->second.at(n)->m_pAct); } itReg++; } } if (bClear) { if (pRegMap) { delete pRegMap; impl.m_regs[nBytes].m_pContainer = NULL; } if (pSubMap) { delete pSubMap; impl.m_substs[nBytes].m_pContainer = NULL; } } } static void reg(OdGsFiler_SubstitutorImpl &impl, const void *pValue, const void *pSubstitution, bool bRegister, bool bImmediate) { if (bRegister) { OdGsFiler_SubstitutorImpl::AbstractTyp &cont = impl.m_regs[nBytes]; if (!cont.m_pContainer) cont.m_pContainer = new RegMap; RegMap &pMap = *(RegMap*)cont.m_pContainer; pMap[*(const ProcTyp*)pValue] = *(const ProcTyp*)pSubstitution; } if (bImmediate) subst(impl, pValue, NULL, NULL, pSubstitution, false); } static void req(OdGsFiler_SubstitutorImpl &impl, void *pPlace, OdGsFiler::SubstitutionActuator *pAct, const void *pValue, bool bRegister, bool bImmediate) { if (bRegister) { if (bImmediate) { RegMap *pRegMap = (RegMap*)impl.m_regs[nBytes].m_pContainer; if (pRegMap) { OD_TYPENAME RegMap::iterator itReg = pRegMap->find(*(const ProcTyp*)pValue); if (itReg != pRegMap->end()) { runSubst(pPlace, itReg->second, pAct); return; } } } OdGsFiler_SubstitutorImpl::AbstractTyp &cont = impl.m_substs[nBytes]; if (!cont.m_pContainer) cont.m_pContainer = new SubstMap; SubstMap &pMap = *(SubstMap*)cont.m_pContainer; pMap[*(const ProcTyp*)pValue].add(pPlace, pAct); } else if (bImmediate) subst(impl, pValue, pPlace, pAct, NULL, false); } static void clear(OdGsFiler_SubstitutorImpl &impl, const void *pValue) { RegMap *pRegMap = (RegMap*)impl.m_regs[nBytes].m_pContainer; SubstMap *pSubMap = (SubstMap*)impl.m_substs[nBytes].m_pContainer; if (pValue) { if (pRegMap) { OD_TYPENAME RegMap::iterator it = pRegMap->find(*(const ProcTyp*)pValue); if (it != pRegMap->end()) pRegMap->erase(it); } if (pSubMap) { OD_TYPENAME SubstMap::iterator it = pSubMap->find(*(const ProcTyp*)pValue); if (it != pSubMap->end()) pSubMap->erase(it); } } else { if (pRegMap) { delete pRegMap; impl.m_regs[nBytes].m_pContainer = NULL; } if (pSubMap) { delete pSubMap; impl.m_substs[nBytes].m_pContainer = NULL; } } } }; static OdGsFiler::SubstitutionActuator g_defActuator; static struct OdRxObjectSubstitutionActuator : public OdGsFiler::SubstitutionActuator { OdRxObjectSubstitutionActuator() { } virtual void applySubstitution(void *pPlace, const void *pValue, SetPtrFunc pSetFunc) { OdGsFiler::SubstitutionActuator::applySubstitution(pPlace, pValue, pSetFunc); if (pPlace) (*reinterpret_cast(pPlace))->addRef(); } } g_rxObjectActuator; // Register known substitution virtual void registerSubstitution(const void *pValue, const void *pSubstitution, OdUInt32 size = sizeof(OdIntPtr), bool bRegister = true, bool bImmediate = false); // Register substitution request virtual void requestSubstitution(void *pPlace, const void *pValue, OdUInt32 size = sizeof(OdIntPtr), bool bRegister = true, bool bImmediate = true); // Register substitution request for smart pointer virtual void requestSubstitution(OdBaseObjectPtr *pPlace, const void *pValue, bool bRegister = true, bool bImmediate = true); // Register substitution with non-default behavior virtual void requestSubstitution(void *pPlace, OdGsFiler::SubstitutionActuator *pActuator, const void *pValue, OdUInt32 size = sizeof(OdIntPtr), bool bRegister = true, bool bImmediate = true); // Clear substitutions virtual void clearSubstitutions(const void *pValue = NULL, OdUInt32 size = 0); // Run substitutions virtual void runSubstitutions(const void *pValue = NULL, OdUInt32 size = 0, bool bClear = true); #undef REG_FUNCCALL ~OdGsFiler_SubstitutorImpl() { clearSubstitutions(); } }; // Implement V1 version filer class GS_TOOLKIT_EXPORT OdGsFilerV100Impl : public OdGsFiler { protected: enum Flags { kOpenedForWrite = (1 << 0), kLastFlag = kOpenedForWrite }; protected: mutable OdStreamBufPtr m_pStream; OdGsFilerDbLinkerPtr m_pLinker; OdUInt64 m_nSectionsToWrite; OdUInt64 m_nSectionsToRead; OdUInt32 m_nFlags; OdUInt32 m_nVersion; mutable Section m_nCurSection; mutable OdUInt32 m_nCurSectionSize; struct WrSectionData { OdGsFiler::Section m_type; OdUInt64 m_begin; WrSectionData() : m_type(OdGsFiler::kEOFSection) , m_begin(0) { } WrSectionData(OdGsFiler::Section section, OdUInt32 tell) : m_type(section) , m_begin(tell) { } }; OdStack m_sectionStack; mutable OdSmartPtr m_subst; typedef std::map ArbDataMap; ArbDataMap m_arbData; typedef std::set RegPtrsSet; RegPtrsSet m_regPtrs; protected: bool isWriting() const { return GETBIT(m_nFlags, kOpenedForWrite); } void setWriting(bool bSet) { SETBIT(m_nFlags, kOpenedForWrite, bSet); } void assertWr() const { if (!isWriting()) throw OdError(eNotOpenForWrite); } void assertRd() const { if (isWriting()) throw OdError(eNotOpenForRead); } public: OdGsFilerV100Impl() : m_nSectionsToWrite(OdUInt64(-1)) , m_nSectionsToRead(OdUInt64(-1)) , m_nFlags(0) , m_nVersion(kV2) , m_nCurSection(kEOFSection) , m_nCurSectionSize(0) { m_subst = OdRxObjectImpl::createObject(); } ~OdGsFilerV100Impl() { } OdUInt32 headerTestChunk() const; bool rdHeaderSection(); void wrHeaderSection(); virtual bool setStream(OdStreamBuf *pStream, bool bWrite = false); virtual OdStreamBufPtr getStream() const; virtual void setDatabase(const OdDbBaseDatabase *pDb); virtual OdDbBaseDatabase *getDatabase() const; virtual void setVersion(OdUInt32 nVersion); virtual OdUInt32 version() const; virtual void wrDbHash(const OdDbBaseDatabase *pDb); virtual bool checkDbHash(const OdDbBaseDatabase *pDb); virtual void setWriteSections(OdUInt64 nSections); virtual void setWriteSection(Section section, bool bSet); virtual bool isWriteSection(Section section) const; virtual void setReadSections(OdUInt64 nSections); virtual void setReadSection(Section section, bool bSet); virtual bool isReadSection(Section section) const; virtual void wrSectionBegin(Section section); virtual void wrSectionEnd(Section section); virtual void wrEOFSection(); virtual Section rdSection() const; virtual Section curSection() const; virtual void skipSection() const; virtual void rdBackSection() const; virtual bool checkEOF() const; virtual Substitutor *subst() const; virtual void makeSubstitutions(bool bClear = true) const; virtual OdRxObjectPtr getSubstitutor() const; virtual void setSubstitutor(OdRxObject *pSubst); virtual void setArbitraryData(const OdChar *pName, OdRxObject *pObject); virtual OdRxObjectPtr getArbitraryData(const OdChar *pName) const; virtual bool hasArbitraryData(const OdChar *pName) const; virtual void clearArbitraryData(); virtual void registerPtr(const void *pPtr); virtual void unregisterPtr(const void *pPtr); virtual bool isPtrRegistered(const void *pPtr) const; virtual void clearRegisteredPtrs(); virtual void wrHandle(OdDbStub *pHandle); virtual OdDbStub *rdHandle() const; virtual void wrClass(OdRxObject *pObj); virtual OdRxObjectPtr rdClass() const; virtual void wrRawData(const void *pData, OdUInt32 nDataSize); virtual void rdRawData(void *pData, OdUInt32 nDataSize) const; }; #include "TD_PackPop.h" #endif // __OdGsFilerV100Impl_H__