📄 objostr.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: objostr.cpp,v $ * PRODUCTION Revision 1000.4 2004/06/01 19:41:09 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.95 * PRODUCTION * =========================================================================== *//* $Id: objostr.cpp,v 1000.4 2004/06/01 19:41:09 gouriano Exp $* ===========================================================================** PUBLIC DOMAIN NOTICE* National Center for Biotechnology Information** This software/database is a "United States Government Work" under the* terms of the United States Copyright Act. It was written as part of* the author's official duties as a United States Government employee and* thus cannot be copyrighted. This software/database is freely available* to the public for use. The National Library of Medicine and the U.S.* Government have not placed any restriction on its use or reproduction.** Although all reasonable efforts have been taken to ensure the accuracy* and reliability of the software and data, the NLM and the U.S.* Government do not and cannot warrant the performance or results that* may be obtained by using this software or data. The NLM and the U.S.* Government disclaim all warranties, express or implied, including* warranties of performance, merchantability or fitness for any particular* purpose.** Please cite the author in any work or product based on this material.** ===========================================================================** Author: Eugene Vasilchenko** File Description:* !!! PUT YOUR DESCRIPTION HERE !!!** ===========================================================================*/#include <ncbi_pch.hpp>#include <corelib/ncbistd.hpp>#include <corelib/ncbi_safe_static.hpp>#include <corelib/ncbimtx.hpp>#include <util/bytesrc.hpp>#include <serial/objostr.hpp>#include <serial/objistr.hpp>#include <serial/objcopy.hpp>#include <serial/typeref.hpp>#include <serial/objlist.hpp>#include <serial/memberid.hpp>#include <serial/typeinfo.hpp>#include <serial/enumvalues.hpp>#include <serial/memberlist.hpp>#include <serial/delaybuf.hpp>#include <serial/classinfo.hpp>#include <serial/choice.hpp>#include <serial/aliasinfo.hpp>#include <serial/continfo.hpp>#include <serial/member.hpp>#include <serial/variant.hpp>#include <serial/objectinfo.hpp>#include <serial/objectiter.hpp>#include <serial/objlist.hpp>#include <serial/serialimpl.hpp>#undef _TRACE#define _TRACE(arg) ((void)0)BEGIN_NCBI_SCOPECObjectOStream* CObjectOStream::Open(ESerialDataFormat format, const string& fileName, TSerialOpenFlags openFlags){ CNcbiOstream* outStream = 0; bool deleteStream; if ( (openFlags & eSerial_StdWhenEmpty) && fileName.empty() || (openFlags & eSerial_StdWhenDash) && fileName == "-" || (openFlags & eSerial_StdWhenStd) && fileName == "stdout" ) { outStream = &NcbiCout; deleteStream = false; } else { switch ( format ) { case eSerial_AsnText: case eSerial_Xml: outStream = new CNcbiOfstream(fileName.c_str()); break; case eSerial_AsnBinary: outStream = new CNcbiOfstream(fileName.c_str(), IOS_BASE::out | IOS_BASE::binary); break; default: NCBI_THROW(CSerialException,eFail, "CObjectOStream::Open: unsupported format"); } if ( !*outStream ) { delete outStream; NCBI_THROW(CSerialException,eFail, "cannot open file"); } deleteStream = true; } return Open(format, *outStream, deleteStream);}CObjectOStream* CObjectOStream::Open(ESerialDataFormat format, CNcbiOstream& outStream, bool deleteStream){ switch ( format ) { case eSerial_AsnText: return OpenObjectOStreamAsn(outStream, deleteStream); case eSerial_AsnBinary: return OpenObjectOStreamAsnBinary(outStream, deleteStream); case eSerial_Xml: return OpenObjectOStreamXml(outStream, deleteStream); default: break; } NCBI_THROW(CSerialException,eFail, "CObjectOStream::Open: unsupported format");}/////////////////////////////////////////////////////////////////////////////// data verification setupESerialVerifyData CObjectOStream::ms_VerifyDataDefault = eSerialVerifyData_Default;static CSafeStaticRef< CTls<int> > s_VerifyTLS;void CObjectOStream::SetVerifyDataThread(ESerialVerifyData verify){ x_GetVerifyDataDefault(); ESerialVerifyData tls_verify = ESerialVerifyData(long(s_VerifyTLS->GetValue())); if (tls_verify != eSerialVerifyData_Never && tls_verify != eSerialVerifyData_Always && tls_verify != eSerialVerifyData_DefValueAlways) { s_VerifyTLS->SetValue(reinterpret_cast<int*>(verify)); }}void CObjectOStream::SetVerifyDataGlobal(ESerialVerifyData verify){ x_GetVerifyDataDefault(); if (ms_VerifyDataDefault != eSerialVerifyData_Never && ms_VerifyDataDefault != eSerialVerifyData_Always && ms_VerifyDataDefault != eSerialVerifyData_DefValueAlways) { ms_VerifyDataDefault = verify; }}ESerialVerifyData CObjectOStream::x_GetVerifyDataDefault(void){ ESerialVerifyData verify; if (ms_VerifyDataDefault == eSerialVerifyData_Never || ms_VerifyDataDefault == eSerialVerifyData_Always || ms_VerifyDataDefault == eSerialVerifyData_DefValueAlways) { verify = ms_VerifyDataDefault; } else { verify = ESerialVerifyData(long(s_VerifyTLS->GetValue())); if (verify == eSerialVerifyData_Default) { if (ms_VerifyDataDefault == eSerialVerifyData_Default) { // change the default here, if you wish ms_VerifyDataDefault = eSerialVerifyData_Yes; //ms_VerifyDataDefault = eSerialVerifyData_No; const char* str = getenv(SERIAL_VERIFY_DATA_WRITE); if (str) { if (NStr::CompareNocase(str,"YES") == 0) { ms_VerifyDataDefault = eSerialVerifyData_Yes; } else if (NStr::CompareNocase(str,"NO") == 0) { ms_VerifyDataDefault = eSerialVerifyData_No; } else if (NStr::CompareNocase(str,"NEVER") == 0) { ms_VerifyDataDefault = eSerialVerifyData_Never; } else if (NStr::CompareNocase(str,"ALWAYS") == 0) { ms_VerifyDataDefault = eSerialVerifyData_Always; } else if (NStr::CompareNocase(str,"DEFVALUE") == 0) { ms_VerifyDataDefault = eSerialVerifyData_DefValue; } else if (NStr::CompareNocase(str,"DEFVALUE_ALWAYS") == 0) { ms_VerifyDataDefault = eSerialVerifyData_DefValueAlways; } } } verify = ms_VerifyDataDefault; } } return verify;}/////////////////////////////////////////////////////////////////////////////CObjectOStream::CObjectOStream(ESerialDataFormat format, CNcbiOstream& out, bool deleteOut) : m_Output(out, deleteOut), m_Fail(fNoError), m_Flags(fFlagNone), m_Separator(""), m_AutoSeparator(false), m_DataFormat(format), m_VerifyData(x_GetVerifyDataDefault()){}CObjectOStream::~CObjectOStream(void){ try { Close(); ResetLocalHooks(); } catch (...) { ERR_POST("Can not close output stream"); }}void CObjectOStream::Close(void){ if (m_Fail != fNotOpen) { try { m_Output.Flush(); if ( m_Objects ) m_Objects->Clear(); ClearStack(); m_Fail = fNotOpen; } catch (...) { if ( InGoodState() ) ThrowError(fWriteError, "cannot close output stream"); } }}void CObjectOStream::ResetLocalHooks(void){ CMutexGuard guard(GetTypeInfoMutex()); m_ObjectHookKey.Clear(); m_ClassMemberHookKey.Clear(); m_ChoiceVariantHookKey.Clear();}CObjectOStream::TFailFlags CObjectOStream::SetFailFlagsNoError(TFailFlags flags){ TFailFlags old = m_Fail; m_Fail |= flags; return old;}CObjectOStream::TFailFlags CObjectOStream::SetFailFlags(TFailFlags flags, const char* message){ TFailFlags old = m_Fail; m_Fail |= flags; if ( !old && flags ) { // first fail ERR_POST("CObjectOStream: error at "<< GetPosition()<<": "<<GetStackTrace() << ": " << message); } return old;}bool CObjectOStream::InGoodState(void){ if ( fail() ) { // fail flag already set return false; } else if ( m_Output.fail() ) { // IO exception thrown without setting fail flag SetFailFlags(fWriteError, m_Output.GetError()); m_Output.ResetFail(); return false; } else { // ok return true; }}void CObjectOStream::Unended(const string& msg){ if ( InGoodState() ) ThrowError(fFail, msg);}void CObjectOStream::UnendedFrame(void){ Unended("internal error: unended object stack frame");}void CObjectOStream::x_SetPathHooks(bool set){ if (!m_PathWriteObjectHooks.IsEmpty()) { CWriteObjectHook* hook = m_PathWriteObjectHooks.GetHook(*this); if (hook) { CTypeInfo* item = m_PathWriteObjectHooks.FindType(*this); if (item) { if (set) { item->SetLocalWriteHook(*this, hook); } else { item->ResetLocalWriteHook(*this); } } } } if (!m_PathWriteMemberHooks.IsEmpty()) { CWriteClassMemberHook* hook = m_PathWriteMemberHooks.GetHook(*this); if (hook) { CMemberInfo* item = m_PathWriteMemberHooks.FindItem(*this); if (item) { if (set) { item->SetLocalWriteHook(*this, hook); } else { item->ResetLocalWriteHook(*this); } } } } if (!m_PathWriteVariantHooks.IsEmpty()) { CWriteChoiceVariantHook* hook = m_PathWriteVariantHooks.GetHook(*this); if (hook) { CVariantInfo* item = m_PathWriteVariantHooks.FindItem(*this); if (item) { if (set) { item->SetLocalWriteHook(*this, hook); } else { item->ResetLocalWriteHook(*this); } } } }}void CObjectOStream::SetPathWriteObjectHook(const string& path, CWriteObjectHook* hook){ m_PathWriteObjectHooks.SetHook(path,hook); WatchPathHooks();}void CObjectOStream::SetPathWriteMemberHook(const string& path, CWriteClassMemberHook* hook){ m_PathWriteMemberHooks.SetHook(path,hook); WatchPathHooks();}void CObjectOStream::SetPathWriteVariantHook(const string& path, CWriteChoiceVariantHook* hook){ m_PathWriteVariantHooks.SetHook(path,hook); WatchPathHooks();}string CObjectOStream::GetStackTrace(void) const{ return GetStackTraceASN();}size_t CObjectOStream::GetStreamOffset(void) const{ return m_Output.GetStreamOffset();}string CObjectOStream::GetPosition(void) const{ return "byte "+NStr::UIntToString(GetStreamOffset());}void CObjectOStream::ThrowError1(const char* file, int line, TFailFlags fail, const char* message){ ThrowError1(file,line,fail,string(message));}void CObjectOStream::ThrowError1(const char* file, int line, TFailFlags fail, const string& message){ CSerialException::EErrCode err; SetFailFlags(fail, message.c_str()); try { Flush(); } catch(...) { } switch(fail) { case fNoError: CNcbiDiag(file, line, eDiag_Trace) << message; return; case fEOF: err = CSerialException::eEOF; break; default: case fWriteError: err = CSerialException::eIoError; break; case fFormatError: err = CSerialException::eFormatError; break; case fOverflow: err = CSerialException::eOverflow; break; case fInvalidData: err = CSerialException::eInvalidData; break; case fIllegalCall: err = CSerialException::eIllegalCall; break; case fFail: err = CSerialException::eFail; break; case fNotOpen: err = CSerialException::eNotOpen; break; case fUnassigned: throw CUnassignedMember(file,line,0,CUnassignedMember::eWrite, GetPosition()+": "+message); } throw CSerialException(file,line,0,err,GetPosition()+": "+message);}void CObjectOStream::EndOfWrite(void){ FlushBuffer(); if ( m_Objects ) m_Objects->Clear();} void CObjectOStream::WriteObject(const CConstObjectInfo& object){ WriteObject(object.GetObjectPtr(), object.GetTypeInfo());}void CObjectOStream::WriteClassMember(const CConstObjectInfo::CMemberIterator& member){ const CMemberInfo* memberInfo = member.GetMemberInfo(); TConstObjectPtr classPtr = member.GetClassObject().GetObjectPtr(); WriteClassMember(memberInfo->GetId(), memberInfo->GetTypeInfo(), memberInfo->GetMemberPtr(classPtr));}void CObjectOStream::WriteChoiceVariant(const CConstObjectInfoCV& object){ const CVariantInfo* variantInfo = object.GetVariantInfo(); TConstObjectPtr choicePtr = object.GetChoiceObject().GetObjectPtr(); variantInfo->DefaultWriteVariant(*this, choicePtr);}void CObjectOStream::Write(const CConstObjectInfo& object){ // root writer BEGIN_OBJECT_FRAME2(eFrameNamed, object.GetTypeInfo()); WriteFileHeader(object.GetTypeInfo()); WriteObject(object); EndOfWrite(); END_OBJECT_FRAME(); if ( GetAutoSeparator() ) Separator(*this);}void CObjectOStream::Write(TConstObjectPtr object, TTypeInfo typeInfo){ // root writer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -