ini_parser.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "ini_parser.h"
00016 #include "table_configurator.h"
00017 #include "variable_tokenizer.h"
00018
00019 #include <basis/astring.h>
00020 #include <basis/functions.h>
00021 #include <structures/amorph.h>
00022 #include <structures/string_array.h>
00023 #include <structures/string_table.h>
00024 #include <textual/parser_bits.h>
00025
00026
00027
00028
00029 #undef LOG
00030 #ifdef DEBUG_INI_PARSER
00031 #define LOG(to_print) printf("%s\n", astring(to_print).s())
00032 #else
00033 #define LOG(a) {}
00034 #endif
00035
00037
00038 using namespace basis;
00039 using namespace structures;
00040 using namespace textual;
00041
00042
00043 namespace configuration {
00044
00045
00046
00047
00048
00049
00050
00051 ini_parser::ini_parser(const astring &to_parse, treatment_of_defaults behavior)
00052 : table_configurator(behavior),
00053 _well_formed(false),
00054 _preface(new astring)
00055 {
00056 reset(to_parse);
00057 }
00058
00059 ini_parser::~ini_parser()
00060 {
00061 WHACK(_preface);
00062 }
00063
00064 void ini_parser::chow_through_eol(astring &to_chow)
00065 {
00066 while (to_chow.length()) {
00067 if (parser_bits::is_eol(to_chow[0])) {
00068
00069 while (to_chow.length() && parser_bits::is_eol(to_chow[0])) {
00070 *_preface += to_chow[0];
00071 to_chow.zap(0, 0);
00072 }
00073 return;
00074 }
00075 *_preface += to_chow[0];
00076 to_chow.zap(0, 0);
00077 }
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 void ini_parser::reset(const astring &to_parse)
00111 {
00112 _well_formed = false;
00113 table_configurator::reset();
00114 _preface->reset();
00115 add(to_parse);
00116 }
00117
00118 void ini_parser::add(const astring &to_parse)
00119 {
00120 astring parsing = to_parse;
00121
00122 _preface->reset();
00123 while (parsing.length()) {
00124 astring section_name;
00125 bool found_sect = parse_section(parsing, section_name);
00126 if (!found_sect) {
00127
00128 chow_through_eol(parsing);
00129 continue;
00130 }
00131
00132 int next_sect = 0;
00133 for (next_sect = 0; next_sect < parsing.length(); next_sect++) {
00134
00135 if (parser_bits::is_eol(parsing[next_sect])) {
00136
00137
00138
00139 if (parsing[next_sect + 1] == '[') {
00140
00141 break;
00142 }
00143 }
00144 }
00145
00146 if (next_sect >= parsing.length()) next_sect--;
00147
00148 LOG(a_sprintf("bounds are %d to %d, string len is %d.", 0, next_sect,
00149 parsing.length()));
00150 astring sect_parsing = parsing.substring(0, next_sect);
00151 LOG(astring("going to parse: >>") + sect_parsing + "<<");
00152 parsing.zap(0, next_sect);
00153 variable_tokenizer section_reader("\n", "=");
00154 section_reader.set_comment_chars(";#");
00155 section_reader.parse(sect_parsing);
00156 LOG(astring("read: ") + section_reader.text_form());
00157 merge_section(section_name, section_reader.table());
00158 }
00159 _well_formed = true;
00160 }
00161
00162 void ini_parser::merge_section(const astring §ion_name,
00163 const string_table &to_merge)
00164 {
00165 if (!section_exists(section_name)) {
00166
00167 put_section(section_name, to_merge);
00168 return;
00169 }
00170
00171
00172
00173 for (int i = 0; i < to_merge.symbols(); i++)
00174 put(section_name, to_merge.name(i), to_merge[i]);
00175 }
00176
00177 bool ini_parser::parse_section(astring &to_parse, astring §ion_name)
00178 {
00179 section_name = "";
00180
00181
00182 enum states {
00183 SEEKING_OPENING_BRACKET,
00184 EATING_SECTION_NAME
00185 };
00186 states state = SEEKING_OPENING_BRACKET;
00187
00188
00189 for (int i = 0; i < to_parse.length(); i++) {
00190 char curr = to_parse[i];
00191 LOG(astring("<") + astring(curr, 1) + ">");
00192 switch (state) {
00193 case SEEKING_OPENING_BRACKET:
00194
00195 if (parser_bits::white_space(curr)) continue;
00196 if (curr != '[') return false;
00197 state = EATING_SECTION_NAME;
00198 break;
00199 case EATING_SECTION_NAME:
00200
00201 if (curr == ']') {
00202
00203 to_parse.zap(0, i);
00204
00205
00206 return true;
00207 }
00208 section_name += curr;
00209 break;
00210 default:
00211
00212 return false;
00213 }
00214 }
00215
00216
00217 return false;
00218 }
00219
00220 bool ini_parser::restate(astring &new_ini, bool add_spaces)
00221 {
00222 new_ini = *_preface;
00223 string_array sects;
00224 sections(sects);
00225 for (int i = 0; i < sects.length(); i++) {
00226 new_ini += astring("[") + sects[i] + "]" + parser_bits::platform_eol_to_chars();
00227 string_table tab;
00228 if (!get_section(sects[i], tab)) continue;
00229 tab.add_spaces(add_spaces);
00230 new_ini += tab.text_form();
00231 }
00232 return true;
00233 }
00234
00235 }
00236
00237