1 /*  $Id: variant.cpp 576490 2018-12-17 14:45:09Z 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 *   !!! PUT YOUR DESCRIPTION HERE !!!
30 *
31 * ===========================================================================
32 */
33 
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbistd.hpp>
36 #include <corelib/ncbimtx.hpp>
37 
38 #include <serial/impl/variant.hpp>
39 #include <serial/objectinfo.hpp>
40 #include <serial/objectiter.hpp>
41 #include <serial/objistr.hpp>
42 #include <serial/objostr.hpp>
43 #include <serial/objcopy.hpp>
44 #include <serial/delaybuf.hpp>
45 #include <serial/impl/choiceptr.hpp>
46 #include <serial/impl/ptrinfo.hpp>
47 #include <serial/serialimpl.hpp>
48 
49 BEGIN_NCBI_SCOPE
50 
51 class CVariantInfoFunctions
52 {
53 public:
54 
55     static
56     TConstObjectPtr GetConstInlineVariant(const CVariantInfo* variantInfo,
57                                           TConstObjectPtr choicePtr);
58     static
59     TConstObjectPtr GetConstPointerVariant(const CVariantInfo* variantInfo,
60                                            TConstObjectPtr choicePtr);
61     static
62     TConstObjectPtr GetConstDelayedVariant(const CVariantInfo* variantInfo,
63                                            TConstObjectPtr choicePtr);
64     static
65     TConstObjectPtr GetConstSubclassVariant(const CVariantInfo* variantInfo,
66                                             TConstObjectPtr choicePtr);
67     static TObjectPtr GetInlineVariant(const CVariantInfo* variantInfo,
68                                        TObjectPtr choicePtr);
69     static TObjectPtr GetPointerVariant(const CVariantInfo* variantInfo,
70                                         TObjectPtr choicePtr);
71     static TObjectPtr GetDelayedVariant(const CVariantInfo* variantInfo,
72                                         TObjectPtr choicePtr);
73     static TObjectPtr GetSubclassVariant(const CVariantInfo* variantInfo,
74                                          TObjectPtr choicePtr);
75 
76     static void ReadInlineVariant(CObjectIStream& in,
77                                   const CVariantInfo* variantInfo,
78                                   TObjectPtr choicePtr);
79     static void ReadPointerVariant(CObjectIStream& in,
80                                    const CVariantInfo* variantInfo,
81                                    TObjectPtr choicePtr);
82     static void ReadObjectPointerVariant(CObjectIStream& in,
83                                          const CVariantInfo* variantInfo,
84                                          TObjectPtr choicePtr);
85     static void ReadDelayedVariant(CObjectIStream& in,
86                                    const CVariantInfo* variantInfo,
87                                    TObjectPtr choicePtr);
88     static void ReadSubclassVariant(CObjectIStream& in,
89                                     const CVariantInfo* variantInfo,
90                                     TObjectPtr choicePtr);
91     static void ReadHookedVariant(CObjectIStream& in,
92                                   const CVariantInfo* variantInfo,
93                                   TObjectPtr choicePtr);
94     static void WriteInlineVariant(CObjectOStream& out,
95                                    const CVariantInfo* variantInfo,
96                                    TConstObjectPtr choicePtr);
97     static void WritePointerVariant(CObjectOStream& out,
98                                     const CVariantInfo* variantInfo,
99                                     TConstObjectPtr choicePtr);
100     static void WriteObjectPointerVariant(CObjectOStream& out,
101                                           const CVariantInfo* variantInfo,
102                                           TConstObjectPtr choicePtr);
103     static void WriteSubclassVariant(CObjectOStream& out,
104                                      const CVariantInfo* variantInfo,
105                                      TConstObjectPtr choicePtr);
106     static void WriteDelayedVariant(CObjectOStream& out,
107                                     const CVariantInfo* variantInfo,
108                                     TConstObjectPtr choicePtr);
109     static void WriteHookedVariant(CObjectOStream& out,
110                                    const CVariantInfo* variantInfo,
111                                    TConstObjectPtr choicePtr);
112     static void SkipNonObjectVariant(CObjectIStream& in,
113                                      const CVariantInfo* variantInfo);
114     static void SkipObjectPointerVariant(CObjectIStream& in,
115                                          const CVariantInfo* variantInfo);
116     static void SkipHookedVariant(CObjectIStream& in,
117                                   const CVariantInfo* variantInfo);
118     static void CopyNonObjectVariant(CObjectStreamCopier& copier,
119                                      const CVariantInfo* variantInfo);
120     static void CopyObjectPointerVariant(CObjectStreamCopier& copier,
121                                          const CVariantInfo* variantInfo);
122     static void CopyHookedVariant(CObjectStreamCopier& copier,
123                                   const CVariantInfo* variantInfo);
124 };
125 
126 typedef CVariantInfoFunctions TFunc;
127 
CVariantInfo(const CChoiceTypeInfo * choiceType,const CMemberId & id,TPointerOffsetType offset,const CTypeRef & type)128 CVariantInfo::CVariantInfo(const CChoiceTypeInfo* choiceType,
129                            const CMemberId& id, TPointerOffsetType offset,
130                            const CTypeRef& type)
131     : CParent(id, offset, type), m_ChoiceType(choiceType),
132       m_VariantType(eInlineVariant), m_DelayOffset(eNoOffset),
133       m_GetConstFunction(&TFunc::GetConstInlineVariant),
134       m_GetFunction(&TFunc::GetInlineVariant),
135       m_ReadHookData(&TFunc::ReadInlineVariant, &TFunc::ReadHookedVariant),
136       m_WriteHookData(&TFunc::WriteInlineVariant, &TFunc::WriteHookedVariant),
137       m_SkipHookData(&TFunc::SkipNonObjectVariant, &TFunc::SkipHookedVariant),
138       m_CopyHookData(&TFunc::CopyNonObjectVariant, &TFunc::CopyHookedVariant)
139 {
140 }
141 
CVariantInfo(const CChoiceTypeInfo * choiceType,const CMemberId & id,TPointerOffsetType offset,TTypeInfo type)142 CVariantInfo::CVariantInfo(const CChoiceTypeInfo* choiceType,
143                            const CMemberId& id, TPointerOffsetType offset,
144                            TTypeInfo type)
145     : CParent(id, offset, type), m_ChoiceType(choiceType),
146       m_VariantType(eInlineVariant), m_DelayOffset(eNoOffset),
147       m_GetConstFunction(&TFunc::GetConstInlineVariant),
148       m_GetFunction(&TFunc::GetInlineVariant),
149       m_ReadHookData(&TFunc::ReadInlineVariant, &TFunc::ReadHookedVariant),
150       m_WriteHookData(&TFunc::WriteInlineVariant, &TFunc::WriteHookedVariant),
151       m_SkipHookData(&TFunc::SkipNonObjectVariant, &TFunc::SkipHookedVariant),
152       m_CopyHookData(&TFunc::CopyNonObjectVariant, &TFunc::CopyHookedVariant)
153 {
154 }
155 
CVariantInfo(const CChoiceTypeInfo * choiceType,const char * id,TPointerOffsetType offset,const CTypeRef & type)156 CVariantInfo::CVariantInfo(const CChoiceTypeInfo* choiceType,
157                            const char* id, TPointerOffsetType offset,
158                            const CTypeRef& type)
159     : CParent(id, offset, type), m_ChoiceType(choiceType),
160       m_VariantType(eInlineVariant), m_DelayOffset(eNoOffset),
161       m_GetConstFunction(&TFunc::GetConstInlineVariant),
162       m_GetFunction(&TFunc::GetInlineVariant),
163       m_ReadHookData(&TFunc::ReadInlineVariant, &TFunc::ReadHookedVariant),
164       m_WriteHookData(&TFunc::WriteInlineVariant, &TFunc::WriteHookedVariant),
165       m_SkipHookData(&TFunc::SkipNonObjectVariant, &TFunc::SkipHookedVariant),
166       m_CopyHookData(&TFunc::CopyNonObjectVariant, &TFunc::CopyHookedVariant)
167 {
168 }
169 
CVariantInfo(const CChoiceTypeInfo * choiceType,const char * id,TPointerOffsetType offset,TTypeInfo type)170 CVariantInfo::CVariantInfo(const CChoiceTypeInfo* choiceType,
171                            const char* id, TPointerOffsetType offset,
172                            TTypeInfo type)
173     : CParent(id, offset, type), m_ChoiceType(choiceType),
174       m_VariantType(eInlineVariant), m_DelayOffset(eNoOffset),
175       m_GetConstFunction(&TFunc::GetConstInlineVariant),
176       m_GetFunction(&TFunc::GetInlineVariant),
177       m_ReadHookData(&TFunc::ReadInlineVariant, &TFunc::ReadHookedVariant),
178       m_WriteHookData(&TFunc::WriteInlineVariant, &TFunc::WriteHookedVariant),
179       m_SkipHookData(&TFunc::SkipNonObjectVariant, &TFunc::SkipHookedVariant),
180       m_CopyHookData(&TFunc::CopyNonObjectVariant, &TFunc::CopyHookedVariant)
181 {
182 }
183 
SetPointer(void)184 CVariantInfo* CVariantInfo::SetPointer(void)
185 {
186     if ( !IsInline() ) {
187         NCBI_THROW(CSerialException,eIllegalCall,
188                    "SetPointer() is not first call");
189     }
190     m_VariantType = eNonObjectPointerVariant;
191     UpdateFunctions();
192     return this;
193 }
194 
SetObjectPointer(void)195 CVariantInfo* CVariantInfo::SetObjectPointer(void)
196 {
197     if ( !IsInline() ) {
198         NCBI_THROW(CSerialException,eIllegalCall,
199                    "SetObjectPointer() is not first call");
200     }
201     m_VariantType = eObjectPointerVariant;
202     UpdateFunctions();
203     return this;
204 }
205 
SetSubClass(void)206 CVariantInfo* CVariantInfo::SetSubClass(void)
207 {
208     if ( !IsInline() ) {
209         NCBI_THROW(CSerialException,eIllegalCall,
210                    "SetSubClass() is not first call");
211     }
212     if ( CanBeDelayed() ) {
213         NCBI_THROW(CSerialException,eIllegalCall,
214                   "sub class cannot be delayed");
215     }
216     m_VariantType = eSubClassVariant;
217     UpdateFunctions();
218     return this;
219 }
220 
221 bool NCBI_XSERIAL_EXPORT EnabledDelayBuffers(void);
222 
SetDelayBuffer(CDelayBuffer * buffer)223 CVariantInfo* CVariantInfo::SetDelayBuffer(CDelayBuffer* buffer)
224 {
225     if ( IsSubClass() ) {
226         NCBI_THROW(CSerialException,eIllegalCall,
227                    "sub class cannot be delayed");
228     }
229     if ( EnabledDelayBuffers() ) {
230         m_DelayOffset = TPointerOffsetType(buffer);
231         UpdateFunctions();
232     }
233     return this;
234 }
235 
UpdateFunctions(void)236 void CVariantInfo::UpdateFunctions(void)
237 {
238     // determine function pointers
239     TVariantGetConst getConstFunc;
240     TVariantGet getFunc;
241     TVariantReadFunction readFunc;
242     TVariantWriteFunction writeFunc;
243     TVariantSkipFunction skipFunc;
244     TVariantCopyFunction copyFunc;
245 
246     // read/write/get
247     if ( CanBeDelayed() ) {
248         _ASSERT(!IsSubClass());
249         getConstFunc = &TFunc::GetConstDelayedVariant;
250         getFunc = &TFunc::GetDelayedVariant;
251         readFunc = &TFunc::ReadDelayedVariant;
252         writeFunc = &TFunc::WriteDelayedVariant;
253     }
254     else if ( IsInline() ) {
255         getConstFunc = &TFunc::GetConstInlineVariant;
256         getFunc = &TFunc::GetInlineVariant;
257         readFunc = &TFunc::ReadInlineVariant;
258         writeFunc = &TFunc::WriteInlineVariant;
259     }
260     else if ( IsObjectPointer() ) {
261         getConstFunc = &TFunc::GetConstPointerVariant;
262         getFunc = &TFunc::GetPointerVariant;
263         readFunc = &TFunc::ReadObjectPointerVariant;
264         writeFunc = &TFunc::WriteObjectPointerVariant;
265     }
266     else if ( IsNonObjectPointer() ) {
267         getConstFunc = &TFunc::GetConstPointerVariant;
268         getFunc = &TFunc::GetPointerVariant;
269         readFunc = &TFunc::ReadPointerVariant;
270         writeFunc = &TFunc::WritePointerVariant;
271     }
272     else { // subclass
273         getConstFunc = &TFunc::GetConstSubclassVariant;
274         getFunc = &TFunc::GetSubclassVariant;
275         readFunc = &TFunc::ReadSubclassVariant;
276         writeFunc = &TFunc::WriteSubclassVariant;
277     }
278 
279     // copy/skip
280     if ( IsObject() ) {
281         copyFunc = &TFunc::CopyObjectPointerVariant;
282         skipFunc = &TFunc::SkipObjectPointerVariant;
283     }
284     else {
285         copyFunc = &TFunc::CopyNonObjectVariant;
286         skipFunc = &TFunc::SkipNonObjectVariant;
287     }
288 
289     // update function pointers
290     m_GetConstFunction = getConstFunc;
291     m_GetFunction = getFunc;
292     m_ReadHookData.SetDefaultFunction(readFunc);
293     m_WriteHookData.SetDefaultFunction(writeFunc);
294     m_SkipHookData.SetDefaultFunction(skipFunc);
295     m_CopyHookData.SetDefaultFunction(copyFunc);
296 }
297 
UpdateDelayedBuffer(CObjectIStream & in,TObjectPtr choicePtr) const298 void CVariantInfo::UpdateDelayedBuffer(CObjectIStream& in,
299                                        TObjectPtr choicePtr) const
300 {
301     _ASSERT(CanBeDelayed());
302     _ASSERT(GetDelayBuffer(choicePtr).GetIndex() == GetIndex());
303 
304     TObjectPtr variantPtr = GetItemPtr(choicePtr);
305     TTypeInfo variantType = GetTypeInfo();
306     if ( IsPointer() ) {
307         // create object itself
308         variantPtr = CTypeConverter<TObjectPtr>::Get(variantPtr) =
309             variantType->Create();
310         if ( IsObjectPointer() ) {
311             _TRACE("Should check for real pointer type (CRef...)");
312             CTypeConverter<CObject>::Get(variantPtr).AddReference();
313         }
314     }
315 
316     BEGIN_OBJECT_FRAME_OF2(in, eFrameChoice, GetChoiceType());
317     BEGIN_OBJECT_FRAME_OF2(in, eFrameChoiceVariant, GetId());
318     variantType->ReadData(in, variantPtr);
319     END_OBJECT_FRAME_OF(in);
320     END_OBJECT_FRAME_OF(in);
321 }
322 
SetReadFunction(TVariantReadFunction func)323 void CVariantInfo::SetReadFunction(TVariantReadFunction func)
324 {
325     m_ReadHookData.SetDefaultFunction(func);
326 }
327 
SetWriteFunction(TVariantWriteFunction func)328 void CVariantInfo::SetWriteFunction(TVariantWriteFunction func)
329 {
330     m_WriteHookData.SetDefaultFunction(func);
331 }
332 
SetCopyFunction(TVariantCopyFunction func)333 void CVariantInfo::SetCopyFunction(TVariantCopyFunction func)
334 {
335     m_CopyHookData.SetDefaultFunction(func);
336 }
337 
SetSkipFunction(TVariantSkipFunction func)338 void CVariantInfo::SetSkipFunction(TVariantSkipFunction func)
339 {
340     m_SkipHookData.SetDefaultFunction(func);
341 }
342 
CreateChoice(void) const343 TObjectPtr CVariantInfo::CreateChoice(void) const
344 {
345     return GetChoiceType()->Create();
346 }
347 
348 TConstObjectPtr
GetConstInlineVariant(const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)349 CVariantInfoFunctions::GetConstInlineVariant(const CVariantInfo* variantInfo,
350                                              TConstObjectPtr choicePtr)
351 {
352     _ASSERT(!variantInfo->CanBeDelayed());
353     _ASSERT(variantInfo->IsInline());
354     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
355             variantInfo->GetIndex());
356     return variantInfo->GetItemPtr(choicePtr);
357 }
358 
359 TConstObjectPtr
GetConstPointerVariant(const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)360 CVariantInfoFunctions::GetConstPointerVariant(const CVariantInfo* variantInfo,
361                                               TConstObjectPtr choicePtr)
362 {
363     _ASSERT(!variantInfo->CanBeDelayed());
364     _ASSERT(variantInfo->IsPointer());
365     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
366             variantInfo->GetIndex());
367     TConstObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
368     variantPtr = CTypeConverter<TConstObjectPtr>::Get(variantPtr);
369     _ASSERT(variantPtr);
370     return variantPtr;
371 }
372 
373 TConstObjectPtr
GetConstDelayedVariant(const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)374 CVariantInfoFunctions::GetConstDelayedVariant(const CVariantInfo* variantInfo,
375                                               TConstObjectPtr choicePtr)
376 {
377     _ASSERT(variantInfo->CanBeDelayed());
378     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
379             variantInfo->GetIndex());
380     const_cast<CDelayBuffer&>(variantInfo->GetDelayBuffer(choicePtr)).Update();
381     TConstObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
382     if ( variantInfo->IsPointer() ) {
383         variantPtr = CTypeConverter<TConstObjectPtr>::Get(variantPtr);
384         _ASSERT(variantPtr);
385     }
386     return variantPtr;
387 }
388 
389 TConstObjectPtr
GetConstSubclassVariant(const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)390 CVariantInfoFunctions::GetConstSubclassVariant(const CVariantInfo* variantInfo,
391                                                TConstObjectPtr choicePtr)
392 {
393     _ASSERT(variantInfo->IsSubClass());
394     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
395             variantInfo->GetIndex());
396     const CChoiceTypeInfo* choiceType = variantInfo->GetChoiceType();
397     const CChoicePointerTypeInfo* choicePtrType =
398         CTypeConverter<CChoicePointerTypeInfo>::SafeCast(choiceType);
399     TConstObjectPtr variantPtr =
400         choicePtrType->GetPointerTypeInfo()->GetObjectPointer(choicePtr);
401     _ASSERT(variantPtr);
402     return variantPtr;
403 }
404 
405 TObjectPtr
GetInlineVariant(const CVariantInfo * variantInfo,TObjectPtr choicePtr)406 CVariantInfoFunctions::GetInlineVariant(const CVariantInfo* variantInfo,
407                                         TObjectPtr choicePtr)
408 {
409     _ASSERT(!variantInfo->CanBeDelayed());
410     _ASSERT(variantInfo->IsInline());
411     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
412             variantInfo->GetIndex());
413     return variantInfo->GetItemPtr(choicePtr);
414 }
415 
416 TObjectPtr
GetPointerVariant(const CVariantInfo * variantInfo,TObjectPtr choicePtr)417 CVariantInfoFunctions::GetPointerVariant(const CVariantInfo* variantInfo,
418                                          TObjectPtr choicePtr)
419 {
420     _ASSERT(!variantInfo->CanBeDelayed());
421     _ASSERT(variantInfo->IsPointer());
422     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
423             variantInfo->GetIndex());
424     TObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
425     variantPtr = CTypeConverter<TObjectPtr>::Get(variantPtr);
426     _ASSERT(variantPtr);
427     return variantPtr;
428 }
429 
430 TObjectPtr
GetDelayedVariant(const CVariantInfo * variantInfo,TObjectPtr choicePtr)431 CVariantInfoFunctions::GetDelayedVariant(const CVariantInfo* variantInfo,
432                                          TObjectPtr choicePtr)
433 {
434     _ASSERT(variantInfo->CanBeDelayed());
435     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
436             variantInfo->GetIndex());
437     variantInfo->GetDelayBuffer(choicePtr).Update();
438     TObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
439     if ( variantInfo->IsPointer() ) {
440         variantPtr = CTypeConverter<TObjectPtr>::Get(variantPtr);
441         _ASSERT(variantPtr);
442     }
443     return variantPtr;
444 }
445 
446 TObjectPtr
GetSubclassVariant(const CVariantInfo * variantInfo,TObjectPtr choicePtr)447 CVariantInfoFunctions::GetSubclassVariant(const CVariantInfo* variantInfo,
448                                           TObjectPtr choicePtr)
449 {
450     _ASSERT(variantInfo->IsSubClass());
451     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
452             variantInfo->GetIndex());
453     const CChoiceTypeInfo* choiceType = variantInfo->GetChoiceType();
454     const CChoicePointerTypeInfo* choicePtrType =
455         CTypeConverter<CChoicePointerTypeInfo>::SafeCast(choiceType);
456     TObjectPtr variantPtr =
457         choicePtrType->GetPointerTypeInfo()->GetObjectPointer(choicePtr);
458     _ASSERT(variantPtr);
459     return variantPtr;
460 }
461 
ReadInlineVariant(CObjectIStream & in,const CVariantInfo * variantInfo,TObjectPtr choicePtr)462 void CVariantInfoFunctions::ReadInlineVariant(CObjectIStream& in,
463                                               const CVariantInfo* variantInfo,
464                                               TObjectPtr choicePtr)
465 {
466     _ASSERT(!variantInfo->CanBeDelayed());
467     _ASSERT(variantInfo->IsInline());
468     const CChoiceTypeInfo* choiceType = variantInfo->GetChoiceType();
469     TMemberIndex index = variantInfo->GetIndex();
470     choiceType->SetIndex(choicePtr, index, in.GetMemoryPool());
471     in.ReadObject(variantInfo->GetItemPtr(choicePtr),
472                   variantInfo->GetTypeInfo());
473     if (in.GetVerifyData() == eSerialVerifyData_Yes) {
474         variantInfo->Validate(choicePtr, in);
475     }
476 }
477 
ReadPointerVariant(CObjectIStream & in,const CVariantInfo * variantInfo,TObjectPtr choicePtr)478 void CVariantInfoFunctions::ReadPointerVariant(CObjectIStream& in,
479                                                const CVariantInfo* variantInfo,
480                                                TObjectPtr choicePtr)
481 {
482     _ASSERT(!variantInfo->CanBeDelayed());
483     _ASSERT(variantInfo->IsNonObjectPointer());
484     const CChoiceTypeInfo* choiceType = variantInfo->GetChoiceType();
485     TMemberIndex index = variantInfo->GetIndex();
486     choiceType->SetIndex(choicePtr, index, in.GetMemoryPool());
487     TObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
488     variantPtr = CTypeConverter<TObjectPtr>::Get(variantPtr);
489     _ASSERT(variantPtr != 0 );
490     in.ReadObject(variantPtr, variantInfo->GetTypeInfo());
491 }
492 
ReadObjectPointerVariant(CObjectIStream & in,const CVariantInfo * variantInfo,TObjectPtr choicePtr)493 void CVariantInfoFunctions::ReadObjectPointerVariant(CObjectIStream& in,
494                                                      const CVariantInfo* variantInfo,
495                                                      TObjectPtr choicePtr)
496 {
497     _ASSERT(!variantInfo->CanBeDelayed());
498     _ASSERT(variantInfo->IsObjectPointer());
499     const CChoiceTypeInfo* choiceType = variantInfo->GetChoiceType();
500     TMemberIndex index = variantInfo->GetIndex();
501     choiceType->SetIndex(choicePtr, index, in.GetMemoryPool());
502     TObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
503     variantPtr = CTypeConverter<TObjectPtr>::Get(variantPtr);
504     _ASSERT(variantPtr != 0 );
505     in.ReadExternalObject(variantPtr, variantInfo->GetTypeInfo());
506 }
507 
ReadSubclassVariant(CObjectIStream & in,const CVariantInfo * variantInfo,TObjectPtr choicePtr)508 void CVariantInfoFunctions::ReadSubclassVariant(CObjectIStream& in,
509                                                 const CVariantInfo* variantInfo,
510                                                 TObjectPtr choicePtr)
511 {
512     _ASSERT(!variantInfo->CanBeDelayed());
513     _ASSERT(variantInfo->IsSubClass());
514     const CChoiceTypeInfo* choiceType = variantInfo->GetChoiceType();
515     TMemberIndex index = variantInfo->GetIndex();
516     choiceType->SetIndex(choicePtr, index, in.GetMemoryPool());
517     const CChoicePointerTypeInfo* choicePtrType =
518         CTypeConverter<CChoicePointerTypeInfo>::SafeCast(choiceType);
519     TObjectPtr variantPtr =
520         choicePtrType->GetPointerTypeInfo()->GetObjectPointer(choicePtr);
521     _ASSERT(variantPtr);
522     in.ReadExternalObject(variantPtr, variantInfo->GetTypeInfo());
523 }
524 
ReadDelayedVariant(CObjectIStream & in,const CVariantInfo * variantInfo,TObjectPtr choicePtr)525 void CVariantInfoFunctions::ReadDelayedVariant(CObjectIStream& in,
526                                                const CVariantInfo* variantInfo,
527                                                TObjectPtr choicePtr)
528 {
529     _ASSERT(variantInfo->CanBeDelayed());
530     const CChoiceTypeInfo* choiceType = variantInfo->GetChoiceType();
531     TMemberIndex index = variantInfo->GetIndex();
532     TTypeInfo variantType = variantInfo->GetTypeInfo();
533     if ( index != choiceType->GetIndex(choicePtr) ) {
534         // index is differnet from current -> first, reset choice
535         choiceType->ResetIndex(choicePtr);
536         CDelayBuffer& buffer = variantInfo->GetDelayBuffer(choicePtr);
537         if ( !buffer ) {
538             in.StartDelayBuffer();
539             if ( variantInfo->IsObjectPointer() )
540                 in.SkipExternalObject(variantType);
541             else
542                 in.SkipObject(variantType);
543             in.EndDelayBuffer(buffer, variantInfo, choicePtr);
544             // update index
545             choiceType->SetDelayIndex(choicePtr, index);
546             return;
547         }
548         buffer.Update();
549         _ASSERT(!variantInfo->GetDelayBuffer(choicePtr));
550     }
551     // select for reading
552     choiceType->SetIndex(choicePtr, index, in.GetMemoryPool());
553 
554     TObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
555     if ( variantInfo->IsPointer() ) {
556         variantPtr = CTypeConverter<TObjectPtr>::Get(variantPtr);
557         _ASSERT(variantPtr != 0 );
558         if ( variantInfo->IsObjectPointer() ) {
559             in.ReadExternalObject(variantPtr, variantType);
560             return;
561         }
562     }
563     in.ReadObject(variantPtr, variantType);
564 }
565 
WriteInlineVariant(CObjectOStream & out,const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)566 void CVariantInfoFunctions::WriteInlineVariant(CObjectOStream& out,
567                                                const CVariantInfo* variantInfo,
568                                                TConstObjectPtr choicePtr)
569 {
570     _ASSERT(!variantInfo->CanBeDelayed());
571     _ASSERT(variantInfo->IsInline());
572     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
573             variantInfo->GetIndex());
574     if (out.GetVerifyData() == eSerialVerifyData_Yes) {
575         variantInfo->Validate(choicePtr, out);
576     }
577     out.WriteObject(variantInfo->GetItemPtr(choicePtr),
578                     variantInfo->GetTypeInfo());
579 }
580 
WritePointerVariant(CObjectOStream & out,const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)581 void CVariantInfoFunctions::WritePointerVariant(CObjectOStream& out,
582                                                 const CVariantInfo* variantInfo,
583                                                 TConstObjectPtr choicePtr)
584 {
585     _ASSERT(!variantInfo->CanBeDelayed());
586     _ASSERT(variantInfo->IsNonObjectPointer());
587     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
588             variantInfo->GetIndex());
589     TConstObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
590     variantPtr = CTypeConverter<TConstObjectPtr>::Get(variantPtr);
591     _ASSERT(variantPtr != 0 );
592     out.WriteObject(variantPtr, variantInfo->GetTypeInfo());
593 }
594 
WriteObjectPointerVariant(CObjectOStream & out,const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)595 void CVariantInfoFunctions::WriteObjectPointerVariant(CObjectOStream& out,
596                                                       const CVariantInfo* variantInfo,
597                                                       TConstObjectPtr choicePtr)
598 {
599     _ASSERT(!variantInfo->CanBeDelayed());
600     _ASSERT(variantInfo->IsObjectPointer());
601     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
602             variantInfo->GetIndex());
603     TConstObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
604     variantPtr = CTypeConverter<TConstObjectPtr>::Get(variantPtr);
605     _ASSERT(variantPtr != 0 );
606     out.WriteExternalObject(variantPtr, variantInfo->GetTypeInfo());
607 }
608 
WriteSubclassVariant(CObjectOStream & out,const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)609 void CVariantInfoFunctions::WriteSubclassVariant(CObjectOStream& out,
610                                                  const CVariantInfo* variantInfo,
611                                                  TConstObjectPtr choicePtr)
612 {
613     _ASSERT(!variantInfo->CanBeDelayed());
614     _ASSERT(variantInfo->IsSubClass());
615     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
616             variantInfo->GetIndex());
617     const CChoiceTypeInfo* choiceType = variantInfo->GetChoiceType();
618     const CChoicePointerTypeInfo* choicePtrType =
619         CTypeConverter<CChoicePointerTypeInfo>::SafeCast(choiceType);
620     TConstObjectPtr variantPtr =
621         choicePtrType->GetPointerTypeInfo()->GetObjectPointer(choicePtr);
622     _ASSERT(variantPtr);
623     out.WriteExternalObject(variantPtr, variantInfo->GetTypeInfo());
624 }
625 
WriteDelayedVariant(CObjectOStream & out,const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)626 void CVariantInfoFunctions::WriteDelayedVariant(CObjectOStream& out,
627                                                 const CVariantInfo* variantInfo,
628                                                 TConstObjectPtr choicePtr)
629 {
630     _ASSERT(variantInfo->CanBeDelayed());
631     _ASSERT(variantInfo->GetChoiceType()->GetIndex(choicePtr) ==
632             variantInfo->GetIndex());
633     const CDelayBuffer& buffer = variantInfo->GetDelayBuffer(choicePtr);
634     if ( buffer.GetIndex() == variantInfo->GetIndex() ) {
635         if ( buffer.HaveFormat(out.GetDataFormat()) ) {
636             out.Write(buffer.GetSource());
637             return;
638         }
639         const_cast<CDelayBuffer&>(buffer).Update();
640         _ASSERT(!variantInfo->GetDelayBuffer(choicePtr));
641     }
642     TConstObjectPtr variantPtr = variantInfo->GetItemPtr(choicePtr);
643     if ( variantInfo->IsPointer() ) {
644         variantPtr = CTypeConverter<TConstObjectPtr>::Get(variantPtr);
645         _ASSERT(variantPtr != 0 );
646         if ( variantInfo->IsObjectPointer() ) {
647             out.WriteExternalObject(variantPtr, variantInfo->GetTypeInfo());
648             return;
649         }
650     }
651     out.WriteObject(variantPtr, variantInfo->GetTypeInfo());
652 }
653 
CopyNonObjectVariant(CObjectStreamCopier & copier,const CVariantInfo * variantInfo)654 void CVariantInfoFunctions::CopyNonObjectVariant(CObjectStreamCopier& copier,
655                                                  const CVariantInfo* variantInfo)
656 {
657     _ASSERT(variantInfo->IsNotObject());
658     copier.CopyObject(variantInfo->GetTypeInfo());
659 }
660 
CopyObjectPointerVariant(CObjectStreamCopier & copier,const CVariantInfo * variantInfo)661 void CVariantInfoFunctions::CopyObjectPointerVariant(CObjectStreamCopier& copier,
662                                                      const CVariantInfo* variantInfo)
663 {
664     _ASSERT(variantInfo->IsObjectPointer());
665     copier.CopyExternalObject(variantInfo->GetTypeInfo());
666 }
667 
SkipNonObjectVariant(CObjectIStream & in,const CVariantInfo * variantInfo)668 void CVariantInfoFunctions::SkipNonObjectVariant(CObjectIStream& in,
669                                                  const CVariantInfo* variantInfo)
670 {
671     _ASSERT(variantInfo->IsNotObject());
672     in.SkipObject(variantInfo->GetTypeInfo());
673 }
674 
SkipObjectPointerVariant(CObjectIStream & in,const CVariantInfo * variantInfo)675 void CVariantInfoFunctions::SkipObjectPointerVariant(CObjectIStream& in,
676                                                      const CVariantInfo* variantInfo)
677 {
678     _ASSERT(variantInfo->IsObjectPointer());
679     in.SkipExternalObject(variantInfo->GetTypeInfo());
680 }
681 
ReadHookedVariant(CObjectIStream & stream,const CVariantInfo * variantInfo,TObjectPtr choicePtr)682 void CVariantInfoFunctions::ReadHookedVariant(CObjectIStream& stream,
683                                               const CVariantInfo* variantInfo,
684                                               TObjectPtr choicePtr)
685 {
686     CReadChoiceVariantHook* hook =
687         variantInfo->m_ReadHookData.GetHook(stream.m_ChoiceVariantHookKey);
688     if (!hook) {
689         hook = variantInfo->m_ReadHookData.GetPathHook(stream);
690     }
691     if ( hook ) {
692         CObjectInfo choice(choicePtr, variantInfo->GetChoiceType());
693         TMemberIndex index = variantInfo->GetIndex();
694         CObjectInfo::CChoiceVariant variant(choice, index);
695         _ASSERT(variant.Valid());
696         hook->ReadChoiceVariant(stream, variant);
697     }
698     else
699         variantInfo->DefaultReadVariant(stream, choicePtr);
700 }
701 
WriteHookedVariant(CObjectOStream & stream,const CVariantInfo * variantInfo,TConstObjectPtr choicePtr)702 void CVariantInfoFunctions::WriteHookedVariant(CObjectOStream& stream,
703                                                const CVariantInfo* variantInfo,
704                                                TConstObjectPtr choicePtr)
705 {
706     CWriteChoiceVariantHook* hook =
707         variantInfo->m_WriteHookData.GetHook(stream.m_ChoiceVariantHookKey);
708     if (!hook) {
709         hook = variantInfo->m_WriteHookData.GetPathHook(stream);
710     }
711     if ( hook ) {
712         CConstObjectInfo choice(choicePtr, variantInfo->GetChoiceType());
713         TMemberIndex index = variantInfo->GetIndex();
714         CConstObjectInfo::CChoiceVariant variant(choice, index);
715         _ASSERT(variant.Valid());
716         hook->WriteChoiceVariant(stream, variant);
717     }
718     else
719         variantInfo->DefaultWriteVariant(stream, choicePtr);
720 }
721 
SkipHookedVariant(CObjectIStream & stream,const CVariantInfo * variantInfo)722 void CVariantInfoFunctions::SkipHookedVariant(CObjectIStream& stream,
723                                               const CVariantInfo* variantInfo)
724 {
725     CSkipChoiceVariantHook* hook =
726         variantInfo->m_SkipHookData.GetHook(stream.m_ChoiceVariantSkipHookKey);
727     if (!hook) {
728         hook = variantInfo->m_SkipHookData.GetPathHook(stream);
729     }
730     if ( hook ) {
731         CObjectTypeInfo type(variantInfo->GetChoiceType());
732         TMemberIndex index = variantInfo->GetIndex();
733         CObjectTypeInfo::CChoiceVariant variant(type, index);
734         _ASSERT(variant.Valid());
735         hook->SkipChoiceVariant(stream, variant);
736     }
737     else
738         variantInfo->DefaultSkipVariant(stream);
739 }
740 
CopyHookedVariant(CObjectStreamCopier & stream,const CVariantInfo * variantInfo)741 void CVariantInfoFunctions::CopyHookedVariant(CObjectStreamCopier& stream,
742                                               const CVariantInfo* variantInfo)
743 {
744     CCopyChoiceVariantHook* hook =
745         variantInfo->m_CopyHookData.GetHook(stream.m_ChoiceVariantHookKey);
746     if (!hook) {
747         hook = variantInfo->m_CopyHookData.GetPathHook(stream.In());
748     }
749     if ( hook ) {
750         CObjectTypeInfo type(variantInfo->GetChoiceType());
751         TMemberIndex index = variantInfo->GetIndex();
752         CObjectTypeInfo::CChoiceVariant variant(type, index);
753         _ASSERT(variant.Valid());
754         hook->CopyChoiceVariant(stream, variant);
755     }
756     else
757         variantInfo->DefaultCopyVariant(stream);
758 }
759 
SetGlobalReadHook(CReadChoiceVariantHook * hook)760 void CVariantInfo::SetGlobalReadHook(CReadChoiceVariantHook* hook)
761 {
762     XSERIAL_TYPEINFO_WRITELOCK;
763     m_ReadHookData.SetGlobalHook(hook);
764 }
765 
SetLocalReadHook(CObjectIStream & stream,CReadChoiceVariantHook * hook)766 void CVariantInfo::SetLocalReadHook(CObjectIStream& stream,
767                                     CReadChoiceVariantHook* hook)
768 {
769     XSERIAL_TYPEINFO_WRITELOCK;
770     m_ReadHookData.SetLocalHook(stream.m_ChoiceVariantHookKey, hook);
771 }
772 
ResetGlobalReadHook(void)773 void CVariantInfo::ResetGlobalReadHook(void)
774 {
775     XSERIAL_TYPEINFO_WRITELOCK;
776     m_ReadHookData.ResetGlobalHook();
777 }
778 
ResetLocalReadHook(CObjectIStream & stream)779 void CVariantInfo::ResetLocalReadHook(CObjectIStream& stream)
780 {
781     XSERIAL_TYPEINFO_WRITELOCK;
782     m_ReadHookData.ResetLocalHook(stream.m_ChoiceVariantHookKey);
783 }
784 
SetPathReadHook(CObjectIStream * in,const string & path,CReadChoiceVariantHook * hook)785 void CVariantInfo::SetPathReadHook(CObjectIStream* in, const string& path,
786                                    CReadChoiceVariantHook* hook)
787 {
788     XSERIAL_TYPEINFO_WRITELOCK;
789     m_ReadHookData.SetPathHook(in,path,hook);
790 }
791 
SetGlobalWriteHook(CWriteChoiceVariantHook * hook)792 void CVariantInfo::SetGlobalWriteHook(CWriteChoiceVariantHook* hook)
793 {
794     XSERIAL_TYPEINFO_WRITELOCK;
795     m_WriteHookData.SetGlobalHook(hook);
796 }
797 
SetLocalWriteHook(CObjectOStream & stream,CWriteChoiceVariantHook * hook)798 void CVariantInfo::SetLocalWriteHook(CObjectOStream& stream,
799                                      CWriteChoiceVariantHook* hook)
800 {
801     XSERIAL_TYPEINFO_WRITELOCK;
802     m_WriteHookData.SetLocalHook(stream.m_ChoiceVariantHookKey, hook);
803 }
804 
ResetGlobalWriteHook(void)805 void CVariantInfo::ResetGlobalWriteHook(void)
806 {
807     XSERIAL_TYPEINFO_WRITELOCK;
808     m_WriteHookData.ResetGlobalHook();
809 }
810 
ResetLocalWriteHook(CObjectOStream & stream)811 void CVariantInfo::ResetLocalWriteHook(CObjectOStream& stream)
812 {
813     XSERIAL_TYPEINFO_WRITELOCK;
814     m_WriteHookData.ResetLocalHook(stream.m_ChoiceVariantHookKey);
815 }
816 
SetPathWriteHook(CObjectOStream * out,const string & path,CWriteChoiceVariantHook * hook)817 void CVariantInfo::SetPathWriteHook(CObjectOStream* out, const string& path,
818                                     CWriteChoiceVariantHook* hook)
819 {
820     XSERIAL_TYPEINFO_WRITELOCK;
821     m_WriteHookData.SetPathHook(out,path,hook);
822 }
823 
SetLocalSkipHook(CObjectIStream & stream,CSkipChoiceVariantHook * hook)824 void CVariantInfo::SetLocalSkipHook(CObjectIStream& stream,
825                                     CSkipChoiceVariantHook* hook)
826 {
827     XSERIAL_TYPEINFO_WRITELOCK;
828     m_SkipHookData.SetLocalHook(stream.m_ChoiceVariantSkipHookKey, hook);
829 }
830 
ResetLocalSkipHook(CObjectIStream & stream)831 void CVariantInfo::ResetLocalSkipHook(CObjectIStream& stream)
832 {
833     XSERIAL_TYPEINFO_WRITELOCK;
834     m_SkipHookData.ResetLocalHook(stream.m_ChoiceVariantSkipHookKey);
835 }
836 
SetPathSkipHook(CObjectIStream * in,const string & path,CSkipChoiceVariantHook * hook)837 void CVariantInfo::SetPathSkipHook(CObjectIStream* in, const string& path,
838                                    CSkipChoiceVariantHook* hook)
839 {
840     XSERIAL_TYPEINFO_WRITELOCK;
841     m_SkipHookData.SetPathHook(in,path,hook);
842 }
843 
SetGlobalCopyHook(CCopyChoiceVariantHook * hook)844 void CVariantInfo::SetGlobalCopyHook(CCopyChoiceVariantHook* hook)
845 {
846     XSERIAL_TYPEINFO_WRITELOCK;
847     m_CopyHookData.SetGlobalHook(hook);
848 }
849 
SetLocalCopyHook(CObjectStreamCopier & stream,CCopyChoiceVariantHook * hook)850 void CVariantInfo::SetLocalCopyHook(CObjectStreamCopier& stream,
851                                     CCopyChoiceVariantHook* hook)
852 {
853     XSERIAL_TYPEINFO_WRITELOCK;
854     m_CopyHookData.SetLocalHook(stream.m_ChoiceVariantHookKey, hook);
855 }
856 
ResetGlobalCopyHook(void)857 void CVariantInfo::ResetGlobalCopyHook(void)
858 {
859     XSERIAL_TYPEINFO_WRITELOCK;
860     m_CopyHookData.ResetGlobalHook();
861 }
862 
ResetLocalCopyHook(CObjectStreamCopier & stream)863 void CVariantInfo::ResetLocalCopyHook(CObjectStreamCopier& stream)
864 {
865     XSERIAL_TYPEINFO_WRITELOCK;
866     m_CopyHookData.ResetLocalHook(stream.m_ChoiceVariantHookKey);
867 }
868 
SetPathCopyHook(CObjectStreamCopier * stream,const string & path,CCopyChoiceVariantHook * hook)869 void CVariantInfo::SetPathCopyHook(CObjectStreamCopier* stream, const string& path,
870                                    CCopyChoiceVariantHook* hook)
871 {
872     XSERIAL_TYPEINFO_WRITELOCK;
873     m_CopyHookData.SetPathHook(stream ? &(stream->In()) : 0,path,hook);
874 }
875 
876 END_NCBI_SCOPE
877