Scarab  v1.6.1
Project 8 C++ Utility Library
param.cc
Go to the documentation of this file.
1 /*
2  * param.cc
3  *
4  * Created on: Jan 14, 2014
5  * Author: nsoblath
6  */
7 
8 #define SCARAB_API_EXPORTS
9 
10 #include <sstream>
11 using std::string;
12 using std::stringstream;
13 
14 #include "param.hh"
15 
16 //#include "logger.hh"
17 
18 
19 namespace scarab
20 {
21  //LOGGER( slog, "param" );
22 
23  SCARAB_API unsigned param::s_indent_level = 0;
24 
26  {
27  }
28 
29  param::param( const param& )
30  {
31  }
32 
34  {
35  }
36 
37  bool param::has_subset( const param& /*a_subset*/ ) const
38  {
39  // this version of has_subset should only ever be called if a_subset is a null param (i.e. not one of the derived classes)
40  return true;
41  }
42 
43  //************************************
44  //*********** VALUE ****************
45  //************************************
46 
48  param(),
49  f_value_type( k_invalid ),
50  f_buffer()
51  {
52  //LWARN( dlog, "param_value constructor: k_invalid" );
53  }
54 
55  param_value::param_value( bool a_value ) :
56  param(),
58  f_buffer()
59  {
60  f_value.f_bool = a_value;
61  //LWARN( dlog, "param_value constructor: bool --> bool" );
62  }
63 
64  param_value::param_value( uint8_t a_value ) :
65  param(),
67  f_buffer()
68  {
69  f_value.f_uint = a_value;
70  //LWARN( dlog, "param_value constructor: uint8 --> uint" );
71  }
72 
73  param_value::param_value( uint16_t a_value ) :
74  param(),
76  f_buffer()
77  {
78  f_value.f_uint = a_value;
79  //LWARN( dlog, "param_value constructor: uint16 --> uint" );
80  }
81 
82  param_value::param_value( uint32_t a_value ) :
83  param(),
85  f_buffer()
86  {
87  f_value.f_uint = a_value;
88  //LWARN( dlog, "param_value constructor: uint32 --> uint" );
89  }
90 
91  param_value::param_value( uint64_t a_value ) :
92  param(),
94  f_buffer()
95  {
96  f_value.f_uint = a_value;
97  //LWARN( dlog, "param_value constructor: uint64 --> uint" );
98  }
99 
100  param_value::param_value( int8_t a_value ) :
101  param(),
102  f_value_type( k_int ),
103  f_buffer()
104  {
105  f_value.f_int = a_value;
106  //LWARN( dlog, "param_value constructor: int8 --> int" );
107  }
108 
109  param_value::param_value( int16_t a_value ) :
110  param(),
111  f_value_type( k_int ),
112  f_buffer()
113  {
114  f_value.f_int = a_value;
115  //LWARN( dlog, "param_value constructor: int16 --> int" );
116  }
117 
118 
119  param_value::param_value( int32_t a_value ) :
120  param(),
121  f_value_type( k_int ),
122  f_buffer()
123  {
124  f_value.f_int = a_value;
125  //LWARN( dlog, "param_value constructor: int32 --> int" );
126  }
127 
128  param_value::param_value( int64_t a_value ) :
129  param(),
130  f_value_type( k_int ),
131  f_buffer()
132  {
133  f_value.f_int = a_value;
134  //LWARN( dlog, "param_value constructor: int64 --> int" );
135  }
136 
137  param_value::param_value( float a_value ) :
138  param(),
140  f_buffer()
141  {
142  f_value.f_double = a_value;
143  //LWARN( dlog, "param_value constructor: float --> double" );
144  }
145 
146  param_value::param_value( double a_value ) :
147  param(),
149  f_buffer()
150  {
151  f_value.f_double = a_value;
152  //LWARN( dlog, "param_value constructor: double --> double" );
153  }
154 
155  param_value::param_value( const char* a_value ) :
156  param(),
158  f_buffer()
159  {
160  f_value.f_string = new string( a_value );
161  //LWARN( dlog, "param_value constructor: char* --> k_string" );
162  }
163 
164  param_value::param_value( const string& a_value ) :
165  param(),
167  f_buffer()
168  {
169  f_value.f_string = new string( a_value );
170  //LWARN( dlog, "param_value constructor: string --> k_string" );
171  }
172 
174  param( orig ),
175  f_value( orig.f_value ),
176  f_value_type( orig.f_value_type ),
177  f_buffer()
178  {
179  if( f_value_type == k_string )
180  {
181  f_value.f_string = new string( *orig.f_value.f_string );
182  }
183  //LWARN( dlog, "param_value copy constructor: " << type() );
184  }
185 
187  {
188  if( f_value_type == k_string )
189  {
190  delete f_value.f_string;
191  }
192  }
193 
195  {
196  if( &rhs == this ) return *this;
197 
198  if( f_value_type == k_string )
199  {
200  delete f_value.f_string;
201  }
202 
203  if( rhs.f_value_type == k_string )
204  {
205  f_value.f_string = new string( *rhs.f_value.f_string );
206  }
207  else
208  {
209  f_value = rhs.f_value;
210  }
212 
213  return *this;
214  }
215 
216  std::string param_value::type() const
217  {
218  switch( f_value_type )
219  {
220  case k_invalid:
221  return string( "invalid" );
222  break;
223  case k_bool:
224  return string( "bool" );
225  break;
226  case k_uint:
227  return string( "uint" );
228  break;
229  case k_int:
230  return string( "int" );
231  break;
232  case k_double:
233  return string( "double" );
234  break;
235  case k_string:
236  return string( "string" );
237  break;
238  }
239  return string( "unknown" );
240  }
241 
242  bool param_value::as_bool() const
243  {
244  if( f_value_type == k_bool ) return f_value.f_bool;
245  else if( f_value_type == k_uint ) return f_value.f_uint != 0;
246  else if( f_value_type == k_int ) return f_value.f_int != 0;
247  else if( f_value_type == k_double ) return f_value.f_double != 0.;
248  else if( f_value_type == k_string )
249  {
250  if( f_value.f_string->empty() ) return false;
251 
252  std::string t_str_val;
253  bool t_is_numeric = true;
254  for( std::string::const_iterator t_val_it = f_value.f_string->begin(); t_val_it != f_value.f_string->end(); ++t_val_it )
255  {
256  t_is_numeric = t_is_numeric && ::isdigit( *t_val_it );
257  t_str_val.push_back( ::tolower( *t_val_it ) );
258  }
259 
260  if( t_is_numeric ) return std::stoi( t_str_val );
261 
262  std::istringstream t_iss_val( t_str_val );
263  bool t_bool_val;
264  t_iss_val >> std::boolalpha >> t_bool_val;
265  return t_bool_val;
266  }
267  return false;
268  }
269 
270  uint64_t param_value::as_uint() const
271  {
272  if( f_value_type == k_bool ) return (uint64_t)f_value.f_bool;
273  else if( f_value_type == k_uint ) return f_value.f_uint;
274  else if( f_value_type == k_int ) return (uint64_t)f_value.f_int;
275  else if( f_value_type == k_double ) return (uint64_t)f_value.f_double;
276  else if( f_value_type == k_string )
277  {
278  std::stringstream t_conv;
279  t_conv << *f_value.f_string;
280  uint64_t t_return;
281  t_conv >> t_return;
282  return t_return;
283  }
284  return 0.;
285  }
286  int64_t param_value::as_int() const
287  {
288  if( f_value_type == k_bool ) return (int64_t)f_value.f_bool;
289  else if( f_value_type == k_uint ) return (int64_t)f_value.f_uint;
290  else if( f_value_type == k_int ) return f_value.f_int;
291  else if( f_value_type == k_double ) return (int64_t)f_value.f_double;
292  else if( f_value_type == k_string )
293  {
294  std::stringstream t_conv;
295  t_conv << *f_value.f_string;
296  int64_t t_return;
297  t_conv >> t_return;
298  return t_return;
299  }
300  return 0.;
301  }
302  double param_value::as_double() const
303  {
304  if( f_value_type == k_bool ) return f_value.f_bool;
305  else if( f_value_type == k_uint ) return (double)f_value.f_uint;
306  else if( f_value_type == k_int ) return (double)f_value.f_int;
307  else if( f_value_type == k_double ) return f_value.f_double;
308  else if( f_value_type == k_string )
309  {
310  std::stringstream t_conv;
311  t_conv << *f_value.f_string;
312  double t_return;
313  t_conv >> t_return;
314  return t_return;
315  }
316  return 0.;
317  }
318  const string& param_value::as_string() const
319  {
320  if( f_value_type == k_string ) return *f_value.f_string;
321 
322  std::stringstream t_conv;
323  if( f_value_type == k_bool ) t_conv << (as_bool() ? "true" : "false");
324  else if( f_value_type == k_uint ) t_conv << as_uint();
325  else if( f_value_type == k_int ) t_conv << as_int();
326  else if( f_value_type == k_double ) t_conv << as_double();
327 
328  t_conv >> f_buffer;
329  return f_buffer;
330  }
331 
333  {
334  if( f_value_type == k_string ) return path( *f_value.f_string );
335  return path();
336  }
337 
339  {
340  if( f_value_type == k_bool ) f_value.f_bool = false;
341  else if( f_value_type == k_uint ) f_value.f_uint = 0;
342  else if( f_value_type == k_int ) f_value.f_int = 0;
343  else if( f_value_type == k_double ) f_value.f_double = 0.;
344  else if( f_value_type == k_string ) f_value.f_string->clear();
345  return;
346  }
347 
348  bool param_value::has_subset( const param& a_subset ) const
349  {
350  if( ! a_subset.is_value() ) return false;
351  return true;
352  }
353 
354 
355  //************************************
356  //*********** ARRAY ****************
357  //************************************
358 
360  param(),
361  f_contents()
362  {
363  }
364 
366  param( orig ),
367  f_contents( orig.f_contents.size() )
368  {
369  for( unsigned ind = 0; ind < f_contents.size(); ++ind )
370  {
371  this->assign( ind, orig[ ind ].clone() );
372  }
373  }
374 
376  {
377  clear();
378  }
379 
381  {
382  clear();
383  resize(rhs.size());
384  for( unsigned ind = 0; ind < rhs.f_contents.size(); ++ind )
385  {
386  this->assign( ind, rhs[ ind ].clone() );
387  }
388  return *this;
389  }
390 
391  bool param_array::has_subset( const param& a_subset ) const
392  {
393  if( ! a_subset.is_array() ) return false;
394  const param_array& t_subset_array = a_subset.as_array();
395  if( t_subset_array.size() > f_contents.size() ) return false;
396  const_iterator t_this_it = f_contents.begin();
397  const_iterator t_that_it = t_subset_array.begin();
398  while( t_that_it != t_subset_array.end() ) // loop condition is on a_subset because it's smaller or equal to this
399  {
400  if( ! (*t_this_it)->has_subset( **t_that_it ) ) return false;
401  ++t_this_it;
402  ++t_that_it;
403  }
404  return true;
405  }
406 
407  void param_array::resize( unsigned a_size )
408  {
409  unsigned curr_size = f_contents.size();
410  for( unsigned ind = a_size; ind < curr_size; ++ind )
411  {
412  delete f_contents[ ind ];
413  }
414  f_contents.resize( a_size );
415  return;
416  }
417 
418  std::string param_array::to_string() const
419  {
420  stringstream out;
421  string indentation;
422  for ( unsigned i=0; i<param::s_indent_level; ++i )
423  indentation += " ";
424  out << '\n' << indentation << "[\n";
425  param::s_indent_level++;
426  for( const_iterator it = begin(); it != end(); ++it )
427  {
428  out << indentation << " " << **it << '\n';
429  }
430  param::s_indent_level--;
431  out << indentation << "]\n";
432  return out.str();
433  }
434 
435 
436 
437  //************************************
438  //*********** NODE *****************
439  //************************************
440 
442  param(),
443  f_contents()
444  {
445  }
446 
448  param( orig ),
449  f_contents()
450  {
451  for( const_iterator it = orig.f_contents.begin(); it != orig.f_contents.end(); ++it )
452  {
453  add( it->first, it->second->clone() );
454  }
455  }
456 
458  {
459  clear();
460  }
461 
463  {
464  clear();
465  for( const_iterator it = rhs.f_contents.begin(); it != rhs.f_contents.end(); ++it )
466  {
467  this->replace( it->first, *it->second );
468  }
469  return *this;
470  }
471 
472  bool param_node::has_subset( const param& a_subset ) const
473  {
474  if( ! a_subset.is_node() ) return false;
475  const param_node& t_subset_node = a_subset.as_node();
476  if( t_subset_node.size() > f_contents.size() ) return false;
477  for( const_iterator t_subset_it = t_subset_node.begin(); t_subset_it != t_subset_node.end(); ++t_subset_it )
478  {
479  if( ! has( t_subset_it->first ) ) return false;
480  if( ! f_contents.at( t_subset_it->first )->has_subset( *t_subset_it->second ) ) return false;
481  }
482  return true;
483  }
484 
485  void param_node::merge( const param_node& a_object )
486  {
487  //LDEBUG( dlog, "merging object with " << a_object.size() << " items:\n" << a_object );
488  for( const_iterator it = a_object.f_contents.begin(); it != a_object.f_contents.end(); ++it )
489  {
490  if( ! has( it->first ) )
491  {
492  //LDEBUG( dlog, "do not have object <" << it->first << "> = <" << *it->second << ">" );
493  add( it->first, *it->second );
494  continue;
495  }
496  param& t_param = (*this)[ it->first ];
497  if( t_param.is_value() )
498  {
499  //LDEBUG( dlog, "replacing the value of \"" << it->first << "\" <" << get_value( it->first ) << "> with <" << *it->second << ">" );
500  replace( it->first, *it->second );
501  continue;
502  }
503  if( t_param.is_node() && it->second->is_node() )
504  {
505  //LDEBUG( dlog, "merging nodes")
506  t_param.as_node().merge( it->second->as_node() );
507  continue;
508  }
509  if( t_param.is_array() && it->second->is_array() )
510  {
511  //LDEBUG( dlog, "appending array" );
512  t_param.as_array().append( it->second->as_array() );
513  continue;
514  }
515  //LDEBUG( dlog, "generic replace" );
516  this->replace( it->first, *it->second );
517  }
518  }
519 
520  std::string param_node::to_string() const
521  {
522  stringstream out;
523  string indentation;
524  for ( unsigned i=0; i<param::s_indent_level; ++i )
525  indentation += " ";
526  out << '\n' << indentation << "{\n";
527  param::s_indent_level++;
528  for( const_iterator it = begin(); it != end(); ++it )
529  {
530  out << indentation << " " << it->first << " : " << *(it->second) << '\n';
531  }
532  param::s_indent_level--;
533  out << indentation << "}\n";
534  return out.str();
535  }
536 
537 
538 
539 
540  SCARAB_API std::ostream& operator<<(std::ostream& out, const param& a_value)
541  {
542  return out << a_value.to_string();
543  }
544 
545 
546  SCARAB_API std::ostream& operator<<(std::ostream& out, const param_value& a_value)
547  {
548  return out << a_value.as_string();
549  }
550 
551 
552  SCARAB_API std::ostream& operator<<(std::ostream& out, const param_array& a_value)
553  {
554  return out << a_value.to_string();
555  }
556 
557 
558  SCARAB_API std::ostream& operator<<(std::ostream& out, const param_node& a_value)
559  {
560  return out << a_value.to_string();
561  }
562 
563 } /* namespace mantis */
virtual bool is_node() const
Definition: param.hh:420
void replace(const std::string &a_name, const param &a_value)
creates a copy of a_value
Definition: param.hh:1142
void merge(const param_node &a_object)
Definition: param.cc:485
std::string type() const
Definition: param.cc:216
std::string * f_string
Definition: param.hh:157
virtual bool has_subset(const param &a_subset) const
Definition: param.cc:37
virtual bool has_subset(const param &a_subset) const
Definition: param.cc:391
fs::path path
Definition: path.hh:25
virtual bool has_subset(const param &a_subset) const
Definition: param.cc:348
virtual bool has_subset(const param &a_subset) const
Definition: param.cc:472
param_array & operator=(const param_array &rhs)
Definition: param.cc:380
contents f_contents
Definition: param.hh:295
virtual std::string to_string() const
Definition: param.cc:418
path as_path() const
Definition: param.cc:332
iterator begin()
Definition: param.hh:1189
virtual bool is_value() const
Definition: param.hh:410
virtual ~param_array()
Definition: param.cc:375
#define SCARAB_API
Definition: scarab_api.hh:24
virtual std::string to_string() const
Definition: param.hh:491
SCARAB_API std::ostream & operator<<(std::ostream &out, const param &a_value)
Definition: param.cc:540
virtual ~param()
Definition: param.cc:33
virtual param * clone() const
Definition: param.hh:729
int64_t as_int() const
Definition: param.cc:286
static unsigned s_indent_level
Definition: param.hh:75
std::string f_buffer
Definition: param.hh:170
union scarab::param_value::Values f_value
unsigned size() const
Definition: param.hh:986
enum scarab::param_value::ValueTypes f_value_type
iterator end()
Definition: param.hh:920
unsigned size() const
Definition: param.hh:744
bool has(const std::string &a_name) const
Definition: param.hh:996
contents::const_iterator const_iterator
Definition: param.hh:305
param_node & operator=(const param_node &rhs)
Definition: param.cc:462
void append(const param_array &an_array)
Definition: param.hh:880
iterator end()
Definition: param.hh:1199
virtual std::string to_string() const
Definition: param.cc:520
iterator begin()
Definition: param.hh:911
virtual ~param_node()
Definition: param.cc:457
virtual ~param_value()
Definition: param.cc:186
const std::string & as_string() const
Definition: param.cc:318
param_node & as_node()
Definition: param.hh:437
void assign(unsigned a_index, const param &a_value)
Definition: param.hh:844
param_array & as_array()
Definition: param.hh:431
bool as_bool() const
Definition: param.cc:242
contents::const_iterator const_iterator
Definition: param.hh:179
contents f_contents
Definition: param.hh:395
bool add(const std::string &a_name, const param &a_value)
creates a copy of a_value
Definition: param.hh:1120
double as_double() const
Definition: param.cc:302
uint64_t as_uint() const
Definition: param.cc:270
virtual bool is_array() const
Definition: param.hh:415
param_value & operator=(const param_value &rhs)
Definition: param.cc:194
void resize(unsigned a_size)
Definition: param.cc:407