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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: enumtype.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:42:58  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.26
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: enumtype.cpp,v 1000.1 2004/06/01 19:42:58 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: Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Type description for enumerated types
  38. *
  39. * ---------------------------------------------------------------------------
  40. * $Log: enumtype.cpp,v $
  41. * Revision 1000.1  2004/06/01 19:42:58  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.26
  43. *
  44. * Revision 1.26  2004/05/17 21:03:14  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.25  2004/05/12 18:33:01  gouriano
  48. * Added type conversion check (when using _type DEF file directive)
  49. *
  50. * Revision 1.24  2003/06/16 14:41:05  gouriano
  51. * added possibility to convert DTD to XML schema
  52. *
  53. * Revision 1.23  2003/05/14 14:42:22  gouriano
  54. * added generation of XML schema
  55. *
  56. * Revision 1.22  2003/03/11 20:06:47  kuznets
  57. * iterate -> ITERATE
  58. *
  59. * Revision 1.21  2001/05/17 15:07:12  lavr
  60. * Typos corrected
  61. *
  62. * Revision 1.20  2000/12/15 15:38:51  vasilche
  63. * Added support of Int8 and long double.
  64. * Added support of BigInt ASN.1 extension - mapped to Int8.
  65. * Enum values now have type Int4 instead of long.
  66. *
  67. * Revision 1.19  2000/11/29 17:42:44  vasilche
  68. * Added CComment class for storing/printing ASN.1/XML module comments.
  69. * Added srcutil.hpp file to reduce file dependency.
  70. *
  71. * Revision 1.18  2000/11/20 17:26:32  vasilche
  72. * Fixed warnings on 64 bit platforms.
  73. * Updated names of config variables.
  74. *
  75. * Revision 1.17  2000/11/15 20:34:54  vasilche
  76. * Added user comments to ENUMERATED types.
  77. * Added storing of user comments to ASN.1 module definition.
  78. *
  79. * Revision 1.16  2000/11/14 21:41:24  vasilche
  80. * Added preserving of ASN.1 definition comments.
  81. *
  82. * Revision 1.15  2000/11/08 17:02:51  vasilche
  83. * Added generation of modular DTD files.
  84. *
  85. * Revision 1.14  2000/11/07 17:26:25  vasilche
  86. * Added module names to CTypeInfo and CEnumeratedTypeValues
  87. * Added possibility to set include directory for whole module
  88. *
  89. * Revision 1.13  2000/09/18 20:00:29  vasilche
  90. * Separated CVariantInfo and CMemberInfo.
  91. * Implemented copy hooks.
  92. * All hooks now are stored in CTypeInfo/CMemberInfo/CVariantInfo.
  93. * Most type specific functions now are implemented via function pointers instead of virtual functions.
  94. *
  95. * Revision 1.12  2000/08/25 15:59:21  vasilche
  96. * Renamed directory tool -> datatool.
  97. *
  98. * Revision 1.11  2000/05/24 20:09:28  vasilche
  99. * Implemented DTD generation.
  100. *
  101. * Revision 1.10  2000/04/17 19:11:08  vasilche
  102. * Fixed failed assertion.
  103. * Removed redundant namespace specifications.
  104. *
  105. * Revision 1.9  2000/04/12 15:36:51  vasilche
  106. * Added -on <namespace> argument to datatool.
  107. * Removed unnecessary namespace specifications in generated files.
  108. *
  109. * Revision 1.8  2000/04/07 19:26:25  vasilche
  110. * Added namespace support to datatool.
  111. * By default with argument -oR datatool will generate objects in namespace
  112. * NCBI_NS_NCBI::objects (aka ncbi::objects).
  113. * Datatool's classes also moved to NCBI namespace.
  114. *
  115. * Revision 1.7  2000/02/17 20:05:07  vasilche
  116. * Inline methods now will be generated in *_Base.inl files.
  117. * Fixed processing of StringStore.
  118. * Renamed in choices: Selected() -> Which(), E_choice -> E_Choice.
  119. * Enumerated values now will preserve case as in ASN.1 definition.
  120. *
  121. * Revision 1.6  2000/02/01 21:47:57  vasilche
  122. * Added CGeneratedChoiceTypeInfo for generated choice classes.
  123. * Removed CMemberInfo subclasses.
  124. * Added support for DEFAULT/OPTIONAL members.
  125. * Changed class generation.
  126. * Moved datatool headers to include/internal/serial/tool.
  127. *
  128. * Revision 1.5  1999/12/21 17:18:33  vasilche
  129. * Added CDelayedFostream class which rewrites file only if contents is changed.
  130. *
  131. * Revision 1.4  1999/12/03 21:42:11  vasilche
  132. * Fixed conflict of enums in choices.
  133. *
  134. * Revision 1.3  1999/12/01 17:36:25  vasilche
  135. * Fixed CHOICE processing.
  136. *
  137. * Revision 1.2  1999/11/15 19:36:14  vasilche
  138. * Fixed warnings on GCC
  139. *
  140. * ===========================================================================
  141. */
  142. #include <ncbi_pch.hpp>
  143. #include <serial/datatool/enumtype.hpp>
  144. #include <serial/datatool/blocktype.hpp>
  145. #include <serial/datatool/value.hpp>
  146. #include <serial/datatool/enumstr.hpp>
  147. #include <serial/datatool/module.hpp>
  148. #include <serial/datatool/srcutil.hpp>
  149. #include <serial/enumerated.hpp>
  150. BEGIN_NCBI_SCOPE
  151. CEnumDataType::CEnumDataType(void)
  152. {
  153.     ForbidVar("_type", "string");
  154. }
  155. const char* CEnumDataType::GetASNKeyword(void) const
  156. {
  157.     return "ENUMERATED";
  158. }
  159. bool CEnumDataType::IsInteger(void) const
  160. {
  161.     return false;
  162. }
  163. CEnumDataType::TValue& CEnumDataType::AddValue(const string& valueName,
  164.                                                TEnumValueType value)
  165. {
  166.     m_Values.push_back(TValue(valueName, value));
  167.     return m_Values.back();
  168. }
  169. void CEnumDataType::PrintASN(CNcbiOstream& out, int indent) const
  170. {
  171.     out << GetASNKeyword() << " {";
  172.     ++indent;
  173.     ITERATE ( TValues, i, m_Values ) {
  174.         PrintASNNewLine(out, indent);
  175.         TValues::const_iterator next = i;
  176.         bool last = ++next == m_Values.end();
  177.         bool oneLineComment = i->GetComments().OneLine();
  178.         if ( !oneLineComment )
  179.             i->GetComments().PrintASN(out, indent);
  180.         out << i->GetName() << " (" << i->GetValue() << ")";
  181.         if ( !last )
  182.             out << ',';
  183.         if ( oneLineComment )
  184.             i->GetComments().PrintASN(out, indent, CComments::eOneLine);
  185.     }
  186.     --indent;
  187.     PrintASNNewLine(out, indent);
  188.     m_LastComments.PrintASN(out, indent, CComments::eMultiline);
  189.     out << "}";
  190. }
  191. void CEnumDataType::PrintDTDElement(CNcbiOstream& out) const
  192. {
  193.     out <<
  194.         "<!ELEMENT "<<XmlTagName()<<" ";
  195.     if ( IsInteger() )
  196.         out << "( %INTEGER; )>";
  197.     else
  198.         out << "%ENUM; >";
  199. }
  200. void CEnumDataType::PrintDTDExtra(CNcbiOstream& out) const
  201. {
  202.     out <<
  203.         "<!ATTLIST "<<XmlTagName()<<" value (n";
  204.     bool haveComments = false;
  205.     ITERATE ( TValues, i, m_Values ) {
  206.         if ( i != m_Values.begin() )
  207.             out << " |n";
  208.         out << "               " << i->GetName();
  209.         if ( !i->GetComments().Empty() )
  210.             haveComments = true;
  211.     }
  212.     out << " ) ";
  213.     if ( IsInteger() )
  214.         out << "#IMPLIED";
  215.     else
  216.         out << "#REQUIRED";
  217.     out << " >n";
  218.     if ( haveComments ) {
  219.         out << "<!--n";
  220.         ITERATE ( TValues, i, m_Values ) {
  221.             if ( !i->GetComments().Empty() ) {
  222.                 i->GetComments().Print(out, "    "+i->GetName()+" - ",
  223.                                        "n        ", "n");
  224.             }
  225.         }
  226.         out << "-->n";
  227.     }
  228.     m_LastComments.PrintDTD(out, CComments::eMultiline);
  229. }
  230. // XML schema generator submitted by
  231. // Marc Dumontier, Blueprint initiative, dumontier@mshri.on.ca
  232. // modified by Andrei Gourianov, gouriano@ncbi
  233. void CEnumDataType::PrintXMLSchemaElement(CNcbiOstream& out) const
  234. {
  235.     string tag(XmlTagName());
  236.     string use("required");
  237.     string value("value");
  238.     bool inAttlist= false;
  239.     if (GetEnforcedStdXml() &&
  240.         GetParentType() && 
  241.         GetParentType()->GetDataMember() &&
  242.         GetParentType()->GetDataMember()->Attlist()) {
  243.         const CDataMember* mem = GetDataMember();
  244.         inAttlist = true;
  245.         value = tag;
  246.         if (mem->Optional()) {
  247.             use = "optional";
  248.             if (mem->GetDefault()) {
  249.                 use += "" default="" + mem->GetDefault()->GetXmlString();
  250.             }
  251.         } else {
  252.             use = "required";
  253.         }
  254.     }
  255.     if (!inAttlist) {
  256.         out << "<xs:element name="" << tag << "">n";
  257.         out << "  <xs:complexType>n";
  258.         if(IsInteger()) {
  259.             out << "    <xs:simpleContent>n"
  260.                 << "      <xs:extension base="xs:integer">n";
  261.         }
  262.     }
  263.     out << "        <xs:attribute name="" << value << "" use="" << use << "">n";
  264.     out << "          <xs:simpleType>n";
  265.     out << "            <xs:restriction base="xs:string">n";
  266.     bool haveComments = false;
  267.     ITERATE ( TValues, i, m_Values ) {
  268.         out << "              <xs:enumeration value="" << i->GetName() << ""/>n";
  269.         if ( !i->GetComments().Empty() )
  270.             haveComments = true;
  271.     }
  272.     if ( haveComments ) {
  273.         out << "<!--n";
  274.         ITERATE ( TValues, i, m_Values ) {
  275.             if ( !i->GetComments().Empty() ) {
  276.                 i->GetComments().Print(out, "    "+i->GetName()+" - ",
  277.                                        "n        ", "n");
  278.             }
  279.         }
  280.         out << "-->n";
  281.     }
  282.     m_LastComments.PrintDTD(out, CComments::eMultiline);
  283.     out << "            </xs:restriction>n"
  284.         << "          </xs:simpleType>n"
  285.         << "        </xs:attribute>n";
  286.     if (!inAttlist) {
  287.         if(IsInteger()) {
  288.             out << "      </xs:extension>n"
  289.                 << "    </xs:simpleContent>n";
  290.         }
  291.         out << "  </xs:complexType>n";
  292.         out << "</xs:element>n";
  293.     }
  294. }
  295. bool CEnumDataType::CheckValue(const CDataValue& value) const
  296. {
  297.     const CIdDataValue* id = dynamic_cast<const CIdDataValue*>(&value);
  298.     if ( id ) {
  299.         ITERATE ( TValues, i, m_Values ) {
  300.             if ( i->GetName() == id->GetValue() )
  301.                 return true;
  302.         }
  303.         value.Warning("illegal ENUMERATED value: " + id->GetValue());
  304.         return false;
  305.     }
  306.     const CIntDataValue* intValue =
  307.         dynamic_cast<const CIntDataValue*>(&value);
  308.     if ( !intValue ) {
  309.         value.Warning("ENUMERATED or INTEGER value expected");
  310.         return false;
  311.     }
  312.     if ( !IsInteger() ) {
  313.         ITERATE ( TValues, i, m_Values ) {
  314.             if ( i->GetValue() == intValue->GetValue() )
  315.                 return true;
  316.         }
  317.         value.Warning("illegal INTEGER value: " + intValue->GetValue());
  318.         return false;
  319.     }
  320.     return true;
  321. }
  322. TObjectPtr CEnumDataType::CreateDefault(const CDataValue& value) const
  323. {
  324.     const CIdDataValue* id = dynamic_cast<const CIdDataValue*>(&value);
  325.     if ( id == 0 ) {
  326.         return new TEnumValueType(dynamic_cast<const CIntDataValue&>(value).GetValue());
  327.     }
  328.     ITERATE ( TValues, i, m_Values ) {
  329.         if ( i->GetName() == id->GetValue() )
  330.             return new TEnumValueType(i->GetValue());
  331.     }
  332.     value.Warning("illegal ENUMERATED value: " + id->GetValue());
  333.     return 0;
  334. }
  335. string CEnumDataType::GetDefaultString(const CDataValue& value) const
  336. {
  337.     const CIdDataValue* id = dynamic_cast<const CIdDataValue*>(&value);
  338.     if ( id ) {
  339.         return GetEnumCInfo().valuePrefix + Identifier(id->GetValue(), false);
  340.     }
  341.     else {
  342.         const CIntDataValue* intValue =
  343.             dynamic_cast<const CIntDataValue*>(&value);
  344.         return NStr::IntToString(intValue->GetValue());
  345.     }
  346. }
  347. CTypeInfo* CEnumDataType::CreateTypeInfo(void)
  348. {
  349.     AutoPtr<CEnumeratedTypeValues>
  350.         info(new CEnumeratedTypeValues(GlobalName(), IsInteger()));
  351.     ITERATE ( TValues, i, m_Values ) {
  352.         info->AddValue(i->GetName(), i->GetValue());
  353.     }
  354.     if ( HaveModuleName() )
  355.         info->SetModuleName(GetModule()->GetName());
  356.     return new CEnumeratedTypeInfo(sizeof(TEnumValueType), info.release());
  357. }
  358. string CEnumDataType::DefaultEnumName(void) const
  359. {
  360.     // generate enum name from ASN type or field name
  361.     if ( !GetParentType() ) {
  362.         // root enum
  363.         return 'E' + Identifier(IdName());
  364.     }
  365.     else {
  366.         // internal enum
  367.         return 'E' + Identifier(GetKeyPrefix());
  368.     }
  369. }
  370. CEnumDataType::SEnumCInfo CEnumDataType::GetEnumCInfo(void) const
  371. {
  372.     string typeName = GetAndVerifyVar("_type");
  373.     string enumName;
  374.     if ( !typeName.empty() && typeName[0] == 'E' ) {
  375.         enumName = typeName;
  376.     }
  377.     else {
  378.         // make C++ type name
  379.         enumName = DefaultEnumName();
  380.         if ( typeName.empty() ) {
  381.             if ( IsInteger() )
  382.                 typeName = "int";
  383.             else
  384.                 typeName = enumName;
  385.         }
  386.     }
  387.     string prefix = GetVar("_prefix");
  388.     if ( prefix.empty() ) {
  389.         prefix = char(tolower(enumName[0])) + enumName.substr(1) + '_';
  390.     }
  391.     return SEnumCInfo(enumName, typeName, prefix);
  392. }
  393. AutoPtr<CTypeStrings> CEnumDataType::GetRefCType(void) const
  394. {
  395.     SEnumCInfo enumInfo = GetEnumCInfo();
  396.     return AutoPtr<CTypeStrings>(new CEnumRefTypeStrings(enumInfo.enumName,
  397.                                                          enumInfo.cType,
  398.                                                          Namespace(),
  399.                                                          FileName()));
  400. }
  401. AutoPtr<CTypeStrings> CEnumDataType::GetFullCType(void) const
  402. {
  403.     SEnumCInfo enumInfo = GetEnumCInfo();
  404.     AutoPtr<CEnumTypeStrings> 
  405.         e(new CEnumTypeStrings(GlobalName(), enumInfo.enumName,
  406.                                enumInfo.cType, IsInteger(),
  407.                                m_Values, enumInfo.valuePrefix));
  408.     return AutoPtr<CTypeStrings>(e.release());
  409. }
  410. AutoPtr<CTypeStrings> CEnumDataType::GenerateCode(void) const
  411. {
  412.     return GetFullCType();
  413. }
  414. const char* CIntEnumDataType::GetASNKeyword(void) const
  415. {
  416.     return "INTEGER";
  417. }
  418. bool CIntEnumDataType::IsInteger(void) const
  419. {
  420.     return true;
  421. }
  422. const char* CBigIntEnumDataType::GetASNKeyword(void) const
  423. {
  424.     return "BigInt";
  425. }
  426. END_NCBI_SCOPE