📄 objistr.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: objistr.cpp,v $ * PRODUCTION Revision 1000.4 2004/06/01 19:40:54 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.129 * PRODUCTION * =========================================================================== *//* $Id: objistr.cpp,v 1000.4 2004/06/01 19:40:54 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/ncbiutil.hpp>#include <corelib/ncbimtx.hpp>#include <exception>#include <util/bytesrc.hpp>#include <serial/objistr.hpp>#include <serial/typeref.hpp>#include <serial/member.hpp>#include <serial/variant.hpp>#include <serial/classinfo.hpp>#include <serial/choice.hpp>#include <serial/aliasinfo.hpp>#include <serial/continfo.hpp>#include <serial/enumvalues.hpp>#include <serial/memberlist.hpp>#include <serial/delaybuf.hpp>#include <serial/objistrimpl.hpp>#include <serial/objectinfo.hpp>#include <serial/objectiter.hpp>#include <serial/objlist.hpp>#include <serial/choiceptr.hpp>#include <serial/serialimpl.hpp>#include <serial/pack_string.hpp>#include <limits.h>#if HAVE_WINDOWS_H// In MSVC limits.h doesn't define FLT_MIN & FLT_MAX# include <float.h>#endif#undef _TRACE#define _TRACE(arg) ((void)0)BEGIN_NCBI_SCOPECRef<CByteSource> CObjectIStream::GetSource(ESerialDataFormat format, const string& fileName, TSerialOpenFlags openFlags){ if ( (openFlags & eSerial_StdWhenEmpty) && fileName.empty() || (openFlags & eSerial_StdWhenDash) && fileName == "-" || (openFlags & eSerial_StdWhenStd) && fileName == "stdin" ) { return CRef<CByteSource>(new CStreamByteSource(NcbiCin)); } else { bool binary; switch ( format ) { case eSerial_AsnText: case eSerial_Xml: binary = false; break; case eSerial_AsnBinary: binary = true; break; default: NCBI_THROW(CSerialException,eFail, "CObjectIStream::Open: unsupported format"); } if ( (openFlags & eSerial_UseFileForReread) ) { // use file as permanent file return CRef<CByteSource>(new CFileByteSource(fileName, binary)); } else { // open file as stream return CRef<CByteSource>(new CFStreamByteSource(fileName, binary)); } }}CRef<CByteSource> CObjectIStream::GetSource(CNcbiIstream& inStream, bool deleteInStream){ if ( deleteInStream ) { return CRef<CByteSource>(new CFStreamByteSource(inStream)); } else { return CRef<CByteSource>(new CStreamByteSource(inStream)); }}CObjectIStream* CObjectIStream::Create(ESerialDataFormat format){ switch ( format ) { case eSerial_AsnText: return CreateObjectIStreamAsn(); case eSerial_AsnBinary: return CreateObjectIStreamAsnBinary(); case eSerial_Xml: return CreateObjectIStreamXml(); default: break; } NCBI_THROW(CSerialException,eFail, "CObjectIStream::Open: unsupported format");}CObjectIStream* CObjectIStream::Create(ESerialDataFormat format, CByteSource& source){ AutoPtr<CObjectIStream> stream(Create(format)); stream->Open(source); return stream.release();}CObjectIStream* CObjectIStream::Create(ESerialDataFormat format, CByteSourceReader& reader){ AutoPtr<CObjectIStream> stream(Create(format)); stream->Open(reader); return stream.release();}CObjectIStream* CObjectIStream::Open(ESerialDataFormat format, CNcbiIstream& inStream, bool deleteInStream){ CRef<CByteSource> src = GetSource(inStream, deleteInStream); return Create(format, *src);}CObjectIStream* CObjectIStream::Open(ESerialDataFormat format, const string& fileName, TSerialOpenFlags openFlags){ CRef<CByteSource> src = GetSource(format, fileName, openFlags); return Create(format, *src);}/////////////////////////////////////////////////////////////////////////////// data verification setupESerialVerifyData CObjectIStream::ms_VerifyDataDefault = eSerialVerifyData_Default;static CSafeStaticRef< CTls<int> > s_VerifyTLS;void CObjectIStream::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 CObjectIStream::SetVerifyDataGlobal(ESerialVerifyData verify){ x_GetVerifyDataDefault(); if (ms_VerifyDataDefault != eSerialVerifyData_Never && ms_VerifyDataDefault != eSerialVerifyData_Always && ms_VerifyDataDefault != eSerialVerifyData_DefValueAlways) { ms_VerifyDataDefault = verify; }}ESerialVerifyData CObjectIStream::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_READ); 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;}/////////////////////////////////////////////////////////////////////////////// skip unknown members setupESerialSkipUnknown CObjectIStream::ms_SkipUnknownDefault = eSerialSkipUnknown_Default;static CSafeStaticRef< CTls<int> > s_SkipTLS;void CObjectIStream::SetSkipUnknownThread(ESerialSkipUnknown skip){ x_GetSkipUnknownDefault(); ESerialSkipUnknown tls_skip = ESerialSkipUnknown(long(s_SkipTLS->GetValue())); if (tls_skip != eSerialSkipUnknown_Never && tls_skip != eSerialSkipUnknown_Always) { s_SkipTLS->SetValue(reinterpret_cast<int*>(skip)); }}void CObjectIStream::SetSkipUnknownGlobal(ESerialSkipUnknown skip){ x_GetSkipUnknownDefault(); if (ms_SkipUnknownDefault != eSerialSkipUnknown_Never && ms_SkipUnknownDefault != eSerialSkipUnknown_Always) { ms_SkipUnknownDefault = skip; }}ESerialSkipUnknown CObjectIStream::x_GetSkipUnknownDefault(void){ ESerialSkipUnknown skip; if (ms_SkipUnknownDefault == eSerialSkipUnknown_Never || ms_SkipUnknownDefault == eSerialSkipUnknown_Always) { skip = ms_SkipUnknownDefault; } else { skip = ESerialSkipUnknown(long(s_SkipTLS->GetValue())); if (skip == eSerialSkipUnknown_Default) { if (ms_SkipUnknownDefault == eSerialSkipUnknown_Default) { // change the default here, if you wish ms_SkipUnknownDefault = eSerialSkipUnknown_No; //ms_SkipUnknownDefault = eSerialSkipUnknown_Yes; const char* str = getenv(SERIAL_SKIP_UNKNOWN_MEMBERS); if (str) { if (NStr::CompareNocase(str,"YES") == 0) { ms_SkipUnknownDefault = eSerialSkipUnknown_Yes; } else if (NStr::CompareNocase(str,"NO") == 0) { ms_SkipUnknownDefault = eSerialSkipUnknown_No; } else if (NStr::CompareNocase(str,"NEVER") == 0) { ms_SkipUnknownDefault = eSerialSkipUnknown_Never; } else if (NStr::CompareNocase(str,"ALWAYS") == 0) { ms_SkipUnknownDefault = eSerialSkipUnknown_Always; } } } skip = ms_SkipUnknownDefault; } } return skip;}/////////////////////////////////////////////////////////////////////////////CObjectIStream::CObjectIStream(ESerialDataFormat format) : m_DiscardCurrObject(false), m_DataFormat(format), m_VerifyData(x_GetVerifyDataDefault()), m_SkipUnknown(x_GetSkipUnknownDefault()), m_Fail(fNotOpen), m_Flags(fFlagNone){}CObjectIStream::~CObjectIStream(void){ try { Close(); ResetLocalHooks(); } catch (...) { ERR_POST("Can not close input stream"); }}void CObjectIStream::Open(CByteSourceReader& reader){ Close(); _ASSERT(m_Fail == fNotOpen); m_Input.Open(reader); m_Fail = 0;}void CObjectIStream::Open(CByteSource& source){ CRef<CByteSourceReader> reader = source.Open(); Open(*reader);}void CObjectIStream::Open(CNcbiIstream& inStream, bool deleteInStream){ CRef<CByteSource> src = GetSource(inStream, deleteInStream); Open(*src);}void CObjectIStream::ResetLocalHooks(void){ CMutexGuard guard(GetTypeInfoMutex()); m_ObjectHookKey.Clear(); m_ClassMemberHookKey.Clear(); m_ChoiceVariantHookKey.Clear(); m_ObjectSkipHookKey.Clear(); m_ClassMemberSkipHookKey.Clear(); m_ChoiceVariantSkipHookKey.Clear();}void CObjectIStream::Close(void){ if (m_Fail != fNotOpen) { m_Input.Close(); if ( m_Objects ) m_Objects->Clear(); ClearStack(); m_Fail = fNotOpen; }}CObjectIStream::TFailFlags CObjectIStream::SetFailFlags(TFailFlags flags, const char* message){ TFailFlags old = m_Fail; if (flags == fNoError) { m_Fail = flags; } else { m_Fail |= flags; if ( !old && flags ) { // first fail// redundant// ERR_POST(Error << "CObjectIStream: error at "<<// GetPosition()<<": "<<GetStackTrace() << ": " << message); } } return old;}bool CObjectIStream::InGoodState(void){ if ( fail() ) { // fail flag already set return false; } else if ( m_Input.fail() ) { // IO exception thrown without setting fail flag SetFailFlags(fReadError, m_Input.GetError()); m_Input.ResetFail(); return false; } else { // ok return true; }}void CObjectIStream::Unended(const string& msg){ if ( InGoodState() ) ThrowError(fFail, msg);}void CObjectIStream::UnendedFrame(void){ Unended("internal error: unended object stack frame");}void CObjectIStream::x_SetPathHooks(bool set){ if (!m_PathReadObjectHooks.IsEmpty()) { CReadObjectHook* hook = m_PathReadObjectHooks.GetHook(*this); if (hook) { CTypeInfo* item = m_PathReadObjectHooks.FindType(*this); if (item) { if (set) { item->SetLocalReadHook(*this, hook); } else { item->ResetLocalReadHook(*this); } } } } if (!m_PathSkipObjectHooks.IsEmpty()) { CSkipObjectHook* hook = m_PathSkipObjectHooks.GetHook(*this); if (hook) { CTypeInfo* item = m_PathSkipObjectHooks.FindType(*this); if (item) { if (set) { item->SetLocalSkipHook(*this, hook); } else { item->ResetLocalSkipHook(*this); } } } } if (!m_PathReadMemberHooks.IsEmpty()) { CReadClassMemberHook* hook = m_PathReadMemberHooks.GetHook(*this); if (hook) { CMemberInfo* item = m_PathReadMemberHooks.FindItem(*this); if (item) { if (set) { item->SetLocalReadHook(*this, hook); } else { item->ResetLocalReadHook(*this); } } } } if (!m_PathSkipMemberHooks.IsEmpty()) { CSkipClassMemberHook* hook = m_PathSkipMemberHooks.GetHook(*this); if (hook) { CMemberInfo* item = m_PathSkipMemberHooks.FindItem(*this); if (item) { if (set) { item->SetLocalSkipHook(*this, hook); } else { item->ResetLocalSkipHook(*this); } } } } if (!m_PathReadVariantHooks.IsEmpty()) { CReadChoiceVariantHook* hook = m_PathReadVariantHooks.GetHook(*this); if (hook) { CVariantInfo* item = m_PathReadVariantHooks.FindItem(*this); if (item) { if (set) { item->SetLocalReadHook(*this, hook); } else { item->ResetLocalReadHook(*this); } } } } if (!m_PathSkipVariantHooks.IsEmpty()) { CSkipChoiceVariantHook* hook = m_PathSkipVariantHooks.GetHook(*this); if (hook) { CVariantInfo* item = m_PathSkipVariantHooks.FindItem(*this); if (item) { if (set) { item->SetLocalSkipHook(*this, hook); } else { item->ResetLocalSkipHook(*this); } } } }}void CObjectIStream::SetPathReadObjectHook(const string& path, CReadObjectHook* hook){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -