serialobject.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:17k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: serialobject.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 19:41:49  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.24
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: serialobject.cpp,v 1000.4 2004/06/01 19:41:49 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author:  Aleksey Grichenko
  35. *
  36. * File Description:
  37. *   Base class for serializable objects
  38. *
  39. * ---------------------------------------------------------------------------
  40. * $Log: serialobject.cpp,v $
  41. * Revision 1000.4  2004/06/01 19:41:49  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.24
  43. *
  44. * Revision 1.24  2004/05/17 21:03:03  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.23  2004/03/25 15:57:08  gouriano
  48. * Added possibility to copy and compare serial object non-recursively
  49. *
  50. * Revision 1.22  2004/02/09 18:22:35  gouriano
  51. * enforced checking environment vars when setting initialization
  52. * verification parameters
  53. *
  54. * Revision 1.21  2004/01/16 19:56:09  gouriano
  55. * Added I/O stream manipulators for serializable objects
  56. *
  57. * Revision 1.20  2003/11/21 16:17:44  vasilche
  58. * Correct closing of ASN.1 stream in DebugDump.
  59. *
  60. * Revision 1.19  2003/11/17 22:13:23  gouriano
  61. * in CSerialObject::Assign: on self-assignment issue a warning only
  62. *
  63. * Revision 1.18  2003/11/17 14:39:15  gouriano
  64. * Prohibit assignment of a serial object to itself
  65. *
  66. * Revision 1.17  2003/11/13 14:07:38  gouriano
  67. * Elaborated data verification on read/write/get to enable skipping mandatory class data members
  68. *
  69. * Revision 1.16  2003/09/22 20:56:31  gouriano
  70. * Changed base type of AnyContent object to CSerialObject
  71. *
  72. * Revision 1.15  2003/09/16 14:48:36  gouriano
  73. * Enhanced AnyContent objects to support XML namespaces and attribute info items.
  74. *
  75. * Revision 1.14  2003/08/25 15:59:09  gouriano
  76. * added possibility to use namespaces in XML i/o streams
  77. *
  78. * Revision 1.13  2003/08/13 15:47:45  gouriano
  79. * implemented serialization of AnyContent objects
  80. *
  81. * Revision 1.12  2003/07/17 18:48:01  gouriano
  82. * re-enabled initialization verification
  83. *
  84. * Revision 1.11  2003/06/25 17:49:05  gouriano
  85. * fixed verification flag initialization, disabled verification
  86. *
  87. * Revision 1.10  2003/06/04 21:23:04  gouriano
  88. * changed the value of ms_UnassignedStr
  89. *
  90. * Revision 1.9  2003/05/21 16:12:04  vasilche
  91. * Correct index argument to ThrowUnassigned() to match index of GetItemInfo().
  92. *
  93. * Revision 1.8  2003/05/21 16:01:52  vasilche
  94. * Avoid failed assert while generating exception message.
  95. *
  96. * Revision 1.7  2003/04/29 18:30:37  gouriano
  97. * object data member initialization verification
  98. *
  99. * Revision 1.6  2003/01/22 18:54:09  gouriano
  100. * added unfreezing of the string stream
  101. *
  102. * Revision 1.5  2003/01/06 17:14:15  gouriano
  103. * corrected CSerialObject::DebugDump: disabled autoseparator in output stream
  104. *
  105. * Revision 1.4  2002/07/30 20:24:58  grichenk
  106. * Fixed error messages in Assign() and Equals()
  107. *
  108. * Revision 1.3  2002/05/30 14:16:44  gouriano
  109. * fix in debugdump: memory leak
  110. *
  111. * Revision 1.2  2002/05/29 21:19:17  gouriano
  112. * added debug dump
  113. *
  114. * Revision 1.1  2002/05/15 20:20:38  grichenk
  115. * Initial revision
  116. *
  117. *
  118. * ===========================================================================
  119. */
  120. #include <ncbi_pch.hpp>
  121. #include <corelib/ncbi_safe_static.hpp>
  122. #include <serial/serialbase.hpp>
  123. #include <serial/typeinfo.hpp>
  124. #include <serial/objostr.hpp>
  125. #include <serial/objistr.hpp>
  126. #include <serial/classinfob.hpp>
  127. BEGIN_NCBI_SCOPE
  128. CSerialObject::CSerialObject(void)
  129. {
  130. }
  131. CSerialObject::~CSerialObject()
  132. {
  133. }
  134. void CSerialObject::Assign(const CSerialObject& source, ESerialRecursionMode how)
  135. {
  136.     if (this == &source) {
  137.         ERR_POST(Warning <<
  138.             "CSerialObject::Assign(): an attempt to assign a serial object to itself");
  139.         return;
  140.     }
  141.     if ( typeid(source) != typeid(*this) ) {
  142.         ERR_POST(Fatal <<
  143.             "CSerialObject::Assign() -- Assignment of incompatible types: " <<
  144.             typeid(*this).name() << " = " << typeid(source).name());
  145.     }
  146.     GetThisTypeInfo()->Assign(this, &source, how);
  147. }
  148. bool CSerialObject::Equals(const CSerialObject& object, ESerialRecursionMode how) const
  149. {
  150.     if ( typeid(object) != typeid(*this) ) {
  151.         ERR_POST(Fatal <<
  152.             "CSerialObject::Equals() -- Can not compare types: " <<
  153.             typeid(*this).name() << " == " << typeid(object).name());
  154.     }
  155.     return GetThisTypeInfo()->Equals(this, &object, how);
  156. }
  157. void CSerialObject::DebugDump(CDebugDumpContext ddc, unsigned int depth) const
  158. {
  159.     ddc.SetFrame("CSerialObject");
  160.     CObject::DebugDump( ddc, depth);
  161. // this is not good, but better than nothing
  162.     CNcbiOstrstream ostr;
  163.     ostr << "n****** begin ASN dump ******n";
  164.     {{
  165.         auto_ptr<CObjectOStream> oos(CObjectOStream::Open(eSerial_AsnText,
  166.                                                           ostr));
  167.         oos->SetAutoSeparator(false);
  168.         oos->Write(this, GetThisTypeInfo());
  169.     }}
  170.     ostr << "n****** end   ASN dump ******n" << '';
  171.     const char* str = ostr.str();
  172.     ostr.freeze();
  173.     ddc.Log( "Serial_AsnText", str);
  174. }
  175. /////////////////////////////////////////////////////////////////////////////
  176. // data verification setup
  177. const char* CSerialObject::ms_UnassignedStr = "<*unassigned*>";
  178. const char  CSerialObject::ms_UnassignedByte = char(0xcd);
  179. ESerialVerifyData CSerialObject::ms_VerifyDataDefault = eSerialVerifyData_Default;
  180. static CSafeStaticRef< CTls<int> > s_VerifyTLS;
  181. void CSerialObject::SetVerifyDataThread(ESerialVerifyData verify)
  182. {
  183.     x_GetVerifyData();
  184.     ESerialVerifyData tls_verify = ESerialVerifyData(long(s_VerifyTLS->GetValue()));
  185.     if (tls_verify != eSerialVerifyData_Never &&
  186.         tls_verify != eSerialVerifyData_Always &&
  187.         tls_verify != eSerialVerifyData_DefValueAlways) {
  188.         s_VerifyTLS->SetValue(reinterpret_cast<int*>(verify));
  189.     }
  190. }
  191. void CSerialObject::SetVerifyDataGlobal(ESerialVerifyData verify)
  192. {
  193.     x_GetVerifyData();
  194.     if (ms_VerifyDataDefault != eSerialVerifyData_Never &&
  195.         ms_VerifyDataDefault != eSerialVerifyData_Always &&
  196.         ms_VerifyDataDefault != eSerialVerifyData_DefValueAlways) {
  197.         ms_VerifyDataDefault = verify;
  198.     }
  199. }
  200. ESerialVerifyData CSerialObject::x_GetVerifyData(void)
  201. {
  202.     ESerialVerifyData verify;
  203.     if (ms_VerifyDataDefault == eSerialVerifyData_Never ||
  204.         ms_VerifyDataDefault == eSerialVerifyData_Always ||
  205.         ms_VerifyDataDefault == eSerialVerifyData_DefValueAlways) {
  206.         verify = ms_VerifyDataDefault;
  207.     } else {
  208.         verify = ESerialVerifyData(long(s_VerifyTLS->GetValue()));
  209.         if (verify == eSerialVerifyData_Default) {
  210.             if (ms_VerifyDataDefault == eSerialVerifyData_Default) {
  211.                 // change the default here, if you wish
  212.                 ms_VerifyDataDefault = eSerialVerifyData_Yes;
  213.                 //ms_VerifyDataDefault = eSerialVerifyData_No;
  214.                 const char* str = getenv(SERIAL_VERIFY_DATA_GET);
  215.                 if (str) {
  216.                     if (NStr::CompareNocase(str,"YES") == 0) {
  217.                         ms_VerifyDataDefault = eSerialVerifyData_Yes;
  218.                     } else if (NStr::CompareNocase(str,"NO") == 0) {
  219.                         ms_VerifyDataDefault = eSerialVerifyData_No;
  220.                     } else if (NStr::CompareNocase(str,"NEVER") == 0) {
  221.                         ms_VerifyDataDefault = eSerialVerifyData_Never;
  222.                     } else  if (NStr::CompareNocase(str,"ALWAYS") == 0) {
  223.                         ms_VerifyDataDefault = eSerialVerifyData_Always;
  224.                     } else  if (NStr::CompareNocase(str,"DEFVALUE") == 0) {
  225.                         ms_VerifyDataDefault = eSerialVerifyData_DefValue;
  226.                     } else  if (NStr::CompareNocase(str,"DEFVALUE_ALWAYS") == 0) {
  227.                         ms_VerifyDataDefault = eSerialVerifyData_DefValueAlways;
  228.                     }
  229.                 }
  230.             }
  231.             verify = ms_VerifyDataDefault;
  232.         }
  233.     }
  234.     switch (verify) {
  235.     default:
  236.     case eSerialVerifyData_Default:
  237.         return ms_VerifyDataDefault;
  238.     case eSerialVerifyData_No:
  239.     case eSerialVerifyData_Never:
  240.         return eSerialVerifyData_No;
  241.         break;
  242.     case eSerialVerifyData_Yes:
  243.     case eSerialVerifyData_Always:
  244.         return eSerialVerifyData_Yes;
  245.         break;
  246.     case eSerialVerifyData_DefValue:
  247.     case eSerialVerifyData_DefValueAlways:
  248.         return eSerialVerifyData_No;
  249.     }
  250. }
  251. void CSerialObject::ThrowUnassigned(TMemberIndex index) const
  252. {
  253.     if (x_GetVerifyData() == eSerialVerifyData_Yes) {
  254.         const CTypeInfo* type = GetThisTypeInfo();
  255.         CNcbiOstrstream s;
  256.         s << type->GetModuleName() << "::" << type->GetName() << ".";
  257.         const CClassTypeInfoBase* classtype =
  258.             dynamic_cast<const CClassTypeInfoBase*>(type);
  259.         // offset index as the argument is zero based but items are 1 based
  260.         index += classtype->GetItems().FirstIndex();
  261.         if ( classtype &&
  262.              index >= classtype->GetItems().FirstIndex() &&
  263.              index <= classtype->GetItems().LastIndex() ) {
  264.             s << classtype->GetItems().GetItemInfo(index)->GetId().GetName();
  265.         } else {
  266.             s << '[' << index << ']';
  267.         }
  268.         NCBI_THROW(CUnassignedMember,eGet,CNcbiOstrstreamToString(s));
  269.     }
  270. }
  271. bool CSerialObject::HasNamespaceName(void) const
  272. {
  273.     return GetThisTypeInfo()->HasNamespaceName();
  274. }
  275. const string& CSerialObject::GetNamespaceName(void) const
  276. {
  277.     return GetThisTypeInfo()->GetNamespaceName();
  278. }
  279. void CSerialObject::SetNamespaceName(const string& ns_name)
  280. {
  281.     GetThisTypeInfo()->SetNamespaceName(ns_name);
  282. }
  283. bool CSerialObject::HasNamespacePrefix(void) const
  284. {
  285.     return GetThisTypeInfo()->HasNamespacePrefix();
  286. }
  287. const string& CSerialObject::GetNamespacePrefix(void) const
  288. {
  289.     return GetThisTypeInfo()->GetNamespacePrefix();
  290. }
  291. void CSerialObject::SetNamespacePrefix(const string& ns_prefix)
  292. {
  293.     GetThisTypeInfo()->SetNamespacePrefix(ns_prefix);
  294. }
  295. CSerialAttribInfoItem::CSerialAttribInfoItem(
  296.     const string& name, const string& ns_name, const string& value)
  297.     : m_Name(name), m_NsName(ns_name), m_Value(value)
  298. {
  299. }
  300. CSerialAttribInfoItem::CSerialAttribInfoItem(const CSerialAttribInfoItem& other)
  301.     : m_Name(other.m_Name), m_NsName(other.m_NsName), m_Value(other.m_Value)
  302. {
  303. }
  304. CSerialAttribInfoItem::~CSerialAttribInfoItem(void)
  305. {
  306. }
  307. const string& CSerialAttribInfoItem::GetName(void) const
  308. {
  309.     return m_Name;
  310. }
  311. const string& CSerialAttribInfoItem::GetNamespaceName(void) const
  312. {
  313.     return m_NsName;
  314. }
  315. const string& CSerialAttribInfoItem::GetValue(void) const
  316. {
  317.     return m_Value;
  318. }
  319. CAnyContentObject::CAnyContentObject(void)
  320. {
  321. }
  322. CAnyContentObject::CAnyContentObject(const CAnyContentObject& other)
  323. {
  324.     x_Copy(other);
  325. }
  326. CAnyContentObject::~CAnyContentObject(void)
  327. {
  328. }
  329. const CTypeInfo* CAnyContentObject::GetTypeInfo(void)
  330. {
  331.     return CStdTypeInfo<ncbi::CAnyContentObject>::GetTypeInfo();
  332. }
  333. void CAnyContentObject::Reset(void)
  334. {
  335.     m_Name.erase();
  336.     m_Value.erase();
  337.     m_NsName.erase();
  338.     m_NsPrefix.erase();
  339.     m_Attlist.clear();
  340. }
  341. void CAnyContentObject::x_Copy(const CAnyContentObject& other)
  342. {
  343.     m_Name = other.m_Name;
  344.     m_Value= other.m_Value;
  345.     m_NsName= other.m_NsName;
  346.     m_NsPrefix= other.m_NsPrefix;
  347.     m_Attlist.clear();
  348.     vector<CSerialAttribInfoItem>::const_iterator it;
  349.     for (it = other.m_Attlist.begin(); it != other.m_Attlist.end(); ++it) {
  350.         m_Attlist.push_back( *it);
  351.     }
  352. }
  353. CAnyContentObject& CAnyContentObject::operator= (const CAnyContentObject& other)
  354. {
  355.     x_Copy(other);
  356.     return *this;
  357. }
  358. bool CAnyContentObject::operator== (const CAnyContentObject& other) const
  359. {
  360.     return m_Name == other.GetName() &&
  361.            m_Value == other.GetValue() &&
  362.            m_NsName == other.m_NsName;
  363. }
  364. void CAnyContentObject::SetName(const string& name)
  365. {
  366.     m_Name = name;
  367. }
  368. const string& CAnyContentObject::GetName(void) const
  369. {
  370.     return m_Name;
  371. }
  372. void CAnyContentObject::SetValue(const string& value)
  373. {
  374.     x_Decode(value);
  375. }
  376. const string& CAnyContentObject::GetValue(void) const
  377. {
  378.     return m_Value;
  379. }
  380. void CAnyContentObject::SetNamespaceName(const string& ns_name)
  381. {
  382.     m_NsName = ns_name;
  383. }
  384. const string& CAnyContentObject::GetNamespaceName(void) const
  385. {
  386.     return m_NsName;
  387. }
  388. void CAnyContentObject::SetNamespacePrefix(const string& ns_prefix)
  389. {
  390.     m_NsPrefix = ns_prefix;
  391. }
  392. const string& CAnyContentObject::GetNamespacePrefix(void) const
  393. {
  394.     return m_NsPrefix;
  395. }
  396. void CAnyContentObject::x_Decode(const string& value)
  397. {
  398.     m_Value = value;
  399. }
  400. void CAnyContentObject::AddAttribute(
  401.     const string& name, const string& ns_name, const string& value)
  402. {
  403. // TODO: check if an attrib with this name+ns_name already exists
  404.     m_Attlist.push_back( CSerialAttribInfoItem( name,ns_name,value));
  405. }
  406. const vector<CSerialAttribInfoItem>&
  407. CAnyContentObject::GetAttributes(void) const
  408. {
  409.     return m_Attlist;
  410. }
  411. /////////////////////////////////////////////////////////////////////////////
  412. //  I/O stream manipulators and helpers for serializable objects
  413. #define  eFmt_AsnText     (1l <<  0)
  414. #define  eFmt_AsnBinary   (1l <<  1)
  415. #define  eFmt_Xml         (1l <<  2)
  416. #define  eFmt_All         (eFmt_AsnText | eFmt_AsnBinary | eFmt_Xml)
  417. #define  eVerify_No       (1l <<  8)
  418. #define  eVerify_Yes      (1l <<  9)
  419. #define  eVerify_DefValue (1l << 10)
  420. #define  eVerify_All      (eVerify_No | eVerify_Yes | eVerify_DefValue)
  421. static
  422. long& s_SerFlags(CNcbiIos& io)
  423. {
  424.     static int s_SerIndex;
  425.     {{  // Make sure to get a unique IOS index
  426.         static bool s_HaveIndex = false;
  427.         if ( !s_HaveIndex ) {
  428.             s_SerIndex = CNcbiIos::xalloc();
  429.             s_HaveIndex = true;
  430.         }
  431.     }}
  432.     return io.iword(s_SerIndex);
  433. }
  434. static
  435. ESerialDataFormat s_SerFormat(CNcbiIos& io)
  436. {
  437.     switch (s_SerFlags(io) & eFmt_All) {
  438.     case eFmt_AsnText:     return eSerial_AsnText;
  439.     case eFmt_AsnBinary:   return eSerial_AsnBinary;
  440.     case eFmt_Xml:         return eSerial_Xml;
  441.     default:               return eSerial_None;
  442.     }
  443. }
  444. static
  445. ESerialVerifyData s_SerVerify(CNcbiIos& io)
  446. {
  447.     switch (s_SerFlags(io) & eVerify_All) {
  448.     case eVerify_No:       return eSerialVerifyData_No;
  449.     case eVerify_Yes:      return eSerialVerifyData_Yes;
  450.     case eVerify_DefValue: return eSerialVerifyData_DefValue;
  451.     default:               return eSerialVerifyData_Default;
  452.     }
  453. }
  454. // Formatting
  455. CNcbiIos& MSerial_AsnText(CNcbiIos& io)
  456. {
  457.     s_SerFlags(io) = (s_SerFlags(io) & ~eFmt_All) | eFmt_AsnText;
  458.     return io;
  459. }
  460. CNcbiIos& MSerial_AsnBinary(CNcbiIos& io)
  461. {
  462.     s_SerFlags(io) = (s_SerFlags(io) & ~eFmt_All) | eFmt_AsnBinary;
  463.     return io;
  464. }
  465. CNcbiIos& MSerial_Xml(CNcbiIos& io)
  466. {
  467.     s_SerFlags(io) = (s_SerFlags(io) & ~eFmt_All) | eFmt_Xml;
  468.     return io;
  469. }
  470. // Class member assignment verification
  471. CNcbiIos& MSerial_VerifyDefault(CNcbiIos& io)
  472. {
  473.     s_SerFlags(io) = (s_SerFlags(io) & ~eVerify_All);
  474.     return io;
  475. }
  476. CNcbiIos& MSerial_VerifyNo(CNcbiIos& io)
  477. {
  478.     s_SerFlags(io) = (s_SerFlags(io) & ~eVerify_All) | eVerify_No;
  479.     return io;
  480. }
  481. CNcbiIos& MSerial_VerifyYes(CNcbiIos& io)
  482. {
  483.     s_SerFlags(io) = (s_SerFlags(io) & ~eVerify_All) | eVerify_Yes;
  484.     return io;
  485. }
  486. CNcbiIos& MSerial_VerifyDefValue(CNcbiIos& io)
  487. {
  488.     s_SerFlags(io) = (s_SerFlags(io) & ~eVerify_All) | eVerify_DefValue;
  489.     return io;
  490. }
  491. // Input/output
  492. CNcbiOstream& operator<< (CNcbiOstream& os, const CSerialObject& obj)
  493. {
  494.     auto_ptr<CObjectOStream> ostr( CObjectOStream::Open(s_SerFormat(os), os) );
  495.     ostr->SetVerifyData(s_SerVerify(os));
  496.     ostr->Write(&obj,obj.GetThisTypeInfo());
  497.     return os;
  498. }
  499. CNcbiIstream& operator>> (CNcbiIstream& is, CSerialObject& obj)
  500. {
  501.     auto_ptr<CObjectIStream> istr( CObjectIStream::Open(s_SerFormat(is), is) );
  502.     istr->SetVerifyData(s_SerVerify(is));
  503.     istr->Read(&obj,obj.GetThisTypeInfo());
  504.     return is;
  505. }
  506. END_NCBI_SCOPE