1 /*  $Id: continfo.cpp 463313 2015-03-26 17:05:21Z vasilche $
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 *   !!! PUT YOUR DESCRIPTION HERE !!!
30 */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbistd.hpp>
34 #include <corelib/ncbiutil.hpp>
35 #include <serial/impl/continfo.hpp>
36 #include <serial/objistr.hpp>
37 #include <serial/objostr.hpp>
38 #include <serial/objcopy.hpp>
39 #include <serial/serialutil.hpp>
40 #include <serial/error_codes.hpp>
41 
42 
43 #define NCBI_USE_ERRCODE_X   Serial_TypeInfo
44 
45 BEGIN_NCBI_SCOPE
46 
CContainerTypeInfo(size_t size,TTypeInfo elementType,bool randomOrder)47 CContainerTypeInfo::CContainerTypeInfo(size_t size,
48                                        TTypeInfo elementType,
49                                        bool randomOrder)
50     : CParent(eTypeFamilyContainer, size),
51       m_ElementType(elementType), m_RandomOrder(randomOrder)
52 {
53     InitContainerTypeInfoFunctions();
54 }
55 
CContainerTypeInfo(size_t size,const CTypeRef & elementType,bool randomOrder)56 CContainerTypeInfo::CContainerTypeInfo(size_t size,
57                                        const CTypeRef& elementType,
58                                        bool randomOrder)
59     : CParent(eTypeFamilyContainer, size),
60       m_ElementType(elementType), m_RandomOrder(randomOrder)
61 {
62     InitContainerTypeInfoFunctions();
63 }
64 
CContainerTypeInfo(size_t size,const char * name,TTypeInfo elementType,bool randomOrder)65 CContainerTypeInfo::CContainerTypeInfo(size_t size, const char* name,
66                                        TTypeInfo elementType,
67                                        bool randomOrder)
68     : CParent(eTypeFamilyContainer, size, name),
69       m_ElementType(elementType), m_RandomOrder(randomOrder)
70 {
71     InitContainerTypeInfoFunctions();
72 }
73 
CContainerTypeInfo(size_t size,const char * name,const CTypeRef & elementType,bool randomOrder)74 CContainerTypeInfo::CContainerTypeInfo(size_t size, const char* name,
75                                        const CTypeRef& elementType,
76                                        bool randomOrder)
77     : CParent(eTypeFamilyContainer, size, name),
78       m_ElementType(elementType), m_RandomOrder(randomOrder)
79 {
80     InitContainerTypeInfoFunctions();
81 }
82 
CContainerTypeInfo(size_t size,const string & name,TTypeInfo elementType,bool randomOrder)83 CContainerTypeInfo::CContainerTypeInfo(size_t size, const string& name,
84                                        TTypeInfo elementType,
85                                        bool randomOrder)
86     : CParent(eTypeFamilyContainer, size, name),
87       m_ElementType(elementType), m_RandomOrder(randomOrder)
88 {
89     InitContainerTypeInfoFunctions();
90 }
91 
CContainerTypeInfo(size_t size,const string & name,const CTypeRef & elementType,bool randomOrder)92 CContainerTypeInfo::CContainerTypeInfo(size_t size, const string& name,
93                                        const CTypeRef& elementType,
94                                        bool randomOrder)
95     : CParent(eTypeFamilyContainer, size, name),
96       m_ElementType(elementType), m_RandomOrder(randomOrder)
97 {
98     InitContainerTypeInfoFunctions();
99 }
100 
101 class CContainerTypeInfoFunctions
102 {
103 public:
104     NCBI_NORETURN
Throw(const char * message)105     static void Throw(const char* message)
106         {
107             NCBI_THROW(CSerialException,eFail, message);
108         }
InitIteratorConst(CContainerTypeInfo::CConstIterator &)109     static bool InitIteratorConst(CContainerTypeInfo::CConstIterator&)
110         {
111             Throw("cannot create iterator");
112             return false;
113         }
InitIterator(CContainerTypeInfo::CIterator &)114     static bool InitIterator(CContainerTypeInfo::CIterator&)
115         {
116             Throw("cannot create iterator");
117             return false;
118         }
AddElement(const CContainerTypeInfo *,TObjectPtr,TConstObjectPtr,ESerialRecursionMode)119     static TObjectPtr AddElement(const CContainerTypeInfo* /*containerType*/,
120                                  TObjectPtr /*containerPtr*/,
121                                  TConstObjectPtr /*elementPtr*/,
122                                  ESerialRecursionMode)
123         {
124             Throw("illegal call");
125             return 0;
126         }
127 
AddElementIn(const CContainerTypeInfo *,TObjectPtr,CObjectIStream &)128     static TObjectPtr AddElementIn(const CContainerTypeInfo* /*containerType*/,
129                                    TObjectPtr /*containerPtr*/,
130                                    CObjectIStream& /*in*/)
131         {
132             Throw("illegal call");
133             return 0;
134         }
135 
GetElementCount(const CContainerTypeInfo *,TConstObjectPtr)136     static size_t GetElementCount(const CContainerTypeInfo*, TConstObjectPtr)
137         {
138             Throw("illegal call");
139             return 0;
140         }
141 };
142 
InitContainerTypeInfoFunctions(void)143 void CContainerTypeInfo::InitContainerTypeInfoFunctions(void)
144 {
145     SetTag(m_RandomOrder ? CAsnBinaryDefs::eSetOf : CAsnBinaryDefs::eSequenceOf);
146     SetReadFunction(&ReadContainer);
147     SetWriteFunction(&WriteContainer);
148     SetCopyFunction(&CopyContainer);
149     SetSkipFunction(&SkipContainer);
150     m_InitIteratorConst = &CContainerTypeInfoFunctions::InitIteratorConst;
151     m_InitIterator = &CContainerTypeInfoFunctions::InitIterator;
152     m_AddElement = &CContainerTypeInfoFunctions::AddElement;
153     m_AddElementIn = &CContainerTypeInfoFunctions::AddElementIn;
154     m_GetElementCount = &CContainerTypeInfoFunctions::GetElementCount;
155 }
156 
SetAddElementFunctions(TAddElement addElement,TAddElementIn addElementIn)157 void CContainerTypeInfo::SetAddElementFunctions(TAddElement addElement,
158                                                 TAddElementIn addElementIn)
159 {
160     m_AddElement = addElement;
161     m_AddElementIn = addElementIn;
162 }
163 
SetCountFunctions(TGetElementCount getElementCount,TReserveElements reserveElements)164 void CContainerTypeInfo::SetCountFunctions(TGetElementCount getElementCount,
165                                            TReserveElements reserveElements)
166 {
167     m_GetElementCount = getElementCount;
168     m_ReserveElements = reserveElements;
169 }
170 
SetConstIteratorFunctions(TInitIteratorConst init,TReleaseIteratorConst release,TCopyIteratorConst copy,TNextElementConst next,TGetElementPtrConst get)171 void CContainerTypeInfo::SetConstIteratorFunctions(TInitIteratorConst init,
172                                                    TReleaseIteratorConst release,
173                                                    TCopyIteratorConst copy,
174                                                    TNextElementConst next,
175                                                    TGetElementPtrConst get)
176 {
177     m_InitIteratorConst = init;
178     m_ReleaseIteratorConst = release;
179     m_CopyIteratorConst = copy;
180     m_NextElementConst = next;
181     m_GetElementPtrConst = get;
182 }
183 
SetIteratorFunctions(TInitIterator init,TReleaseIterator release,TCopyIterator copy,TNextElement next,TGetElementPtr get,TEraseElement erase,TEraseAllElements erase_all)184 void CContainerTypeInfo::SetIteratorFunctions(TInitIterator init,
185                                               TReleaseIterator release,
186                                               TCopyIterator copy,
187                                               TNextElement next,
188                                               TGetElementPtr get,
189                                               TEraseElement erase,
190                                               TEraseAllElements erase_all)
191 {
192     m_InitIterator = init;
193     m_ReleaseIterator = release;
194     m_CopyIterator = copy;
195     m_NextElement = next;
196     m_GetElementPtr = get;
197     m_EraseElement = erase;
198     m_EraseAllElements = erase_all;
199 }
200 
201 CTypeInfo::EMayContainType
GetMayContainType(TTypeInfo type) const202 CContainerTypeInfo::GetMayContainType(TTypeInfo type) const
203 {
204     return GetElementType()->IsOrMayContainType(type);
205 }
206 
Assign(TObjectPtr dst,TConstObjectPtr src,ESerialRecursionMode how) const207 void CContainerTypeInfo::Assign(TObjectPtr dst, TConstObjectPtr src,
208                                 ESerialRecursionMode how) const
209 {
210     if (how == eShallowChildless) {
211         SetDefault(dst); // clear destination container
212         return;
213     }
214     CIterator idst;
215     CConstIterator isrc;
216     bool old_element = InitIterator(idst,dst);
217     if ( InitIterator(isrc, src) ) {
218         TTypeInfo elementType = GetElementType();
219         do {
220             TConstObjectPtr elementPtr = GetElementPtr(isrc);
221             if (old_element) {
222                 elementType->Assign(GetElementPtr(idst), elementPtr, how);
223                 old_element = NextElement(idst);
224             } else {
225                 AddElement(dst, elementPtr, how);
226             }
227         } while ( NextElement(isrc) );
228     }
229     if (old_element) {
230         EraseAllElements(idst);
231     }
232 }
233 
Equals(TConstObjectPtr object1,TConstObjectPtr object2,ESerialRecursionMode how) const234 bool CContainerTypeInfo::Equals(TConstObjectPtr object1, TConstObjectPtr object2,
235                                 ESerialRecursionMode how) const
236 {
237     if (how == eShallowChildless) {
238         return true;
239     }
240     TTypeInfo elementType = GetElementType();
241     CConstIterator i1, i2;
242     if ( InitIterator(i1, object1) ) {
243         if ( !InitIterator(i2, object2) )
244             return false;
245         if ( !elementType->Equals(GetElementPtr(i1),
246                                   GetElementPtr(i2), how) )
247             return false;
248         while ( NextElement(i1) ) {
249             if ( !NextElement(i2) )
250                 return false;
251             if ( !elementType->Equals(GetElementPtr(i1),
252                                       GetElementPtr(i2), how) )
253                 return false;
254         }
255         return !NextElement(i2);
256     }
257     else {
258         return !InitIterator(i2, object2);
259     }
260 }
261 
ReadContainer(CObjectIStream & in,TTypeInfo objectType,TObjectPtr objectPtr)262 void CContainerTypeInfo::ReadContainer(CObjectIStream& in,
263                                        TTypeInfo objectType,
264                                        TObjectPtr objectPtr)
265 {
266     const CContainerTypeInfo* containerType =
267         CTypeConverter<CContainerTypeInfo>::SafeCast(objectType);
268 
269     in.ReadContainer(containerType, objectPtr);
270 }
271 
WriteContainer(CObjectOStream & out,TTypeInfo objectType,TConstObjectPtr objectPtr)272 void CContainerTypeInfo::WriteContainer(CObjectOStream& out,
273                                         TTypeInfo objectType,
274                                         TConstObjectPtr objectPtr)
275 {
276     const CContainerTypeInfo* containerType =
277         CTypeConverter<CContainerTypeInfo>::SafeCast(objectType);
278 
279     out.WriteContainer(containerType, objectPtr);
280 }
281 
CopyContainer(CObjectStreamCopier & copier,TTypeInfo objectType)282 void CContainerTypeInfo::CopyContainer(CObjectStreamCopier& copier,
283                                        TTypeInfo objectType)
284 {
285     const CContainerTypeInfo* containerType =
286         CTypeConverter<CContainerTypeInfo>::SafeCast(objectType);
287 
288     copier.CopyContainer(containerType);
289 }
290 
SkipContainer(CObjectIStream & in,TTypeInfo objectType)291 void CContainerTypeInfo::SkipContainer(CObjectIStream& in,
292                                        TTypeInfo objectType)
293 {
294     const CContainerTypeInfo* containerType =
295         CTypeConverter<CContainerTypeInfo>::SafeCast(objectType);
296 
297     in.SkipContainer(containerType);
298 }
299 
300 END_NCBI_SCOPE
301