1 /* $Id: serialobject.cpp 554977 2018-01-11 14:18:53Z 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: Aleksey Grichenko
27 *
28 * File Description:
29 * Base class for serializable objects
30 *
31 */
32
33 #include <ncbi_pch.hpp>
34 #include <corelib/ncbi_safe_static.hpp>
35 #include <corelib/ncbimtx.hpp>
36 #include <corelib/ncbithr.hpp>
37 #include <corelib/ncbi_param.hpp>
38 #include <serial/serialbase.hpp>
39 #include <serial/typeinfo.hpp>
40
41 #include <serial/objostr.hpp>
42 #include <serial/objistr.hpp>
43 #include <serial/objostrxml.hpp>
44 #include <serial/objistrxml.hpp>
45
46 #include <serial/impl/classinfob.hpp>
47 #include <serial/error_codes.hpp>
48
49
50 #define NCBI_USE_ERRCODE_X Serial_Core
51
52
53 BEGIN_NCBI_SCOPE
54
IsSameTypeInfo(const CSerialObject & obj1,const CSerialObject & obj2)55 static bool IsSameTypeInfo( const CSerialObject& obj1,
56 const CSerialObject& obj2 )
57 {
58 TTypeInfo type1 = obj1.GetThisTypeInfo();
59 while (type1->GetTypeFamily() == eTypeFamilyPointer) {
60 const CPointerTypeInfo* t = dynamic_cast<const CPointerTypeInfo*>(type1);
61 type1 = t->GetPointedType();
62 }
63 TTypeInfo type2 = obj2.GetThisTypeInfo();
64 while (type2->GetTypeFamily() == eTypeFamilyPointer) {
65 const CPointerTypeInfo* t = dynamic_cast<const CPointerTypeInfo*>(type2);
66 type2 = t->GetPointedType();
67 }
68 return (type1 == type2);
69 }
70
71
CSerialObject(void)72 CSerialObject::CSerialObject(void)
73 {
74 }
75
~CSerialObject()76 CSerialObject::~CSerialObject()
77 {
78 }
79
Assign(const CSerialObject & source,ESerialRecursionMode how)80 void CSerialObject::Assign(const CSerialObject& source, ESerialRecursionMode how)
81 {
82 if (this == &source) {
83 ERR_POST_X(3, Warning <<
84 "CSerialObject::Assign(): an attempt to assign a serial object to itself");
85 return;
86 }
87 if ( typeid(source) != typeid(*this) && !IsSameTypeInfo(source, *this) ) {
88 string msg("Assignment of incompatible types: ");
89 msg += typeid(*this).name();
90 msg += " = ";
91 msg += typeid(source).name();
92 NCBI_THROW(CSerialException,eIllegalCall, msg);
93 }
94 GetThisTypeInfo()->Assign(this, &source, how);
95 }
96
97
Equals(const CSerialObject & object,ESerialRecursionMode how) const98 bool CSerialObject::Equals(const CSerialObject& object, ESerialRecursionMode how) const
99 {
100 if ( typeid(object) != typeid(*this) && !IsSameTypeInfo(object, *this) ) {
101 string msg("Cannot compare types: ");
102 msg += typeid(*this).name();
103 msg += " == ";
104 msg += typeid(object).name();
105 NCBI_THROW(CSerialException,eIllegalCall, msg);
106 }
107 return GetThisTypeInfo()->Equals(this, &object, how);
108 }
109
DebugDump(CDebugDumpContext ddc,unsigned int depth) const110 void CSerialObject::DebugDump(CDebugDumpContext ddc, unsigned int depth) const
111 {
112 ddc.SetFrame("CSerialObject");
113 CObject::DebugDump( ddc, depth);
114 // this is not good, but better than nothing
115 CNcbiOstrstream ostr;
116 ostr << "\n****** begin ASN dump ******\n";
117 {{
118 unique_ptr<CObjectOStream> oos(CObjectOStream::Open(eSerial_AsnText,
119 ostr));
120 oos->SetAutoSeparator(false);
121 oos->SetVerifyData(eSerialVerifyData_No);
122 oos->Write(this, GetThisTypeInfo());
123 }}
124 ostr << "\n****** end ASN dump ******\n";
125 ddc.Log( "Serial_AsnText", CNcbiOstrstreamToString(ostr));
126 }
127
128 /////////////////////////////////////////////////////////////////////////////
129 // data verification setup
130
131 const char* CSerialObject::ms_UnassignedStr = "<*unassigned*>";
132 const char CSerialObject::ms_UnassignedByte = char(0xcd);
133
NCBI_PARAM_ENUM_ARRAY(ESerialVerifyData,SERIAL,VERIFY_DATA_GET)134 NCBI_PARAM_ENUM_ARRAY(ESerialVerifyData, SERIAL, VERIFY_DATA_GET)
135 {
136 {"NO", eSerialVerifyData_No},
137 {"NEVER", eSerialVerifyData_Never},
138 {"YES", eSerialVerifyData_Yes},
139 {"ALWAYS", eSerialVerifyData_Always},
140 {"DEFVALUE", eSerialVerifyData_DefValue},
141 {"DEFVALUE_ALWAYS", eSerialVerifyData_DefValueAlways}
142 };
143 NCBI_PARAM_ENUM_DECL(ESerialVerifyData, SERIAL, VERIFY_DATA_GET);
144 NCBI_PARAM_ENUM_DEF(ESerialVerifyData, SERIAL, VERIFY_DATA_GET, eSerialVerifyData_Default);
145 typedef NCBI_PARAM_TYPE(SERIAL, VERIFY_DATA_GET) TSerialVerifyData;
146
147
SetVerifyDataThread(ESerialVerifyData verify)148 void CSerialObject::SetVerifyDataThread(ESerialVerifyData verify)
149 {
150 ESerialVerifyData now = TSerialVerifyData::GetThreadDefault();
151 if (now != eSerialVerifyData_Never &&
152 now != eSerialVerifyData_Always &&
153 now != eSerialVerifyData_DefValueAlways) {
154 if (verify == eSerialVerifyData_Default) {
155 TSerialVerifyData::ResetThreadDefault();
156 } else {
157 TSerialVerifyData::SetThreadDefault(verify);
158 }
159 }
160 }
161
SetVerifyDataGlobal(ESerialVerifyData verify)162 void CSerialObject::SetVerifyDataGlobal(ESerialVerifyData verify)
163 {
164 ESerialVerifyData now = TSerialVerifyData::GetDefault();
165 if (now != eSerialVerifyData_Never &&
166 now != eSerialVerifyData_Always &&
167 now != eSerialVerifyData_DefValueAlways) {
168 if (verify == eSerialVerifyData_Default) {
169 TSerialVerifyData::ResetDefault();
170 } else {
171 TSerialVerifyData::SetDefault(verify);
172 }
173 }
174 }
175
x_GetVerifyData(void)176 ESerialVerifyData CSerialObject::x_GetVerifyData(void)
177 {
178 ESerialVerifyData now = TSerialVerifyData::GetThreadDefault();
179 if (now == eSerialVerifyData_Default) {
180 now = TSerialVerifyData::GetDefault();
181 if (now == eSerialVerifyData_Default) {
182 // this is to provide compatibility with old implementation
183 const char* str = getenv(SERIAL_VERIFY_DATA_GET);
184 if (str) {
185 if (NStr::CompareNocase(str,"YES") == 0) {
186 now = eSerialVerifyData_Yes;
187 } else if (NStr::CompareNocase(str,"NO") == 0) {
188 now = eSerialVerifyData_No;
189 } else if (NStr::CompareNocase(str,"NEVER") == 0) {
190 now = eSerialVerifyData_Never;
191 } else if (NStr::CompareNocase(str,"ALWAYS") == 0) {
192 now = eSerialVerifyData_Always;
193 } else if (NStr::CompareNocase(str,"DEFVALUE") == 0) {
194 now = eSerialVerifyData_DefValue;
195 } else if (NStr::CompareNocase(str,"DEFVALUE_ALWAYS") == 0) {
196 now = eSerialVerifyData_DefValueAlways;
197 }
198 }
199 }
200 }
201 switch (now) {
202 default:
203 case eSerialVerifyData_Default:
204 break;
205 case eSerialVerifyData_No:
206 case eSerialVerifyData_Never:
207 return eSerialVerifyData_No;
208 case eSerialVerifyData_Yes:
209 case eSerialVerifyData_Always:
210 return eSerialVerifyData_Yes;
211 case eSerialVerifyData_DefValue:
212 case eSerialVerifyData_DefValueAlways:
213 return eSerialVerifyData_No;
214 }
215 // change the default here, if you like
216 return eSerialVerifyData_Yes;
217 }
218
219 BEGIN_LOCAL_NAMESPACE;
220
221 struct SPrintIdentifier
222 {
SPrintIdentifierSPrintIdentifier223 SPrintIdentifier(const CTempString& s) : m_String(s) { }
224 CTempString m_String;
225 };
operator <<(CNcbiOstream & out,SPrintIdentifier s)226 CNcbiOstream& operator<<(CNcbiOstream& out, SPrintIdentifier s)
227 {
228 SIZE_TYPE size = s.m_String.size();
229 SIZE_TYPE e_pos = NPOS;
230 if ( size > 2 && NStr::EndsWith(s.m_String, ".E") ) {
231 e_pos = s.m_String.rfind('.', size-3);
232 if ( e_pos != NPOS ) {
233 size -= 2;
234 }
235 }
236 bool capitalize = true;
237 for ( SIZE_TYPE i = 0; i < size; ++i ) {
238 char c = s.m_String[i];
239 if ( c == '.' ) {
240 out << "::C_";
241 if ( i == e_pos ) {
242 out << "E_";
243 }
244 capitalize = true;
245 }
246 else {
247 if ( c == '-' ) {
248 c = '_';
249 }
250 if ( capitalize ) {
251 c = (char)toupper((unsigned char)c);
252 capitalize = false;
253 }
254 out << c;
255 }
256 }
257 return out;
258 }
259
260 END_LOCAL_NAMESPACE;
261
ThrowUnassigned(TMemberIndex index,const char * file_name,int file_line) const262 void CSerialObject::ThrowUnassigned(TMemberIndex index,
263 const char* file_name,
264 int file_line) const
265 {
266 if (x_GetVerifyData() == eSerialVerifyData_Yes) {
267 const CTypeInfo* type = GetThisTypeInfo();
268 const CClassTypeInfoBase* classtype =
269 dynamic_cast<const CClassTypeInfoBase*>(type);
270 // offset index as the argument is zero based but items are 1 based
271 string member_name;
272 if ( classtype ) {
273 index += classtype->GetItems().FirstIndex();
274 if ( index >= classtype->GetItems().FirstIndex() &&
275 index <= classtype->GetItems().LastIndex() ) {
276 member_name = classtype->GetItems().GetItemInfo(index)->GetId().GetName();
277 }
278 }
279 CNcbiOstrstream s;
280 if ( true ) {
281 // make class name
282 s << "C" << SPrintIdentifier(type->GetAccessName());
283 }
284 if ( !member_name.empty() ) {
285 // make method name
286 s << "::Get" << SPrintIdentifier(member_name) << "()";
287 }
288 s << ": Attempt to get unassigned member "
289 << type->GetAccessModuleName() <<"::"<< type->GetAccessName() << '.';
290 if ( !member_name.empty() ) {
291 s << member_name;
292 } else {
293 s << '[' << index << ']';
294 }
295 // set temporary diag compile info to use argument file name and line
296 #undef DIAG_COMPILE_INFO
297 #define DIAG_COMPILE_INFO \
298 NCBI_NS_NCBI::CDiagCompileInfo(file_name? file_name: __FILE__, \
299 file_line? file_line: __LINE__, \
300 NCBI_CURRENT_FUNCTION, \
301 NCBI_MAKE_MODULE(NCBI_MODULE))
302 NCBI_THROW(CUnassignedMember,eGet,CNcbiOstrstreamToString(s));
303 // restore original diag compile info definition
304 #undef DIAG_COMPILE_INFO
305 #define DIAG_COMPILE_INFO \
306 NCBI_NS_NCBI::CDiagCompileInfo(__FILE__, \
307 __LINE__, \
308 NCBI_CURRENT_FUNCTION, \
309 NCBI_MAKE_MODULE(NCBI_MODULE))
310 }
311 }
312
ThrowUnassigned(TMemberIndex index) const313 void CSerialObject::ThrowUnassigned(TMemberIndex index) const
314 {
315 ThrowUnassigned(index, 0, 0);
316 }
317
HasNamespaceName(void) const318 bool CSerialObject::HasNamespaceName(void) const
319 {
320 return GetThisTypeInfo()->HasNamespaceName();
321 }
322
GetNamespaceName(void) const323 const string& CSerialObject::GetNamespaceName(void) const
324 {
325 return GetThisTypeInfo()->GetNamespaceName();
326 }
327
HasNamespacePrefix(void) const328 bool CSerialObject::HasNamespacePrefix(void) const
329 {
330 return GetThisTypeInfo()->HasNamespacePrefix();
331 }
332
GetNamespacePrefix(void) const333 const string& CSerialObject::GetNamespacePrefix(void) const
334 {
335 return GetThisTypeInfo()->GetNamespacePrefix();
336 }
337
338
CSerialAttribInfoItem(const string & name,const string & ns_name,const CStringUTF8 & value)339 CSerialAttribInfoItem::CSerialAttribInfoItem(
340 const string& name, const string& ns_name, const CStringUTF8& value)
341 : m_Name(name), m_NsName(ns_name), m_Value(value)
342 {
343 }
CSerialAttribInfoItem(const CSerialAttribInfoItem & other)344 CSerialAttribInfoItem::CSerialAttribInfoItem(const CSerialAttribInfoItem& other)
345 : m_Name(other.m_Name), m_NsName(other.m_NsName), m_Value(other.m_Value)
346 {
347 }
348
~CSerialAttribInfoItem(void)349 CSerialAttribInfoItem::~CSerialAttribInfoItem(void)
350 {
351 }
GetName(void) const352 const string& CSerialAttribInfoItem::GetName(void) const
353 {
354 return m_Name;
355 }
GetNamespaceName(void) const356 const string& CSerialAttribInfoItem::GetNamespaceName(void) const
357 {
358 return m_NsName;
359 }
GetValue(void) const360 const CStringUTF8& CSerialAttribInfoItem::GetValue(void) const
361 {
362 return m_Value;
363 }
364
365
CAnyContentObject(void)366 CAnyContentObject::CAnyContentObject(void)
367 {
368 }
369
CAnyContentObject(const CAnyContentObject & other)370 CAnyContentObject::CAnyContentObject(const CAnyContentObject& other)
371 {
372 x_Copy(other);
373 }
374
~CAnyContentObject(void)375 CAnyContentObject::~CAnyContentObject(void)
376 {
377 }
378
GetTypeInfo(void)379 const CTypeInfo* CAnyContentObject::GetTypeInfo(void)
380 {
381 return CStdTypeInfo<ncbi::CAnyContentObject>::GetTypeInfo();
382 }
383
Reset(void)384 void CAnyContentObject::Reset(void)
385 {
386 m_Name.erase();
387 m_Value.erase();
388 m_NsName.erase();
389 m_NsPrefix.erase();
390 m_Attlist.clear();
391 }
392
x_Copy(const CAnyContentObject & other)393 void CAnyContentObject::x_Copy(const CAnyContentObject& other)
394 {
395 m_Name = other.m_Name;
396 m_Value= other.m_Value;
397 m_NsName= other.m_NsName;
398 m_NsPrefix= other.m_NsPrefix;
399 m_Attlist.clear();
400 vector<CSerialAttribInfoItem>::const_iterator it;
401 for (it = other.m_Attlist.begin(); it != other.m_Attlist.end(); ++it) {
402 m_Attlist.push_back( *it);
403 }
404 }
operator =(const CAnyContentObject & other)405 CAnyContentObject& CAnyContentObject::operator= (const CAnyContentObject& other)
406 {
407 x_Copy(other);
408 return *this;
409 }
410
operator ==(const CAnyContentObject & other) const411 bool CAnyContentObject::operator== (const CAnyContentObject& other) const
412 {
413 return m_Name == other.GetName() &&
414 m_Value == other.GetValue() &&
415 m_NsName == other.m_NsName;
416 }
417
SetName(const string & name)418 void CAnyContentObject::SetName(const string& name)
419 {
420 m_Name = name;
421 }
GetName(void) const422 const string& CAnyContentObject::GetName(void) const
423 {
424 return m_Name;
425 }
SetValue(const CStringUTF8 & value)426 void CAnyContentObject::SetValue(const CStringUTF8& value)
427 {
428 x_Decode(value);
429 }
GetValue(void) const430 const CStringUTF8& CAnyContentObject::GetValue(void) const
431 {
432 return m_Value;
433 }
SetNamespaceName(const string & ns_name)434 void CAnyContentObject::SetNamespaceName(const string& ns_name)
435 {
436 m_NsName = ns_name;
437 }
GetNamespaceName(void) const438 const string& CAnyContentObject::GetNamespaceName(void) const
439 {
440 return m_NsName;
441 }
SetNamespacePrefix(const string & ns_prefix)442 void CAnyContentObject::SetNamespacePrefix(const string& ns_prefix)
443 {
444 m_NsPrefix = ns_prefix;
445 }
GetNamespacePrefix(void) const446 const string& CAnyContentObject::GetNamespacePrefix(void) const
447 {
448 return m_NsPrefix;
449 }
x_Decode(const CStringUTF8 & value)450 void CAnyContentObject::x_Decode(const CStringUTF8& value)
451 {
452 m_Value = value;
453 }
AddAttribute(const string & name,const string & ns_name,const CStringUTF8 & value)454 void CAnyContentObject::AddAttribute(
455 const string& name, const string& ns_name, const CStringUTF8& value)
456 {
457 // TODO: check if an attrib with this name+ns_name already exists
458 m_Attlist.push_back( CSerialAttribInfoItem( name,ns_name,value));
459 }
460
461 const vector<CSerialAttribInfoItem>&
GetAttributes(void) const462 CAnyContentObject::GetAttributes(void) const
463 {
464 return m_Attlist;
465 }
466
467 /////////////////////////////////////////////////////////////////////////////
468 // I/O stream manipulators and helpers for serializable objects
469
470 #define eFmt_AsnText (1l << 0)
471 #define eFmt_AsnBinary (1l << 1)
472 #define eFmt_Xml (1l << 2)
473 #define eFmt_Json (1l << 3)
474 #define eFmt_All (eFmt_AsnText | eFmt_AsnBinary | eFmt_Xml | eFmt_Json)
475
476 #define eVerify_No (1l << 8)
477 #define eVerify_Yes (1l << 9)
478 #define eVerify_DefValue (1l << 10)
479 #define eVerify_All (eVerify_No | eVerify_Yes | eVerify_DefValue)
480
481 #define eSkipUnkMembers_No (1l << 11)
482 #define eSkipUnkMembers_Yes (1l << 12)
483 #define eSkipUnkMembers_All (eSkipUnkMembers_No | eSkipUnkMembers_Yes)
484
485 #define eSkipUnkVariants_No (1l << 13)
486 #define eSkipUnkVariants_Yes (1l << 14)
487 #define eSkipUnkVariants_All (eSkipUnkVariants_No | eSkipUnkVariants_Yes)
488
489 #define eEncoding_All (255l << 16)
490 #define eFmtFlags_All (255l << 24)
491
492 static
s_SerFlags(CNcbiIos & io)493 long& s_SerFlags(CNcbiIos& io)
494 {
495 static int s_SerIndex;
496 static bool s_HaveIndex = false;
497
498 if ( !s_HaveIndex ) {
499 // Make sure to get a unique IOS index
500 DEFINE_STATIC_FAST_MUTEX(s_IndexMutex);
501 CFastMutexGuard guard(s_IndexMutex);
502 if ( !s_HaveIndex ) {
503 s_SerIndex = CNcbiIos::xalloc();
504 s_HaveIndex = true;
505 }
506 }
507
508 return io.iword(s_SerIndex);
509 }
510 static
s_FlagsToFormat(CNcbiIos & io)511 ESerialDataFormat s_FlagsToFormat(CNcbiIos& io)
512 {
513 switch (s_SerFlags(io) & eFmt_All) {
514 case eFmt_AsnText: return eSerial_AsnText;
515 case eFmt_AsnBinary: return eSerial_AsnBinary;
516 case eFmt_Xml: return eSerial_Xml;
517 case eFmt_Json: return eSerial_Json;
518 default: return eSerial_None;
519 }
520 }
521 static
s_FormatToFlags(ESerialDataFormat fmt)522 long s_FormatToFlags(ESerialDataFormat fmt)
523 {
524 switch (fmt) {
525 case eSerial_AsnText: return eFmt_AsnText;
526 case eSerial_AsnBinary: return eFmt_AsnBinary;
527 case eSerial_Xml: return eFmt_Xml;
528 case eSerial_Json: return eFmt_Json;
529 default: return 0;
530 }
531 }
532
533 static
s_FlagsToVerify(CNcbiIos & io)534 ESerialVerifyData s_FlagsToVerify(CNcbiIos& io)
535 {
536 switch (s_SerFlags(io) & eVerify_All) {
537 case eVerify_No: return eSerialVerifyData_No;
538 case eVerify_Yes: return eSerialVerifyData_Yes;
539 case eVerify_DefValue: return eSerialVerifyData_DefValue;
540 default: return eSerialVerifyData_Default;
541 }
542 }
543
544 static
s_VerifyToFlags(ESerialVerifyData fmt)545 long s_VerifyToFlags(ESerialVerifyData fmt)
546 {
547 switch (fmt) {
548 case eSerialVerifyData_Never:
549 case eSerialVerifyData_No: return eVerify_No;
550 case eSerialVerifyData_Always:
551 case eSerialVerifyData_Yes: return eVerify_Yes;
552 case eSerialVerifyData_DefValueAlways:
553 case eSerialVerifyData_DefValue: return eVerify_DefValue;
554 default: return 0;
555 }
556 }
557
558 static
s_FlagsToSkipUnkMembers(CNcbiIos & io)559 ESerialSkipUnknown s_FlagsToSkipUnkMembers(CNcbiIos& io)
560 {
561 switch (s_SerFlags(io) & eSkipUnkMembers_All) {
562 case eSkipUnkMembers_No: return eSerialSkipUnknown_No;
563 case eSkipUnkMembers_Yes: return eSerialSkipUnknown_Yes;
564 default: return eSerialSkipUnknown_Default;
565 }
566 }
567
568 static
s_SkipUnkMembersToFlags(ESerialSkipUnknown fmt)569 long s_SkipUnkMembersToFlags(ESerialSkipUnknown fmt)
570 {
571 switch (fmt) {
572 case eSerialSkipUnknown_Never:
573 case eSerialSkipUnknown_No: return eSkipUnkMembers_No;
574 case eSerialSkipUnknown_Always:
575 case eSerialSkipUnknown_Yes: return eSkipUnkMembers_Yes;
576 default: return 0;
577 }
578 }
579 static
s_FlagsToSkipUnkVariants(CNcbiIos & io)580 ESerialSkipUnknown s_FlagsToSkipUnkVariants(CNcbiIos& io)
581 {
582 switch (s_SerFlags(io) & eSkipUnkVariants_All) {
583 case eSkipUnkVariants_No: return eSerialSkipUnknown_No;
584 case eSkipUnkVariants_Yes: return eSerialSkipUnknown_Yes;
585 default: return eSerialSkipUnknown_Default;
586 }
587 }
588
589 static
s_SkipUnkVariantsToFlags(ESerialSkipUnknown fmt)590 long s_SkipUnkVariantsToFlags(ESerialSkipUnknown fmt)
591 {
592 switch (fmt) {
593 case eSerialSkipUnknown_Never:
594 case eSerialSkipUnknown_No: return eSkipUnkVariants_No;
595 case eSerialSkipUnknown_Always:
596 case eSerialSkipUnknown_Yes: return eSkipUnkVariants_Yes;
597 default: return 0;
598 }
599 }
600
601 static
s_FlagsToEncoding(CNcbiIos & io)602 EEncoding s_FlagsToEncoding(CNcbiIos& io)
603 {
604 long enc = (s_SerFlags(io) & eEncoding_All) >> 16;
605 switch (enc) {
606 default: return eEncoding_Unknown;
607 case 1: return eEncoding_UTF8;
608 case 2: return eEncoding_Ascii;
609 case 3: return eEncoding_ISO8859_1;
610 case 4: return eEncoding_Windows_1252;
611 }
612 }
613
614 static
s_EncodingToFlags(EEncoding fmt)615 long s_EncodingToFlags(EEncoding fmt)
616 {
617 long enc = 0;
618 switch (fmt) {
619 default: enc = 0; break;
620 case eEncoding_UTF8: enc = 1; break;
621 case eEncoding_Ascii: enc = 2; break;
622 case eEncoding_ISO8859_1: enc = 3; break;
623 case eEncoding_Windows_1252: enc = 4; break;
624 }
625 return (enc << 16);
626 }
627
628 static
s_FlagsToFormatFlags(CNcbiIos & io)629 TSerial_Format_Flags s_FlagsToFormatFlags(CNcbiIos& io)
630 {
631 TSerial_Format_Flags t = (TSerial_Format_Flags)(s_SerFlags(io) & eFmtFlags_All);
632 return t >> 24;
633 }
634
635 static
s_FormatFlagsToFlags(unsigned long flags)636 long s_FormatFlagsToFlags(unsigned long flags)
637 {
638 return flags << 24;
639 }
640
HasSerialFormatting(CNcbiIos & io)641 bool MSerial_Flags::HasSerialFormatting(CNcbiIos& io)
642 {
643 return s_FlagsToFormat(io) != eSerial_None;
644 }
645
MSerial_Flags(unsigned long all,unsigned long flags)646 MSerial_Flags::MSerial_Flags(unsigned long all, unsigned long flags)
647 : m_All(all), m_Flags(flags)
648 {
649 }
SetFlags(CNcbiIos & io) const650 void MSerial_Flags::SetFlags(CNcbiIos& io) const
651 {
652 s_SerFlags(io) = (s_SerFlags(io) & ~m_All) | m_Flags;
653 }
654
SetFormatFlags(unsigned long flags)655 void MSerial_Flags::SetFormatFlags(unsigned long flags)
656 {
657 m_Flags = (m_Flags & ~eFmtFlags_All) | s_FormatFlagsToFlags(flags);
658 }
659
MSerial_Format(ESerialDataFormat fmt,TSerial_Format_Flags flags)660 MSerial_Format::MSerial_Format(ESerialDataFormat fmt, TSerial_Format_Flags flags)
661 : MSerial_Flags(eFmt_All | eFmtFlags_All,
662 s_FormatToFlags(fmt) | s_FormatFlagsToFlags(flags))
663 {
664 }
665
operator ()(TSerial_AsnText_Flags flags)666 MSerial_Format& MSerial_Format_AsnText::operator()(TSerial_AsnText_Flags flags)
667 {
668 SetFormatFlags(flags);
669 return *this;
670 }
operator ()(TSerial_Xml_Flags flags)671 MSerial_Format& MSerial_Format_Xml::operator()(TSerial_Xml_Flags flags)
672 {
673 SetFormatFlags(flags);
674 return *this;
675 }
operator ()(TSerial_Json_Flags flags)676 MSerial_Format& MSerial_Format_Json::operator()(TSerial_Json_Flags flags)
677 {
678 SetFormatFlags(flags);
679 return *this;
680 }
681
MSerial_VerifyData(ESerialVerifyData fmt)682 MSerial_VerifyData::MSerial_VerifyData(ESerialVerifyData fmt)
683 : MSerial_Flags(eVerify_All, s_VerifyToFlags(fmt))
684 {
685 }
686
MSerial_SkipUnknownMembers(ESerialSkipUnknown fmt)687 MSerial_SkipUnknownMembers::MSerial_SkipUnknownMembers(ESerialSkipUnknown fmt)
688 : MSerial_Flags(eSkipUnkMembers_All, s_SkipUnkMembersToFlags(fmt))
689 {
690 }
691
MSerial_SkipUnknownVariants(ESerialSkipUnknown fmt)692 MSerial_SkipUnknownVariants::MSerial_SkipUnknownVariants(ESerialSkipUnknown fmt)
693 : MSerial_Flags(eSkipUnkVariants_All, s_SkipUnkVariantsToFlags(fmt))
694 {
695 }
696
MSerialXml_DefaultStringEncoding(EEncoding fmt)697 MSerialXml_DefaultStringEncoding::MSerialXml_DefaultStringEncoding(EEncoding fmt)
698 : MSerial_Flags(eEncoding_All, s_EncodingToFlags(fmt))
699 {
700 }
701
MSerial_None(CNcbiIos & io)702 CNcbiIos& MSerial_None(CNcbiIos& io)
703 {
704 // s_SerFlags(io) = (s_SerFlags(io) & ~eFmt_All);
705 s_SerFlags(io) = 0;
706 return io;
707 }
708
709
710 // Class member assignment verification
MSerial_VerifyDefault(CNcbiIos & io)711 CNcbiIos& MSerial_VerifyDefault(CNcbiIos& io)
712 {
713 s_SerFlags(io) = (s_SerFlags(io) & ~eVerify_All);
714 return io;
715 }
MSerial_VerifyNo(CNcbiIos & io)716 CNcbiIos& MSerial_VerifyNo(CNcbiIos& io)
717 {
718 s_SerFlags(io) = (s_SerFlags(io) & ~eVerify_All) | eVerify_No;
719 return io;
720 }
MSerial_VerifyYes(CNcbiIos & io)721 CNcbiIos& MSerial_VerifyYes(CNcbiIos& io)
722 {
723 s_SerFlags(io) = (s_SerFlags(io) & ~eVerify_All) | eVerify_Yes;
724 return io;
725 }
MSerial_VerifyDefValue(CNcbiIos & io)726 CNcbiIos& MSerial_VerifyDefValue(CNcbiIos& io)
727 {
728 s_SerFlags(io) = (s_SerFlags(io) & ~eVerify_All) | eVerify_DefValue;
729 return io;
730 }
731
732
733 // Input/output
operator <<(CNcbiOstream & os,const CSerialObject & obj)734 CNcbiOstream& operator<< (CNcbiOstream& os, const CSerialObject& obj)
735 {
736 return WriteObject(os,&obj,obj.GetThisTypeInfo());
737 }
738
operator >>(CNcbiIstream & is,CSerialObject & obj)739 CNcbiIstream& operator>> (CNcbiIstream& is, CSerialObject& obj)
740 {
741 return ReadObject(is,&obj,obj.GetThisTypeInfo());
742 }
743
operator <<(CNcbiOstream & os,const CConstObjectInfo & obj)744 CNcbiOstream& operator<< (CNcbiOstream& os, const CConstObjectInfo& obj)
745 {
746 return WriteObject(os,obj.GetObjectPtr(),obj.GetTypeInfo());
747 }
748
operator >>(CNcbiIstream & is,const CObjectInfo & obj)749 CNcbiIstream& operator>> (CNcbiIstream& is, const CObjectInfo& obj)
750 {
751 return ReadObject(is,obj.GetObjectPtr(),obj.GetTypeInfo());
752 }
753
WriteObject(CNcbiOstream & os,TConstObjectPtr ptr,TTypeInfo info)754 CNcbiOstream& WriteObject(CNcbiOstream& os, TConstObjectPtr ptr, TTypeInfo info)
755 {
756 unique_ptr<CObjectOStream> ostr( CObjectOStream::Open( s_FlagsToFormat(os), os) );
757 ostr->SetVerifyData( s_FlagsToVerify(os) );
758 ostr->SetFormattingFlags( s_FlagsToFormatFlags(os) );
759 if (ostr->GetDataFormat() == eSerial_Xml) {
760 dynamic_cast<CObjectOStreamXml*>(ostr.get())->
761 SetDefaultStringEncoding( s_FlagsToEncoding(os) );
762 }
763 ostr->Write(ptr,info);
764 return os;
765 }
ReadObject(CNcbiIstream & is,TObjectPtr ptr,TTypeInfo info)766 CNcbiIstream& ReadObject(CNcbiIstream& is, TObjectPtr ptr, TTypeInfo info)
767 {
768 unique_ptr<CObjectIStream> istr( CObjectIStream::Open(s_FlagsToFormat(is), is) );
769 istr->SetVerifyData(s_FlagsToVerify(is));
770 istr->SetSkipUnknownMembers( s_FlagsToSkipUnkMembers(is));
771 istr->SetSkipUnknownVariants( s_FlagsToSkipUnkVariants(is));
772 TSerial_Format_Flags f = s_FlagsToFormatFlags(is);
773 if (f != 0) {
774 ERR_POST_XX_ONCE(Serial_IStream, 9, Warning <<
775 "ReadObject: ignoring unknown formatting flags");
776 }
777 if (istr->GetDataFormat() == eSerial_Xml) {
778 dynamic_cast<CObjectIStreamXml*>(istr.get())->
779 SetDefaultStringEncoding( s_FlagsToEncoding(is) );
780 }
781 istr->Read(ptr,info);
782 return is;
783 }
784
785
786 END_NCBI_SCOPE
787