1 #ifndef TYPE_HPP
2 #define TYPE_HPP
3 
4 /*  $Id: type.hpp 554977 2018-01-11 14:18:53Z gouriano $
5 * ===========================================================================
6 *
7 *                            PUBLIC DOMAIN NOTICE
8 *               National Center for Biotechnology Information
9 *
10 *  This software/database is a "United States Government Work" under the
11 *  terms of the United States Copyright Act.  It was written as part of
12 *  the author's official duties as a United States Government employee and
13 *  thus cannot be copyrighted.  This software/database is freely available
14 *  to the public for use. The National Library of Medicine and the U.S.
15 *  Government have not placed any restriction on its use or reproduction.
16 *
17 *  Although all reasonable efforts have been taken to ensure the accuracy
18 *  and reliability of the software and data, the NLM and the U.S.
19 *  Government do not and cannot warrant the performance or results that
20 *  may be obtained by using this software or data. The NLM and the U.S.
21 *  Government disclaim all warranties, express or implied, including
22 *  warranties of performance, merchantability or fitness for any particular
23 *  purpose.
24 *
25 *  Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Author: Eugene Vasilchenko
30 *
31 * File Description:
32 *   Type definition
33 *
34 */
35 
36 #include <corelib/ncbistd.hpp>
37 #include <corelib/ncbistre.hpp>
38 #include <corelib/ncbiutil.hpp>
39 #include <serial/impl/typeref.hpp>
40 #include <serial/impl/objstrasnb.hpp>
41 #include "comments.hpp"
42 #include <list>
43 #include <set>
44 #include <functional>
45 
46 BEGIN_NCBI_SCOPE
47 
48 class CTypeInfo;
49 class CDataType;
50 class CDataTypeModule;
51 class CDataValue;
52 class CChoiceDataType;
53 class CUniSequenceDataType;
54 class CReferenceDataType;
55 class CTypeStrings;
56 class CFileCode;
57 class CClassTypeStrings;
58 class CNamespace;
59 class CDataMember;
60 
61 /////////////////////////////////////////////////////////////////////////////
62 // ostream_iterator with corrected delimiter and inserter
63 
64 template<typename TValue, typename TElem = char, typename TTraits = char_traits<TElem> >
65 class Dt_ostream_iterator
66     : public iterator<output_iterator_tag, void, void, void, void>
67 {
68 public:
69 	typedef TElem char_type;
70 	typedef TTraits traits_type;
71 	typedef basic_ostream<TElem, TTraits> ostream_type;
72     typedef function<void(ostream_type&, const TValue&)> TInserter;
73 
Dt_ostream_iterator(ostream_type & ostr,const TElem * delim=nullptr,TInserter fnIn=[](ostream_type & out,const TValue & v){})74 	Dt_ostream_iterator(ostream_type& ostr, const TElem *delim = nullptr,
75         TInserter fnIn = [](ostream_type& out, const TValue& v){ out << v;})
76 		: m_ostr(&ostr), m_delim(delim), m_fnIn(fnIn), m_first(true) {
77 	}
operator =(const TValue & value)78     Dt_ostream_iterator& operator=(const TValue& value) {
79 		if (!m_first && m_delim !=  nullptr) {
80 			*m_ostr << m_delim;
81         }
82 		m_fnIn(*m_ostr, value);
83 		m_first = false;
84         return *this;
85     }
operator *()86 	Dt_ostream_iterator& operator*() {
87 		return *this;
88 	}
operator ++()89 	Dt_ostream_iterator& operator++() {
90 		return *this;
91 	}
operator ++(int)92 	Dt_ostream_iterator& operator++(int) {
93 		return *this;
94 	}
95 protected:
96 	ostream_type *m_ostr;
97     const TElem *m_delim;
98     TInserter    m_fnIn;
99 	bool m_first;
100 };
101 
102 // mark Dt_ostream_iterator as checked
103 #ifdef NCBI_COMPILER_MSVC
104 template<typename TValue, typename TElem, class TTraits>
105 struct _Is_checked_helper<Dt_ostream_iterator<TValue, TElem, TTraits> >
106 		: public true_type {
107 };
108 #endif
109 
110 template<typename TInputIt, typename TOutputIt, class TFnIf, class TFnTr>
111 TOutputIt Dt_transform_if(TInputIt first, TInputIt last, TOutputIt dest,
112                           const TFnIf& funcIf, const TFnTr& funcTransform)
113 {
114 	for (; first != last; ++first, (void)++dest) {
115         if (funcIf(*first)) {
116 		    *dest = funcTransform(*first);
117         }
118     }
119 	return (dest);
120 }
121 /////////////////////////////////////////////////////////////////////////////
122 class CMemberFacet
123 {
124 public:
CMemberFacet(ESerialFacet type,const string & value)125     CMemberFacet(ESerialFacet type, const string& value)
126         : m_Type(type), m_Value(value) {
127     }
GetType(void) const128     ESerialFacet GetType(void) const {
129         return m_Type;
130     }
GetValue(void) const131     const string& GetValue(void) const {
132         return m_Value;
133     }
134 private:
135     ESerialFacet m_Type;
136     string m_Value;
137 };
138 
139 
140 struct AnyType {
141     union {
142         bool booleanValue;
143         Int8 integerValue;
144         void* pointerValue;
145     };
AnyTypeAnyType146     AnyType(void)
147         {
148             pointerValue = 0;
149         }
150 };
151 
152 class CDataType {
153 public:
154     typedef void* TObjectPtr;
155     typedef list<const CReferenceDataType*> TReferences;
156 
157     CDataType(void);
158     virtual ~CDataType(void);
159 
GetParentType(void) const160     const CDataType* GetParentType(void) const
161         {
162             return m_ParentType;
163         }
GetModule(void) const164     const CDataTypeModule* GetModule(void) const
165         {
166             _ASSERT(m_Module != 0);
167             return m_Module;
168         }
HaveModuleName(void) const169     bool HaveModuleName(void) const
170         {
171             return m_ParentType == 0;
172         }
173 
174     const string& GetSourceFileName(void) const;
GetSourceLine(void) const175     int GetSourceLine(void) const
176         {
177             return m_SourceLine;
178         }
179     void SetSourceLine(int line);
180     string LocationString(void) const;
181 
182     string GetKeyPrefix(void) const;
183     string IdName(void) const;
184     string XmlTagName(void) const;
185     const string& GlobalName(void) const; // name of type or empty
186     bool Skipped(void) const;
187     string DefClassMemberName(void) const;
188     string ClassName(void) const;
189     string FileName(void) const;
190     const CNamespace& Namespace(void) const;
191     string InheritFromClass(void) const;
192     const CDataType* InheritFromType(void) const;
193     const string GetVar(const string& value, int collect = 0) const;
194     bool GetBoolVar(const string& value, bool default_value = false) const;
195     void  ForbidVar(const string& var, const string& value);
196     void  AllowVar(const string& var, const string& value);
197     const string GetAndVerifyVar(const string& value) const;
198 
199     bool InChoice(void) const;
200 
201     void PrintASNTypeComments(CNcbiOstream& out, int indent, int flags=0) const;
202     void PrintDTDTypeComments(CNcbiOstream& out, int indent) const;
203     virtual void PrintASN(CNcbiOstream& out, int indent) const = 0;
204     virtual void PrintSpecDump(CNcbiOstream& out, int indent) const;
205     virtual void PrintSpecDumpExtra(CNcbiOstream& out, int indent) const;
206     virtual void PrintJSONSchema(CNcbiOstream& out, int indent, list<string>& required, bool contents_only=false) const = 0;
207     virtual void PrintXMLSchema(CNcbiOstream& out, int indent, bool contents_only=false) const = 0;
208     virtual const char* GetASNKeyword(void) const;
209     virtual string      GetSpecKeyword(void) const;
210     virtual string GetSchemaTypeString(void) const;
211     void PrintDTD(CNcbiOstream& out) const;
212     void PrintDTD(CNcbiOstream& out, const CComments& extra) const;
213     virtual void PrintDTDElement(CNcbiOstream& out, bool contents_only=false) const = 0;
214     virtual void PrintDTDExtra(CNcbiOstream& out) const;
215 
216     virtual CTypeRef GetTypeInfo(void);
217     virtual const CTypeInfo* GetAnyTypeInfo(void);
218     virtual bool NeedAutoPointer(const CTypeInfo* typeInfo) const;
219     virtual const CTypeInfo* GetRealTypeInfo(void);
220     virtual CTypeInfo* CreateTypeInfo(void);
221     CTypeInfo* UpdateModuleName(CTypeInfo* typeInfo) const;
222 
223     void Warning(const string& mess, int err_subcode = 0) const;
224 
225     virtual AutoPtr<CTypeStrings> GenerateCode(void) const;
226     void SetParentClassTo(CClassTypeStrings& code) const;
227 
228     virtual AutoPtr<CTypeStrings> GetRefCType(void) const;
229     virtual AutoPtr<CTypeStrings> GetFullCType(void) const;
230     virtual string GetDefaultString(const CDataValue& value) const;
231 
232     virtual const CDataType* Resolve(void) const;
233     virtual CDataType* Resolve(void);
234 
235     // resolve type from global level
236     CDataType* ResolveGlobal(const string& name) const;
237     // resolve type from local level
238     CDataType* ResolveLocal(const string& name) const;
239 
IsInSet(void) const240     bool IsInSet(void) const
241         {
242             return m_Set != 0;
243         }
GetInSet(void) const244     const CUniSequenceDataType* GetInSet(void) const
245         {
246             return m_Set;
247         }
248     void SetInSet(const CUniSequenceDataType* sequence);
249 
IsInChoice(void) const250     bool IsInChoice(void) const
251         {
252             return m_Choice != 0;
253         }
GetInChoice(void) const254     const CChoiceDataType* GetInChoice(void) const
255         {
256             return m_Choice;
257         }
258     void SetInChoice(const CChoiceDataType* choice);
259 
IsReferenced(void) const260     bool IsReferenced(void) const
261         {
262             return m_References;
263         }
264     void AddReference(const CReferenceDataType* reference);
GetReferences(void) const265     const TReferences& GetReferences(void) const
266         {
267             return *m_References;
268         }
269     bool IsInUniSeq(void) const;
270     bool IsUniSeq(void) const;
271     bool IsContainer(void) const;
272     bool IsEnumType(void) const;
273 
274 /*
275     static string GetTemplateHeader(const string& tmpl);
276     static bool IsSimplePointerTemplate(const string& tmpl);
277     static string GetTemplateNamespace(const string& tmpl);
278     static string GetTemplateMacro(const string& tmpl);
279 */
280 
281     void SetParent(const CDataType* parent, const string& memberName, string xmlName=kEmptyStr);
282     void SetParent(const CDataTypeModule* module, const string& typeName);
283     virtual void FixTypeTree(void) const;
284 
285     bool Check(void);
286     virtual bool CheckType(void) const;
287     virtual bool CheckValue(const CDataValue& value) const = 0;
288     virtual TObjectPtr CreateDefault(const CDataValue& value) const = 0;
289 
Comments(void)290     CComments& Comments(void)
291         {
292             return m_Comments;
293         }
Comments(void) const294     const CComments& Comments(void) const
295         {
296             return m_Comments;
297         }
298 
SetDataMember(CDataMember * dm)299     void SetDataMember(CDataMember* dm) {
300         m_DataMember = dm;
301     }
302 
GetDataMember(void) const303     const CDataMember* GetDataMember(void) const {
304         return m_DataMember;
305     }
306 
307     enum {
308         eNoExplicitTag = -1
309     };
SetTag(CAsnBinaryDefs::TLongTag tag)310     void SetTag(CAsnBinaryDefs::TLongTag tag) {
311         m_Tag = tag;
312     }
313 
GetTag(void) const314     CAsnBinaryDefs::TLongTag GetTag(void) const {
315         return m_Tag;
316     }
317 
HasTag(void) const318     bool HasTag(void) const {
319         return m_Tag != eNoExplicitTag;
320     }
321 
SetTagClass(CAsnBinaryDefs::ETagClass tclass)322     void SetTagClass(CAsnBinaryDefs::ETagClass tclass) {
323         m_TagClass = tclass;
324     }
GetTagClass(void) const325     CAsnBinaryDefs::ETagClass GetTagClass(void) const {
326         return m_TagClass;
327     }
SetTagType(CAsnBinaryDefs::ETagType ttype)328     void SetTagType(CAsnBinaryDefs::ETagType ttype) {
329         m_TagType = ttype;
330     }
GetTagType(void) const331     CAsnBinaryDefs::ETagType GetTagType(void) const {
332         return m_TagType;
333     }
334     CNcbiOstream& PrintASNTag(CNcbiOstream& out) const;
335     static string GetTagClassString(CAsnBinaryDefs::ETagClass tclass);
336     static string GetTagTypeString(CAsnBinaryDefs::ETagType ttype);
337 
SetTypeStr(CClassTypeStrings * TypeStr) const338     void SetTypeStr(CClassTypeStrings* TypeStr) const {
339         m_TypeStr = TypeStr;
340     }
GetTypeStr(void) const341     CClassTypeStrings* GetTypeStr(void) const {
342         return m_TypeStr;
343     }
344 
345     bool IsPrimitive(void) const;
346     bool IsStdType(void) const;
347     bool IsReference(void) const;
348 
SetIsAlias(bool value)349     void SetIsAlias(bool value) {
350         m_IsAlias = value;
351     }
IsAlias(void) const352     bool IsAlias(void) const {
353         return m_IsAlias;
354     }
355     // used when generating code, to provide backward compatibility
SetIsTypeAlias(bool value) const356     void SetIsTypeAlias(bool value) const {
357         m_IsTypeAlias = value;
358     }
IsTypeAlias(void) const359     bool IsTypeAlias(void) const {
360         return m_IsTypeAlias;
361     }
362 
EnableDTDEntities(bool enable=true)363     static void EnableDTDEntities(bool enable = true) {
364         sm_EnableDTDEntities = enable;
365     }
DTDEntitiesEnabled(void)366     static bool DTDEntitiesEnabled(void) {
367         return sm_EnableDTDEntities;
368     }
SetEnforcedStdXml(bool set=true)369     static void SetEnforcedStdXml(bool set = true) {
370         sm_EnforcedStdXml = set;
371     }
GetEnforcedStdXml(void)372     static bool GetEnforcedStdXml(void) {
373         return sm_EnforcedStdXml;
374     }
SetSourceDataSpec(EDataSpec spec)375     static void SetSourceDataSpec(EDataSpec spec) {
376         sm_SourceDataSpec = spec;
377     }
GetSourceDataSpec(void)378     static EDataSpec GetSourceDataSpec(void) {
379         return sm_SourceDataSpec;
380     }
381     static string GetSourceDataSpecString(void);
IsASNDataSpec(void)382     static bool IsASNDataSpec(void) {
383         return sm_SourceDataSpec == EDataSpec::eASN;
384     }
IsXMLDataSpec(void)385     static bool IsXMLDataSpec(void) {
386         return sm_SourceDataSpec == EDataSpec::eDTD || sm_SourceDataSpec == EDataSpec::eXSD;
387     }
388 
389     virtual const char* GetDEFKeyword(void) const;
GetMemberName(void) const390     const string& GetMemberName(void) const
391     {
392         return m_MemberName;
393     }
394 
SetNamespaceName(const string & name)395     void SetNamespaceName(const string& name)
396     {
397         m_Namespace = name;
398     }
GetNamespaceName(void) const399     const string& GetNamespaceName(void) const
400     {
401         return m_Namespace;
402     }
SetNsQualified(bool qualified)403     void SetNsQualified(bool qualified)
404     {
405         m_NsQualified = qualified ? eNSQualified : eNSUnqualified;
406     }
IsNsQualified(void) const407     ENsQualifiedMode IsNsQualified(void) const
408     {
409         return m_NsQualified;
410     }
SetNillable(void)411     void SetNillable(void)
412     {
413         m_IsNillable = true;
414     }
IsNillable(void) const415     bool IsNillable(void) const
416     {
417         return m_IsNillable;
418     }
419     enum EGlobalType {
420         eElement = 0,
421         eType,
422         eGroup
423     };
SetGlobalType(EGlobalType type)424     void SetGlobalType(EGlobalType type) {
425         m_GlobalType = type;
426     }
GetGlobalType(void) const427     EGlobalType GetGlobalType(void) const {
428         return m_GlobalType;
429     }
SetEmptyExternalName(bool set)430     void SetEmptyExternalName(bool set) {
431         m_EmptyExternalName = set;
432     }
HasExternalName(void) const433     bool HasExternalName(void) const {
434         return !m_EmptyExternalName;
435     }
436     string GetFullName(void) const;
SetRestrictions(const list<CMemberFacet> & c)437     void SetRestrictions(const list<CMemberFacet>& c) {
438         m_Restrictions = c;
439     }
GetRestrictions(void) const440     const list<CMemberFacet>& GetRestrictions(void) const {
441         return m_Restrictions;
442     }
443 
444 protected:
445     static bool x_IsSavedName(const string& name);
446     static void x_AddSavedName(const string& name);
447     void x_SetMemberAndClassName(const string& memberName);
448 
449 private:
450     const CDataType* m_ParentType;       // parent type
451     const CDataTypeModule* m_Module;
452     string m_MemberName;
453     string m_ClassName;
454     string m_XmlName;
455     int m_SourceLine;
456     CComments m_Comments;
457     CDataMember* m_DataMember;
458     mutable CClassTypeStrings* m_TypeStr;
459 
460     // tree info
461     const CUniSequenceDataType* m_Set;
462     const CChoiceDataType* m_Choice;
463     AutoPtr<TReferences> m_References;
464 
465     bool m_Checked;
466 
467     CTypeRef m_TypeRef;
468     AutoPtr<CTypeInfo> m_AnyTypeInfo;
469     AutoPtr<CTypeInfo> m_RealTypeInfo;
470     static set<string, PNocase> sm_AllFileNames;
471     mutable string m_CachedFileName;
472     mutable unique_ptr<CNamespace> m_CachedNamespace;
473     CAsnBinaryDefs::TLongTag  m_Tag;
474     CAsnBinaryDefs::ETagClass m_TagClass;
475     CAsnBinaryDefs::ETagType  m_TagType;
476     bool m_IsAlias;
477     mutable bool m_IsTypeAlias;
478     multimap<string,string> m_ForbidVar;
479     string m_Namespace;
480     ENsQualifiedMode m_NsQualified;
481     bool m_IsNillable;
482     EGlobalType m_GlobalType;
483     bool m_EmptyExternalName;
484     list<CMemberFacet> m_Restrictions;
485 
486     CDataType(const CDataType&);
487     CDataType& operator=(const CDataType&);
488     static bool sm_EnableDTDEntities;
489     static bool sm_EnforcedStdXml;
490     static EDataSpec sm_SourceDataSpec;
491     static set<string> sm_SavedNames;
492     static map<string,string> sm_ClassToMember;
493 };
494 
495 #define CheckValueType(value, type, name) do{ \
496 if ( dynamic_cast<const type*>(&(value)) == 0 ) { \
497     (value).Warning(name " value expected", 1); return false; \
498 } } while(0)
499 
500 END_NCBI_SCOPE
501 
502 #endif
503