NCBI C++ ToolKit
User_field.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: User_field.cpp 100341 2023-07-20 17:47:12Z 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: .......
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>
44 
45 // generated classes
46 
48 
49 BEGIN_objects_SCOPE // namespace ncbi::objects::
50 
51 // destructor
53 {
54 }
55 
56 
57 /// add fields to the current user field
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 
71  const string& value)
72 {
74 }
75 
76 
78  const char* value)
79 {
80  return AddField(label, string(value), eParse_String);
81 }
82 
83 
85  const char* value,
86  EParseField parse)
87 {
88  return AddField(label, string(value), parse);
89 }
90 
91 
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 
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
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 
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 
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 
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 
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 
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 
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 
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 
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.
211 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 ) {
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.
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 
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) {
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 
282  ostream & out_name_strm, const string & delim) const
283 {
284  bool bFirst = true;
286  if( bFirst ) {
287  bFirst = false;
288  } else {
289  out_name_strm << delim;
290  }
291  out_name_strm << *chain_iter;
292  }
293 }
294 
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 
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
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.
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() ||
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
393 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.
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 
446 {
447  return SetValue(string(value));
448 }
449 
450 
452 {
453  if ( parse == eParse_Number ) {
454  try {
455  return SetValue(NStr::StringToNumeric<Int8>(value));
456  }
457  catch (...) {
458  }
459 
460  try {
462  }
463  catch (...) {
464  }
465  }
466  return SetValue(value);
467 }
468 
469 
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 
482 {
483  if ( value == int(value) ) {
484  // value fits in 'int' field
485  return SetInt(int(value));
486  }
487  // otherwise the value is stored into 'str' field
489 }
490 
491 
493 {
495  NCBI_THROW_FMT(CSerialException, eOverflow,
496  "array size is too big to fit into User-field.num: " << value);
497  }
498  SetNum(TNum(value));
499 }
500 
501 
503 {
504  SetNumFromSize(value.size());
505  SetData().SetInts() = value;
506  return *this;
507 }
508 
509 
510 CUser_field& CUser_field::SetValue(const vector<double>& value)
511 {
512  SetNumFromSize(value.size());
513  SetData().SetReals() = value;
514  return *this;
515 }
516 
517 
518 CUser_field& CUser_field::SetValue(const vector<string>& value)
519 {
520  SetNumFromSize(value.size());
521  SetData().SetStrs() = value;
522  return *this;
523 }
524 
525 
527 {
529  return *this;
530 }
531 
532 
534 {
535  SetNumFromSize(value.size());
536  SetData().SetObjects() = value;
537  return *this;
538 }
539 
540 
542 {
543  SetNumFromSize(value.size());
544  SetData().SetFields() = value;
545  return *this;
546 }
547 
548 
550 {
551  const C_Data& data = GetData();
552  if ( data.IsInt() ) {
553  return data.GetInt();
554  }
555  if ( data.IsReal() ) {
556  double v = data.GetReal();
557  if ( v >= -kMaxAsReal && v <= kMaxAsReal ) {
558  return Int8(v);
559  }
560  }
561  return NStr::StringToNumeric<Int8>(data.GetStr());
562 }
563 
564 
565 END_objects_SCOPE // namespace ncbi::objects::
566 
static const Int8 kMaxAsReal
Definition: User_field.cpp:478
Root class for all serialization exceptions.
Definition: exception.hpp:50
CRef< CUser_field > SetFieldRef(const string &str, const string &delim=".", NStr::ECase use_case=NStr::eCase)
Return a field reference representing the tokenized key, or a NULL reference if the key cannot be cre...
Definition: User_field.cpp:345
@ fFieldMapFlags_ExcludeThis
= 0x1 (excludes this CUser_field's name and mapping to self from results)
Definition: User_field.hpp:172
bool DeleteField(const string &str, const string &delim=".", NStr::ECase use_case=NStr::eCase)
Delete the named field.
Definition: User_field.cpp:404
CUser_field & SetString(const char *value)
Definition: User_field.cpp:445
const CUser_field & GetField(const string &str, const string &delim=".", NStr::ECase use_case=NStr::eCase) const
Access a named field in this user field.
Definition: User_field.cpp:211
void SetNumFromSize(size_t value)
Set num field from a container size Check for overflow and throw CSerialException::eOverflow if the s...
Definition: User_field.cpp:492
@ eParse_Number
Parse a real or integer number, otherwise string.
Definition: User_field.hpp:61
@ eParse_String
Add string even if all numbers.
Definition: User_field.hpp:60
CUser_field & SetInt8(Int8 value)
Definition: User_field.cpp:481
CUser_field & SetValue(int value)
set a data field to a given value Int8 and TGi values can be stored into 'str' field if the value doe...
Definition: User_field.hpp:283
CUser_field & SetField(const string &str, const string &delim=".", NStr::ECase use_case=NStr::eCase)
Access a named field in this user field.
Definition: User_field.cpp:334
CConstRef< CUser_field > GetFieldRef(const string &str, const string &delim=".", NStr::ECase use_case=NStr::eCase) const
Return a field reference representing the tokenized key, or a NULL reference if the key doesn't exist...
Definition: User_field.cpp:226
~CUser_field(void)
Definition: User_field.cpp:52
void GetFieldsMap(CUser_field::TMapFieldNameToRef &out_mapFieldNameToRef, TFieldMapFlags fFieldMapFlags=0, const SFieldNameChain &parent_name=SFieldNameChain()) const
Recursively get the map of field names like the input for GetFieldRef to the user-field.
Definition: User_field.cpp:295
int TFieldMapFlags
holds bitwise OR of "EFieldMapFlags"
Definition: User_field.hpp:174
CUser_field & AddField(const string &label, int value)
add fields to the current user field
Definition: User_field.cpp:92
CUser_field & SetInt(int value)
set value
Definition: User_field.hpp:245
CUser_field(void)
Definition: User_field.hpp:231
bool HasField(const string &str, const string &delim=".", NStr::ECase use_case=NStr::eCase) const
Verify that a named field exists.
Definition: User_field.cpp:393
Int8 GetInt8(void) const
Definition: User_field.cpp:549
iterator_bool insert(const value_type &val)
Definition: map.hpp:165
container_type::value_type value_type
Definition: map.hpp:52
Definition: map.hpp:338
static DLIST_TYPE *DLIST_NAME() last(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:51
static const char * str(char *buf, int n)
Definition: stats.c:84
static FILE * f
Definition: readconf.c:23
char data[12]
Definition: iconv.c:80
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
#define NULL
Definition: ncbistd.hpp:225
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define NCBI_THROW_FMT(exception_class, err_code, message)
The same as NCBI_THROW but with message processed as output to ostream.
Definition: ncbiexpt.hpp:719
CConstRef< C > ConstRef(const C *object)
Template function for conversion of const object pointer to CConstRef.
Definition: ncbiobj.hpp:2024
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static int StringToInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to int.
Definition: ncbistr.cpp:630
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
Definition: ncbistr.cpp:3452
static double StringToDouble(const CTempStringEx str, TStringToNumFlags flags=0)
Convert string to double.
Definition: ncbistr.cpp:1381
ECase
Which type of string comparison.
Definition: ncbistr.hpp:1204
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
static bool Equal(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2, ECase use_case=eCase)
Test for equality of a substring with another string.
Definition: ncbistr.hpp:5378
@ fSplit_Tokenize
All delimiters are merged and trimmed, to get non-empty tokens only.
Definition: ncbistr.hpp:2510
static const char label[]
bool IsStr(void) const
Check if variant Str is selected.
Definition: Object_id_.hpp:291
TObject & SetObject(void)
Select the variant.
TFields & SetFields(void)
Select the variant.
bool IsId(void) const
Check if variant Id is selected.
Definition: Object_id_.hpp:264
const TData & GetData(void) const
Get the Data member data.
vector< CRef< CUser_field > > TFields
bool IsFields(void) const
Check if variant Fields is selected.
TData & SetData(void)
Assign a value to Data data member.
const TStr & GetStr(void) const
Get the variant data.
Definition: Object_id_.hpp:297
void SetLabel(TLabel &value)
Assign a value to Label data member.
TObjects & SetObjects(void)
Select the variant.
TReals & SetReals(void)
Select the variant.
TInts & SetInts(void)
Select the variant.
TNum & SetNum(void)
Assign a value to Num data member.
const TLabel & GetLabel(void) const
Get the Label member data.
TStrs & SetStrs(void)
Select the variant.
vector< CStringUTF8 > TStrs
TId GetId(void) const
Get the variant data.
Definition: Object_id_.hpp:270
E_Choice Which(void) const
Which variant is currently selected.
@ e_not_set
No variant selected.
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
#define NCBI_CONST_INT8(v)
64-bit integers
Definition: ncbi_std.h:195
T max(T x_, T y_)
Generic utility macros and templates for exploring NCBI objects.
#define FIELD_IS_SET_AND_IS(Var, Fld, Chs)
FIELD_IS_SET_AND_IS base macro.
For functions that don't use delims, we instead use a chain of names.
Definition: User_field.hpp:149
void Join(ostream &out_name_strm, const string &delim=".") const
Convenience func.
Definition: User_field.cpp:281
TFieldNameChainUnderlying m_FieldNameChain
Definition: User_field.hpp:164
vector< CTempStringEx > TFieldNameChainUnderlying
Definition: User_field.hpp:163
Modified on Fri Sep 20 14:57:29 2024 by modify_doxy.py rev. 669887