NCBI C++ ToolKit
enumtype.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: enumtype.cpp 79463 2017-09-12 17:04:06Z gouriano $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Eugene Vasilchenko
27 *
28 * File Description:
29 * Type description for enumerated types
30 */
31 
32 #include <ncbi_pch.hpp>
33 #include "enumtype.hpp"
34 #include "blocktype.hpp"
35 #include "value.hpp"
36 #include "enumstr.hpp"
37 #include "module.hpp"
38 #include "srcutil.hpp"
40 #include "stdstr.hpp"
41 
43 
45 {
46 }
47 
48 const char* CEnumDataType::GetASNKeyword(void) const
49 {
50  return "ENUMERATED";
51 }
52 
53 const char* CEnumDataType::GetDEFKeyword(void) const
54 {
55  return "_ENUMERATED_";
56 }
57 
59 {
60  string content("\n");
61  ITERATE ( TValues, i, m_Values ) {
62  if (i != m_Values.begin()) {
63  content += " |\n";
64  }
65  content += " " + i->GetName();
66  }
67  return content;
68 }
69 
70 bool CEnumDataType::IsInteger(void) const
71 {
72  return false;
73 }
74 
76  TEnumValueType value)
77 {
78  m_Values.push_back(TValue(valueName, value));
79  return m_Values.back();
80 }
81 
82 void CEnumDataType::PrintASN(CNcbiOstream& out, int indent) const
83 {
84  PrintASNTag(out);
85  out << GetASNKeyword() << " {";
86  ++indent;
87  ITERATE ( TValues, i, m_Values ) {
88  PrintASNNewLine(out, indent);
89  TValues::const_iterator next = i;
90  bool last = ++next == m_Values.end();
91 
92  bool oneLineComment = i->GetComments().OneLine();
93  if ( !oneLineComment )
94  i->GetComments().PrintASN(out, indent);
95  out << CDataTypeModule::ToAsnId(i->GetName()) << " (" << i->GetValue() << ")";
96  if ( !last )
97  out << ',';
98  if ( oneLineComment ) {
99  out << ' ';
100  i->GetComments().PrintASN(out, indent, CComments::eOneLine);
101  }
102  }
103  --indent;
104  PrintASNNewLine(out, indent);
106  out << "}";
107 }
108 
110 {
111  ++indent;
112  ITERATE ( TValues, i, m_Values ) {
113  PrintASNNewLine(out, indent);
114  out << "V," << i->GetSourceLine() << ',';
115  out << GetFullName() << ':' << i->GetName() << ',' << i->GetValue();
116  i->GetComments().PrintASN(out, indent, CComments::eNoEOL);
117  }
118 }
119 
120 void CEnumDataType::PrintJSONSchema(CNcbiOstream& out, int indent, list<string>& required, bool) const
121 {
122  PrintASNNewLine(out, indent) << "\"type\": " << (IsInteger() ? "\"integer\"" : "\"string\"") << ',';
123  PrintASNNewLine(out, indent) << "\"enum\": [";
124 
125 #if 0
126  bool first = true;
127  ITERATE ( TValues, i, m_Values ) {
128  if (!first) {
129  out << ", ";
130  } else {
131  first = false;
132  }
133  if (IsInteger()) {
134  out << i->GetValue();
135  } else {
136  out << "\"" << i->GetName() << "\"";
137  }
138  }
139 #else
140  if (IsInteger()) {
141  copy( m_Values.begin(), m_Values.end(), Dt_ostream_iterator<TValue>(cout, ", ",
142  [](ostream& out, const TValue& e) {
143  out << e.GetValue();
144  }));
145  } else {
146  copy( m_Values.begin(), m_Values.end(), Dt_ostream_iterator<TValue>(cout, ", ",
147  [](ostream& out, const TValue& e) {
148  out << "\"" << e.GetName() << "\"";
149  }));
150  }
151 #endif
152 
153  const CDataMember* mem = GetDataMember();
154  if (mem && !mem->Optional()) {
155  required.push_back(mem->GetName());
156  }
157  out << ']';
158 }
159 
160 // XML schema generator submitted by
161 // Marc Dumontier, Blueprint initiative, dumontier@mshri.on.ca
162 // modified by Andrei Gourianov, gouriano@ncbi
163 void CEnumDataType::PrintXMLSchema(CNcbiOstream& out, int indent, bool /*contents_only*/) const
164 {
165  string tag(XmlTagName());
166  string use("required");
167  string value("value");
168  string form;
169  bool inAttlist= false;
170  bool isGlobalType = GetGlobalType() == CDataType::eType;
171  list<string> opentag, closetag;
172 
173  if (GetEnforcedStdXml() &&
174  GetParentType() &&
176  GetParentType()->GetDataMember()->Attlist()) {
177  const CDataMember* mem = GetDataMember();
178  inAttlist = true;
179  value = tag;
180  if (mem->Optional()) {
181  use = "optional";
182  if (mem->GetDefault()) {
183  use += "\" default=\"" + GetXmlValueName(mem->GetDefault()->GetXmlString());
184  }
185  } else {
186  use = "required";
187  }
188  if (IsNsQualified() == eNSQualified) {
189  form = " form=\"qualified\"";
190  }
191  }
192  if (!inAttlist && !isGlobalType) {
193  const CDataMember* mem = GetDataMember();
194  string tmp = "<xs:element name=\"" + tag + "\"";
195  if (mem && mem->Optional()) {
196  tmp += " minOccurs=\"0\"";
197  if (mem->GetDefault()) {
198  use = "optional";
199  }
200  }
201 #if _DATATOOL_USE_SCHEMA_STYLE_COMMENTS
202  PrintASNNewLine(out, indent) << tmp;
203  if (!Comments().PrintSchemaComments(out, indent+1)) {
204  out << '>';
205  }
206  ++indent;
207 #else
208  opentag.push_back(tmp + ">");
209 #endif
210  closetag.push_front("</xs:element>");
211  if (IsASNDataSpec()) {
212  opentag.push_back("<xs:complexType>");
213  closetag.push_front("</xs:complexType>");
214  if(IsInteger()) {
215  opentag.push_back("<xs:simpleContent>");
216  closetag.push_front("</xs:simpleContent>");
217  opentag.push_back("<xs:extension base=\"xs:integer\">");
218  closetag.push_front("</xs:extension>");
219  use = "optional";
220  }
221  }
222  }
223  if (IsASNDataSpec()) {
224  string tmp = "<xs:attribute name=\"" + value + "\" use=\"" + use + "\"" + form;
225  const CDataMember* mem = GetDataMember();
226  if (!inAttlist) {
227  if (mem && mem->Optional() && mem->GetDefault()) {
228  tmp += " default=\"" + GetXmlValueName(mem->GetDefault()->GetXmlString()) + "\"";
229  }
230  }
231  opentag.push_back(tmp + ">");
232  closetag.push_front("</xs:attribute>");
233  }
234  if (isGlobalType) {
235  string tmp = "<xs:simpleType name=\"" + tag + "\">";
236  opentag.push_back(tmp);
237  } else {
238  opentag.push_back("<xs:simpleType>");
239  }
240  closetag.push_front("</xs:simpleType>");
241  if (IsASNDataSpec() || !IsInteger()) {
242  opentag.push_back("<xs:restriction base=\"xs:string\">");
243  } else {
244  opentag.push_back("<xs:restriction base=\"xs:integer\">");
245  }
246  closetag.push_front("</xs:restriction>");
247 
248  ITERATE ( list<string>, s, opentag ) {
249  PrintASNNewLine(out, indent++) << *s;
250  }
251  bool haveComments = false;
252  ITERATE ( TValues, i, m_Values ) {
253  if ( !i->GetComments().Empty() ) {
254  haveComments = true;
255  break;
256  }
257  }
258  if ( haveComments ) {
259 #if _DATATOOL_USE_SCHEMA_STYLE_COMMENTS
260  PrintASNNewLine(out, indent) << "<xs:annotation><xs:documentation>";
261  ITERATE ( TValues, i, m_Values ) {
262  if ( !i->GetComments().Empty() ) {
263  i->GetComments().Print(out, "\n "+i->GetName()+"\t- ",
264  "\n ", "");
265  }
266  }
267  PrintASNNewLine(out, indent) << "</xs:documentation></xs:annotation>";
268 #else
269  out << "\n<!--";
270  ITERATE ( TValues, i, m_Values ) {
271  if ( !i->GetComments().Empty() ) {
272  i->GetComments().Print(out, "\n "+i->GetName()+"\t- ",
273  "\n ", "");
274  }
275  }
276  out << "\n-->";
277 #endif
278  }
279  ITERATE ( TValues, i, m_Values ) {
280  PrintASNNewLine(out, indent) <<
281  "<xs:enumeration value=\"" << i->GetName() << "\"";
282  if (IsASNDataSpec() && IsInteger()) {
283  out << " ncbi:intvalue=\"" << i->GetValue() << "\"";
284  }
285  out << "/>";
286  }
287  ITERATE ( list<string>, s, closetag ) {
288  PrintASNNewLine(out, --indent) << *s;
289  }
290  m_LastComments.PrintDTD(out, CComments::eMultiline);
291 }
292 
293 void CEnumDataType::PrintDTDElement(CNcbiOstream& out, bool /*contents_only*/) const
294 {
295  string tag(XmlTagName());
296  string content(GetXMLContents());
297  if (GetParentType() &&
298  GetParentType()->GetDataMember() &&
299  GetParentType()->GetDataMember()->Attlist()) {
300  const CDataMember* mem = GetDataMember();
301  out << "\n " << tag << " (" << content << ") ";
302  if (mem->GetDefault()) {
303  out << "\"" << GetXmlValueName(mem->GetDefault()->GetXmlString()) << "\"";
304  } else {
305  if (mem->Optional()) {
306  out << "#IMPLIED";
307  } else {
308  out << "#REQUIRED";
309  }
310  }
311  } else {
312  out <<
313  "\n<!ELEMENT " << tag << " ";
314  if ( IsInteger() ) {
315  if (DTDEntitiesEnabled()) {
316  out << "(%INTEGER;)>";
317  } else {
318  out << "(#PCDATA)>";
319  }
320  } else {
321  if (DTDEntitiesEnabled()) {
322  out << "%ENUM;>";
323  } else {
324  out << "EMPTY>";
325  }
326  }
327  }
328 }
329 
330 void CEnumDataType::PrintDTDExtra(CNcbiOstream& out) const
331 {
332  bool haveComments = false;
333  ITERATE ( TValues, i, m_Values ) {
334  if ( !i->GetComments().Empty() ) {
335  haveComments = true;
336  break;
337  }
338  }
339  if ( haveComments ) {
340  out << "\n\n<!--\n";
341  ITERATE ( TValues, i, m_Values ) {
342  if ( !i->GetComments().Empty() ) {
343  i->GetComments().Print(out, " "+i->GetName()+"\t- ",
344  "\n ", "\n");
345  }
346  }
347  out << "-->";
348  }
349  out <<
350  "\n<!ATTLIST "<<XmlTagName()<<" value (\n";
351  ITERATE ( TValues, i, m_Values ) {
352  if ( i != m_Values.begin() )
353  out << " |\n";
354  out << " " << i->GetName();
355  }
356  out << "\n ) ";
357  if ( IsInteger() )
358  out << "#IMPLIED";
359  else
360  out << "#REQUIRED";
361  out << " >\n";
362  m_LastComments.PrintDTD(out, CComments::eMultiline);
363 }
364 
365 bool CEnumDataType::CheckValue(const CDataValue& value) const
366 {
367  const CIdDataValue* id = dynamic_cast<const CIdDataValue*>(&value);
368  if ( id ) {
369  ITERATE ( TValues, i, m_Values ) {
370  if ( i->GetName() == id->GetValue() )
371  return true;
372  }
373  value.Warning("illegal ENUMERATED value: " + id->GetValue(), 12);
374  return false;
375  }
376 
377  const CIntDataValue* intValue =
378  dynamic_cast<const CIntDataValue*>(&value);
379  if ( !intValue ) {
380  value.Warning("ENUMERATED or INTEGER value expected", 13);
381  return false;
382  }
383 
384  if ( !IsInteger() ) {
385  ITERATE ( TValues, i, m_Values ) {
386  if ( i->GetValue() == intValue->GetValue() )
387  return true;
388  }
389  value.Warning("illegal INTEGER value: " + NStr::NumericToString(intValue->GetValue()), 14);
390  return false;
391  }
392 
393  return true;
394 }
395 
396 TObjectPtr CEnumDataType::CreateDefault(const CDataValue& value) const
397 {
398  const CIdDataValue* id = dynamic_cast<const CIdDataValue*>(&value);
399  if ( id == 0 ) {
400  return new TEnumValueType((TEnumValueType)dynamic_cast<const CIntDataValue&>(value).GetValue());
401  }
402  ITERATE ( TValues, i, m_Values ) {
403  if ( i->GetName() == id->GetValue() )
404  return new TEnumValueType(i->GetValue());
405  }
406  value.Warning("illegal ENUMERATED value: " + id->GetValue(), 15);
407  return 0;
408 }
409 
410 string CEnumDataType::GetDefaultString(const CDataValue& value) const
411 {
412  CTypeStrings::EKind kind = GetFullCType()->GetKind();
413  const CIdDataValue* id = dynamic_cast<const CIdDataValue*>(&value);
414  if (kind == CTypeStrings::eKindEnum) {
415  if ( id ) {
416  return GetEnumCInfo().valuePrefix + Identifier(id->GetValue(), false);
417  }
418  else {
419  const CIntDataValue* intValue =
420  dynamic_cast<const CIntDataValue*>(&value);
421  return NStr::Int8ToString(intValue->GetValue());
422  }
423  }
424  string val;
425  if ( id ) {
426  val = id->GetValue();
427  }
428  else {
429  const CIntDataValue* intValue =
430  dynamic_cast<const CIntDataValue*>(&value);
431  val = NStr::Int8ToString(intValue->GetValue());
432  }
433  if (kind == CTypeStrings::eKindString) {
434  return string("\"") + val + "\"";
435  }
436  return val;
437 }
438 
439 string CEnumDataType::GetXmlValueName(const string& value) const
440 {
441  return value;
442 }
443 
444 CTypeInfo* CEnumDataType::CreateTypeInfo(void)
445 {
446  AutoPtr<CEnumeratedTypeValues>
447  info(new CEnumeratedTypeValues(GlobalName(), IsInteger()));
448  ITERATE ( TValues, i, m_Values ) {
449  info->AddValue(i->GetName(), i->GetValue());
450  }
451  if ( HaveModuleName() )
452  info->SetModuleName(GetModule()->GetName());
453  return new CEnumeratedTypeInfo(sizeof(TEnumValueType), info.release());
454 }
455 
456 string CEnumDataType::DefaultEnumName(void) const
457 {
458  // generate enum name from ASN type or field name
459  if ( !GetParentType() ) {
460  // root enum
461  return 'E' + Identifier(IdName());
462  }
463  else {
464  // internal enum
465  return 'E' + Identifier(GetKeyPrefix());
466  }
467 }
468 
469 CEnumDataType::SEnumCInfo CEnumDataType::GetEnumCInfo(void) const
470 {
471  string typeName = GetAndVerifyVar("_type");
472  string enumName;
473  if ( !typeName.empty() && typeName[0] == 'E' ) {
474  enumName = typeName;
475  }
476  else {
477  // make C++ type name
478  enumName = DefaultEnumName();
479  if ( typeName.empty() ) {
480  if ( IsInteger() )
481  typeName = "int";
482  else
483  typeName = enumName;
484  }
485  }
486  string prefix = GetVar("_prefix");
487  if ( prefix.empty() ) {
488  prefix = char(tolower((unsigned char) enumName[0])) + enumName.substr(1) + '_';
489  }
490  return SEnumCInfo(enumName, typeName, prefix);
491 }
492 
493 AutoPtr<CTypeStrings> CEnumDataType::GetRefCType(void) const
494 {
495  SEnumCInfo enumInfo = GetEnumCInfo();
496  return AutoPtr<CTypeStrings>(new CEnumRefTypeStrings(enumInfo.enumName,
497  enumInfo.cType,
498  Namespace(),
499  FileName(),
500  Comments()));
501 }
502 
503 AutoPtr<CTypeStrings> CEnumDataType::GetFullCType(void) const
504 {
505  ITERATE ( TValues, i, m_Values ) {
506  string id(Identifier( i->GetEnumId(), false ));
507  string value;
508  value = GetVar(id + "._hidename", false);
509  if (!value.empty()) {
510  if (NStr::StringToBool(value)) {
511  i->SetFlag(CEnumDataTypeValue::eHideName);
512  }
513  }
514  value = GetVar( id, false);
515  if (!value.empty()) {
516  i->SetEnumId(value);
517  }
518  }
519 // in case client wants std type instead of enum.
520 // I must be accurate here to not to mess with GetEnumCInfo()
521  string type = GetAndVerifyVar("_type");
522  if (!type.empty()) {
523  if (NStr::EndsWith(type, "string")) {
524  return AutoPtr<CTypeStrings>(
525  new CStringTypeStrings("NCBI_NS_STD::string",Comments(),true));
526  } else if (NStr::EndsWith(type, "CStringUTF8")) {
527  return AutoPtr<CTypeStrings>(
528  new CStringTypeStrings("NCBI_NS_NCBI::CStringUTF8",Comments(),true));
529  } else if (type == "double") {
530  return AutoPtr<CTypeStrings>(
531  new CStdTypeStrings(type,Comments(),true));
532  }
533  }
534 
535  SEnumCInfo enumInfo = GetEnumCInfo();
536  AutoPtr<CEnumTypeStrings>
537  e(new CEnumTypeStrings(GlobalName(), enumInfo.enumName,
538  GetVar("_packedtype"),
539  enumInfo.cType, IsInteger(),
540  m_Values, enumInfo.valuePrefix,
541  GetNamespaceName(), this, Comments()));
542 
543  string extra = GetVar("_type_extra");
544  if (NStr::CompareNocase(extra, "bitset") == 0) {
545  e->SetBitset(true);
546  }
547  return AutoPtr<CTypeStrings>(e.release());
548 }
549 
550 AutoPtr<CTypeStrings> CEnumDataType::GenerateCode(void) const
551 {
552  return GetFullCType();
553 }
554 
555 const char* CIntEnumDataType::GetASNKeyword(void) const
556 {
557  return "INTEGER";
558 }
559 
560 const char* CIntEnumDataType::GetDEFKeyword(void) const
561 {
562  return "_INTEGER_ENUM_";
563 }
564 
565 bool CIntEnumDataType::IsInteger(void) const
566 {
567  return true;
568 }
569 
570 string CIntEnumDataType::GetXmlValueName(const string& value) const
571 {
572  try {
573 // in case of named integers, value can be a name, not an integer
574  TEnumValueType d = (TEnumValueType)NStr::StringToInt(value);
575  ITERATE(TValues, v, GetValues()) {
576  if (v->GetValue() == d) {
577  return v->GetName();
578  }
579  }
580  } catch (...) {
581  }
582  return value;
583 }
584 
585 const char* CBigIntEnumDataType::GetASNKeyword(void) const
586 {
587  return "BigInt";
588 }
589 
590 const char* CBigIntEnumDataType::GetDEFKeyword(void) const
591 {
592  return "_BigInt_ENUM_";
593 }
594 
595 END_NCBI_SCOPE
static char tmp[2048]
Definition: utf8.c:62
EGlobalType GetGlobalType(void) const
Definition: type.hpp:427
CEnumDataTypeValue TValue
Definition: enumtype.hpp:107
bool Optional(void) const
Definition: blocktype.hpp:68
const double E
std::ofstream out("events_result.xml")
main entry point for tests
TValues m_Values
Definition: enumtype.hpp:162
virtual void PrintXMLSchema(CNcbiOstream &out, int indent, bool contents_only=false) const override
Definition: enumtype.cpp:163
virtual string GetXmlValueName(const string &value) const
Definition: enumtype.cpp:439
const CDataValue * GetDefault(void) const
Definition: blocktype.hpp:88
ENsQualifiedMode IsNsQualified(void) const
Definition: type.hpp:407
static string ToAsnId(const string &name)
Definition: module.cpp:673
virtual void PrintASN(CNcbiOstream &out, int indent) const override
Definition: enumtype.cpp:82
string XmlTagName(void) const
Definition: type.cpp:460
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:790
int i
void copy(Njn::Matrix< S > *matrix_, const Njn::Matrix< T > &matrix0_)
Definition: njn_matrix.hpp:612
const char * tag
int TEnumValueType
Definition: serialdef.hpp:231
TValue & AddValue(const string &name, TEnumValueType value)
Definition: enumtype.cpp:75
CComments m_LastComments
Definition: enumtype.hpp:163
CNcbiOstream & PrintASN(CNcbiOstream &out, int indent, int flags=0) const
Definition: comments.cpp:156
list< TValue > TValues
Definition: enumtype.hpp:108
virtual void PrintJSONSchema(CNcbiOstream &out, int indent, list< string > &required, bool contents_only=false) const override
Definition: enumtype.cpp:120
static bool GetEnforcedStdXml(void)
Definition: type.hpp:372
virtual bool IsInteger(void) const
Definition: enumtype.cpp:70
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:142
const string & GetName(void) const
Definition: blocktype.hpp:56
virtual const char * GetASNKeyword(void) const override
Definition: enumtype.cpp:48
CEnumDataType(void)
Definition: enumtype.cpp:44
virtual string GetXMLContents(void) const
Definition: enumtype.cpp:58
const CDataMember * GetDataMember(void) const
Definition: type.hpp:303
char value[7]
Definition: config.c:428
virtual string GetXmlString(void) const =0
CNcbiOstream & PrintASNTag(CNcbiOstream &out) const
Definition: type.cpp:121
#define _(proto)
Definition: ct_nlmzip_i.h:78
virtual void PrintSpecDumpExtra(CNcbiOstream &out, int indent) const override
Definition: enumtype.cpp:109
virtual const char * GetDEFKeyword(void) const override
Definition: enumtype.cpp:53
string GetFullName(void) const
Definition: type.cpp:970
CComments & Comments(void)
Definition: type.hpp:290
string indent(" ")
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:98
CNcbiOstream & PrintASNNewLine(CNcbiOstream &out, int indent)
Definition: srcutil.cpp:130
const CDataType * GetParentType(void) const
Definition: type.hpp:160
Modified on Sun Nov 19 16:43:21 2017 by modify_doxy.py rev. 546573