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 namespace coil
25 {
33  Properties::Properties(const char* key, const char* value)
34  : name(key), value(value), default_value(""), root(NULL), m_empty("")
35  {
36  leaf.clear();
37  }
38 
46  Properties::Properties(std::map<std::string, std::string>& defaults)
47  : name(""), value(""), default_value(""), root(NULL), m_empty("")
48  {
49  leaf.clear();
50  std::map<std::string, std::string>::iterator it(defaults.begin());
51  std::map<std::string, std::string>::iterator it_end(defaults.end());
52 
53  while (it != it_end)
54  {
55  setDefault(it->first.c_str(), it->second.c_str());
56  ++it;
57  }
58  }
59 
67  Properties::Properties(const char* defaults[], long num)
68  : name(""), value(""), default_value(""), root(NULL), m_empty("")
69  {
70  leaf.clear();
71  setDefaults(defaults, num);
72  }
73 
82  : name(prop.name), value(prop.value),
83  default_value(prop.default_value), root(NULL), m_empty("")
84  {
85  std::vector<std::string> keys;
86  keys = prop.propertyNames();
87  for (size_t i(0), len(keys.size()); i < len; ++i)
88  {
89  const Properties* node(NULL);
90  if ((node = prop.findNode(keys[i])) != NULL)
91  {
92  setDefault(keys[i], node->default_value);
93  setProperty(keys[i], node->value);
94  }
95  }
96  }
97 
106  {
107  clear();
108  name = prop.name;
109  value = prop.value;
111 
112  std::vector<std::string> keys;
113  keys = prop.propertyNames();
114  for (size_t i(0), len(keys.size()); i < len; ++i)
115  {
116  const Properties* node(prop.findNode(keys[i]));
117  if (node != 0)
118  {
119  setDefault(keys[i], node->default_value);
120  setProperty(keys[i], node->value);
121  }
122  }
123 
124  return *this;
125  }
126 
135  {
136  // Delete children
137  clear();
138 
139  // delete myself from parent
140  if (root != NULL)
141  {
142  root->removeNode(name.c_str());
143  }
144  };
145 
146  //============================================================
147  // public fnctions
148  //============================================================
156  const std::string& Properties::getProperty(const std::string& key) const
157  {
158  std::vector<std::string> keys;
159  split(key, '.', keys);
160  Properties* node(NULL);
161  if ((node = _getNode(keys, 0, this)) != NULL)
162  {
163  return (!node->value.empty()) ? node->value : node->default_value;
164  }
165  return m_empty;
166  }
167 
175  const std::string& Properties::getProperty(const std::string& key,
176  const std::string& def) const
177  {
178  const std::string& value((*this)[key]);
179 
180  return value.empty() ? def : value;
181  }
182 
190  const std::string& Properties::operator[](const std::string& key) const
191  {
192  return getProperty(key);
193  }
194 
202  std::string& Properties::operator[](const std::string& key)
203  {
204  setProperty(key, getProperty(key));
205  Properties& prop(getNode(key));
206 
207  return prop.value;
208  }
209 
217  const std::string& Properties::getDefault(const std::string& key) const
218  {
219  std::vector<std::string> keys;
220  split(key, '.', keys);
221  Properties* node(NULL);
222  if ((node = _getNode(keys, 0, this)) != NULL)
223  {
224  return node->default_value;
225  }
226  return m_empty;
227  }
228 
236  std::string Properties::setProperty(const std::string& key,
237  const std::string& value)
238  {
239  std::vector<std::string> keys;
240  split(key, '.', keys);
241 
242  Properties* curr(this);
243  for (size_t i(0), len(keys.size()); i < len; ++i)
244  {
245  Properties* next(curr->hasKey(keys[i].c_str()));
246  if (next == NULL)
247  {
248  next = new Properties(keys[i].c_str());
249  next->root = curr;
250  curr->leaf.push_back(next);
251  }
252  curr = next;
253  }
254  std::string retval(curr->value);
255  curr->value = value;
256  return retval;
257  }
258 
266  std::string Properties::setDefault(const std::string& key,
267  const std::string& value)
268  {
269  std::vector<std::string> keys;
270  split(key, '.', keys);
271 
272  Properties* curr(this);
273  for (size_t i(0), len(keys.size()); i < len; ++i)
274  {
275  Properties* next(curr->hasKey(keys[i].c_str()));
276  if (next == NULL)
277  {
278  next = new Properties(keys[i].c_str());
279  next->root = curr;
280  curr->leaf.push_back(next);
281  }
282  curr = next;
283  }
284  curr->default_value = value;
285  return value;
286  }
287 
295  void Properties::setDefaults(const char* defaults[], long num)
296  {
297  for (long i = 0; i < num && defaults[i][0] != '\0' ; i += 2)
298  {
299  std::string key(defaults[i]);
300  std::string value(defaults[i + 1]);
301 
304 
305  coil::eraseHeadBlank(value);
306  coil::eraseTailBlank(value);
307 
308  setDefault(key.c_str(), value.c_str());
309  }
310  }
311 
312  //============================================================
313  // load and save functions
314  //============================================================
322  void Properties::list(std::ostream& out)
323  {
324  _store(out, "", this);
325  }
326 
334  void Properties::load(std::istream& inStream)
335  {
336  std::string pline;
337 
338  while(!inStream.eof())
339  {
340  std::string tmp;
341  coil::getlinePortable(inStream, tmp);
343 
344  // Skip comments or empty lines
345  if (tmp[0] == '#' || tmp[0] == '!' || tmp == "") continue;
346 
347  // line-end '\' continues entry
348  if (tmp[tmp.size() - 1] == '\\' && !coil::isEscaped(tmp, tmp.size() - 1))
349  {
350  tmp.erase(tmp.size() - 1);
351  pline += tmp;
352  continue;
353  }
354  pline += tmp;
355 
356  // Skip empty line (made of only ' ' or '\t')
357  if (pline == "") continue;
358 
359  std::string key, value;
360  splitKeyValue(pline, key, value);
361  key = coil::unescape(key);
364 
365  value = coil::unescape(value);
366  coil::eraseHeadBlank(value);
367  coil::eraseTailBlank(value);
368 
369  setProperty(key.c_str(), value.c_str());
370  pline.clear();
371  }
372  }
373 
381  void Properties::save(std::ostream& out, const std::string& header)
382  {
383  store(out, header);
384  return;
385  }
386 
394  void Properties::store(std::ostream& out, const std::string& header)
395  {
396  out << "# " << header << std::endl;
397  _store(out, "", this);
398  }
399 
400  //============================================================
401  // other util functions
402  //============================================================
410  std::vector<std::string> Properties::propertyNames() const
411  {
412  std::vector<std::string> names;
413  for (size_t i(0), len(leaf.size()); i < len; ++i)
414  {
415  _propertiyNames(names, leaf[i]->name, leaf[i]);
416  }
417  return names;
418  }
419 
427  int Properties::size(void) const
428  {
429  return static_cast<int>(propertyNames().size());
430  }
431 
439  Properties* const Properties::findNode(const std::string& key) const
440  {
441  if (key.empty()) { return 0; }
442  std::vector<std::string> keys;
443  // std::string value;
444  split(key, '.', keys);
445  return _getNode(keys, 0, this);
446  }
447 
455  Properties& Properties::getNode(const std::string& key)
456  {
457  if (key.empty()) { return *this; }
458  Properties* const leaf(findNode(key));
459  if (leaf != 0)
460  {
461  return *leaf;
462  }
463  this->createNode(key);
464  return *findNode(key);
465  }
466 
474  bool Properties::createNode(const std::string& key)
475  {
476  if (key.empty()) { return false; }
477 
478  if (findNode(key) != 0)
479  {
480  return false;
481  }
482  (*this)[key] = "";
483  return true;
484  }
485 
493  Properties* Properties::removeNode(const char* leaf_name)
494  {
495  std::vector<Properties*>::iterator it(leaf.begin()), it_end(leaf.end());
496  Properties* prop;
497  while (it != it_end)
498  {
499  if ((*it)->name == leaf_name)
500  {
501  prop = *it;
502  leaf.erase(it);
503  return prop;
504  }
505  ++it;
506  }
507  return NULL;
508  }
509 
517  Properties* Properties::hasKey(const char* key) const
518  {
519  for (size_t i(0), len(leaf.size()); i < len; ++i)
520  {
521  if (leaf[i]->name == key)
522  return leaf[i];
523  }
524  return NULL;
525  }
526 
534  void Properties::clear(void)
535  {
536  while (!leaf.empty())
537  {
538  if (leaf.back() != NULL) // recursive delete
539  delete leaf.back(); // back() returns always new
540  }
541  }
542 
551  {
552  std::vector<std::string> keys;
553  keys = prop.propertyNames();
554  for (size_t i(0), len(prop.size()); i < len; ++i)
555  {
556  (*this)[keys[i]] = prop[keys[i]];
557  }
558  return (*this);
559  }
560 
561  //------------------------------------------------------------
562  // Protected functions
563  //------------------------------------------------------------
571  void Properties::splitKeyValue(const std::string& str, std::string& key,
572  std::string& value)
573  {
574  std::string::size_type i(0);
575  std::string::size_type len(str.size());
576 
577  while (i < len)
578  {
579  if ((str[i] == ':' || str[i] == '=') && !coil::isEscaped(str, i))
580  {
581  key = str.substr(0, i); // substr(0, i) returns 0...(i-1) chars.
584  value = str.substr(i + 1);
585  coil::eraseHeadBlank(value);
586  coil::eraseTailBlank(value);
587  return;
588  }
589  ++i;
590  }
591 
592  // If no ':' or '=' exist, ' ' would be delimiter.
593  i = 0;
594  while (i < len)
595  {
596  if ((str[i] == ' ') && !coil::isEscaped(str, i))
597  {
598  key = str.substr(0, i); // substr(0, i) returns 0...(i-1) chars.
601  value = str.substr(i + 1);
602  coil::eraseHeadBlank(value);
603  coil::eraseTailBlank(value);
604  return;
605  }
606  ++i;
607  }
608 
609  key = str;
610  value = "";
611  return;
612  }
613 
621  bool Properties::split(const std::string& str, const char delim,
622  std::vector<std::string>& value)
623  {
624  if (str.empty()) return false;
625 
626  std::string::size_type begin_it(0), end_it(0);
627  std::string::size_type len(str.size());
628 
629  while (end_it < len)
630  {
631  if ((str[end_it] == delim) && !coil::isEscaped(str, end_it))
632  {
633  // substr(0, i) returns 0...(i-1) chars.
634  value.push_back(str.substr(begin_it, end_it - begin_it));
635  begin_it = end_it + 1;
636  }
637  ++end_it;
638  }
639  value.push_back(str.substr(begin_it, end_it));
640  return true;
641  }
642 
650  Properties*
651  Properties::_getNode(std::vector<std::string>& keys,
652  std::vector<Properties*>::size_type index,
653  const Properties* curr)
654  {
655  Properties* next(curr->hasKey(keys[index].c_str()));
656 
657  if (next == NULL)
658  {
659  return NULL;
660  }
661 
662  if (index < keys.size() - 1) // node
663  {
664  return next->_getNode(keys, ++index, next);
665  }
666  else
667  {
668  return next;
669  }
670  return NULL;
671  }
672 
680  void
681  Properties::_propertiyNames(std::vector<std::string>& names,
682  std::string curr_name,
683  const Properties* curr)
684  {
685  if (!curr->leaf.empty())
686  {
687  for (size_t i(0), len(curr->leaf.size()); i < len; ++i)
688  {
689  std::string next_name;
690  // if (curr_name == "") next_name = curr->leaf[i]->name;
691  next_name = curr_name + "." + curr->leaf[i]->name;
692  _propertiyNames(names, next_name, curr->leaf[i]);
693  }
694  }
695  else
696  {
697  names.push_back(curr_name);
698  }
699  return;
700  }
701 
709  void
710  Properties::_store(std::ostream& out, std::string curr_name,
711  Properties* curr)
712  {
713  if (!curr->leaf.empty())
714  {
715 
716  for (size_t i(0), len(curr->leaf.size()); i < len; ++i)
717  {
718  std::string next_name;
719  if (curr_name == "")
720  {
721  next_name = curr->leaf[i]->name;
722  }
723  else
724  {
725  next_name = curr_name + "." + curr->leaf[i]->name;
726  }
727  _store(out, next_name, curr->leaf[i]);
728  }
729  }
730 
731  if (curr->root != NULL)
732  {
733  if (curr->value.length() > 0)
734  {
735  out << curr_name << ": " << coil::escape(curr->value) << std::endl;
736  }
737  }
738  }
739 
747  std::ostream&
748  Properties::_dump(std::ostream& out, const Properties& curr, int index)
749  {
750  if (index != 0) out << indent(index) << "- " << curr.name;
751  if (curr.leaf.empty())
752  {
753  if (curr.value.empty())
754  {
755  out << ": " << curr.default_value << std::endl;
756  }
757  else
758  {
759  out << ": " << curr.value << std::endl;
760  }
761  return out;
762  }
763  if (index != 0) out << std::endl;
764  for (size_t i(0), len(curr.leaf.size()); i < len ;++i)
765  {
766  _dump(out, *(curr.leaf[i]), index + 1);
767  }
768  return out;
769  }
770 
778  std::string Properties::indent(int index)
779  {
780  std::string space;
781  for (int i(0); i < index - 1; ++i)
782  {
783  space += " ";
784  }
785  return space;
786  }
787 
795  std::string indent(int index)
796  {
797  std::string space;
798  for (int i(0); i < index - 1; ++i)
799  {
800  space += " ";
801  }
802  return space;
803  }
804 
812  std::ostream& operator<<(std::ostream& lhs, const Properties& rhs)
813  {
814  return rhs._dump(lhs, rhs, 0);
815  }
816 }; // namespace coil
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:571
static std::string indent(int index)
Create indents.
Definition: Properties.cpp:778
Properties(const char *key="", const char *value="")
Constructor(Create only root node)
Definition: Properties.cpp:33
void clear(void)
Clear the children.
Definition: Properties.cpp:534
void store(std::ostream &out, const std::string &header)
Stores property list to the output stream.
Definition: Properties.cpp:394
void eraseHeadBlank(std::string &str)
Erase the head blank characters of string.
Definition: stringutil.cpp:262
static void _propertiyNames(std::vector< std::string > &names, std::string curr_name, const Properties *curr)
Get property name list.
Definition: Properties.cpp:681
static bool split(const std::string &str, const char delim, std::vector< std::string > &value)
Split the string.
Definition: Properties.cpp:621
Properties * hasKey(const char *key) const
Check whether key exists in the children.
Definition: Properties.cpp:517
void list(std::ostream &out)
Prints this property list out to the specified output stream.
Definition: Properties.cpp:322
Properties * root
Definition: Properties.h:1286
std::string default_value
Definition: Properties.h:1285
void eraseTailBlank(std::string &str)
Erase the tail blank characters of string.
Definition: stringutil.cpp:275
void setDefaults(const char *defaults[], long num=LONG_MAX)
Set a default value together in the property list.
Definition: Properties.cpp:295
const std::string m_empty
Definition: Properties.h:1288
list index
Definition: rtimages.py:10
virtual ~Properties(void)
Destructor.
Definition: Properties.cpp:134
std::string setProperty(const std::string &key, const std::string &value)
Set a value associated with key in the property list.
Definition: Properties.cpp:236
bool createNode(const std::string &key)
Create newly node of Properties.
Definition: Properties.cpp:474
Properties * removeNode(const char *leaf_name)
Remove node of Properties.
Definition: Properties.cpp:493
Properties *const findNode(const std::string &key) const
Get node of properties.
Definition: Properties.cpp:439
void load(std::istream &inStream)
Loads property list that consists of key:value from input stream.
Definition: Properties.cpp:334
prop
Organization::get_organization_property ();.
static std::ostream & _dump(std::ostream &out, const Properties &curr, int index)
Save property&#39;s contents.
Definition: Properties.cpp:748
static void _store(std::ostream &out, std::string curr_name, Properties *curr)
Store the property name list.
Definition: Properties.cpp:710
std::vector< Properties * > leaf
Definition: Properties.h:1287
Properties & operator=(const Properties &prop)
Assignment operator.
Definition: Properties.cpp:105
int getlinePortable(std::istream &istr, std::string &line)
Read a line from input stream.
Definition: stringutil.cpp:94
int size(void) const
Get the number of Properties.
Definition: Properties.cpp:427
const std::string & operator[](const std::string &key) const
Search for the property with the specified key in property list.
Definition: Properties.cpp:190
bool isEscaped(const std::string &str, std::string::size_type pos)
Check whether the character is escaped or not.
Definition: stringutil.cpp:129
std::string value
Definition: Properties.h:1284
std::vector< std::string > propertyNames(void) const
Return an vector of all the keys in this property.
Definition: Properties.cpp:410
Properties & getNode(const std::string &key)
Get node of properties.
Definition: Properties.cpp:455
void save(std::ostream &out, const std::string &header)
Save the property list to the specified stream.
Definition: Properties.cpp:381
std::string name
Definition: Properties.h:1283
const std::string & getDefault(const std::string &key) const
Get the default values with specified key.
Definition: Properties.cpp:217
std::string unescape(const std::string str)
Unescape string.
Definition: stringutil.cpp:225
std::string escape(const std::string str)
Escape string.
Definition: stringutil.cpp:169
Properties & operator<<(const Properties &prop)
Merge properties.
Definition: Properties.cpp:550
static Properties * _getNode(std::vector< std::string > &keys, std::vector< Properties * >::size_type index, const Properties *curr)
Get properties.
Definition: Properties.cpp:651
const std::string & getProperty(const std::string &key) const
Search for the property with the specified key in this property.
Definition: Properties.cpp:156
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:266
Common Object Interface Layer.


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Thu Jun 6 2019 19:25:59