1 /* $Id: User_field.cpp 592620 2019-09-05 00:19:23Z kans $
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: .......
27 *
28 * File Description:
29 * .......
30 *
31 * Remark:
32 * This code was originally generated by application DATATOOL
33 * using specifications from the data definition file
34 * 'general.asn'.
35 */
36
37 // standard includes
38
39 // generated includes
40 #include <ncbi_pch.hpp>
41 #include <objects/general/User_field.hpp>
42 #include <objects/general/User_object.hpp>
43 #include <objects/misc/sequence_util_macros.hpp>
44
45 // generated classes
46
47 BEGIN_NCBI_SCOPE
48
49 BEGIN_objects_SCOPE // namespace ncbi::objects::
50
51 // destructor
~CUser_field(void)52 CUser_field::~CUser_field(void)
53 {
54 }
55
56
57 /// add fields to the current user field
AddField(const string & label,const string & value,EParseField parse)58 CUser_field& CUser_field::AddField(const string& label,
59 const string& value,
60 EParseField parse)
61 {
62 CRef<CUser_field> field(new CUser_field());
63 field->SetLabel().SetStr(label);
64 field->SetValue(value, parse);
65 SetData().SetFields().push_back(field);
66 return *this;
67 }
68
69
AddField(const string & label,const string & value)70 CUser_field& CUser_field::AddField(const string& label,
71 const string& value)
72 {
73 return AddField(label, value, eParse_String);
74 }
75
76
AddField(const string & label,const char * value)77 CUser_field& CUser_field::AddField(const string& label,
78 const char* value)
79 {
80 return AddField(label, string(value), eParse_String);
81 }
82
83
AddField(const string & label,const char * value,EParseField parse)84 CUser_field& CUser_field::AddField(const string& label,
85 const char* value,
86 EParseField parse)
87 {
88 return AddField(label, string(value), parse);
89 }
90
91
AddField(const string & label,int value)92 CUser_field& CUser_field::AddField(const string& label, int value)
93 {
94 CRef<CUser_field> field(new CUser_field());
95 field->SetLabel().SetStr(label);
96 field->SetValue(value);
97 SetData().SetFields().push_back(field);
98 return *this;
99 }
100
101
AddField(const string & label,Int8 value)102 CUser_field& CUser_field::AddField(const string& label, Int8 value)
103 {
104 CRef<CUser_field> field(new CUser_field());
105 field->SetLabel().SetStr(label);
106 field->SetValue(value);
107 SetData().SetFields().push_back(field);
108 return *this;
109 }
110
111
112 #ifdef NCBI_STRICT_GI
AddField(const string & label,TGi value)113 CUser_field& CUser_field::AddField(const string& label, TGi value)
114 {
115 CRef<CUser_field> field(new CUser_field());
116 field->SetLabel().SetStr(label);
117 field->SetValue(value);
118 SetData().SetFields().push_back(field);
119 return *this;
120 }
121 #endif
122
123
AddField(const string & label,double value)124 CUser_field& CUser_field::AddField(const string& label, double value)
125 {
126 CRef<CUser_field> field(new CUser_field());
127 field->SetLabel().SetStr(label);
128 field->SetValue(value);
129 SetData().SetFields().push_back(field);
130 return *this;
131 }
132
133
AddField(const string & label,bool value)134 CUser_field& CUser_field::AddField(const string& label, bool value)
135 {
136 CRef<CUser_field> field(new CUser_field());
137 field->SetLabel().SetStr(label);
138 field->SetValue(value);
139 SetData().SetFields().push_back(field);
140 return *this;
141 }
142
AddField(const string & label,const CUser_field_Base::TData::TStrs & value)143 CUser_field& CUser_field::AddField(const string& label,
144 const CUser_field_Base::TData::TStrs& value)
145 {
146 CRef<CUser_field> field(new CUser_field());
147 field->SetLabel().SetStr(label);
148 field->SetValue(value);
149 SetData().SetFields().push_back(field);
150 return *this;
151 }
152
AddField(const string & label,const vector<int> & value)153 CUser_field& CUser_field::AddField(const string& label,
154 const vector<int>& value)
155 {
156 CRef<CUser_field> field(new CUser_field());
157 field->SetLabel().SetStr(label);
158 field->SetValue(value);
159 SetData().SetFields().push_back(field);
160 return *this;
161 }
162
163
AddField(const string & label,const vector<double> & value)164 CUser_field& CUser_field::AddField(const string& label,
165 const vector<double>& value)
166 {
167 CRef<CUser_field> field(new CUser_field());
168 field->SetLabel().SetStr(label);
169 field->SetValue(value);
170 SetData().SetFields().push_back(field);
171 return *this;
172 }
173
174
AddField(const string & label,CUser_object & value)175 CUser_field& CUser_field::AddField(const string& label,
176 CUser_object& value)
177 {
178 CRef<CUser_field> field(new CUser_field());
179 field->SetLabel().SetStr(label);
180 field->SetValue(value);
181 SetData().SetFields().push_back(field);
182 return *this;
183 }
184
185
AddField(const string & label,const vector<CRef<CUser_object>> & value)186 CUser_field& CUser_field::AddField(const string& label,
187 const vector< CRef<CUser_object> >& value)
188 {
189 CRef<CUser_field> field(new CUser_field());
190 field->SetLabel().SetStr(label);
191 field->SetValue(value);
192 SetData().SetFields().push_back(field);
193 return *this;
194 }
195
196
AddField(const string & label,const vector<CRef<CUser_field>> & value)197 CUser_field& CUser_field::AddField(const string& label,
198 const vector< CRef<CUser_field> >& value)
199 {
200 CRef<CUser_field> field(new CUser_field());
201 field->SetLabel().SetStr(label);
202 field->SetValue(value);
203 SetData().SetFields().push_back(field);
204 return *this;
205 }
206
207
208 /// Access a named field in this user field. This will tokenize the
209 /// string 'str' on the delimiters; if the field doesn't exist, an
210 /// exception will be thrown.
GetField(const string & str,const string & delim,NStr::ECase use_case) const211 const CUser_field& CUser_field::GetField(const string& str,
212 const string& delim,
213 NStr::ECase use_case) const
214 {
215 CConstRef<CUser_field> f = GetFieldRef(str, delim, use_case);
216 if ( !f ) {
217 NCBI_THROW(CException, eUnknown,
218 "failed to find field named " + str);
219 }
220 return *f;
221 }
222
223
224 /// Return a field reference representing the tokenized key, or a
225 /// NULL reference if the key doesn't exist.
GetFieldRef(const string & str,const string & delim,NStr::ECase use_case) const226 CConstRef<CUser_field> CUser_field::GetFieldRef(const string& str,
227 const string& delim,
228 NStr::ECase use_case) const
229 {
230 list<string> toks;
231 NStr::Split(str, delim, toks, NStr::fSplit_Tokenize);
232
233 CConstRef<CUser_field> f(this);
234 if ( !f->GetData().IsFields() ) {
235 if (toks.size() == 1 &&
236 f->GetLabel().IsStr() &&
237 NStr::Equal(f->GetLabel().GetStr(), toks.front(), use_case))
238 {
239 return f;
240 } else {
241 return CConstRef<CUser_field>();
242 }
243 }
244
245 if (toks.size()) {
246 list<string>::const_iterator last = toks.end();
247 --last;
248
249 ITERATE (list<string>, iter, toks) {
250 CConstRef<CUser_field> new_f;
251
252 ITERATE (TData::TFields, field_iter, f->GetData().GetFields()) {
253 const CUser_field& field = **field_iter;
254 if (field.GetLabel().IsStr()) {
255 if (NStr::Equal(field.GetLabel().GetStr(), *iter, use_case) ) {
256 if (iter == last || field.GetData().IsFields()) {
257 new_f = *field_iter;
258 break;
259 }
260 }
261 } else if (field.GetLabel().IsId()) {
262 if (field.GetLabel().GetId() == NStr::StringToInt(*iter)) {
263 if (iter == last || field.GetData().IsFields()) {
264 new_f = *field_iter;
265 break;
266 }
267 }
268 }
269 }
270
271 f = new_f;
272 if ( !f ) {
273 return f;
274 }
275 }
276 }
277
278 return f;
279 }
280
Join(ostream & out_name_strm,const string & delim) const281 void CUser_field::SFieldNameChain::Join(
282 ostream & out_name_strm, const string & delim) const
283 {
284 bool bFirst = true;
285 ITERATE(TFieldNameChainUnderlying, chain_iter, m_FieldNameChain) {
286 if( bFirst ) {
287 bFirst = false;
288 } else {
289 out_name_strm << delim;
290 }
291 out_name_strm << *chain_iter;
292 }
293 }
294
GetFieldsMap(CUser_field::TMapFieldNameToRef & out_mapFieldNameToRef,TFieldMapFlags fFieldMapFlags,const SFieldNameChain & parent_name) const295 void CUser_field::GetFieldsMap(
296 CUser_field::TMapFieldNameToRef & out_mapFieldNameToRef,
297 TFieldMapFlags fFieldMapFlags,
298 const SFieldNameChain & parent_name) const
299 {
300 // get the label
301 if( ! FIELD_IS_SET_AND_IS(*this, Label, Str) ) {
302 // we might eventually support numeric labels
303 return;
304 }
305
306 // copying a vector of CTempStrings is much more efficient
307 // than copying strings, so this should be okay.
308 SFieldNameChain field_name_chain = parent_name;
309
310 if( ! (fFieldMapFlags & fFieldMapFlags_ExcludeThis) ) {
311 field_name_chain += GetLabel().GetStr();
312 out_mapFieldNameToRef.insert(
313 TMapFieldNameToRef::value_type(field_name_chain, ConstRef(this) ) );
314 }
315
316 // recurse, if applicable
317 if( FIELD_IS_SET_AND_IS(*this, Data, Fields) ) {
318 // some flags do not get passed down recursively
319 TFieldMapFlags fChildFieldMapFlags =
320 ( fFieldMapFlags & ~fFieldMapFlags_ExcludeThis );
321
322 ITERATE( CUser_field::C_Data::TFields, field_iter,
323 GetData().GetFields() )
324 {
325 (*field_iter)->GetFieldsMap(out_mapFieldNameToRef,
326 fChildFieldMapFlags,
327 field_name_chain);
328 }
329 }
330 }
331
332 /// Access a named field in this user field. This will tokenize the
333 /// string 'str' on the delimiters and recursively add fields where needed
SetField(const string & str,const string & delim,NStr::ECase use_case)334 CUser_field& CUser_field::SetField(const string& str,
335 const string& delim,
336 NStr::ECase use_case)
337 {
338 CRef<CUser_field> f = SetFieldRef(str, delim, use_case);
339 return *f;
340 }
341
342
343 /// Return a field reference representing the tokenized key, or a
344 /// NULL reference if the key cannot be created for some reason.
SetFieldRef(const string & str,const string & delim,NStr::ECase use_case)345 CRef<CUser_field> CUser_field::SetFieldRef(const string& str,
346 const string& delim,
347 NStr::ECase use_case)
348 {
349 list<string> toks;
350 NStr::Split(str, delim, toks, NStr::fSplit_Tokenize);
351
352 CRef<CUser_field> f(this);
353 if ( ! f->GetData().IsFields() && f->GetData().Which() != CUser_field::TData::e_not_set ) {
354 // There is a value here, not a list of User_fields, no place to recurse downward.
355 NCBI_THROW(CException, eUnknown, "Too many parts in key: \"" + str + "\"");
356 }
357 list<string>::const_iterator last = toks.end();
358 --last;
359 ITERATE (list<string>, iter, toks) {
360 CRef<CUser_field> new_f;
361 NON_CONST_ITERATE (TData::TFields, field_iter, f->SetData().SetFields()) {
362 const CUser_field& field = **field_iter;
363 if (NStr::Equal(field.GetLabel().GetStr(), *iter, use_case) )
364 {
365 if (iter == last) {
366 new_f = *field_iter;
367 break;
368 } else if (field.GetData().IsFields() ||
369 field.GetData().Which() == CUser_field::TData::e_not_set) {
370 new_f = *field_iter;
371 break;
372 } else {
373 // There is a value here, not a list of User_fields, no place to recurse downward.
374 NCBI_THROW(CException, eUnknown, "Too many parts in key: \"" + str + "\"");
375 }
376 }
377 }
378
379 if ( !new_f ) {
380 new_f.Reset(new CUser_field());
381 new_f->SetLabel().SetStr(*iter);
382 f->SetData().SetFields().push_back(new_f);
383 }
384
385 f = new_f;
386 }
387
388 return f;
389 }
390
391
392 /// Verify that a named field exists
HasField(const string & str,const string & delim,NStr::ECase use_case) const393 bool CUser_field::HasField(const string& str,
394 const string& delim,
395 NStr::ECase use_case) const
396 {
397 CConstRef<CUser_field> f = GetFieldRef(str, delim, use_case);
398 return f.GetPointer() != NULL;
399 }
400
401
402
403 /// delete a named field.
DeleteField(const string & str,const string & delim,NStr::ECase use_case)404 bool CUser_field::DeleteField(const string& str,
405 const string& delim,
406 NStr::ECase use_case)
407 {
408 list<string> toks;
409 NStr::Split(str, delim, toks, NStr::fSplit_Tokenize);
410
411 CRef<CUser_field> f(this);
412 list<string>::const_iterator last = toks.end();
413 --last;
414
415 ITERATE (list<string>, iter, toks) {
416 CRef<CUser_field> new_f;
417 if ( !f->GetData().IsFields() ) {
418 return false;
419 }
420 NON_CONST_ITERATE (TData::TFields, field_iter, f->SetData().SetFields()) {
421 const CUser_field& field = **field_iter;
422 if (field.GetLabel().IsStr()
423 && NStr::Equal(field.GetLabel().GetStr(), *iter, use_case) )
424 {
425 if (iter != last && field.GetData().IsFields()) {
426 new_f = *field_iter;
427 break;
428 } else if (iter == last) {
429 // delete this one from f, its parent.
430 f->SetData().SetFields().erase(field_iter);
431 return true;
432 }
433 }
434 }
435 if ( !new_f ) {
436 return false;
437 }
438 f = new_f;
439 }
440 // Never reached.
441 return false;
442 }
443
444
SetString(const char * value)445 CUser_field& CUser_field::SetString(const char* value)
446 {
447 return SetValue(string(value));
448 }
449
450
SetValue(const string & value,EParseField parse)451 CUser_field& CUser_field::SetValue(const string& value, EParseField parse)
452 {
453 if ( parse == eParse_Number ) {
454 try {
455 return SetValue(NStr::StringToNumeric<TData::TInt>(value));
456 }
457 catch (...) {
458 }
459
460 try {
461 return SetValue(NStr::StringToDouble(value));
462 }
463 catch (...) {
464 }
465 }
466 return SetValue(value);
467 }
468
469
SetValue(const char * value,EParseField parse)470 CUser_field& CUser_field::SetValue(const char* value, EParseField parse)
471 {
472 return SetValue(string(value), parse);
473 }
474
475
476 // 15 digits of REAL numbers are preserved in serialization roundtrip
477 // so if the value has 15 digits or less we'll store it in 'real' field
478 static const Int8 kMaxAsReal = NCBI_CONST_INT8(999999999999999);
479
480
SetInt8(Int8 value)481 CUser_field& CUser_field::SetInt8(Int8 value)
482 {
483 if ( value == int(value) ) {
484 // value fits in 'int' field
485 return SetInt(int(value));
486 }
487 if ( value >= -kMaxAsReal && value <= kMaxAsReal ) {
488 return SetDouble(double(value));
489 }
490 // otherwise the value is stored into 'str' field
491 return SetString(NStr::NumericToString(value));
492 }
493
494
SetValue(const vector<int> & value)495 CUser_field& CUser_field::SetValue(const vector<int>& value)
496 {
497 SetNum(value.size());
498 SetData().SetInts() = value;
499 return *this;
500 }
501
502
SetValue(const vector<double> & value)503 CUser_field& CUser_field::SetValue(const vector<double>& value)
504 {
505 SetNum(value.size());
506 SetData().SetReals() = value;
507 return *this;
508 }
509
510
SetValue(const vector<string> & value)511 CUser_field& CUser_field::SetValue(const vector<string>& value)
512 {
513 SetNum(value.size());
514 SetData().SetStrs() = value;
515 return *this;
516 }
517
518
SetValue(CUser_object & value)519 CUser_field& CUser_field::SetValue(CUser_object& value)
520 {
521 SetData().SetObject(value);
522 return *this;
523 }
524
525
SetValue(const vector<CRef<CUser_object>> & value)526 CUser_field& CUser_field::SetValue(const vector< CRef<CUser_object> >& value)
527 {
528 SetNum(value.size());
529 SetData().SetObjects() = value;
530 return *this;
531 }
532
533
SetValue(const vector<CRef<CUser_field>> & value)534 CUser_field& CUser_field::SetValue(const vector< CRef<CUser_field> >& value)
535 {
536 SetNum(value.size());
537 SetData().SetFields() = value;
538 return *this;
539 }
540
541
GetInt8(void) const542 Int8 CUser_field::GetInt8(void) const
543 {
544 const C_Data& data = GetData();
545 if ( data.IsInt() ) {
546 return data.GetInt();
547 }
548 if ( data.IsReal() ) {
549 double v = data.GetReal();
550 if ( v >= -kMaxAsReal && v <= kMaxAsReal ) {
551 return Int8(v);
552 }
553 }
554 return NStr::StringToNumeric<Int8>(data.GetStr());
555 }
556
557
558 END_objects_SCOPE // namespace ncbi::objects::
559
560 END_NCBI_SCOPE
561