libabigail
abg-ini.cc
Go to the documentation of this file.
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2013-2023 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// This file contains the definitions for the ini file reader used in
11 /// the libabigail library.
12 
13 #include <cassert>
14 #include <cstdlib>
15 #include <utility>
16 #include <memory>
17 #include <fstream>
18 #include <sstream>
19 
20 #include "abg-fwd.h"
21 #include "abg-internal.h"
22 // <headers defining libabigail's API go under here>
23 ABG_BEGIN_EXPORT_DECLARATIONS
24 
25 #include "abg-ini.h"
26 
27 ABG_END_EXPORT_DECLARATIONS
28 // </headers defining libabigail's API>
29 
30 namespace abigail
31 {
32 namespace ini
33 {
34 
35 using std::istream;
36 using std::pair;
37 
38 static bool
39 char_is_white_space(int b);
40 
41 static bool
42 char_is_comment_start(int b);
43 
44 /// Test if a given character is a delimiter.
45 ///
46 ///
47 ///@param b the value of the character to test for.
48 ///
49 ///@param include_white_space if true, consider white spaces as a
50 ///delimiter.
51 ///
52 ///@param include_square_bracket if true, consider square brackets as
53 /// delimiters
54 ///
55 /// @param include_equal if true, consider the equal character ('=')
56 /// as a delimiter.
57 ///
58 /// @return true iff @p b is a delimiter.
59 static bool
60 char_is_delimiter(int b, bool include_white_space = true,
61  bool include_square_bracket = true,
62  bool include_equal = true)
63 {
64  return ((include_square_bracket && (b == '['))
65  || (include_square_bracket && (b == ']'))
66  || b == '{'
67  || b == '}'
68  || (include_equal && (b == '='))
69  || b == ','
70  || (include_white_space && char_is_white_space(b))
71  || char_is_comment_start(b));
72 }
73 
74 /// Return true iff a given character can be part of a property
75 /// value.
76 ///
77 /// Note that white spaces, square brackets and the equal character can be
78 /// part of a property value. The reason why we accept the equal
79 /// character is because it can appear in an URL.
80 ///
81 /// @param b the character to test against.
82 ///
83 /// @return true iff @p b is a character that can be part of a
84 /// property value.
85 static bool
86 char_is_property_value_char(int b)
87 {
88  if (char_is_delimiter(b, /*include_white_space=*/false,
89  /*include_square_bracket=*/false,
90  /*include_equal=*/false)
91  || b == '\n')
92  return false;
93  return true;
94 }
95 
96 /// Test if a given character is meant to be part of a section name.
97 ///
98 /// @param b the character to test against.
99 ///
100 /// @return true iff @p b is a character that is meant to be part of
101 /// a section name.
102 static bool
103 char_is_section_name_char(int b)
104 {
105  if (b == '[' || b == ']' || b == '\n' || char_is_comment_start(b))
106  return false;
107  return true;
108 }
109 
110 /// Test if a given character is meant to be part of a property name.
111 ///
112 /// @param b the character to test against.
113 ///
114 /// @return true iff @p b is a character that is meant to be part of
115 /// a section name.
116 static bool
117 char_is_property_name_char(int b)
118 {
119  if (char_is_delimiter(b))
120  return false;
121  return true;
122 }
123 
124 /// Test if a given character is meant to be part of a function name.
125 ///
126 /// @param b the character to test against.
127 ///
128 /// @return true iff @p b is a character that is meant to be part of a
129 /// function name.
130 static bool
131 char_is_function_name_char(int b)
132 {
133  if (char_is_delimiter(b) || b == '(' || b == ')')
134  return false;
135  return true;
136 }
137 
138 /// Test if a given character is meant to be part of a function
139 /// argument.
140 ///
141 /// @param b the character to test against.
142 ///
143 /// @return true iff @p b is a character that is meant to be part of a
144 /// function argument.
145 static bool
146 char_is_function_argument_char(int b)
147 {
148  if (b == '(' || b == ')')
149  return false;
150  return true;
151 }
152 
153 /// Test if a given character is meant to be the start of a comment.
154 ///
155 /// @param b the character to test against.
156 ///
157 /// @return true iff @p b is the start of a comment.
158 static bool
159 char_is_comment_start(int b)
160 {return b == ';' || b == '#';}
161 
162 /// Test if a character is meant to be a white space.
163 ///
164 /// @param b the character to test against.
165 ///
166 /// @return true iff @p b is a white space.
167 static bool
168 char_is_white_space(int b)
169 {return b == ' ' || b == '\t' || b == '\n';}
170 
171 /// Remove the spaces at the begining and at the end of a given string.
172 ///
173 /// @param str the string to remove leading and trailing white spaces from.
174 ///
175 /// @return the string resulting from the removal of white space from @p str.
176 static string
177 trim_white_space(const string& str)
178 {
179  if (str.empty())
180  return str;
181 
182  unsigned s = 0, e = str.size() -1;
183 
184  for (; s <= e; ++s)
185  if (!char_is_white_space(str[s]))
186  break;
187 
188  for (; e > s; --e)
189  if (!char_is_white_space(str[e]))
190  break;
191 
192  return str.substr(s, e - s + 1);
193 }
194 
195 // <property stuff>
196 
197 /// Private data of @ref property type.
198 struct property::priv
199 {
200  string name_;
201 
202  priv()
203  {}
204 
205  priv(const string& name)
206  : name_(name)
207  {}
208 }; // end struct property::priv
209 
210 /// Constructor of @ref property.
212  : priv_(new priv)
213 {}
214 
215 /// Constructor of @ref property
216 ///
217 /// @param name the name of the property.
218 property::property(const string& name)
219  : priv_(new priv(name))
220 {}
221 
222 /// Getter of the name of the property.
223 ///
224 /// @return the name of the property.
225 const string&
227 {return priv_->name_;}
228 
229 /// Setter of the name of the property.
230 ///
231 /// @param name the new name of the property.
232 void
233 property::set_name(const string& name)
234 {priv_->name_ = name;}
235 
236 /// Destructor of the property.
238 {}
239 // </property stuff>
240 
241 // <property_value stuff>
242 
243 /// Private data for the @ref property_value type.
244 struct property_value::priv
245 {
246  enum property_value::value_kind kind_;
247 
248  priv(property_value::value_kind kind = ABSTRACT_PROPERTY_VALUE)
249  : kind_(kind)
250  {}
251 }; // property_value::priv
252 
253 /// Default constructor for the @ref property_value type.
254 ///
255 /// @param kind the of @ref property_value that is being constructed.
257  : priv_(new priv(ABSTRACT_PROPERTY_VALUE))
258 {}
259 
260 /// Constructor for the @ref property_value type.
261 ///
262 /// @param kind the of @ref property_value that is being constructed.
264  : priv_(new priv(kind))
265 {}
266 
267 /// Getter for the kind of the @ref property_value type.
268 ///
269 /// @return the kind of @ref property_value we are looking at.
270 property_value::value_kind
272 {return priv_->kind_;}
273 
274 /// Converts the current property value to a string.
275 ///
276 /// @return the string representation of the property value.
277 property_value::operator const string& () const
278 {return as_string();}
279 
280 /// Destructor for the @ref proprerty_value type.
282 {}
283 // </property_value stuff>
284 
285 // <string_property stuff>
286 
287 /// The private data for the @ref string_property_value type.
288 struct string_property_value::priv
289 {
290  string content_;
291 
292  priv()
293  {}
294 
295  priv(const string& c)
296  : content_(c)
297  {}
298 }; // end struct string_property::priv
299 
300 /// Constructor of the @ref string_property_value type.
302  : property_value(STRING_PROPERTY_VALUE),
303  priv_(new priv())
304 {}
305 
306 /// Constructor of the @ref string_property_value.
307 ///
308 /// @param content the string content of the property value.
310  : property_value(STRING_PROPERTY_VALUE),
311  priv_(new priv(content))
312 {}
313 
314 /// Setter of the content of the string property value.
315 ///
316 /// @param c the new content.
317 void
319 {priv_->content_ = c;}
320 
321 /// Convert the string property value into a string.
322 ///
323 /// @return the string contained in the string property value.
324 const string&
326 {return priv_->content_;}
327 
328 /// Conversion operator to a string, for the @ref
329 /// string_property_value type.
330 ///
331 /// @return the string representing this string_property_value.
332 string_property_value::operator string() const
333 {return as_string();}
334 
335 /// Test if a given property value is a string property value.
336 ///
337 /// @return a pointer to the @ref string_property_value sub-object of
338 /// the @ref property_value instance, if it's an instance of @ref
339 /// string_property_value too.
342 {return dynamic_cast<string_property_value*>(const_cast<property_value*>(v));}
343 
344 /// Test if a given property value is a string property value.
345 ///
346 /// @return a pointer to the @ref string_property_value sub-object of
347 /// the @ref property_value instance, if it's an instance of @ref
348 /// string_property_value too.
351 {return dynamic_pointer_cast<string_property_value>(v);}
352 
353 /// Destructor for the @ref string_property_value
355 {}
356 
357 // </string_property_value stuff>
358 
359 // <list_property_value stuff>
360 struct list_property_value::priv
361 {
362  vector<string> values_;
363  string representation_;
364 
365  priv()
366  {}
367 
368  priv(const vector<string>& vals)
369  : values_(vals)
370  {}
371 }; // end struct list_property_value::priv
372 
373 /// Default constructor of the @ref list_property_value type.
375  : property_value(property_value::LIST_PROPERTY_VALUE),
376  priv_(new priv)
377 {}
378 
379 /// Copy constructor of the @ref list_property_value type.
380 ///
381 /// @param values the instance of @ref list_property_value to copy from.
382 list_property_value::list_property_value(const vector<string>& values)
383  : property_value(property_value::LIST_PROPERTY_VALUE),
384  priv_(new priv(values))
385 {
386 }
387 
388 /// Getter of the content of the @ref list_property_value.
389 ///
390 /// The content of the @ref list_property_value is a vector of
391 /// strings.
392 ///
393 /// @return the vector of strings contained in the @ref
394 /// list_property_value.
395 const vector<string>&
397 {return priv_->values_;}
398 
399 /// Setter of the content of the @ref list_property_value.
400 ///
401 /// @param values the new content, which is a vector of strings.
402 void
403 list_property_value::set_content(const vector<string>& values)
404 {
405  priv_->values_ = values;
406  priv_->representation_.clear();
407 }
408 
409 /// Return a string representation of the @list_property_value.
410 ///
411 /// @return the string representation.
412 const string&
414 {
415  if (priv_->representation_.empty())
416  {
417  for (vector<string>::const_iterator i = priv_->values_.begin();
418  i != priv_->values_.end();
419  ++i)
420  {
421  if (i != priv_->values_.begin())
422  priv_->representation_ += ",";
423  priv_->representation_ += *i;
424  }
425  }
426  return priv_->representation_;
427 }
428 
429 /// Test if an instance of @property_value is a @ref list_property_value.
430 ///
431 /// @param v the property_value to consider.
432 ///
433 /// @return the @ref property_value converted into a @ref
434 /// list_property_value if the @p v is a @ref list_property_value, nil
435 /// otherwise.
438 {return dynamic_cast<list_property_value*>(const_cast<property_value*>(v));}
439 
440 /// Test if an instance of @property_value is a @ref list_property_value.
441 ///
442 /// @param v the property_value to consider.
443 ///
444 /// @return the @ref property_value converted into a @ref
445 /// list_property_value if the @p v is a @ref list_property_value, nil
446 /// otherwise.
449 {return dynamic_pointer_cast<list_property_value>(v);}
450 
451 // </list_property_value stuff>
452 
453 // <tuple_property_value>
454 
455 /// The private data of the @ref tuple_property_value type.
456 struct tuple_property_value::priv
457 {
458  vector<property_value_sptr> value_items_;
459  string string_rep_;
460 
461  priv()
462  {}
463 
464  priv(const vector<property_value_sptr>& value_items)
465  : value_items_(value_items)
466  {}
467 }; // end struct tuple_property_value::priv
468 
469 /// Constructor for the @ref tuple_property_value type.
470 ///
471 /// @param v the tuple content of the value.
472 tuple_property_value::tuple_property_value(const vector<property_value_sptr>& v)
473  : property_value(TUPLE_PROPERTY_VALUE),
474  priv_(new priv(v))
475 {}
476 
477 /// Getter for the content of the @ref tuple_property_value instance.
478 ///
479 /// @return the content of the @ref tuple_property_value instance.
480 const vector<property_value_sptr>&
482 {return priv_->value_items_;}
483 
484 /// Getter for the content of the @ref tuple_property_value instance.
485 ///
486 /// @return the content of the @ref tuple_property_value instance.
487 vector<property_value_sptr>&
489 {return priv_->value_items_;}
490 
491 /// Destructor of the @ref tuple_property_value type.
493 {}
494 
495 /// Convert to the instance of @ref tuple_property_value to a string.
496 ///
497 /// @return the string representation of the @ref tuple_property_value.
498 const string&
500 {
501  if (priv_->string_rep_.empty())
502  {
503  priv_->string_rep_ += '{';
504  for (vector<property_value_sptr>::const_iterator i =
505  get_value_items().begin();
506  i != get_value_items().end();
507  ++i)
508  {
509  if (i != get_value_items().begin())
510  priv_->string_rep_ += ",";
511  priv_->string_rep_ += (*i)->as_string();
512  }
513  priv_->string_rep_ += '}';
514  }
515  return priv_->string_rep_;
516 }
517 
518 /// Test if a given instance of @ref property_value is an instance of
519 /// @ref tuple_property_value too.
520 ///
521 /// @return the @ref tuple_property_value sub-object of the @ref
522 /// property_value instance, if it's an instance of @ref
523 /// tuple_property_value too.
526 {return dynamic_cast<tuple_property_value*>(const_cast<property_value*>(v));}
527 
528 /// Test if a given instance of @ref property_value is an instance of
529 /// @ref tuple_property_value too.
530 ///
531 /// @return the @ref tuple_property_value sub-object of the @ref
532 /// property_value instance, if it's an instance of @ref
533 /// tuple_property_value too.
536 {return dynamic_pointer_cast<tuple_property_value>(v);}
537 
538 // </tuple_property_value>
539 
540 // <simple_property stuff>
541 
542 /// Private data of the @ref simple_property type.
543 struct simple_property::priv
544 {
546 
547  priv()
548  {}
549 
550  priv(const string_property_value_sptr value)
551  : value_(value)
552  {}
553 }; // end struct simple_property::priv
554 
555 /// Default constructor of the @ref simple_property type.
557  : property(),
558  priv_(new priv)
559 {}
560 
561 /// Constructor for the @ref simple_property type.
562 ///
563 /// @param name the name of the property.
564 ///
565 /// @param value the value of the property.
567  const string_property_value_sptr& value)
568  : property(name),
569  priv_(new priv(value))
570 {}
571 
572 /// Constructor for the @ref simple_property type.
573 ///
574 /// This one constructs a property with an empty value.
575 ///
576 /// @param name the name of the property.
578  : property(name),
579  priv_(new priv)
580 {}
581 
582 /// Getter for the string value of the property.
583 ///
584 /// @return the string value of the property.
587 {return priv_->value_;}
588 
589 /// Setter for the string value of the property.
590 ///
591 /// @param value the new string value of the property.
592 void
594 {priv_->value_ = value;}
595 
596 /// Test if the property has an empty value.
597 ///
598 /// An empty value is either no value at all or an empty string value.
599 ///
600 /// @return true iff the property has an empty value.
601 bool
603 {
604  if (!priv_->value_)
605  return true;
606  return priv_->value_->as_string().empty();
607 }
608 
609 /// Destructor of the @ref simple_property type.
611 {}
612 
613 /// Tests if a @ref property is a simple property.
614 ///
615 /// @return a pointer to the @ref simple_property sub-object of the
616 /// @ref property instance, iff it's an @ref simple_property
617 /// instance.
620 {return dynamic_cast<simple_property*>(const_cast<property*>(p));}
621 
622 /// Tests if a @ref property is a simple property.
623 ///
624 /// @return a smart pointer to the @ref simple_property sub-object of
625 /// the @ref property instance, iff it's an @ref simple_property
626 /// instance.
629 {return dynamic_pointer_cast<simple_property>(p);}
630 
631 // </simple_property stuff>
632 
633 // <list_property stuff>
634 struct list_property::priv
635 {
637 
638  priv()
639  {}
640 
641  priv(const list_property_value_sptr value)
642  : value_(value)
643  {}
644 }; //end struct list_property
645 
646 /// Default constructor for @ref list_property.
648  : priv_(new priv)
649 {}
650 
651 /// Constructor for @ref list_property.
652 ///
653 /// @param name the name of the property.
654 ///
655 /// @param value the value of the property.
656 list_property::list_property(const string& name,
657  const list_property_value_sptr& value)
658  : property(name),
659  priv_(new priv(value))
660 {}
661 
662 /// Getter for the value of the @ref list_property_value
665 {return priv_->value_;}
666 
667 /// Setter for the value of the @ref list_property.
668 ///
669 /// @param value the new value.
670 void
672 {priv_->value_ = value;}
673 
674 /// Destructor of the @ref list_property type.
676 {}
677 
678 /// Test if an instance of a @ref property is actually an instance of
679 /// @ref list_property.
680 ///
681 /// @param p the @ref property to test.
682 ///
683 /// @return the @p p converted into a @ref list_property if it's of
684 /// type @ref list_property, or nil otherwise.
687 {return dynamic_cast<list_property*>(const_cast<property*>(p));}
688 
689 /// Test if an instance of a @ref property is actually an instance of
690 /// @ref list_property.
691 ///
692 /// @param p the @ref property to test.
693 ///
694 /// @return the @p p converted into a @ref list_property if it's of
695 /// type @ref list_property, or nil otherwise.
698 {return dynamic_pointer_cast<list_property>(p);}
699 // </list_property stuff>
700 
701 // <tuple_property stuff>
702 struct tuple_property::priv
703 {
705 
706  priv()
707  {}
708 
709  priv(const tuple_property_value_sptr value)
710  : value_(value)
711  {}
712 }; // end struct tuple_property::priv
713 
714 /// Default constructor of the @ref tuple_property type.
716  : property(),
717  priv_(new priv)
718 {}
719 
720 /// Constructor of the @ref tuple_property type.
721 ///
722 /// @param name the name of the property.
723 ///
724 /// @param values the tuple value of the property.
726  const tuple_property_value_sptr value)
727  : property(name),
728  priv_(new priv(value))
729 {}
730 
731 /// Setter for the tuple value of the property.
732 ///
733 /// @param values the new tuple value of the property.
734 void
736 {priv_->value_ = value;}
737 
738 /// Getter for the tuple value of the property.
739 ///
740 /// @return the tuple value of the property.
743 {return priv_->value_;}
744 
745 /// Destructor for the @ref tuple_property type.
747 {}
748 
749 /// Test if an instance of @ref property is an instance of @ref
750 /// tuple_property.
751 ///
752 /// @param p the instance of @ref property to test for.
753 ///
754 /// @return return a pointer to the sub-object of @ref tuple_property
755 /// iff @p p is an instance of @ref tuple_property.
758 {return dynamic_cast<tuple_property*>(const_cast<property*>(p));}
759 
760 /// Test if an instance of @ref property is an instance of @ref
761 /// tuple_property.
762 ///
763 /// @param p the instance of @ref property to test for.
764 ///
765 /// @return return a smart pointer to the sub-object of @ref
766 /// tuple_property iff @p p is an instance of @ref tuple_property.
769 {return dynamic_pointer_cast<tuple_property>(p);}
770 
771 // </tuple_property stuff>
772 
773 class config::section::priv
774 {
775  string name_;
776  properties_type properties_;
777 
778  // Forbid this;
779  priv();
780 
781 public:
782  priv(const string& name)
783  : name_(name)
784  {}
785 
786  friend class config::section;
787 };//end struct config::section::priv
788 
789 // <config::section stuff>
790 
791 /// Constructor for config::section.
792 ///
793 /// @param name the name of the ini section.
794 config::section::section(const string& name)
795  : priv_(new priv(name))
796 {}
797 
798 /// Constructor for the config::section.
799 ///
800 /// @param name the name of the ini section.
801 ///
802 /// @param properties the properties of the section.
803 config::section::section(const string& name,
804  const properties_type& properties)
805  : priv_(new priv(name))
806 {set_properties(properties);}
807 
808 /// Get the name of the section.
809 ///
810 /// @return the name of the section.
811 const string&
813 {return priv_->name_;}
814 
815 /// Get the properties of the section.
816 ///
817 /// @return a vector of the properties of the section.
820 {return priv_->properties_;}
821 
822 /// Set the properties of the section.
823 ///
824 /// @param properties the new properties to set.
825 void
827 {priv_->properties_ = properties;}
828 
829 /// Add one property to this section.
830 ///
831 /// @param prop the property to add to the section.
832 void
834 {priv_->properties_.push_back(prop);}
835 
836 /// Find a property that has a given name.
837 ///
838 /// Note that this only returns the first property with that name.
839 ///
840 /// @param prop_name the name of the property to find.
841 ///
842 /// @return the found property, or nil if no property with the name @p
843 /// prop_name was found.
845 config::section::find_property(const string& prop_name) const
846 {
847  for (properties_type::const_iterator i = get_properties().begin();
848  i != get_properties().end();
849  ++i)
850  if ((*i)->get_name() == prop_name)
851  return *i;
852  return property_sptr();
853 }
854 
855 /// Destructor of config::section.
857 {}
858 // /<config::section stuff>
859 
860 // <read_context stuff>
861 
862 /// The context of the ini file parsing.
863 ///
864 /// This is a private type that is used only in the internals of the
865 /// ini file parsing.
866 class read_context
867 {
868  /// The input stream we are parsing from.
869  istream& in_;
870  /// The current line being parsed.
871  unsigned cur_line_;
872  /// The current column on the current line.
873  unsigned cur_column_;
874  vector<char> buf_;
875 
876  // Forbid this;
877  read_context();
878 
879 public:
880 
881  /// The constructor of @ref read_context.
882  ///
883  /// @param in the input stream to parse from.
884  read_context(istream& in)
885  : in_(in),
886  cur_line_(0),
887  cur_column_(0)
888  {}
889 
890  /// @return the character that is going to be read by the next
891  /// invocation of read_next_char().
892  ///
893  /// Note that this function doesn't alter the input stream.
894  ///
895  /// Also note that this function handles escaping using the '\'
896  /// (backslash) character.
897  ///
898  /// @param escaped This is an output parameter. It's set to true by
899  /// this function if it escaped the peeked character. Otherwise,
900  /// it's set to false.
901  ///
902  /// @return peeked character.
903  char
904  peek(bool& escaped)
905  {
906  if (!buf_.empty())
907  return buf_.back();
908 
909  escaped = false;
910  char c = in_.peek();
911  if (handle_escape(c, /*peek=*/true))
912  {
913  put_back(c);
914  escaped = true;
915  }
916  return c;
917  }
918 
919  /// @return the character that is going to be read by the next
920  /// invocation of read_next_char().
921  ///
922  /// Note that this function doesn't alter the input stream.
923  ///
924  /// Also note that this function handles escaping using the '\'
925  /// (backslash) character.
926  ///
927  /// @return peeked character.
928  char
929  peek()
930  {
931  bool escaped = false;
932  return peek(escaped);
933  }
934 
935  /// Get the next character of the input stream.
936  ///
937  /// This function knows how to handles escaped characters from the
938  /// input stream.
939  ///
940  /// @param do_handle_escape if yes, this function handles escaped
941  /// characters from the input stream.
942  ///
943  /// @return the next character of the input stream.
944  char
945  get(bool do_handle_escape = true)
946  {
947  char result = 0;
948  if (!buf_.empty())
949  {
950  result = buf_.back();
951  buf_.pop_back();
952  }
953  else
954  {
955  result = in_.get();
956  if (do_handle_escape)
957  handle_escape(result);
958  }
959  return result;
960  }
961 
962  /// Put a character that was read from the input stream, back into
963  /// that input stream, so that a subsequent call to
964  /// read_context::get() returns that same character.
965  ///
966  /// @param c the character to put back into the stream.
967  void
968  put_back(char c)
969  {buf_.push_back(c);}
970 
971  /// Test if the status of the input stream is good.
972  ///
973  /// @return true iff the status of the input stream is good.
974  bool
975  good() const
976  {
977  if (!buf_.empty())
978  return true;
979  return in_.good();
980  }
981 
982  /// Tests if the input stream has reached end of file.
983  ///
984  /// @return true iff the input stream has reached end of file.
985  bool
986  eof() const
987  {
988  if (!buf_.empty())
989  return false;
990  return in_.eof();
991  }
992 
993  /// Handles the escaping of a character.
994  ///
995  /// This function must be called whenever the low level character
996  /// reading function encountered a backslash character ('\'). In
997  /// that case, this function reads the subsequent characters from
998  /// the input stream, sees if it needs to escape them and then
999  /// handles the escaping if need be. Otherwise, it does nothing.
1000  ///
1001  /// This is a subroutine of the read_context::get() and
1002  /// read_context::peek() functions.
1003  ///
1004  /// @param peek if true, it means this function was called after the
1005  /// caller issued a read_context::peek() call, rather than a
1006  /// read_context::get() call.
1007  ///
1008  /// @return true if an escaping took place.
1009  bool
1010  handle_escape(char& c, bool peek = false)
1011  {
1012  bool escaped = false;
1013  char b = c;
1014 
1015  if (b == '\\')
1016  {
1017  escaped = true;
1018  b = get(/*escape=*/false);
1019  if (!good())
1020  return escaped;
1021  if (peek)
1022  {
1023  ABG_ASSERT(b == c);
1024  b = get(/*escape=*/false);
1025  if (!good())
1026  return escaped;
1027  }
1028 
1029  switch (b)
1030  {
1031  case '0':
1032  case 'a':
1033  case 'b':
1034  case 'r':
1035  // let's replace this by a space
1036  c = ' ';
1037  break;
1038  case 't':
1039  c = '\t';
1040  break;
1041  case '\n':
1042  // continuation line. So we should drop both the backslash
1043  // character and this end-of-line character on the floor
1044  // just like if they never existed.
1045  ++cur_column_;
1046  b = get(/*escape=*/false);
1047  if (!good())
1048  return escaped;
1049  c = b;
1050  break;
1051  case '\\':
1052  case ';':
1053  case '#':
1054  case '[':
1055  case ']':
1056  default:
1057  c = b;
1058  break;
1059  }
1060  }
1061  else
1062  c = b;
1063 
1064  return escaped;
1065  }
1066 
1067  /// Read the next character from the input stream.
1068  ///
1069  /// This method updates the current line/column number after looking
1070  /// at the actual char that got read. Note that escaped characters
1071  /// are handled transparently at this point.
1072  ///
1073  /// @param c output parameter. This is set by this function to the
1074  /// character that was read. It's set iff the function returned
1075  /// true.
1076  ///
1077  /// @return true if the reading went well and if the input stream is
1078  /// in a non-erratic state.
1079  bool
1080  read_next_char(char& c)
1081  {
1082  char b = get();
1083  if (!good())
1084  return false;
1085 
1086  c = b;
1087 
1088  if (cur_line_ == 0)
1089  cur_line_ = 1;
1090 
1091  if (b == '\n')
1092  {
1093  ++cur_line_;
1094  cur_column_ = 0;
1095  }
1096  else
1097  ++cur_column_;
1098 
1099  return true;
1100  }
1101 
1102  /// Skip (that is, read characters and drop them on the floor) all
1103  /// the characters up to the next line.
1104  ///
1105  /// Note that the new line character (\n' on unices) is skipped as
1106  /// well.
1107  ///
1108  /// @return true iff the skipping proceeded successfully and that
1109  /// the input stream is left in a non-erratic state.
1110  bool
1111  skip_line()
1112  {
1113  char c = 0;
1114  for (bool is_ok = read_next_char(c);
1115  is_ok;
1116  is_ok = read_next_char(c))
1117  if (c == '\n')
1118  break;
1119 
1120  return (c == '\n' || eof());
1121  }
1122 
1123  /// If the current character is a white space, skip it and all the
1124  /// contiguous ones that follow.
1125  ///
1126  /// @return true iff the input stream is left in a non-erratic state.
1127  bool
1128  skip_white_spaces()
1129  {
1130  for (char c = peek(); good(); c = peek())
1131  if (char_is_white_space(c))
1132  ABG_ASSERT(read_next_char(c));
1133  else
1134  break;
1135  return good() || eof();
1136  }
1137 
1138  /// If the current character is the beginning of a comment, skip
1139  /// (read and drop on the floor) the entire remaining line,
1140  /// including the current character.
1141  ///
1142  /// @return true if the input stream is left in a non-erratic state.
1143  bool
1144  skip_comments()
1145  {
1146  for (char c = peek(); good(); c = peek())
1147  if (char_is_comment_start(c))
1148  skip_line();
1149  else
1150  break;
1151  return good() || eof();
1152  }
1153 
1154  /// If the current character is either the beginning of a comment or
1155  /// a white space, skip the entire commented line or the subsequent
1156  /// contiguous white spaces.
1157  ///
1158  /// @return true iff the stream is left in a non-erratic state.
1159  bool
1160  skip_white_spaces_or_comments()
1161  {
1162  int b = 0;
1163  while (good())
1164  {
1165  b = peek();
1166  if (char_is_white_space(b))
1167  skip_white_spaces();
1168  else if (char_is_comment_start(b))
1169  skip_comments();
1170  else
1171  break;
1172  }
1173  return good() || eof();
1174  }
1175 
1176  /// Read a property name.
1177  ///
1178  /// @param name out parameter. Is set to the parsed property name,
1179  /// if any. Note that this is set only if the function returned
1180  /// true.
1181  ///
1182  /// @return true iff the input stream is left in a non-erratic
1183  /// state.
1184  bool
1185  read_property_name(string& name)
1186  {
1187  char c = peek();
1188  if (!good() || !char_is_property_name_char(c))
1189  return false;
1190 
1191  ABG_ASSERT(read_next_char(c));
1192  name += c;
1193 
1194  for (c = peek(); good(); c = peek())
1195  {
1196  if (!char_is_property_name_char(c))
1197  break;
1198  ABG_ASSERT(read_next_char(c));
1199  name += c;
1200  }
1201 
1202  return true;
1203  }
1204 
1205  /// Read a function name.
1206  ///
1207  /// @param name the name of the function. This is an output
1208  /// parameter when this puts the function name that was read, iff
1209  /// this function returns true.
1210  ///
1211  /// @return true iff the function name was successfully read into @p
1212  /// name.
1213  bool
1214  read_function_name(string& name)
1215  {
1216  char c = peek();
1217  if (!good() || !char_is_function_name_char(c))
1218  return false;
1219 
1220  ABG_ASSERT(read_next_char(c));
1221  name += c;
1222 
1223  for (c = peek(); good(); c = peek())
1224  {
1225  if (!char_is_function_name_char(c))
1226  break;
1227  ABG_ASSERT(read_next_char(c));
1228  name += c;
1229  }
1230 
1231  return true;
1232  }
1233 
1234  /// Read a function argument.
1235  ///
1236  /// @param argument the argument of the function that was just
1237  /// read. This is an ouput parameter that is set iff the function
1238  /// returns true.
1239  ///
1240  /// @return true iff parameter @p argument was successful set.
1241  bool
1242  read_function_argument(string& argument)
1243  {
1244  char c = peek();
1245  if (!good() || !char_is_function_argument_char(c))
1246  return false;
1247 
1248  ABG_ASSERT(read_next_char(c));
1249  argument += c;
1250 
1251  for (c = peek(); good(); c = peek())
1252  {
1253  if (!char_is_function_argument_char(c))
1254  break;
1255  ABG_ASSERT(read_next_char(c));
1256  argument += c;
1257  }
1258 
1259  return true;
1260  }
1261 
1262  /// Read a function call expression.
1263  ///
1264  /// The expression this function can read has the form:
1265  /// 'foo(bar,baz, blah)'
1266  ///
1267  /// @param expr this is an output parameter that is set with the
1268  /// resulting function call expression that was read, iff this
1269  /// function returns true.
1270  ///
1271  /// @param return true iff @p expr was successful set with the
1272  /// function call expression that was read.
1273  bool
1275  {
1276  if (!good())
1277  return false;
1278 
1279  skip_white_spaces_or_comments();
1280  if (!good())
1281  return false;
1282 
1283  string name;
1284  if (!read_function_name(name) || name.empty())
1285  return false;
1286 
1287  skip_white_spaces_or_comments();
1288 
1289  int b = peek();
1290  if (!good() || b != '(')
1291  return false;
1292 
1293  char c = 0;
1294  if (!read_next_char(c))
1295  return false;
1296  ABG_ASSERT(c == '(');
1297 
1298  skip_white_spaces_or_comments();
1299  if (!good())
1300  return false;
1301 
1302  // Read function call arguments.
1303  vector<string> arguments;
1304  for (;;)
1305  {
1306  if (peek() == ')')
1307  break;
1308 
1309  string arg;
1310  if (!read_function_argument(arg))
1311  return true;
1312 
1313  skip_white_spaces_or_comments();
1314  if (!good())
1315  return false;
1316 
1317  if (peek() == ',')
1318  {
1319  c = 0;
1320  ABG_ASSERT(read_next_char(c) && c == ',');
1321  skip_white_spaces_or_comments();
1322  if (!good())
1323  return false;
1324  }
1325 
1326  arguments.push_back(arg);
1327  }
1328 
1329  c = 0;
1330  ABG_ASSERT(read_next_char(c) && c == ')');
1331 
1332  expr.reset(new function_call_expr(name, arguments));
1333  return true;
1334  }
1335 
1336  /// Read a property value.
1337  ///
1338  /// @return the property value read.
1340  read_property_value()
1341  {
1342  property_value_sptr nil, result;
1343 
1344  int b = peek();
1345  if (!good())
1346  return nil;
1347 
1348  if (b == '{')
1349  {
1350  if (tuple_property_value_sptr t = read_tuple_property_value())
1351  return t;
1352  return nil;
1353  }
1354 
1355  list_property_value_sptr list = read_list_property_value();
1356  if (list && list->get_content().size() == 1)
1357  result.reset(new string_property_value(list->get_content()[0]));
1358  else
1359  result = list;
1360 
1361  return result;
1362  }
1363 
1364  /// Reads a string from the input stream.
1365  ///
1366  /// A string is just a contiguous set of characters that test
1367  /// positive when passed to
1368  /// read_context::char_is_property_value_char().
1369  ///
1370  /// Note that all escaped characters are suitable to be in a string.
1371  ///
1372  /// @return the string read.
1373  string
1374  read_string()
1375  {
1376  bool escaped = false;
1377  int b = peek(escaped);
1378  if (!good())
1379  return "";
1380 
1381  if (!escaped && char_is_delimiter(b, /*include_white_space=*/false))
1382  // Empty property value. This is accepted.
1383  return "";
1384 
1385  string v;
1386  for (b = peek(escaped); good(); b = peek(escaped))
1387  {
1388  // If the current character is not suitable to be a in string,
1389  // then we reached the end of the string. Note that espaced
1390  // characters are always suitable to be a string.
1391  if (!escaped && !char_is_property_value_char(b))
1392  break;
1393  char c = 0;
1394  ABG_ASSERT(read_next_char(c));
1395  v += c;
1396  }
1397  return trim_white_space(v);
1398  }
1399 
1400  /// Read a string property value.
1401  ///
1402  /// @return the property value that has been parsed.
1404  read_string_property_value()
1405  {
1406  string_property_value_sptr nil, result;
1407  if (!good())
1408  return nil;
1409 
1410  string value = read_string();
1411  result.reset(new string_property_value(value));
1412  return result;
1413  }
1414 
1415  /// Read a @ref list_property_value.
1416  ///
1417  /// @return the instance of @ref list_property_value read, or nil if
1418  /// none was read.
1420  read_list_property_value()
1421  {
1422  list_property_value_sptr nil, result;
1423  string str;
1424  vector<string> content;
1425 
1426  for (;;)
1427  {
1428  str = read_string();
1429  if (str.empty())
1430  break;
1431  content.push_back(str);
1432 
1433  skip_white_spaces();
1434 
1435  int b = peek();
1436  if (!good() || b != ',')
1437  break;
1438  skip_white_spaces();
1439 
1440  char c = 0;
1441  read_next_char(c);
1442  ABG_ASSERT(c == ',');
1443  skip_white_spaces();
1444  }
1445 
1446  if (!content.empty())
1447  result.reset(new list_property_value(content));
1448 
1449  return result;
1450  }
1451 
1452  /// A property value that is a tuple.
1453  ///
1454  /// @param tuple the read property tuple value.
1455  ///
1456  /// @return true iff the tuple property value could be read
1457  /// correctly.
1459  read_tuple_property_value()
1460  {
1461  tuple_property_value_sptr nil, result;
1462  int b = peek();
1463  if (!good())
1464  return nil;
1465 
1466  if (b != '{')
1467  return nil;
1468 
1469  char c = 0;
1470  ABG_ASSERT(read_next_char(c));
1471 
1472  property_value_sptr value;
1473  vector<property_value_sptr> values;
1474  while (good() && peek() != '}')
1475  {
1476  skip_white_spaces();
1477  if ((value = read_property_value()))
1478  values.push_back(value);
1479  skip_white_spaces();
1480  if (good() && peek() == ',')
1481  {
1482  c = 0;
1483  read_next_char(c);
1484  }
1485  }
1486 
1487  b = peek();
1488  if (b != '}')
1489  return nil;
1490 
1491  c = 0;
1492  read_next_char(c);
1493 
1494  result.reset(new tuple_property_value(values));
1495  return result;
1496  }
1497 
1498  /// Read the name of a section.
1499  ///
1500  /// @param name out parameter. Is set to the name of the section
1501  /// that was parsed. Note that this is set only if the function
1502  /// returned true.
1503  ///
1504  /// @return true if the input stream was left in a non-erratic
1505  /// state.
1506  bool
1507  read_section_name(string& name)
1508  {
1509  int b = peek();
1510  if (!good() || !char_is_section_name_char(b))
1511  return false;
1512 
1513  char c = 0;
1514  ABG_ASSERT(read_next_char(c) || char_is_section_name_char(b));
1515  name += c;
1516 
1517  for (b = peek(); good(); b = peek())
1518  {
1519  if (!char_is_section_name_char(b))
1520  break;
1521  ABG_ASSERT(read_next_char(c));
1522  name += c;
1523  }
1524 
1525  return true;
1526  }
1527 
1528  /// Read a property (<name> = <value>).
1529  ///
1530  /// @return the resulting pointer to property iff one could be
1531  /// parsed.
1533  read_property()
1534  {
1535  property_sptr nil;
1536 
1537  string name;
1538  if (!read_property_name(name))
1539  return nil;
1540 
1541  skip_white_spaces();
1542 
1543  property_sptr result;
1544 
1545  char c = peek();
1546  if (c == '=')
1547  {
1548  ABG_ASSERT(read_next_char(c));
1549  ABG_ASSERT(c == '=');
1550  skip_white_spaces();
1551  }
1552  else
1553  {
1554  property_sptr empty_value_property(new simple_property(name));
1555  return empty_value_property;
1556  }
1557 
1558  if (!good())
1559  return nil;
1560 
1561  property_value_sptr value = read_property_value();
1562  if (!value)
1563  return nil;
1564 
1566  result.reset(new tuple_property(name, tv));
1567  else if (list_property_value_sptr lv = is_list_property_value(value))
1568  result.reset(new list_property(name, lv));
1570  result.reset(new simple_property(name, sv));
1571  else
1572  // This new kind of property is not yet supported!
1573  std::abort();
1574 
1575  return result;
1576  }
1577 
1578  /// Read an ini section.
1579  ///
1580  /// @return a pointer to a section iff it could be successfully
1581  /// parsed.
1583  read_section()
1584  {
1586 
1587  int b = peek();
1588  if (!good())
1589  return nil;
1590 
1591  char c = 0;
1592  if (b == '[')
1593  ABG_ASSERT(read_next_char(c) && c == '[');
1594 
1595  string name;
1596  if (!read_section_name(name))
1597  return nil;
1598 
1599  if (!skip_white_spaces())
1600  return nil;
1601 
1602  if (! read_next_char(c) || c != ']')
1603  return nil;
1604 
1605  if (!skip_white_spaces_or_comments())
1606  return nil;
1607 
1608  config::properties_type properties;
1609  while (property_sptr prop = read_property())
1610  {
1611  properties.push_back(prop);
1612  skip_white_spaces_or_comments();
1613  }
1614 
1615  if (!properties.empty())
1616  {
1617  config::section_sptr section(new config::section(name, properties));
1618  return section;
1619  }
1620 
1621  return nil;
1622  }
1623 };//end struct read_context
1624 
1625 // </read_context stuff>
1626 
1627 // <config stuff>
1628 
1629 class config::priv
1630 {
1631  string path_;
1632  sections_type sections_;
1633 
1634 public:
1635  friend class config;
1636 
1637  priv()
1638  {}
1639 
1640  priv(const string& path,
1641  sections_type& sections)
1642  : path_(path),
1643  sections_(sections)
1644  {}
1645 
1646 };
1647 
1648 /// @param path the path to the config file.
1649 ///
1650 /// @param sections the sections of the config file.
1651 config::config(const string& path,
1652  sections_type& sections)
1653  : priv_(new priv(path, sections))
1654 {}
1655 
1656 config::config()
1657  : priv_(new priv)
1658 {}
1659 
1660 config::~config()
1661 {}
1662 
1663 /// @return the path to the config file.
1664 const string&
1666 {return priv_->path_;}
1667 
1668 /// Set the path to the config file.
1669 ///
1670 /// @param the new path to the config file.
1671 void
1672 config::set_path(const string& path)
1673 {priv_->path_ = path;}
1674 
1675 /// @return the sections of the config file.
1676 const config::sections_type&
1678 {return priv_->sections_;}
1679 
1680 /// Set new sections to the ini config
1681 ///
1682 /// @param sections the new sections to set.
1683 void
1685 {priv_->sections_ = sections;}
1686 
1687 // </config stuff>
1688 
1689 // <config reader stuff>
1690 
1691 /// Parse the sections of an *.ini file.
1692 ///
1693 /// @param input the input stream to parse the ini file from.
1694 ///
1695 /// @param section out parameter. This is set to the vector of
1696 /// sections that have been parsed from the input stream.
1697 ///
1698 /// @return true upon successful completion and if if the stream is
1699 /// left in a non-erratic state.
1700 bool
1701 read_sections(std::istream& input,
1702  config::sections_type& sections)
1703 {
1704  read_context ctxt(input);
1705 
1706  while (input.good())
1707  {
1708  ctxt.skip_white_spaces_or_comments();
1709  if (config::section_sptr section = ctxt.read_section())
1710  sections.push_back(section);
1711  else
1712  break;
1713  }
1714 
1715  return input.good() || input.eof();
1716 }
1717 
1718 /// Parse the sections of an *.ini file.
1719 ///
1720 /// @param path the path of the ini file to parse.
1721 ///
1722 /// @param section out parameter. This is set to the vector of
1723 /// sections that have been parsed from the input stream.
1724 ///
1725 /// @return true upon successful completion and if if the stream is
1726 /// left in a non-erratic state.
1727 bool
1728 read_sections(const string& path,
1729  config::sections_type& sections)
1730 {
1731  std::ifstream in(path.c_str(), std::ifstream::binary);
1732  if (!in.good())
1733  return false;
1734 
1735  bool is_ok = read_sections(in, sections);
1736  in.close();
1737 
1738  return is_ok;
1739 }
1740 
1741 /// Parse an ini config file from an input stream.
1742 ///
1743 /// @param input the input stream to parse the ini config file from.
1744 ///
1745 /// @return true upon successful parsing.
1746 bool
1747 read_config(istream& input,
1748  config& conf)
1749 {
1750  config::sections_type sections;
1751  if (!read_sections(input, sections))
1752  return false;
1753  conf.set_sections(sections);
1754  return true;
1755 }
1756 
1757 /// Parse an ini config file from a file on disk.
1758 ///
1759 /// @param path the path to the ini file to parse.
1760 ///
1761 /// @param conf the resulting config file to populate as a result of
1762 /// the parsing. This is populated iff the function returns true.
1763 ///
1764 /// @return true upon succcessful completion.
1765 bool
1766 read_config(const string& path,
1767  config& conf)
1768 {
1769  config::sections_type sections;
1770  if (!read_sections(path, sections))
1771  return false;
1772  conf.set_path(path);
1773  conf.set_sections(sections);
1774  return true;
1775 }
1776 
1777 /// Parse an ini config file from an input stream.
1778 ///
1779 /// @return a shared pointer to the resulting config, or nil if it
1780 /// couldn't be parsed.
1782 read_config(std::istream& input)
1783 {
1784  config_sptr c(new config);
1785  if (!read_config(input, *c))
1786  return config_sptr();
1787  return c;
1788 }
1789 
1790 
1791 /// Parse an ini config file from an on-disk file.
1792 ///
1793 /// @return a shared pointer to the resulting config, or nil if it
1794 /// couldn't be parsed.
1796 read_config(const string& path)
1797 {
1798  config_sptr c(new config);
1799  if (!read_config(path, *c))
1800  return config_sptr();
1801  return c;
1802 }
1803 // <config reader stuff>
1804 
1805 // <config writer stuff>
1806 
1807 /// Serialize the value of a property to a string.
1808 ///
1809 /// @param prop the property which value to serialize.
1810 ///
1811 /// @return the string that represents the value of @p prop.
1812 static string
1813 write_property_value(const property_sptr& prop)
1814 {
1815  string result;
1816  if (simple_property_sptr simple_prop = is_simple_property(prop))
1817  {
1818  if (!simple_prop->has_empty_value())
1819  result = simple_prop->get_value()->as_string();
1820  }
1821  else if (list_property_sptr list_prop = is_list_property(prop))
1822  result = list_prop->get_value()->as_string();
1823  else if (tuple_property_sptr tuple_prop = is_tuple_property(prop))
1824  result = tuple_prop->get_value()->as_string();
1825  else
1826  // This new kind of property is not yet supported!
1827  abort();
1828  return result;
1829 }
1830 
1831 /// Serialize an ini property to an output stream.
1832 ///
1833 /// @param prop the property to serialize to the output stream.
1834 ///
1835 /// @param out the output stream to serialize to.
1836 ///
1837 /// @return true if the ouput stream is left in a non-erratic state.
1838 static bool
1839 write_property(const property_sptr& prop,
1840  std::ostream& out)
1841 {
1842  out << prop->get_name();
1843  string value = write_property_value(prop);
1844  if (!value.empty())
1845  out << " = " << write_property_value(prop);
1846  return out.good();
1847 }
1848 
1849 /// Serialize an ini section to an output stream.
1850 ///
1851 /// @param section the ini section to serialize.
1852 ///
1853 /// @param out the output stream to serialize the section to.
1854 static bool
1855 write_section(const config::section& section,
1856  std::ostream& out)
1857 {
1858  out << "[" << section.get_name() << "]\n";
1859  for (config::properties_type::const_iterator i =
1860  section.get_properties().begin();
1861  i != section.get_properties().end();
1862  ++i)
1863  {
1864  out << " ";
1865  write_property(*i, out);
1866  out << "\n";
1867  }
1868  return out.good();
1869 }
1870 
1871 /// Serialize a vector of sections that make up an ini config file to
1872 /// an output stream.
1873 ///
1874 /// Note that an ini config is just a collection of sections.
1875 ///
1876 /// @param sections the vector of sections to serialize.
1877 ///
1878 /// @param out the output stream.
1879 ///
1880 /// @return true if the output stream is left in a non-erratic state.
1881 bool
1883  std::ostream& out)
1884 {
1885  for (config::sections_type::const_iterator i = sections.begin();
1886  i != sections.end();
1887  ++i)
1888  {
1889  write_section(**i, out);
1890  out << "\n";
1891  }
1892  return out.good();
1893 }
1894 
1895 /// Serialize a vector of sections that make up an ini config to a
1896 /// file.
1897 ///
1898 /// @param sections the vector of sections to serialize.
1899 ///
1900 /// @param out the output stream.
1901 ///
1902 /// @return true if the output stream is left in a non-erratic state.
1903 bool
1905  const string& path)
1906 {
1907  std::ofstream f(path.c_str(), std::ofstream::binary);
1908 
1909  if (!f.good())
1910  return false;
1911 
1912  bool is_ok = write_sections(sections, f);
1913 
1914  f.close();
1915 
1916  return is_ok;
1917 }
1918 
1919 /// Serialize an instance of @ref config to an output stream.
1920 ///
1921 /// @param conf the instance of @ref config to serialize.
1922 ///
1923 /// @param output the output stream to serialize @p conf to.
1924 ///
1925 /// @return true upon successful completion.
1926 bool
1927 write_config(const config& conf,
1928  std::ostream& output)
1929 {
1930  if (!write_sections(conf.get_sections(), output))
1931  return false;
1932  return true;
1933 }
1934 
1935 /// Serialize an instance of @ref conf to an on-disk file.
1936 ///
1937 /// @param conf the instance of @ref config to serialize.
1938 ///
1939 /// @param path the path to the on-disk file to serialize to.
1940 ///
1941 /// @return true upon successful completion.
1942 bool
1943 write_config(const config& conf,
1944  const string& path)
1945 {
1946  if (!write_sections(conf.get_sections(), path))
1947  return false;
1948  return true;
1949 }
1950 // </config writer stuff>
1951 
1952 // <function_call_expr stuff>
1953 
1954 /// The private data type of @ref function_call_expr.
1955 struct function_call_expr::priv
1956 {
1957  string name_;
1958  vector<string> arguments_;
1959 
1960  priv()
1961  {}
1962 
1963  priv(const string& name,
1964  const vector<string>& arguments)
1965  : name_(name),
1966  arguments_(arguments)
1967  {}
1968 }; // end struct function_call_expr::priv
1969 
1970 /// Constructor for the @ref function_call_expr type.
1971 ///
1972 /// @param name the name of the function being called.
1973 ///
1974 /// @param args a vector of the arguements of the function being
1975 /// called.
1976 function_call_expr::function_call_expr(const string& name,
1977  const vector<string>& args)
1978  : priv_(new priv(name, args))
1979 {}
1980 
1981 /// Getter of the name of the function being called.
1982 ///
1983 /// @return the name of the function being called.
1984 const string&
1986 {return priv_->name_;}
1987 
1988 /// Getter for the arguments of the function call expression.
1989 ///
1990 /// That is, a getter for the arguments of the function call.
1991 ///
1992 /// @return the operands of the function call expression.
1993 const vector<string>&
1995 {return priv_->arguments_;}
1996 
1997 /// Getter for the arguments of the function call expression.
1998 ///
1999 /// That is, a getter for the arguments of the function call.
2000 ///
2001 /// @return the operands of the function call expression.
2002 vector<string>&
2004 {return priv_->arguments_;}
2005 
2006 /// Read a function call expression and build its representation.
2007 ///
2008 /// @param input the input stream where to read the function call
2009 /// expression from.
2010 ///
2011 /// @param expr the expression resulting from the parsing. This is an
2012 /// output parameter that is set iff this function returns true.
2013 ///
2014 /// @return true iff the parameter @p expr is successfully set with
2015 /// the resulting of parsing the @p input.
2016 bool
2017 read_function_call_expr(std::istream& input,
2019 {
2020  read_context ctxt(input);
2021  return ctxt.read_function_call_expr(expr);
2022 }
2023 
2024 /// Read a function call expression and build its representation.
2025 ///
2026 /// @param input a string where to read the function call expression
2027 /// from.
2028 ///
2029 /// @param expr the expression resulting from the parsing. This is an
2030 /// output parameter that is set iff this function returns true.
2031 ///
2032 /// @return true iff the parameter @p expr is successfully set with
2033 /// the resulting of parsing the @p input.
2034 bool
2035 read_function_call_expr(const string& input,
2037 {
2038  std::istringstream in(input);
2039  return read_function_call_expr(in, expr);
2040 }
2041 
2042 /// Read a function call expression and build its representation.
2043 ///
2044 /// @param input a string where to read the function call expression
2045 /// from.
2046 ///
2047 /// @return the representation of the expression resulting from the
2048 /// parsing.
2050 read_function_call_expr(const string& input)
2051 {
2053  read_function_call_expr(input, expr);
2054  return expr;
2055 }
2056 // </function_call_expr stuff>
2057 }// end namespace ini
2058 }// end namespace abigail
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
Definition: abg-fwd.h:1714
This file contains the declarations for the ini file reader used in the libabigail library.
const string & get_name() const
Get the name of the section.
Definition: abg-ini.cc:812
void set_properties(const properties_type &properties)
Set the properties of the section.
Definition: abg-ini.cc:826
property_sptr find_property(const string &prop_name) const
Find a property that has a given name.
Definition: abg-ini.cc:845
const properties_type & get_properties() const
Get the properties of the section.
Definition: abg-ini.cc:819
virtual ~section()
Destructor of config::section.
Definition: abg-ini.cc:856
void add_property(const property_sptr prop)
Add one property to this section.
Definition: abg-ini.cc:833
The abstraction of the structured content of an .ini file. This roughly follows what is explained at ...
Definition: abg-ini.h:322
vector< property_sptr > properties_type
A convenience typedef for a vector of property_sptr.
Definition: abg-ini.h:335
shared_ptr< section > section_sptr
A convenience typedef for a shared pointer to a config::section.
Definition: abg-ini.h:327
void set_path(const string &path)
Set the path to the config file.
Definition: abg-ini.cc:1672
void set_sections(const sections_type &sections)
Set new sections to the ini config.
Definition: abg-ini.cc:1684
vector< section_sptr > sections_type
A convenience typedef for a vector of config::section_sptr.
Definition: abg-ini.h:332
const sections_type & get_sections() const
Definition: abg-ini.cc:1677
const string & get_path() const
Definition: abg-ini.cc:1665
const vector< string > & get_arguments() const
Getter for the arguments of the function call expression.
Definition: abg-ini.cc:1994
const string & get_name() const
Getter of the name of the function being called.
Definition: abg-ini.cc:1985
Abstracts the value of a property representing a list of strings.
Definition: abg-ini.h:142
list_property_value()
Default constructor of the list_property_value type.
Definition: abg-ini.cc:374
void set_content(const vector< string > &)
Setter of the content of the list_property_value.
Definition: abg-ini.cc:403
virtual const string & as_string() const
Return a string representation of the @list_property_value.
Definition: abg-ini.cc:413
const vector< string > & get_content() const
Getter of the content of the list_property_value.
Definition: abg-ini.cc:396
A class representing a list property.
Definition: abg-ini.h:255
list_property()
Default constructor for list_property.
Definition: abg-ini.cc:647
virtual ~list_property()
Destructor of the list_property type.
Definition: abg-ini.cc:675
const list_property_value_sptr & get_value() const
Getter for the value of the list_property_value.
Definition: abg-ini.cc:664
void set_value(const list_property_value_sptr &value)
Setter for the value of the list_property.
Definition: abg-ini.cc:671
Base class of propertie values.
Definition: abg-ini.h:67
property_value()
Default constructor for the property_value type.
Definition: abg-ini.cc:256
value_kind get_kind() const
Getter for the kind of the property_value type.
Definition: abg-ini.cc:271
virtual ~property_value()
Destructor for the proprerty_value type.
Definition: abg-ini.cc:281
The base class of the different kinds of properties of an INI file.
Definition: abg-ini.h:41
property()
Constructor of property.
Definition: abg-ini.cc:211
virtual ~property()
Destructor of the property.
Definition: abg-ini.cc:237
const string & get_name() const
Getter of the name of the property.
Definition: abg-ini.cc:226
void set_name(const string &name)
Setter of the name of the property.
Definition: abg-ini.cc:233
A simple property. That is, one which value is a string_property_value.
Definition: abg-ini.h:211
void set_value(const string_property_value_sptr &value)
Setter for the string value of the property.
Definition: abg-ini.cc:593
bool has_empty_value() const
Test if the property has an empty value.
Definition: abg-ini.cc:602
const string_property_value_sptr & get_value() const
Getter for the string value of the property.
Definition: abg-ini.cc:586
virtual ~simple_property()
Destructor of the simple_property type.
Definition: abg-ini.cc:610
simple_property()
Default constructor of the simple_property type.
Definition: abg-ini.cc:556
A property value which is a string.
Definition: abg-ini.h:101
virtual ~string_property_value()
Destructor for the string_property_value.
Definition: abg-ini.cc:354
void set_content(const string &)
Setter of the content of the string property value.
Definition: abg-ini.cc:318
virtual const string & as_string() const
Convert the string property value into a string.
Definition: abg-ini.cc:325
string_property_value()
Constructor of the string_property_value type.
Definition: abg-ini.cc:301
A property value that is a tuple.
Definition: abg-ini.h:177
virtual ~tuple_property_value()
Destructor of the tuple_property_value type.
Definition: abg-ini.cc:492
tuple_property_value(const vector< property_value_sptr > &)
Constructor for the tuple_property_value type.
Definition: abg-ini.cc:472
const vector< property_value_sptr > & get_value_items() const
Getter for the content of the tuple_property_value instance.
Definition: abg-ini.cc:481
virtual const string & as_string() const
Convert to the instance of tuple_property_value to a string.
Definition: abg-ini.cc:499
Abstraction of a tuple property. A tuple property is a property which value is a tuple_property_value...
Definition: abg-ini.h:287
tuple_property()
Default constructor of the tuple_property type.
Definition: abg-ini.cc:715
void set_value(const tuple_property_value_sptr value)
Setter for the tuple value of the property.
Definition: abg-ini.cc:735
virtual ~tuple_property()
Destructor for the tuple_property type.
Definition: abg-ini.cc:746
const tuple_property_value_sptr & get_value() const
Getter for the tuple value of the property.
Definition: abg-ini.cc:742
shared_ptr< property_value > property_value_sptr
Convenience typedef for a shared_ptr to property_value.
Definition: abg-ini.h:60
shared_ptr< list_property_value > list_property_value_sptr
A convenience typedef for a shared_ptr to list_property_value.
Definition: abg-ini.h:126
bool read_config(istream &input, config &conf)
Parse an ini config file from an input stream.
Definition: abg-ini.cc:1747
bool read_function_call_expr(std::istream &input, function_call_expr_sptr &expr)
Read a function call expression and build its representation.
Definition: abg-ini.cc:2017
list_property * is_list_property(const property *p)
Test if an instance of a property is actually an instance of list_property.
Definition: abg-ini.cc:686
bool write_config(const config &conf, std::ostream &output)
Serialize an instance of config to an output stream.
Definition: abg-ini.cc:1927
shared_ptr< property > property_sptr
Convenience typefef for shared_ptr to property.
Definition: abg-ini.h:34
shared_ptr< list_property > list_property_sptr
A convenience typedef for a shared_ptr to a list_property.
Definition: abg-ini.h:241
shared_ptr< config > config_sptr
A convenience typedef for a shared pointer to config.
Definition: abg-ini.h:313
list_property_value * is_list_property_value(const property_value *v)
Test if an instance of @property_value is a list_property_value.
Definition: abg-ini.cc:437
bool read_sections(std::istream &input, config::sections_type &sections)
Parse the sections of an *.ini file.
Definition: abg-ini.cc:1701
shared_ptr< tuple_property > tuple_property_sptr
Convenience typedef for a shared_ptr of tuple_property.
Definition: abg-ini.h:280
shared_ptr< simple_property > simple_property_sptr
Convenience typedef for a shared_ptr to an simple_property.
Definition: abg-ini.h:204
shared_ptr< function_call_expr > function_call_expr_sptr
Convenience typedef for a shared pointer to function_call_expr.
Definition: abg-ini.h:427
shared_ptr< string_property_value > string_property_value_sptr
A convenience typedef for a shared_ptr to string_property_value.
Definition: abg-ini.h:94
string_property_value * is_string_property_value(const property_value *v)
Test if a given property value is a string property value.
Definition: abg-ini.cc:341
tuple_property * is_tuple_property(const property *p)
Test if an instance of property is an instance of tuple_property.
Definition: abg-ini.cc:757
shared_ptr< tuple_property_value > tuple_property_value_sptr
Convenience typedef for a shared_ptr to a tuple_property_value.
Definition: abg-ini.h:166
simple_property * is_simple_property(const property *p)
Tests if a property is a simple property.
Definition: abg-ini.cc:619
tuple_property_value * is_tuple_property_value(const property_value *v)
Test if a given instance of property_value is an instance of tuple_property_value too.
Definition: abg-ini.cc:525
bool write_sections(const config::sections_type &sections, std::ostream &out)
Serialize a vector of sections that make up an ini config file to an output stream.
Definition: abg-ini.cc:1882
Toplevel namespace for libabigail.