]>
Dogcows Code - chaz/yoink/blob - src/stlplus/subsystems/ini_manager.cpp
1 ////////////////////////////////////////////////////////////////////////////////
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004-2009
6 // License: BSD License, see ../docs/license.html
8 ////////////////////////////////////////////////////////////////////////////////
9 #include "ini_manager.hpp"
10 #include "file_system.hpp"
16 ////////////////////////////////////////////////////////////////////////////////
21 ////////////////////////////////////////////////////////////////////////////////
24 static std::string
trim(const std::string
& val
)
26 std::string result
= val
;
27 while (!result
.empty() && isspace(result
[0]))
28 result
.erase(result
.begin());
29 while (!result
.empty() && isspace(result
[result
.size()-1]))
30 result
.erase(result
.end()-1);
34 ////////////////////////////////////////////////////////////////////////////////
35 // internal data structure for storing a single entry (i.e. line) from an ini file
36 // lines are categorised as blanks, comments or variables
37 // TODO - do I need an error category?
38 ////////////////////////////////////////////////////////////////////////////////
43 enum kind_t
{BLANK
, COMMENT
, VARIABLE
};
44 friend std::string
to_string(kind_t kind
)
48 case BLANK
: return "BLANK";
49 case COMMENT
: return "COMMENT";
50 case VARIABLE
: return "VARIABLE";
52 return "<*unknown kind*>";
63 ini_entry(unsigned line
) : m_line(line
), m_kind(BLANK
) {}
64 ini_entry(unsigned line
, const std::string
& comment
) : m_line(line
), m_kind(COMMENT
), m_text("; " + comment
) {}
65 ini_entry(unsigned line
, const std::string
& name
, const std::string
& value
) : m_line(line
), m_kind(VARIABLE
), m_text(name
+ " = " + value
), m_name(name
), m_value(value
) {}
68 unsigned line(void) const {return m_line
;}
69 kind_t
kind(void) const {return m_kind
;}
70 bool blank(void) const {return m_kind
== BLANK
;}
71 bool comment(void) const {return m_kind
== COMMENT
;}
72 bool variable(void) const {return m_kind
== VARIABLE
;}
74 const std::string
& text(void) const {return m_text
;}
75 const std::string
& variable_name(void) const {return m_name
;}
76 const std::string
& variable_value(void) const {return m_value
;}
78 bool print(std::ostream
& str
) const
80 str
<< " " << m_line
<< ":" << to_string(m_kind
) << ": " << m_text
<< std::endl
;
85 ////////////////////////////////////////////////////////////////////////////////
86 // internal data structure representing an ini file section containing all the
87 // entries for that section from a single ini file
88 ////////////////////////////////////////////////////////////////////////////////
93 friend class ini_file
;
95 std::list
<ini_entry
> m_entries
;
98 ini_section(const std::string
& title
) :
107 const std::string
& title(void) const
112 bool empty(void) const
114 // a section is empty if it contains no variables
115 for (std::list
<ini_entry
>::const_iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
128 bool variable_exists(const std::string variable
) const
130 for (std::list
<ini_entry
>::const_iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
132 if (i
->variable() && i
->variable_name() == variable
)
138 unsigned variables_size(void) const
141 for (std::list
<ini_entry
>::const_iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
147 std::string
variable_name(unsigned offset
) const
150 for (std::list
<ini_entry
>::const_iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
155 return i
->variable_name();
159 return std::string();
162 std::vector
<std::string
> variable_names(void) const
164 std::vector
<std::string
> result
;
165 for (std::list
<ini_entry
>::const_iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
167 result
.push_back(i
->variable_name());
171 std::string
variable_value(unsigned offset
) const
174 for (std::list
<ini_entry
>::const_iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
179 return i
->variable_value();
183 return std::string();
186 std::string
variable_value(const std::string variable
) const
188 for (std::list
<ini_entry
>::const_iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
190 if (i
->variable() && i
->variable_name() == variable
)
191 return i
->variable_value();
193 return std::string();
196 unsigned variable_line(const std::string variable
) const
198 for (std::list
<ini_entry
>::const_iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
200 if (i
->variable() && i
->variable_name() == variable
)
206 bool add_variable(unsigned line
, const std::string
& variable
, const std::string
& value
)
208 erase_variable(variable
);
209 m_entries
.push_back(ini_entry(line
? line
: m_entries
.size(), variable
, value
));
213 bool add_comment(unsigned line
, const std::string
& comment
)
215 m_entries
.push_back(ini_entry(line
? line
: m_entries
.size(), comment
));
219 bool add_blank(unsigned line
)
221 m_entries
.push_back(ini_entry(line
? line
: m_entries
.size()));
225 bool erase_variable(const std::string
& variable
)
227 for (std::list
<ini_entry
>::iterator i
= m_entries
.begin(); i
!= m_entries
.end(); i
++)
229 if (i
->variable() && i
->variable_name() == variable
)
238 bool print(std::ostream
& str
) const
240 str
<< " [" << m_title
<< "]" << std::endl
;
241 for (std::list
<ini_entry
>::const_iterator entry
= m_entries
.begin(); entry
!= m_entries
.end(); entry
++)
247 ////////////////////////////////////////////////////////////////////////////////
248 // internal data structure representing a single ini file
249 ////////////////////////////////////////////////////////////////////////////////
254 friend class ini_section
;
255 std::string m_filename
;
258 std::list
<ini_section
> m_sections
;
260 std::list
<ini_section
>::const_iterator
find_section(const std::string
& section
) const
262 for (std::list
<ini_section
>::const_iterator i
= m_sections
.begin(); i
!= m_sections
.end(); i
++)
264 if (i
->title() == section
)
267 return m_sections
.end();
270 std::list
<ini_section
>::iterator
find_section(const std::string
& section
)
272 for (std::list
<ini_section
>::iterator i
= m_sections
.begin(); i
!= m_sections
.end(); i
++)
274 if (i
->title() == section
)
277 return m_sections
.end();
282 ini_file(void) : m_changed(false), m_writable(false)
286 ini_file(const std::string
& filename
) : m_changed(false), m_writable(false)
297 bool initialised(void) const
299 return !m_filename
.empty();
302 bool writable(void) const
307 bool read_file(const std::string
& filename
)
309 m_filename
= filename
;
311 // file may not yet exist - possible to create an Ini file using this class
312 // so it is writable if the file exists and is writable or if the folder is writable
313 m_writable
= file_writable(m_filename
);
314 if (!file_exists(m_filename
))
316 // create a dummy top section to hold file comments
317 std::list
<ini_section
>::iterator section
= m_sections
.insert(m_sections
.end(), ini_section(""));
318 std::ifstream
source(m_filename
.c_str());
319 unsigned line_number
= 0;
321 while(std::getline(source
,line
))
325 while(i
< line
.size() && isspace(line
[i
]))
327 if (i
< line
.size() && line
[i
] == '[')
329 // found a section title
332 // get the text up to the end ] or the end of the line
334 while (i
< line
.size() && line
[i
] != ']')
336 // create a new section and make it the current section
337 section
= m_sections
.insert(m_sections
.end(), ini_section(title
));
339 else if (i
< line
.size() && line
[i
] == ';')
342 // skip the ; because that is not part of the comment
344 // add the rest of the line as a comment to the current section
345 section
->add_comment(line_number
, line
.substr(i
, line
.size()-1));
347 else if (i
== line
.size())
349 // found a blank line
350 section
->add_blank(line_number
);
354 // found a *possible* variable - now scan forwards for the = operator
356 while (i
< line
.size() && line
[i
] != '=')
359 // TODO - detect a missing = sign here and convert to an error
362 // trim trailing whitespace off the name
364 // now get the value, minus any leading whitespace
366 while(i
< line
.size() && isspace(line
[i
]))
368 while (i
< line
.size())
370 // trim trailing whitespace off the value
372 // and finally add the name/value pair to the data structure
373 section
->add_variable(line_number
, name
, value
);
381 if (!initialised()) return false;
382 if (!m_changed
) return true;
383 if (!m_writable
) return false;
384 std::ofstream
output(m_filename
.c_str());
385 for (std::list
<ini_section
>::iterator section
= m_sections
.begin(); section
!= m_sections
.end(); section
++)
387 if (!(section
->title().empty()))
388 output
<< "[" << section
->title() << "]" << std::endl
;
389 for (std::list
<ini_entry
>::iterator entry
= section
->m_entries
.begin(); entry
!= section
->m_entries
.end(); entry
++)
390 output
<< entry
->text() << std::endl
;
396 std::string
filename(void) const
401 bool empty(void) const
403 // file is empty if it has either no sections or an empty header section
404 if (m_sections
.empty()) return true;
405 if ((m_sections
.begin() == --m_sections
.end()) && m_sections
.begin()->empty()) return true;
409 bool section_exists(const std::string
& title
) const
411 return find_section(title
) != m_sections
.end();
414 bool add_section(const std::string
& section
)
416 if (!m_writable
) return false;
417 m_sections
.push_back(ini_section(section
));
422 bool empty_section(const std::string
& section
)
424 std::list
<ini_section
>::iterator found
= find_section(section
);
425 if (found
== m_sections
.end()) return false;
426 return found
->empty();
429 bool erase_section(const std::string
& section
)
431 if (!m_writable
) return false;
432 std::list
<ini_section
>::iterator found
= find_section(section
);
433 if (found
== m_sections
.end()) return false;
434 m_sections
.erase(found
);
439 bool clear_section(const std::string
& section
)
441 if (!m_writable
) return false;
442 std::list
<ini_section
>::iterator found
= find_section(section
);
443 if (found
== m_sections
.end()) return false;
449 unsigned sections_size(void) const
451 return m_sections
.size();
454 const std::string
& section_name(unsigned i
) const
456 std::list
<ini_section
>::const_iterator result
= m_sections
.begin();
457 for (unsigned j
= 1; j
<= i
; j
++)
459 return result
->title();
462 std::vector
<std::string
> section_names(void) const
464 std::vector
<std::string
> result
;
465 for (unsigned j
= 0; j
< sections_size(); j
++)
466 result
.push_back(section_name(j
));
470 bool variable_exists(const std::string
& section
, const std::string variable
) const
472 std::list
<ini_section
>::const_iterator found
= find_section(section
);
473 if (found
== m_sections
.end()) return false;
474 return found
->variable_exists(variable
);
477 std::vector
<std::string
> variable_names(const std::string
& section
) const
479 std::list
<ini_section
>::const_iterator found
= find_section(section
);
480 if (found
== m_sections
.end()) return std::vector
<std::string
>();
481 return found
->variable_names();
484 unsigned variables_size(const std::string
& section
) const
486 std::list
<ini_section
>::const_iterator found
= find_section(section
);
487 if (found
== m_sections
.end()) return 0;
488 return found
->variables_size();
491 unsigned variable_line(const std::string
& section
, const std::string variable
) const
493 std::list
<ini_section
>::const_iterator found
= find_section(section
);
494 if (found
== m_sections
.end()) return 0;
495 return found
->variable_line(variable
);
498 std::string
variable_name(const std::string
& section
, unsigned i
) const
500 std::list
<ini_section
>::const_iterator found
= find_section(section
);
501 if (found
== m_sections
.end()) return std::string();
502 return found
->variable_name(i
);
505 std::string
variable_value(const std::string
& section
, unsigned i
) const
507 std::list
<ini_section
>::const_iterator found
= find_section(section
);
508 if (found
== m_sections
.end()) return std::string();
509 return found
->variable_value(i
);
512 std::string
variable_value(const std::string
& section
, const std::string variable
) const
514 std::list
<ini_section
>::const_iterator found
= find_section(section
);
515 if (found
== m_sections
.end()) return std::string();
516 return found
->variable_value(variable
);
519 bool add_variable(const std::string
& section
, const std::string
& variable
, const std::string
& value
)
521 if (!m_writable
) return false;
522 std::list
<ini_section
>::iterator found
= find_section(section
);
523 if (found
== m_sections
.end()) found
= m_sections
.insert(m_sections
.end(),ini_section(section
));
524 if (found
->add_variable(0,variable
,value
))
529 bool add_comment(const std::string
& section
, const std::string
& comment
)
531 if (!m_writable
) return false;
532 std::list
<ini_section
>::iterator found
= find_section(section
);
533 if (found
== m_sections
.end()) found
= m_sections
.insert(m_sections
.end(),ini_section(section
));
534 if (found
->add_comment(0,comment
))
539 bool add_blank(const std::string
& section
)
541 if (!m_writable
) return false;
542 std::list
<ini_section
>::iterator found
= find_section(section
);
543 if (found
== m_sections
.end()) found
= m_sections
.insert(m_sections
.end(),ini_section(section
));
544 if (found
->add_blank(0))
549 bool erase_variable(const std::string
& section
, const std::string
& variable
)
551 if (!m_writable
) return false;
552 std::list
<ini_section
>::iterator found
= find_section(section
);
553 if (found
== m_sections
.end()) return false;
554 if (found
->erase_variable(variable
))
562 bool print(std::ostream
& str
) const
564 str
<< "file: " << m_filename
<< std::endl
;
565 for (std::list
<ini_section
>::const_iterator section
= m_sections
.begin(); section
!= m_sections
.end(); section
++)
571 ////////////////////////////////////////////////////////////////////////////////
572 // body data structure contains all the data and is pointed-to by exported data structure
574 class ini_manager_body
577 std::vector
<ini_file
> m_files
;
580 ini_manager_body(const ini_manager_body
&);
581 ini_manager_body
& operator= (const ini_manager_body
&);
585 ini_manager_body(void) : m_count(1)
589 ~ini_manager_body(void)
605 //////////////////////////////////////////////////////////////////////////////
608 // add files starting with the most local file (e.g. the current project) which has depth 0
609 // and working back to the most global (e.g. the installation settings) which has a depth of size()-1
610 // This does nothing if the file has already been loaded - it is not permitted to manage the same file twice.
611 // Returns true if the file loaded okay or was already loaded (it is counted as successful if the file did
612 // not exist, only read errors cause a failure)
613 bool add_file(const std::string
& filename
)
615 // if this file has been loaded, don't load it again
616 // this is not an error
617 for (unsigned i
= 0; i
< m_files
.size(); i
++)
619 if (filespec_to_path(filename
) == filespec_to_path(m_files
[i
].filename()))
622 // add a new file to the back of the list and then load it
623 // I do it in two steps rather than passing the filename to the constructor in order to return the load status
624 m_files
.push_back(ini_file());
625 return m_files
.back().read_file(filename
);
628 // as above, returns false if *none* of the files were added
629 // filenames[0] is the local file, and so on
630 bool add_files(const std::vector
<std::string
>& filenames
)
633 for (unsigned i
= 0; i
< filenames
.size(); i
++)
634 result
&= add_file(filenames
[i
]);
638 // saves modified ini files - returns true if all modified files were written successfully
642 for (unsigned i
= 0; i
< m_files
.size(); i
++)
643 result
&= m_files
[i
].save_file();
647 // get the number of files being managed
648 unsigned size(void) const
650 return m_files
.size();
653 // get the ini filename associated with a depth
654 std::string
filename(unsigned depth
) const
656 return m_files
[depth
].filename();
659 // test whether a file in the ini manager is writable
660 bool writable(unsigned depth
) const
662 return m_files
[depth
].writable();
665 // test whether a file is empty
666 // An ini file is considered empty if it has no named sections and the header is empty or missing
667 bool empty(unsigned depth
) const
669 return m_files
[depth
].empty();
672 // erase the ini file from the ini manager and from the disk
673 bool erase(unsigned depth
)
675 std::string file
= filename(depth
);
677 return file_delete(file
);
680 // remove the file from the ini manager but do not erase it from the disk
681 bool remove(unsigned depth
)
683 if (m_files
[depth
].writable())
684 m_files
[depth
].save_file();
685 m_files
.erase(m_files
.begin() + depth
);
689 //////////////////////////////////////////////////////////////////////////////
690 // section management
692 // returns the union of all section names in all of the ini files
693 std::vector
<std::string
> section_names(void) const
695 std::vector
<std::string
> result
;
696 for (unsigned i
= 0; i
< m_files
.size(); i
++)
698 std::vector
<std::string
> file_result
= section_names(i
);
699 for (unsigned j
= 0; j
< file_result
.size(); j
++)
701 if (std::find(result
.begin(), result
.end(), file_result
[j
]) == result
.end())
702 result
.push_back(file_result
[j
]);
708 // returns the section names in one of the ini files
709 std::vector
<std::string
> section_names(unsigned depth
) const
711 return m_files
[depth
].section_names();
714 // tests whether a section is found in any of the ini files
715 bool section_exists(const std::string
& title
) const
717 for (unsigned i
= 0; i
< m_files
.size(); i
++)
719 if (m_files
[i
].section_exists(title
))
725 // tests whether the section is found in the specific ini file
726 bool section_exists(const std::string
& title
, unsigned depth
) const
728 return m_files
[depth
].section_exists(title
);
731 // adds a section to the specified ini file - does nothing if it is already present
732 bool add_section(const std::string
& section
, unsigned depth
)
734 return m_files
[depth
].add_section(section
);
737 // test whether a section is empty
738 bool empty_section(const std::string
& section
, unsigned depth
)
740 return m_files
[depth
].empty_section(section
);
743 // removes a section from the specified ini file if it exists there but cannot remove it from any other file
744 bool erase_section(const std::string
& section
, unsigned depth
)
746 return m_files
[depth
].erase_section(section
);
749 // removes all the contents of a section from the specified ini file but keeps the empty section
750 bool clear_section(const std::string
& section
, unsigned depth
)
752 return m_files
[depth
].clear_section(section
);
755 //////////////////////////////////////////////////////////////////////////////
756 // variable management
758 // test whether a variable exists in any of the ini files
759 bool variable_exists(const std::string
& section
, const std::string variable
) const
761 for (unsigned i
= 0; i
< m_files
.size(); i
++)
763 if (variable_exists(section
, variable
, i
))
769 // test whether a variable exists in specified ini file
770 bool variable_exists(const std::string
& section
, const std::string variable
, unsigned depth
) const
772 return m_files
[depth
].variable_exists(section
, variable
);
775 // get the union of all variables declared in all ini files
776 std::vector
<std::string
> variable_names(const std::string
& section
) const
778 std::vector
<std::string
> result
;
779 for (unsigned i
= 0; i
< m_files
.size(); i
++)
781 std::vector
<std::string
> file_result
= variable_names(section
, i
);
782 for (unsigned j
= 0; j
< file_result
.size(); j
++)
784 if (std::find(result
.begin(), result
.end(), file_result
[j
]) == result
.end())
785 result
.push_back(file_result
[j
]);
791 // get the set of all varaibale names from one file
792 std::vector
<std::string
> variable_names(const std::string
& section
, unsigned depth
) const
794 return m_files
[depth
].variable_names(section
);
797 // get the depth of the first ini file to define a variable
798 // returns 0 if defined in the local ini file, etc. Returns (unsigned)-1 if the variable doesn't exist
799 unsigned variable_depth(const std::string
& section
, const std::string variable
) const
801 for (unsigned i
= 0; i
< m_files
.size(); i
++)
803 if (variable_exists(section
, variable
, i
))
809 // get the filename that first defines the variable
810 std::string
variable_filename(const std::string
& section
, const std::string variable
) const
812 for (unsigned i
= 0; i
< m_files
.size(); i
++)
814 if (variable_exists(section
, variable
, i
))
817 return std::string();
820 unsigned variable_linenumber(const std::string
& section
, const std::string variable
) const
822 for (unsigned i
= 0; i
< m_files
.size(); i
++)
824 if (variable_exists(section
, variable
, i
))
825 return m_files
[i
].variable_line(section
,variable
);
830 // get the value of a variable as a single unprocessed string
831 // if the variable does not exist the string will be empty, but beware that
832 // you also get an empty string if a variable exists but has no value
833 // you can differentiate between the two cases by using variable_exists_all above
834 std::string
variable_value(const std::string
& section
, const std::string variable
) const
836 for (unsigned i
= 0; i
< m_files
.size(); i
++)
838 if (variable_exists(section
, variable
, i
))
839 return variable_value(section
, variable
, i
);
841 return std::string();
844 // get the value from the specified file
845 std::string
variable_value(const std::string
& section
, const std::string variable
, unsigned depth
) const
847 return m_files
[depth
].variable_value(section
, variable
);
850 // get the value of a variable as a processed string
851 // processing splits the value at commas and furthermore supports quoted
852 // strings (so that values can contain commas for example)
853 // quoted strings are dequoted before they are added to the result
854 // the result is a vector of dequoted strings, one per value in the comma-separated list
855 std::vector
<std::string
> variable_values(const std::string
& section
, const std::string variable
) const
857 for (unsigned i
= 0; i
< m_files
.size(); i
++)
859 if (variable_exists(section
, variable
, i
))
860 return variable_values(section
, variable
, i
);
862 return std::vector
<std::string
>();
865 // get the processed variable from the specified file
866 std::vector
<std::string
> variable_values(const std::string
& section
, const std::string variable
, unsigned depth
) const
868 // get the unprocessed value and then do the processing into processed separate values
869 std::string value
= variable_value(section
, variable
, depth
);
870 std::vector
<std::string
> result
;
873 result
.push_back(std::string());
875 // loop which is repeated for each element in the comma-separated list
876 while(i
< value
.size())
878 // skip leading whitespace
879 while (i
< value
.size() && isspace(value
[i
])) i
++;
880 // get the value - this means all text up to the next comma or end of line
881 // also allow escaped characters
882 while (i
< value
.size())
884 if (value
[i
] == ',') break;
885 if (value
[i
] == '\\')
887 // found an escaped character - de-escape it by only getting the next character
888 // beware of an escape character at the end of the line which just gets ignored
890 if (i
< value
.size()) result
.back() += value
[i
++];
892 else if (value
[i
] == '"')
894 // get a quoted substring
895 // first skip the opening quote
897 // keep getting characters until a close-quote, but allow the quote character to be escaped by itself
898 while (i
< value
.size())
902 // found a quote skip it
904 // now establish whether its an escaped quote
905 // if it is, keep it, but de-escape it by only getting the next character
906 // it it isn't, break out and continue processing the value as a non-quoted string
907 if (i
< value
.size() && value
[i
] != '"') break;
908 if (i
< value
.size()) result
.back() += value
[i
++];
912 // non-quote and non-escape so just get the character
913 result
.back() += value
[i
++];
919 // non-escape so just get the character
920 result
.back() += value
[i
++];
923 // trim trailing whitespace off the value
924 while (!result
.back().empty() && isspace(result
.back()[result
.back().size()-1])) result
.back().erase(result
.back().size()-1,1);
925 // now check for whether there is a comma or end of line
926 if (i
<= value
.size() && value
[i
] == ',')
928 // skip the comma and add a new string to the result ready for the next iteration
930 result
.push_back(std::string());
934 // end of line found so break out
942 // add a variable to the specified file
943 bool add_variable(const std::string
& section
, const std::string
& variable
, const std::string
& value
, unsigned depth
)
945 return m_files
[depth
].add_variable(section
, variable
, value
);
948 // add a variable as a processed string
949 // processing means that the values in the string vector are converted into a comma-separated list
950 // values containing reserved characters are automatically quoted - so you should not even try to quote them yourself
951 bool add_variable(const std::string
& section
, const std::string
& variable
, const std::vector
<std::string
>& values
, unsigned depth
)
953 // convert the values vector into a comma-separated string with each value escaped so that special characters do not confuse the reader
954 // the characters escaped are: '\', ',', '"'
956 for (unsigned v
= 0; v
< values
.size(); v
++)
958 const std::string
& element
= values
[v
];
959 // add the comma between values === add a comma before all but the first value
960 if (v
> 0) value
+= ',';
961 for (unsigned i
= 0; i
< element
.size(); i
++)
963 // add a character at a time, escaping special characters
964 if (element
[i
] == '"' || element
[i
] == ',' || element
[i
] == '\\')
966 // escape the character
972 return add_variable(section
, variable
, value
, depth
);
975 // erase a variable from the specified file
976 // this does not remove the variable from other ini files, so the variable may still exist
977 // to mask a global variable, set the variable to an empty string instead
978 bool erase_variable(const std::string
& section
, const std::string
& variable
, unsigned depth
)
980 return m_files
[depth
].erase_variable(section
, variable
);
983 //////////////////////////////////////////////////////////////////////////////
984 // sundry line-entry management
986 // add a comment to the specified ini file
987 bool add_comment(const std::string
& section
, const std::string
& comment
, unsigned depth
)
989 return m_files
[depth
].add_comment(section
, comment
);
992 // add a blank line to the specified ini file
993 bool add_blank(const std::string
& section
, unsigned depth
)
995 return m_files
[depth
].add_blank(section
);
998 bool print(std::ostream
& str
) const
1000 str
<< "----------------------------------------" << std::endl
;
1001 for (unsigned depth
= 0; depth
< m_files
.size(); depth
++)
1003 m_files
[depth
].print(str
);
1004 str
<< "----------------------------------------" << std::endl
;
1010 ////////////////////////////////////////////////////////////////////////////////
1011 // exported data structure representing the set of all ini files and providing
1012 // the access functions exported by the class
1013 ////////////////////////////////////////////////////////////////////////////////
1015 ////////////////////////////////////////////////////////////////////////////////
1016 // constructors/destructors
1018 ini_manager::ini_manager(void) : m_body(new ini_manager_body
)
1022 ini_manager::ini_manager(const std::vector
<std::string
>& filenames
) : m_body(new ini_manager_body
)
1024 add_files(filenames
);
1027 ini_manager::ini_manager(const ini_manager
& manager
) : m_body(0)
1029 m_body
= manager
.m_body
;
1030 m_body
->increment();
1033 ini_manager
& ini_manager::operator= (const ini_manager
& manager
)
1035 if (m_body
== manager
.m_body
) return *this;
1036 if (m_body
->decrement())
1038 m_body
= manager
.m_body
;
1039 m_body
->increment();
1043 ini_manager::~ini_manager(void)
1045 if (m_body
->decrement())
1049 ////////////////////////////////////////////////////////////////////////////////
1052 bool ini_manager::add_file(const std::string
& filename
)
1054 return m_body
->add_file(filename
);
1057 bool ini_manager::add_files(const std::vector
<std::string
>& filenames
)
1059 return m_body
->add_files(filenames
);
1062 bool ini_manager::save(void)
1064 return m_body
->save();
1067 unsigned ini_manager::size(void) const
1069 return m_body
->size();
1072 std::string
ini_manager::filename(unsigned depth
) const
1074 return m_body
->filename(depth
);
1077 bool ini_manager::writable(unsigned depth
) const
1079 return m_body
->writable(depth
);
1082 bool ini_manager::empty(unsigned depth
) const
1084 return m_body
->empty(depth
);
1087 bool ini_manager::erase(unsigned depth
)
1089 return m_body
->erase(depth
);
1092 bool ini_manager::remove(unsigned depth
)
1094 return m_body
->remove(depth
);
1097 ////////////////////////////////////////////////////////////////////////////////
1098 // section management
1100 std::vector
<std::string
> ini_manager::section_names(void) const
1102 return m_body
->section_names();
1105 std::vector
<std::string
> ini_manager::section_names(unsigned depth
) const
1107 return m_body
->section_names(depth
);
1110 bool ini_manager::section_exists(const std::string
& section
) const
1112 return m_body
->section_exists(section
);
1115 bool ini_manager::section_exists(const std::string
& section
, unsigned depth
) const
1117 return m_body
->section_exists(section
, depth
);
1120 bool ini_manager::add_section(const std::string
& section
, unsigned depth
)
1122 return m_body
->add_section(section
, depth
);
1125 bool ini_manager::empty_section(const std::string
& section
, unsigned depth
)
1127 return m_body
->empty_section(section
, depth
);
1130 bool ini_manager::erase_section(const std::string
& section
, unsigned depth
)
1132 return m_body
->erase_section(section
, depth
);
1135 bool ini_manager::clear_section(const std::string
& section
, unsigned depth
)
1137 return m_body
->clear_section(section
, depth
);
1140 ////////////////////////////////////////////////////////////////////////////////
1141 // variable management
1143 bool ini_manager::variable_exists(const std::string
& section
, const std::string variable
) const
1145 return m_body
->variable_exists(section
, variable
);
1148 bool ini_manager::variable_exists(const std::string
& section
, const std::string variable
, unsigned depth
) const
1150 return m_body
->variable_exists(section
, variable
, depth
);
1153 std::vector
<std::string
> ini_manager::variable_names(const std::string
& section
) const
1155 return m_body
->variable_names(section
);
1158 std::vector
<std::string
> ini_manager::variable_names(const std::string
& section
, unsigned depth
) const
1160 return m_body
->variable_names(section
, depth
);
1163 unsigned ini_manager::variable_depth(const std::string
& section
, const std::string variable
) const
1165 return m_body
->variable_depth(section
, variable
);
1168 std::string
ini_manager::variable_filename(const std::string
& section
, const std::string variable
) const
1170 return m_body
->variable_filename(section
, variable
);
1173 unsigned ini_manager::variable_linenumber(const std::string
& section
, const std::string variable
) const
1175 return m_body
->variable_linenumber(section
, variable
);
1178 std::string
ini_manager::variable_value(const std::string
& section
, const std::string variable
) const
1180 return m_body
->variable_value(section
, variable
);
1183 std::string
ini_manager::variable_value(const std::string
& section
, const std::string variable
, unsigned depth
) const
1185 return m_body
->variable_value(section
, variable
, depth
);
1188 std::vector
<std::string
> ini_manager::variable_values(const std::string
& section
, const std::string variable
) const
1190 return m_body
->variable_values(section
, variable
);
1193 std::vector
<std::string
> ini_manager::variable_values(const std::string
& section
, const std::string variable
, unsigned depth
) const
1195 return m_body
->variable_values(section
, variable
, depth
);
1198 bool ini_manager::add_variable(const std::string
& section
, const std::string
& variable
, const std::string
& value
, unsigned depth
)
1200 return m_body
->add_variable(section
, variable
, value
, depth
);
1203 bool ini_manager::add_variable(const std::string
& section
, const std::string
& variable
, const std::vector
<std::string
>& values
, unsigned depth
)
1205 return m_body
->add_variable(section
, variable
, values
, depth
);
1208 bool ini_manager::erase_variable(const std::string
& section
, const std::string
& variable
, unsigned depth
)
1210 return m_body
->erase_variable(section
, variable
, depth
);
1214 ////////////////////////////////////////////////////////////////////////////////
1217 bool ini_manager::add_comment(const std::string
& section
, const std::string
& comment
, unsigned depth
)
1219 return m_body
->add_comment(section
, comment
, depth
);
1222 bool ini_manager::add_blank(const std::string
& section
, unsigned depth
)
1224 return m_body
->add_blank(section
, depth
);
1227 bool ini_manager::print(std::ostream
& str
) const
1229 return m_body
->print(str
);
1232 ////////////////////////////////////////////////////////////////////////////////
1235 std::ostream
& operator << (std::ostream
& str
, const ini_manager
& manager
)
1241 ////////////////////////////////////////////////////////////////////////////////
1243 } // end namespace stlplus
This page took 0.096391 seconds and 4 git commands to generate.