Properties.cpp
Go to the documentation of this file.
1 // -*- C++ -*-
20 #include <coil/Properties.h>
21 #include <coil/stringutil.h>
22 #include <iostream>
23 
24 #ifdef __QNX__
25 using std::size_t;
26 #endif
27 
28 namespace coil
29 {
37  Properties::Properties(const char* key, const char* value)
38  : name(key), value(value), default_value(""), root(NULL), m_empty("")
39  {
40  leaf.clear();
41  }
42 
50  Properties::Properties(std::map<std::string, std::string>& defaults)
51  : name(""), value(""), default_value(""), root(NULL), m_empty("")
52  {
53  leaf.clear();
54  std::map<std::string, std::string>::iterator it(defaults.begin());
55  std::map<std::string, std::string>::iterator it_end(defaults.end());
56 
57  while (it != it_end)
58  {
59  setDefault(it->first.c_str(), it->second.c_str());
60  ++it;
61  }
62  }
63 
71  Properties::Properties(const char* defaults[], long num)
72  : name(""), value(""), default_value(""), root(NULL), m_empty("")
73  {
74  leaf.clear();
75  setDefaults(defaults, num);
76  }
77 
86  : name(prop.name), value(prop.value),
87  default_value(prop.default_value), root(NULL), m_empty("")
88  {
89  std::vector<std::string> keys;
90  keys = prop.propertyNames();
91  for (size_t i(0), len(keys.size()); i < len; ++i)
92  {
93  const Properties* node(NULL);
94  if ((node = prop.findNode(keys[i])) != NULL)
95  {
96  setDefault(keys[i], node->default_value);
97  setProperty(keys[i], node->value);
98  }
99  }
100  }
101 
110  {
111  clear();
112  name = prop.name;
113  value = prop.value;
115 
116  std::vector<std::string> keys;
117  keys = prop.propertyNames();
118  for (size_t i(0), len(keys.size()); i < len; ++i)
119  {
120  const Properties* node(prop.findNode(keys[i]));
121  if (node != 0)
122  {
123  setDefault(keys[i], node->default_value);
124  setProperty(keys[i], node->value);
125  }
126  }
127 
128  return *this;
129  }
130 
139  {
140  // Delete children
141  clear();
142 
143  // delete myself from parent
144  if (root != NULL)
145  {
146  root->removeNode(name.c_str());
147  }
148  };
149 
150  //============================================================
151  // public fnctions
152  //============================================================
160  const std::string& Properties::getProperty(const std::string& key) const
161  {
162  std::vector<std::string> keys;
163  split(key, '.', keys);
164  Properties* node(NULL);
165  if ((node = _getNode(keys, 0, this)) != NULL)
166  {
167  return (!node->value.empty()) ? node->value : node->default_value;
168  }
169  return m_empty;
170  }
171 
179  const std::string& Properties::getProperty(const std::string& key,
180  const std::string& def) const
181  {
182  const std::string& value((*this)[key]);
183 
184  return value.empty() ? def : value;
185  }
186 
194  const std::string& Properties::operator[](const std::string& key) const
195  {
196  return getProperty(key);
197  }
198 
206  std::string& Properties::operator[](const std::string& key)
207  {
208  setProperty(key, getProperty(key));
209  Properties& prop(getNode(key));
210 
211  return prop.value;
212  }
213 
221  const std::string& Properties::getDefault(const std::string& key) const
222  {
223  std::vector<std::string> keys;
224  split(key, '.', keys);
225  Properties* node(NULL);
226  if ((node = _getNode(keys, 0, this)) != NULL)
227  {
228  return node->default_value;
229  }
230  return m_empty;
231  }
232 
240  std::string Properties::setProperty(const std::string& key,
241  const std::string& value)
242  {
243  std::vector<std::string> keys;
244  split(key, '.', keys);
245 
246  Properties* curr(this);
247  for (size_t i(0), len(keys.size()); i < len; ++i)
248  {
249  Properties* next(curr->hasKey(keys[i].c_str()));
250  if (next == NULL)
251  {
252  next = new Properties(keys[i].c_str());
253  next->root = curr;
254  curr->leaf.push_back(next);
255  }
256  curr = next;
257  }
258  std::string retval(curr->value);
259  curr->value = value;
260  return retval;
261  }
262 
270  std::string Properties::setDefault(const std::string& key,
271  const std::string& value)
272  {
273  std::vector<std::string> keys;
274  split(key, '.', keys);
275 
276  Properties* curr(this);
277  for (size_t i(0), len(keys.size()); i < len; ++i)
278  {
279  Properties* next(curr->hasKey(keys[i].c_str()));
280  if (next == NULL)
281  {
282  next = new Properties(keys[i].c_str());
283  next->root = curr;
284  curr->leaf.push_back(next);
285  }
286  curr = next;
287  }
288  curr->default_value = value;
289  return value;
290  }
291 
299  void Properties::setDefaults(const char* defaults[], long num)
300  {
301  for (long i = 0; i < num && defaults[i][0] != '\0' ; i += 2)
302  {
303  std::string key(defaults[i]);
304  std::string value(defaults[i + 1]);
305 
308 
309  coil::eraseHeadBlank(value);
310  coil::eraseTailBlank(value);
311 
312  setDefault(key.c_str(), value.c_str());
313  }
314  }
315 
316  //============================================================
317  // load and save functions
318  //============================================================
326  void Properties::list(std::ostream& out)
327  {
328  _store(out, "", this);
329  }
330 
338  void Properties::load(std::istream& inStream)
339  {
340  std::string pline;
341 
342  while(!inStream.eof())
343  {
344  std::string tmp;
345  coil::getlinePortable(inStream, tmp);
347 
348  // Skip comments or empty lines
349  if (tmp.empty()) { continue; }
350  if (tmp[0] == '#' || tmp[0] == '!') { continue; }
351 
352  // line-end '\' continues entry
353  if (tmp[tmp.size() - 1] == '\\' && !coil::isEscaped(tmp, tmp.size() - 1))
354  {
355  tmp.erase(tmp.size() - 1);
356  pline += tmp;
357  continue;
358  }
359  pline += tmp;
360 
361  // Skip empty line (made of only ' ' or '\t')
362  if (pline.empty()) { continue; }
363 
364  std::string key, value;
365  splitKeyValue(pline, key, value);
366  key = coil::unescape(key);
369 
370  value = coil::unescape(value);
371  coil::eraseHeadBlank(value);
372  coil::eraseTailBlank(value);
373 
374  setProperty(key.c_str(), value.c_str());
375  pline.clear();
376  }
377  }
378 
386  void Properties::save(std::ostream& out, const std::string& header)
387  {
388  store(out, header);
389  return;
390  }
391 
399  void Properties::store(std::ostream& out, const std::string& header)
400  {
401  out << "# " << header << std::endl;
402  _store(out, "", this);
403  }
404 
405  //============================================================
406  // other util functions
407  //============================================================
415  std::vector<std::string> Properties::propertyNames() const
416  {
417  std::vector<std::string> names;
418  for (size_t i(0), len(leaf.size()); i < len; ++i)
419  {
420  _propertiyNames(names, leaf[i]->name, leaf[i]);
421  }
422  return names;
423  }
424 
432  int Properties::size(void) const
433  {
434  return static_cast<int>(propertyNames().size());
435  }
436 
444  Properties* const Properties::findNode(const std::string& key) const
445  {
446  if (key.empty()) { return 0; }
447  std::vector<std::string> keys;
448  // std::string value;
449  split(key, '.', keys);
450  return _getNode(keys, 0, this);
451  }
452 
460  Properties& Properties::getNode(const std::string& key)
461  {
462  if (key.empty()) { return *this; }
463  Properties* const leaf(findNode(key));
464  if (leaf != 0)
465  {
466  return *leaf;
467  }
468  this->createNode(key);
469  return *findNode(key);
470  }
471 
479  bool Properties::createNode(const std::string& key)
480  {
481  if (key.empty()) { return false; }
482 
483  if (findNode(key) != 0)
484  {
485  return false;
486  }
487  (*this)[key] = "";
488  return true;
489  }
490 
498  Properties* Properties::removeNode(const char* leaf_name)
499  {
500  std::vector<Properties*>::iterator it(leaf.begin()), it_end(leaf.end());
501  Properties* prop;
502  while (it != it_end)
503  {
504  if ((*it)->name == leaf_name)
505  {
506  prop = *it;
507  leaf.erase(it);
508  return prop;
509  }
510  ++it;
511  }
512  return NULL;
513  }
514 
522  Properties* Properties::hasKey(const char* key) const
523  {
524  for (size_t i(0), len(leaf.size()); i < len; ++i)
525  {
526  if (leaf[i]->name == key)
527  return leaf[i];
528  }
529  return NULL;
530  }
531 
539  void Properties::clear(void)
540  {
541  while (!leaf.empty())
542  {
543  if (leaf.back() != NULL) // recursive delete
544  delete leaf.back(); // back() returns always new
545  }
546  }
547 
556  {
557  std::vector<std::string> keys;
558  keys = prop.propertyNames();
559  for (size_t i(0), len(prop.size()); i < len; ++i)
560  {
561  (*this)[keys[i]] = prop[keys[i]];
562  }
563  return (*this);
564  }
565 
566  //------------------------------------------------------------
567  // Protected functions
568  //------------------------------------------------------------
576  void Properties::splitKeyValue(const std::string& str, std::string& key,
577  std::string& value)
578  {
579  std::string::size_type i(0);
580  std::string::size_type len(str.size());
581 
582  while (i < len)
583  {
584  if ((str[i] == ':' || str[i] == '=') && !coil::isEscaped(str, i))
585  {
586  key = str.substr(0, i); // substr(0, i) returns 0...(i-1) chars.
589  value = str.substr(i + 1);
590  coil::eraseHeadBlank(value);
591  coil::eraseTailBlank(value);
592  return;
593  }
594  ++i;
595  }
596 
597  // If no ':' or '=' exist, ' ' would be delimiter.
598  i = 0;
599  while (i < len)
600  {
601  if ((str[i] == ' ') && !coil::isEscaped(str, i))
602  {
603  key = str.substr(0, i); // substr(0, i) returns 0...(i-1) chars.
606  value = str.substr(i + 1);
607  coil::eraseHeadBlank(value);
608  coil::eraseTailBlank(value);
609  return;
610  }
611  ++i;
612  }
613 
614  key = str;
615  value = "";
616  return;
617  }
618 
626  bool Properties::split(const std::string& str, const char delim,
627  std::vector<std::string>& value)
628  {
629  if (str.empty()) return false;
630 
631  std::string::size_type begin_it(0), end_it(0);
632  std::string::size_type len(str.size());
633 
634  while (end_it < len)
635  {
636  if ((str[end_it] == delim) && !coil::isEscaped(str, end_it))
637  {
638  // substr(0, i) returns 0...(i-1) chars.
639  value.push_back(str.substr(begin_it, end_it - begin_it));
640  begin_it = end_it + 1;
641  }
642  ++end_it;
643  }
644  value.push_back(str.substr(begin_it, end_it));
645  return true;
646  }
647 
655  Properties*
656  Properties::_getNode(std::vector<std::string>& keys,
657  std::vector<Properties*>::size_type index,
658  const Properties* curr)
659  {
660  Properties* next(curr->hasKey(keys[index].c_str()));
661 
662  if (next == NULL)
663  {
664  return NULL;
665  }
666 
667  if (index < keys.size() - 1) // node
668  {
669  return next->_getNode(keys, ++index, next);
670  }
671  else
672  {
673  return next;
674  }
675  return NULL;
676  }
677 
685  void
686  Properties::_propertiyNames(std::vector<std::string>& names,
687  std::string curr_name,
688  const Properties* curr)
689  {
690  if (!curr->leaf.empty())
691  {
692  for (size_t i(0), len(curr->leaf.size()); i < len; ++i)
693  {
694  std::string next_name;
695  // if (curr_name == "") next_name = curr->leaf[i]->name;
696  next_name = curr_name + "." + curr->leaf[i]->name;
697  _propertiyNames(names, next_name, curr->leaf[i]);
698  }
699  }
700  else
701  {
702  names.push_back(curr_name);
703  }
704  return;
705  }
706 
714  void
715  Properties::_store(std::ostream& out, std::string curr_name,
716  Properties* curr)
717  {
718  if (!curr->leaf.empty())
719  {
720 
721  for (size_t i(0), len(curr->leaf.size()); i < len; ++i)
722  {
723  std::string next_name;
724  if (curr_name == "")
725  {
726  next_name = curr->leaf[i]->name;
727  }
728  else
729  {
730  next_name = curr_name + "." + curr->leaf[i]->name;
731  }
732  _store(out, next_name, curr->leaf[i]);
733  }
734  }
735 
736  if (curr->root != NULL)
737  {
738  if (curr->value.length() > 0)
739  {
740  out << curr_name << ": " << coil::escape(curr->value) << std::endl;
741  }
742  }
743  }
744 
752  std::ostream&
753  Properties::_dump(std::ostream& out, const Properties& curr, int index)
754  {
755  if (index != 0) out << indent(index) << "- " << curr.name;
756  if (curr.leaf.empty())
757  {
758  if (curr.value.empty())
759  {
760  out << ": " << curr.default_value << std::endl;
761  }
762  else
763  {
764  out << ": " << curr.value << std::endl;
765  }
766  return out;
767  }
768  if (index != 0) out << std::endl;
769  for (size_t i(0), len(curr.leaf.size()); i < len ;++i)
770  {
771  _dump(out, *(curr.leaf[i]), index + 1);
772  }
773  return out;
774  }
775 
783  std::string Properties::indent(int index)
784  {
785  std::string space;
786  for (int i(0); i < index - 1; ++i)
787  {
788  space += " ";
789  }
790  return space;
791  }
792 
800  std::string indent(int index)
801  {
802  std::string space;
803  for (int i(0); i < index - 1; ++i)
804  {
805  space += " ";
806  }
807  return space;
808  }
809 
817  std::ostream& operator<<(std::ostream& lhs, const Properties& rhs)
818  {
819  return rhs._dump(lhs, rhs, 0);
820  }
821 }; // namespace coil
const std::string & getDefault(const std::string &key) const
Get the default values with specified key.
Definition: Properties.cpp:221
static void splitKeyValue(const std::string &str, std::string &key, std::string &value)
Split the string into a pair of the key and the value.
Definition: Properties.cpp:576
static std::string indent(int index)
Create indents.
Definition: Properties.cpp:783
Properties(const char *key="", const char *value="")
Constructor(Create only root node)
Definition: Properties.cpp:37
void clear(void)
Clear the children.
Definition: Properties.cpp:539
void store(std::ostream &out, const std::string &header)
Stores property list to the output stream.
Definition: Properties.cpp:399
void eraseHeadBlank(std::string &str)
Erase the head blank characters of string.
Definition: stringutil.cpp:267
static void _propertiyNames(std::vector< std::string > &names, std::string curr_name, const Properties *curr)
Get property name list.
Definition: Properties.cpp:686
std::vector< std::string > propertyNames(void) const
Return an vector of all the keys in this property.
Definition: Properties.cpp:415
static bool split(const std::string &str, const char delim, std::vector< std::string > &value)
Split the string.
Definition: Properties.cpp:626
void list(std::ostream &out)
Prints this property list out to the specified output stream.
Definition: Properties.cpp:326
Properties * root
Definition: Properties.h:1286
Properties * hasKey(const char *key) const
Check whether key exists in the children.
Definition: Properties.cpp:522
std::string default_value
Definition: Properties.h:1285
void eraseTailBlank(std::string &str)
Erase the tail blank characters of string.
Definition: stringutil.cpp:280
void setDefaults(const char *defaults[], long num=LONG_MAX)
Set a default value together in the property list.
Definition: Properties.cpp:299
const std::string & getProperty(const std::string &key) const
Search for the property with the specified key in this property.
Definition: Properties.cpp:160
const std::string m_empty
Definition: Properties.h:1288
Properties *const findNode(const std::string &key) const
Get node of properties.
Definition: Properties.cpp:444
list index
Definition: rtimages.py:10
virtual ~Properties(void)
Destructor.
Definition: Properties.cpp:138
std::string setProperty(const std::string &key, const std::string &value)
Set a value associated with key in the property list.
Definition: Properties.cpp:240
bool createNode(const std::string &key)
Create newly node of Properties.
Definition: Properties.cpp:479
Properties * removeNode(const char *leaf_name)
Remove node of Properties.
Definition: Properties.cpp:498
void load(std::istream &inStream)
Loads property list that consists of key:value from input stream.
Definition: Properties.cpp:338
static Properties * _getNode(std::vector< std::string > &keys, std::vector< Properties *>::size_type index, const Properties *curr)
Get properties.
Definition: Properties.cpp:656
prop
Organization::get_organization_property ();.
const std::string & operator[](const std::string &key) const
Search for the property with the specified key in property list.
Definition: Properties.cpp:194
static std::ostream & _dump(std::ostream &out, const Properties &curr, int index)
Save property&#39;s contents.
Definition: Properties.cpp:753
static void _store(std::ostream &out, std::string curr_name, Properties *curr)
Store the property name list.
Definition: Properties.cpp:715
std::vector< Properties * > leaf
Definition: Properties.h:1287
Properties & operator=(const Properties &prop)
Assignment operator.
Definition: Properties.cpp:109
int getlinePortable(std::istream &istr, std::string &line)
Read a line from input stream.
Definition: stringutil.cpp:99
int size(void) const
Get the number of Properties.
Definition: Properties.cpp:432
bool isEscaped(const std::string &str, std::string::size_type pos)
Check whether the character is escaped or not.
Definition: stringutil.cpp:134
std::string value
Definition: Properties.h:1284
Properties & getNode(const std::string &key)
Get node of properties.
Definition: Properties.cpp:460
void save(std::ostream &out, const std::string &header)
Save the property list to the specified stream.
Definition: Properties.cpp:386
std::string name
Definition: Properties.h:1283
std::string unescape(const std::string str)
Unescape string.
Definition: stringutil.cpp:230
std::string escape(const std::string str)
Escape string.
Definition: stringutil.cpp:174
Properties & operator<<(const Properties &prop)
Merge properties.
Definition: Properties.cpp:555
std::string setDefault(const std::string &key, const std::string &value)
Set a default value associated with key in the property list.
Definition: Properties.cpp:270
Common Object Interface Layer.


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Mon Feb 28 2022 23:00:44