00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _terimber_xmlconfig_h_
00029 #define _terimber_xmlconfig_h_
00030
00031 #include "base/string.hpp"
00032 #include "base/memory.hpp"
00033 #include "base/map.hpp"
00034 #include "xml/xmlimpl.hpp"
00035
00036 BEGIN_TERIMBER_NAMESPACE
00037 #pragma pack(4)
00038
00039 typedef map< string_t, string_t > xmlconfiglist_t;
00042 class xmlconfig
00043 {
00044 public:
00046 xmlconfig( const char* filename,
00047 const char* path,
00048 const char* key
00049 ) :
00050 _parser(4096)
00051 {
00052
00053 _filename = filename;
00054
00055 string_t root;
00056
00057
00058 if (!_parser.load(filename, 0)
00059 || !_parser.select_root())
00060 {
00061
00062 _parser.load(0, 0, 0, 0);
00063 }
00064 else
00065 {
00066 _root = _parser.get_name();
00067 root = _root;
00068 }
00069
00070 if (path && *path)
00071 {
00072
00073
00074 if (!_parser.select_xpath(path))
00075 {
00076 string_t next_key;
00077 const char* begin = path, *end = 0, *next = 0;
00078
00079 while (0 != (next = strchr(begin, '/')))
00080 {
00081 end = next;
00082
00083 next_key.assign(begin, end - begin);
00084
00085 if (next_key != root)
00086 {
00087 string_t path_key(_root);
00088 if (_root.length())
00089 path_key += "/";
00090 path_key += next_key;
00091
00092 _parser.select_root();
00093 if (!_parser.select_xpath(path_key))
00094 {
00095 _parser.select_root();
00096 _parser.select_xpath(_root);
00097 _parser.add_child(ELEMENT_NODE, next_key, 0, false);
00098 }
00099
00100 if (_root.length())
00101 _root += "/";
00102 _root += next_key;
00103 }
00104
00105 begin = next + 1;
00106 }
00107
00108
00109 if (begin && *begin)
00110 {
00111 string_t path_key(_root);
00112 if (_root.length())
00113 path_key += "/";
00114 path_key += "/";
00115 path_key += begin;
00116
00117 _parser.select_root();
00118 if (!_parser.select_xpath(path_key))
00119 {
00120 _parser.select_root();
00121 _parser.select_xpath(_root);
00122 _parser.add_child(ELEMENT_NODE, begin, 0, false);
00123 }
00124
00125 if (_root.length())
00126 _root += "/";
00127 _root += begin;
00128 }
00129 }
00130 else
00131 {
00132 _root = path;
00133 }
00134 }
00135
00136 if (key && *key)
00137 {
00138 string_t path_key(_root);
00139 if (_root.length())
00140 path_key += "/";
00141 path_key += key;
00142
00143 _parser.select_root();
00144 if (!_parser.select_xpath(path_key))
00145 {
00146 _parser.select_root();
00147 _parser.select_xpath(_root);
00148 _parser.add_child(ELEMENT_NODE, key, 0, false);
00149 }
00150
00151 if (_root.length())
00152 _root += "/";
00153 _root += key;
00154 }
00155 }
00156
00158 ~xmlconfig()
00159 {
00160 _parser.save((const char*)_filename, false);
00161 }
00162
00164 void
00165 make_path( string_t& path,
00166 const char* subkey
00167 ) const
00168 {
00169 path = _root;
00170
00171 if (subkey)
00172 {
00173 path += "/";
00174 path += subkey;
00175 }
00176 }
00177
00180 void
00181 set( const char* subkey,
00182 const char* name,
00183 const char* val
00184 )
00185 {
00186 string_t path;
00187 make_path(path, subkey);
00188
00189 if (_parser.select_root()
00190 && _parser.select_xpath(path))
00191 {
00192 if (_parser.select_attribute_by_name(name))
00193 _parser.update_value(val);
00194 else
00195 _parser.add_child(ATTRIBUTE_NODE, name, val, false);
00196 }
00197 else if (_parser.select_root()
00198 && _parser.select_xpath(_root))
00199 {
00200 if (subkey)
00201 _parser.add_child(ELEMENT_NODE, subkey, 0, false);
00202
00203 _parser.add_child(ATTRIBUTE_NODE, name, val, false);
00204 }
00205 }
00206
00209 void
00210 set( const char* subkey,
00211 const char* name,
00212 int val
00213 )
00214 {
00215 char buf[32];
00216 str_template::strprint(buf, 32, "%d", val);
00217 set(subkey, name, buf);
00218 }
00219
00222 bool
00223 get( const char* subkey,
00224 const char* name,
00225 string_t& val
00226 ) const
00227 {
00228 string_t path;
00229 make_path(path, subkey);
00230
00231 if (!_parser.select_root()
00232 || !_parser.select_xpath(path)
00233 || !_parser.select_attribute_by_name(name)
00234 )
00235 return false;
00236
00237 val = _parser.get_value();
00238 return true;
00239 }
00240
00243 bool
00244 get( const char* subkey,
00245 const char* name,
00246 int& val
00247 ) const
00248 {
00249 string_t s;
00250 return get(subkey, name, s)
00251 && s.length()
00252 && sscanf(s, "%d", &val) == 1;
00253 }
00254
00257 void
00258 getset( const char* subkey,
00259 const char* name,
00260 string_t& val
00261 )
00262 {
00263 if (!get(subkey, name, val))
00264 set(subkey, name, val);
00265 }
00266
00269 void
00270 getset( const char* subkey,
00271 const char* name,
00272 int& val
00273 )
00274 {
00275 if (!get(subkey, name, val))
00276 set(subkey, name, val);
00277 }
00278
00279 bool
00280 getlist( const char* subkey,
00281 const char* name,
00282 xmlconfiglist_t& val
00283 )
00284 {
00285 string_t path;
00286 make_path(path, subkey);
00287 const char* n, *v;
00288
00289 if (!_parser.select_root()
00290 || !_parser.select_xpath(path)
00291 || !_parser.select_first_child()
00292 )
00293 return false;
00294
00295 do
00296 {
00297 if (_parser.get_type() != ELEMENT_NODE
00298 || !(n = _parser.get_name())
00299 || TERIMBER::str_template::strnocasecmp(n, name, os_minus_one)
00300 )
00301 continue;
00302
00303 if (_parser.select_attribute_by_name("name"))
00304 {
00305 n = _parser.get_value();
00306 _parser.select_parent();
00307 }
00308
00309 if (_parser.select_attribute_by_name("value"))
00310 {
00311 v = _parser.get_value();
00312 _parser.select_parent();
00313 }
00314
00315 if (n && v)
00316 {
00317 xmlconfiglist_t::iterator it = val.find(n);
00318 if (it != val.end())
00319 *it = v;
00320 else
00321 val.insert(n, v);
00322 }
00323 }
00324 while (_parser.select_next_sibling());
00325
00326 return true;
00327 }
00328
00329 void
00330 setlist( const char* subkey,
00331 const char* name,
00332 const xmlconfiglist_t& val
00333 )
00334 {
00335 string_t path;
00336 make_path(path, subkey);
00337
00338 if (_parser.select_root()
00339 && _parser.select_xpath(path))
00340 {
00341 ;
00342 }
00343 else if (_parser.select_root()
00344 && _parser.select_xpath(_root))
00345 {
00346 if (subkey)
00347 _parser.add_child(ELEMENT_NODE, subkey, 0, false);
00348 }
00349 else
00350 return;
00351
00352 const char* n;
00353 for (xmlconfiglist_t::const_iterator it = val.begin(); it != val.end(); ++it)
00354 {
00355 bool found = false;
00356
00357
00358 if (_parser.select_first_child())
00359 {
00360 do
00361 {
00362 if (_parser.get_type() != ELEMENT_NODE
00363 || !(n = _parser.get_name())
00364 || TERIMBER::str_template::strnocasecmp(n, name, os_minus_one)
00365 )
00366 continue;
00367
00368 if (_parser.select_attribute_by_name("name"))
00369 {
00370 n = _parser.get_value();
00371 _parser.select_parent();
00372 }
00373
00374 if (n && !TERIMBER::str_template::strnocasecmp(n, it.key(), os_minus_one))
00375 {
00376 if (_parser.select_attribute_by_name("value"))
00377 {
00378 _parser.update_value(*it);
00379 _parser.select_parent();
00380 }
00381 else
00382 _parser.add_child(ATTRIBUTE_NODE, "value", *it, true);
00383
00384 found = true;
00385 }
00386 }
00387 while (!found && _parser.select_next_sibling());
00388
00389 _parser.select_parent();
00390 }
00391
00392 if (!found)
00393 {
00394 _parser.add_child(ELEMENT_NODE, name, 0, false);
00395 _parser.add_child(ATTRIBUTE_NODE, "name", it.key(), true);
00396 _parser.add_child(ATTRIBUTE_NODE, "value", *it, true);
00397 _parser.select_parent();
00398 }
00399 }
00400 }
00401
00402 void
00403 getsetlist( const char* subkey,
00404 const char* name,
00405 xmlconfiglist_t& val
00406 )
00407 {
00408 if (!getlist(subkey, name, val))
00409 setlist(subkey, name, val);
00410 }
00411
00412 private:
00413 xml_designer_impl _parser;
00414 string_t _filename;
00415 string_t _root;
00416 };
00417
00418 #pragma pack()
00419 END_TERIMBER_NAMESPACE
00420
00421 #endif
00422
00423
00424