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

Go to the SVN repository for this file.

1 /* $Id: reg_file.cpp 39959 2017-11-30 17:10:19Z katargir $
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  * Authors: Mike DiCuccio
27  *
28  * File Description:
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbireg.hpp>
37 
38 
41 
42 static const string kConfigObjClass("NCBI");
43 static const string kConfigObjType("GUI-App-Registry");
44 static const string kMetaSuffix = "-meta";
45 static const string kDecimalDot = ".";
46 
47 
49 {
50  SetRegistry();
51 }
52 
53 
55 {
56  Read(istr);
57 }
58 
59 
60 CRegistryFile::CRegistryFile(const objects::CUser_object& obj)
61 {
62  SetRegistry(obj);
63 }
64 
65 CRegistryReadView CRegistryFile::GetReadView(const string& section) const
66 {
67  return CRegistryReadView(GetField(section));
68 }
69 
71 {
72  return CRegistryWriteView(section, *this);
73 }
74 
75 /// recursively navigate an object tree, retrieving an existing named key
76 static CConstRef<CUser_field> s_GetFieldAt(const CUser_object& obj, const string& key, const string& delim)
77 {
78 #ifdef _DEBUG
79  {{
80  _ASSERT(key.find(delim + delim) == string::npos);
81  _ASSERT(key.find_first_of(delim) != 0);
82  _ASSERT(key.size() && key.find_first_of(delim) != key.size() - 1);
83  }}
84 #endif
85 
86  string first_key(key);
87  string remainder;
88  string::size_type pos = key.find_first_of(delim);
89  if (pos != string::npos) {
90  first_key = key.substr(0, pos);
91  remainder = key.substr(pos + 1, key.length() - pos - 1);
92  }
93 
94  CConstRef<CUser_field> field_ref;
95  ITERATE(CUser_object::TData, field_iter, obj.GetData()) {
96  const CUser_field& f = **field_iter;
97  if (f.GetLabel().GetStr() == first_key) {
98  if (remainder.empty()) {
99  field_ref.Reset(&f);
100  break;
101  }
102  else if (f.GetData().IsFields()) {
103  field_ref = f.GetFieldRef(remainder, delim);
104  if (field_ref) {
105  break;
106  }
107  }
108  }
109  }
110  return field_ref;
111 }
112 
113 /// recursively navigate an object tree, setting keys where necessary to get
114 /// a named level
115 static CRef<CUser_field> s_SetFieldAt(CUser_object& obj, const string& key, const string& delim)
116 {
117 #ifdef _DEBUG
118  {{
119  _ASSERT(key.find(delim + delim) == string::npos);
120  _ASSERT(key.find_first_of(delim) != 0);
121  _ASSERT(key.size() && key.find_first_of(delim) != key.size() - 1);
122  }}
123 #endif
124 
125  string first_key(key);
126  string remainder;
127  string::size_type pos = key.find_first_of(delim);
128  if (pos != string::npos) {
129  first_key = key.substr(0, pos);
130  remainder = key.substr(pos + 1, key.length() - pos - 1);
131  }
132 
133  CRef<CUser_field> field_ref;
134  NON_CONST_ITERATE(CUser_object::TData, field_iter, obj.SetData()) {
135  CUser_field& f = **field_iter;
136  if (f.GetLabel().GetStr() == first_key) {
137  if (remainder.empty()) {
138  field_ref.Reset(&f);
139  break;
140  }
141  else {
142  field_ref = f.SetFieldRef(remainder, delim);
143  if (field_ref) {
144  break;
145  }
146  }
147  }
148  }
149 
150  if (!field_ref) {
151  /// create the field for this level
152  field_ref.Reset(new CUser_field());
153  field_ref->SetLabel().SetStr(first_key);
154  obj.SetData().push_back(field_ref);
155 
156  if (!remainder.empty()) {
157  CRef<CUser_field> f = field_ref->SetFieldRef(remainder, delim);
158  field_ref = f;
159  }
160  }
161 
162  return field_ref;
163 }
164 
166 {
167  // in the incoming registry, meta sections will end with this:
168  static string kMetaKey(".meta");
169 
171 
172  list<string> meta_sections;
173  list<string> sections;
175  ITERATE (list<string>, iter, sections) {
176  string section(*iter);
177  string::size_type meta_pos = iter->find(kMetaKey);
178  if (meta_pos == iter->length() - kMetaKey.length()) {
179  // replace NcbiRegistry's meta key with CGuiRegistry's meta suffix.
180  string non_meta = section.erase(meta_pos);
181  section = non_meta + kMetaSuffix;
182  meta_sections.push_back(section);
183 
185  if ( !cf ) {
186  /// add an empty string field
188  f->SetData().SetStr();
189  }
190  }
191 
192  list<string> entries;
194  ITERATE (list<string>, ent_iter, entries) {
195 
196  string val = reg.Get(*iter, *ent_iter, IRegistry::fInternalSpaces);
197 
199  _ASSERT(obj);
200 
201  try {
202  int i = NStr::StringToInt(val);
203  obj->AddField(*ent_iter, i);
204  continue;
205  }
206  catch (std::exception&) {
207  }
208 
209  try {
210  double d = NStr::StringToDouble(val);
211  obj->AddField(*ent_iter, d);
212  continue;
213  }
214  catch (std::exception&) {
215  }
216 
217  try {
218  bool b = NStr::StringToBool(val);
219  obj->AddField(*ent_iter, b);
220  continue;
221  }
222  catch (std::exception&) {
223  }
224 
225  obj->AddField(*ent_iter, val);
226  }
227  }
228 
229  ITERATE (list<string>, iter, meta_sections) {
230  // we currently only post-process the type field
231  CConstRef<CUser_field> type_field = GetField(*iter + ".Type");
232  if ( !type_field || !type_field->GetData().IsStr() ) {
233  continue;
234  }
235  string type = type_field->GetData().GetStr();
236  if (type.empty()) {
237  continue;
238  }
239 
240  string::size_type pos;
241  string section(*iter);
242 
243  // erase the '-meta'
244  pos = section.rfind(kMetaSuffix);
245  section.erase(pos);
246 
247  CRef<CUser_field> field = SetField(section);
248  if ( !field ) {
249  continue;
250  }
251 
252  if (type == "intvec") {
253  vector<int> val;
254 
255  switch (field->GetData().Which()) {
257  {{
258  string str = field->GetData().GetStr();
259  list<string> toks;
261  ITERATE (list<string>, it, toks) {
262  val.push_back
264  }
265  field->SetData().SetInts() = val;
266  }}
267  break;
268 
270  val.push_back(field->GetData().GetInt());
271  field->SetData().SetInts() = val;
272  break;
273 
275  break;
276 
277  default:
278  LOG_POST(Error << "unexpected type in conversion to int-vec");
279  break;
280  }
281 
282  } else if (type == "realvec") {
283  vector<double> val;
284 
285  switch (field->GetData().Which()) {
287  {{
288  string str = field->GetData().GetStr();
289  list<string> toks;
291  ITERATE (list<string>, it, toks) {
292  val.push_back
294  }
295  field->SetData().SetReals() = val;
296  }}
297  break;
298 
300  val.push_back(field->GetData().GetReal());
301  field->SetData().SetReals() = val;
302  break;
303 
305  break;
306 
307  default:
308  LOG_POST(Error << "unexpected type in conversion to int-vec");
309  break;
310  }
311 
312  } else if (type == "stringvec") {
314 
315  switch (field->GetData().Which()) {
317  {{
318  string str = field->GetData().GetStr();
319  list<string> toks;
321  ITERATE (list<string>, it, toks) {
322  val.push_back(NStr::TruncateSpaces(*it));
323  }
324  field->SetData().SetStrs() = val;
325  }}
326  break;
327 
329  val.push_back(NStr::IntToString(field->GetData().GetInt()));
330  field->SetData().SetStrs() = val;
331  break;
332 
334  break;
335 
336  default:
337  LOG_POST(Error << "unexpected type in conversion to string-vec");
338  break;
339  }
340  }
341  }
342 }
343 
344 
345 static void s_ScanRecursive(const CUser_object& obj,
346  CNcbiRegistry& reg,
347  const string& field_tag = kEmptyStr)
348 {
349  ITERATE (CUser_object::TData, iter, obj.GetData()) {
350 
351  const CUser_field& field = **iter;
352 
353  switch (field.GetData().Which()) {
355  {{
356  string tag(field_tag);
357  if ( !tag.empty() ) {
358  tag += '.';
359  }
360  tag += field.GetLabel().GetStr();
361  s_ScanRecursive(field.GetData().GetObject(), reg, tag);
362  }}
363  break;
364 
366  reg.Set(field_tag, field.GetLabel().GetStr(),
369  break;
370 
372  reg.Set(field_tag, field.GetLabel().GetStr(),
373  NStr::IntToString(field.GetData().GetInt()),
375  break;
376 
378  {{
379  string str;
380  ITERATE (CUser_field::TData::TInts, iter, field.GetData().GetInts()) {
381  if ( !str.empty() ) {
382  str += ", ";
383  }
384  str += NStr::IntToString(*iter);
385  }
386  reg.Set(field_tag, field.GetLabel().GetStr(), str,
388  }}
389  break;
390 
392  reg.Set(field_tag, field.GetLabel().GetStr(),
395  break;
396 
398  {{
399  string str;
401  if ( !str.empty() ) {
402  str += ", ";
403  }
404  str += NStr::DoubleToString(*iter);
405  }
406  reg.Set(field_tag, field.GetLabel().GetStr(), str,
408  }}
409  break;
410 
412  reg.Set(field_tag, field.GetLabel().GetStr(),
413  field.GetData().GetStr(),
415  break;
416 
418  {{
419  string str;
420  ITERATE (CUser_field::TData::TStrs, iter, field.GetData().GetStrs()) {
421  if ( !str.empty() ) {
422  str += ", ";
423  }
424  str += *iter;
425  }
426  reg.Set(field_tag, field.GetLabel().GetStr(), str,
428  }}
429  break;
430 
431  default:
432  LOG_POST(Warning << "unhandled tag: "
433  << field_tag << kDecimalDot << field.GetLabel().GetStr());
434  break;
435  }
436  }
437 }
438 
440 {
441  if ( !m_Registry ) {
442  return;
443  }
444 
445  CNcbiRegistry reg;
446 
448  reg.Write(ostr);
449 }
450 
451 
453 {
454  istr >> MSerial_AsnText >> SetRegistry();
455 }
456 
458 {
459  if (m_Registry) {
460  ostr << MSerial_AsnText << GetRegistry();
461  }
462 }
463 
464 
465 bool CRegistryFile::HasField(const string& key) const
466 {
467  if ( !m_Registry ) {
468  return false;
469  }
470 
472  return obj ? true : false;
473 }
474 
475 
477 {
479  if (m_Registry) {
481  }
482  return f;
483 }
484 
485 
486 
488 {
490 }
491 
492 
493 bool CRegistryFile::DeleteField(const string& key)
494 {
495  string first_key, remainder;
496  if (!NStr::SplitInTwo(key, kDecimalDot, first_key, remainder)) {
497  // should be no need to delete top-level keys.
498  // if there is, need to implement it in CUser_object.
499  return false;
500  }
501 
502  CRef<CUser_field> parent_field = SetField(first_key);
503  if (! parent_field) {
504  return false;
505  }
506  return parent_field->DeleteField(remainder, kDecimalDot);
507 }
508 
509 
511 {
512  if ( !m_Registry ) {
514  }
515  return *m_Registry;
516 }
517 
518 
519 
520 void CRegistryFile::SetRegistry(const objects::CUser_object& reg)
521 {
522  _ASSERT(IsRegistry(reg));
523 
524  m_Registry.Reset();
525  SetRegistry();
526  m_Registry->Assign(reg);
527 }
528 
529 
531 {
533  return *m_Registry;
534 }
535 
536 
538 {
539  CRef<CUser_field> field = SetField(key);
540  if (field->GetData().IsFields()) {
541  // field is a place for subkeys, not for a value.
543  "Too few components in key \"" + key + "\"");
544  }
545  return field;
546 }
547 
548 
549 bool CRegistryFile::IsRegistry(const objects::CUser_object& uo)
550 {
551  return uo.CanGetClass() && uo.GetClass() == kConfigObjClass &&
552  uo.GetType().IsStr() && uo.GetType().GetStr() == kConfigObjType ;
553 }
554 
555 
557 {
559 
560  uo_ref.Reset(new CUser_object());
561  uo_ref->SetClass(kConfigObjClass);
562  uo_ref->SetType().SetStr(kConfigObjType);
563  uo_ref->SetData();
564  return uo_ref;
565 }
566 
567 
CNcbiRegistry –.
Definition: ncbireg.hpp:913
CConstRef< objects::CUser_field > GetField(const string &key) const
Definition: reg_file.cpp:476
const objects::CUser_object & GetRegistry() const
Definition: reg_file.cpp:530
CRegistryReadView GetReadView(const string &section) const
Definition: reg_file.cpp:65
CRef< objects::CUser_field > SetFieldToValue(const string &key)
Definition: reg_file.cpp:537
void Read(CNcbiIstream &istr)
Definition: reg_file.cpp:452
void ToConfigFile(CNcbiOstream &istr) const
Definition: reg_file.cpp:439
CRef< objects::CUser_object > m_Registry
Definition: reg_file.hpp:81
void FromConfigFile(CNcbiIstream &istr)
Definition: reg_file.cpp:165
objects::CUser_object & SetRegistry()
Definition: reg_file.cpp:510
CRef< objects::CUser_field > SetField(const string &key)
Definition: reg_file.cpp:487
static bool IsRegistry(const objects::CUser_object &uo)
Is this user object suitable to use as a gui-registry site?
Definition: reg_file.cpp:549
static CRef< objects::CUser_object > NewRegistryObject()
make a new user object suitable to use as a gui-registry site.
Definition: reg_file.cpp:556
bool HasField(const string &key) const
Definition: reg_file.cpp:465
void Write(CNcbiOstream &istr) const
Definition: reg_file.cpp:457
bool DeleteField(const string &key)
Definition: reg_file.cpp:493
CRegistryWriteView GetWriteView(const string &section)
Definition: reg_file.cpp:70
class CRegistryReadView provides a nested hierarchical view at a particular key.
Definition: reg_view.hpp:58
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
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 & AddField(const string &label, int value)
add fields to the current user field
Definition: User_field.cpp:92
#define true
Definition: bool.h:35
static const char * str(char *buf, int n)
Definition: stats.c:84
static FILE * f
Definition: readconf.c:23
#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 LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
#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
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
#define MSerial_AsnText
I/O stream manipulators –.
Definition: serialbase.hpp:696
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:1439
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
virtual void EnumerateSections(list< string > *sections, TFlags flags=fAllLayers) const
Enumerate section names.
Definition: ncbireg.cpp:497
virtual const string & Get(const string &section, const string &name, TFlags flags=0) const
Get the parameter value.
Definition: ncbireg.cpp:262
virtual void EnumerateEntries(const string &section, list< string > *entries, TFlags flags=fAllLayers) const
Enumerate parameter names for a specified section.
Definition: ncbireg.cpp:514
bool Write(CNcbiOstream &os, TFlags flags=0) const
Write the registry content to output stream.
Definition: ncbireg.cpp:196
bool Set(const string &section, const string &name, const string &value, TFlags flags=0, const string &comment=kEmptyStr)
Set the configuration parameter value.
Definition: ncbireg.cpp:826
@ fInternalSpaces
Allow internal whitespace in names.
Definition: ncbireg.hpp:92
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:149
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
Definition: ncbistre.hpp:146
static bool StringToBool(const CTempString str)
Convert string to bool.
Definition: ncbistr.cpp:2812
static string DoubleToString(double value, int precision=-1, TNumToStringFlags flags=0)
Convert double to string.
Definition: ncbistr.hpp:5181
#define kEmptyStr
Definition: ncbistr.hpp:123
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
static const string BoolToString(bool value)
Convert bool to string.
Definition: ncbistr.cpp:2806
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5078
static bool SplitInTwo(const CTempString str, const CTempString delim, string &str1, string &str2, TSplitFlags flags=0)
Split a string into two pieces using the specified delimiters.
Definition: ncbistr.cpp:3545
static string TruncateSpaces(const string &str, ETrunc where=eTrunc_Both)
Truncate whitespace in a string.
Definition: ncbistr.cpp:3177
@ fSplit_Tokenize
All delimiters are merged and trimmed, to get non-empty tokens only.
Definition: ncbistr.hpp:2510
const TStr & GetStr(void) const
Get the variant data.
const TStrs & GetStrs(void) const
Get the variant data.
const TData & GetData(void) const
Get the Data member data.
vector< double > TReals
TBool GetBool(void) const
Get the variant data.
bool IsFields(void) const
Check if variant Fields is selected.
bool IsStr(void) const
Check if variant Str 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.
TInt GetInt(void) const
Get the variant data.
const TData & GetData(void) const
Get the Data member data.
const TObject & GetObject(void) const
Get the variant data.
TReal GetReal(void) const
Get the variant data.
const TReals & GetReals(void) const
Get the variant data.
void SetData(TData &value)
Assign a value to Data data member.
const TLabel & GetLabel(void) const
Get the Label member data.
vector< CStringUTF8 > TStrs
vector< CRef< CUser_field > > TData
E_Choice Which(void) const
Which variant is currently selected.
const TInts & GetInts(void) const
Get the variant data.
@ e_Object
for using other definitions
int i
const struct ncbi::grid::netcache::search::fields::KEY key
const char * tag
Process information in the NCBI Registry, including working with configuration files.
USING_SCOPE(objects)
static CRef< CUser_field > s_SetFieldAt(CUser_object &obj, const string &key, const string &delim)
recursively navigate an object tree, setting keys where necessary to get a named level
Definition: reg_file.cpp:115
static const string kDecimalDot
Definition: reg_file.cpp:45
static CConstRef< CUser_field > s_GetFieldAt(const CUser_object &obj, const string &key, const string &delim)
recursively navigate an object tree, retrieving an existing named key
Definition: reg_file.cpp:76
static const string kConfigObjClass("NCBI")
static const string kConfigObjType("GUI-App-Registry")
static const string kMetaSuffix
Definition: reg_file.cpp:44
static void s_ScanRecursive(const CUser_object &obj, CNcbiRegistry &reg, const string &field_tag=kEmptyStr)
Definition: reg_file.cpp:345
Definition: type.c:6
#define _ASSERT
static wxAcceleratorEntry entries[3]
Modified on Fri Sep 20 14:57:56 2024 by modify_doxy.py rev. 669887