00001 #ifndef INI_CONFIG_IMPLEMENTATION_FILE
00002 #define INI_CONFIG_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef __UNIX__
00019 #include "byte_filer.h"
00020 #endif
00021 #include "command_line.h"
00022 #include "directory.h"
00023 #include "filename.h"
00024 #include "ini_config.h"
00025 #include "path_configuration.h"
00026
00027 #include <basis/convert_utf.h>
00028 #include <basis/function.h>
00029 #include <basis/istring.h>
00030 #include <basis/mutex.h>
00031 #include <basis/portable.h>
00032 #include <basis/string_array.h>
00033 #include <data_struct/static_memory_gremlin.h>
00034 #include <data_struct/string_table.h>
00035 #include <data_struct/symbol_table.cpp>
00036 #include <opsystem/byte_filer.h>
00037 #include <textual/tokenizer.h>
00038
00039 #undef LOG
00040 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00041
00042
00043
00044
00045 const int MAXIMUM_LINE_INI_CONFIG = 16384;
00046
00047
00048 SAFE_STATIC_CONST(istring_object, ini_configurator::ini_str_fake_default,
00049 ("NoTomatoesNorPotatoesNorQuayle"))
00050
00051 ini_configurator::ini_configurator(const istring &ini_filename,
00052 treatment_of_defaults behavior, file_location_default where)
00053 : configurator(behavior),
00054 _ini_name(new filename),
00055 #ifdef __UNIX__
00056 _parser(new ini_parser("", behavior)),
00057 #endif
00058 _where(where),
00059 _add_spaces(false)
00060 {
00061 name(ini_filename);
00062 }
00063
00064 ini_configurator::~ini_configurator()
00065 {
00066 WHACK(_ini_name);
00067 #ifdef __UNIX__
00068 WHACK(_parser);
00069 #endif
00070 }
00071
00072 istring ini_configurator::name() const { return _ini_name->raw(); }
00073
00074 void ini_configurator::name(const istring &name)
00075 {
00076 *_ini_name = name;
00077
00078 bool use_appdir = true;
00079
00080
00081 if (_where == OS_DIRECTORY) use_appdir = false;
00082 if (_where == ALL_USERS_DIRECTORY) use_appdir = false;
00083 #ifndef __WIN32__
00084 use_appdir = true;
00085 #endif
00086
00087 if (!_ini_name->had_directory()) {
00088 if (use_appdir) {
00089
00090
00091 *_ini_name = filename(path_configuration::application_directory(),
00092 _ini_name->basename());
00093 } else if (!use_appdir && (_where == ALL_USERS_DIRECTORY) ) {
00094
00095
00096 directory::make_directory(portable::env_string("ALLUSERSPROFILE")
00097 + "/" + software_product_name());
00098 *_ini_name = filename(portable::env_string("ALLUSERSPROFILE")
00099 + "/" + software_product_name(),
00100 _ini_name->basename());
00101 }
00102 }
00103 #ifdef __UNIX__
00104
00105 read_ini_file();
00106 #endif
00107 }
00108
00109 void ini_configurator::sections(string_array &list)
00110 {
00111 list = string_array();
00112
00113 byte_filer section8(*_ini_name, "rb");
00114 if (!section8.good()) return;
00115 istring line_found;
00116
00117
00118 while (section8.read(line_found, MAXIMUM_LINE_INI_CONFIG) > 0) {
00119
00120
00121 line_found.strip_white_spaces();
00122 if (line_found[0] != '[') continue;
00123 line_found.zap(0, 0);
00124 int close_brack_indy = line_found.find(']');
00125 if (negative(close_brack_indy)) continue;
00126 line_found.zap(close_brack_indy, line_found.end());
00127 list += line_found;
00128 }
00129 }
00130
00131
00132 bool ini_configurator::section_exists(const istring §ion)
00133 {
00134 #ifdef __WIN32__
00135 string_table infos;
00136
00137 return get_section(section, infos);
00138 #else
00139 return _parser->section_exists(section);
00140 #endif
00141 }
00142
00143 #ifdef __UNIX__
00144 void ini_configurator::read_ini_file()
00145 {
00146 FUNCDEF("read_ini_file");
00147 _parser->reset("");
00148 byte_filer ini_file;
00149 bool open_ret = ini_file.open(*_ini_name, "rb");
00150 #ifdef DEBUG_INI_CONFIGURATOR
00151 if (!open_ret) LOG(istring("failed to open ini file: ") + *_ini_name);
00152 if (!ini_file.good()) LOG(istring("ini file not good: ") + *_ini_name);
00153 #endif
00154 if (!open_ret || !ini_file.good()) {
00155 return;
00156 }
00157 int file_size = ini_file.length();
00158
00159 istring contents(' ', file_size + 3);
00160 int bytes_read = ini_file.read((byte *)contents.observe(), file_size);
00161 contents.zap(bytes_read + 1, contents.end());
00162 _parser->reset(contents);
00163 }
00164
00165 void ini_configurator::write_ini_file()
00166 {
00167 FUNCDEF("write_ini_file");
00168
00169
00170
00171 byte_filer ini_file;
00172 bool open_ret = ini_file.open(*_ini_name, "wb");
00173
00174 #ifdef DEBUG_INI_CONFIGURATOR
00175 if (!open_ret) LOG(istring("failed to open ini file: ") + *_ini_name);
00176 if (!ini_file.good()) LOG(istring("ini file not good: ") + *_ini_name);
00177 #endif
00178 if (!open_ret || !ini_file.good()) return;
00179
00180
00181 istring text;
00182 _parser->restate(text, _add_spaces);
00183 ini_file.write((byte *)text.observe(), text.length());
00184 }
00185 #endif //UNIX
00186
00187 bool ini_configurator::delete_section(const istring §ion)
00188 {
00189 #ifdef __WIN32__
00190 return put_profile_string(section, "", "");
00191 #else
00192
00193 bool to_return = _parser->delete_section(section);
00194
00195 write_ini_file();
00196 return to_return;
00197 #endif
00198 }
00199
00200 bool ini_configurator::delete_entry(const istring §ion, const istring &ent)
00201 {
00202 #ifdef __WIN32__
00203 return put_profile_string(section, ent, "");
00204 #else
00205
00206 bool to_return = _parser->delete_entry(section, ent);
00207
00208 write_ini_file();
00209 return to_return;
00210 #endif
00211 }
00212
00213 bool ini_configurator::put(const istring §ion, const istring &entry,
00214 const istring &to_store)
00215 {
00216 FUNCDEF("put");
00217 if (!to_store.length()) return delete_entry(section, entry);
00218 else if (!entry.length()) return delete_section(section);
00219 else if (!section.length()) return false;
00220 #ifdef __WIN32__
00221 return put_profile_string(section, entry, to_store);
00222 #else
00223
00224 bool to_return = _parser->put(section, entry, to_store);
00225
00226 write_ini_file();
00227 return to_return;
00228 #endif
00229 }
00230
00231 bool ini_configurator::get(const istring §ion, const istring &entry,
00232 istring &found)
00233 {
00234 #ifndef __WIN32__
00235 return _parser->get(section, entry, found);
00236 #else
00237 flexichar temp_buffer[MAXIMUM_LINE_INI_CONFIG];
00238 temp_buffer[0] = 0;
00239 get_profile_string(section, entry, ini_str_fake_default(),
00240 temp_buffer, MAXIMUM_LINE_INI_CONFIG - 1);
00241 found = from_unicode_temp(temp_buffer);
00242 return !(ini_str_fake_default() == found);
00243 #endif
00244 }
00245
00246 bool ini_configurator::get_section(const istring §ion, string_table &info)
00247 {
00248 FUNCDEF("get_section");
00249 #ifndef __WIN32__
00250 return _parser->get_section(section, info);
00251 #else
00252 info.reset();
00253 const int buffer_size = 200000;
00254
00255 flexichar low_buff[buffer_size + 3];
00256 int read_len = GetPrivateProfileSection(to_unicode_temp(section.observe()),
00257 low_buff, buffer_size - 1, to_unicode_temp(name()));
00258 if (!read_len) return false;
00259
00260 low_buff[read_len] = '\1';
00261 low_buff[read_len + 1] = '\0';
00262
00263 bool last_was_nil = false;
00264
00265
00266 for (int i = 0; i < read_len; i++) {
00267 if (!low_buff[i] && last_was_nil) {
00268
00269
00270 break;
00271 } else if (!low_buff[i]) {
00272 low_buff[i] = '\1';
00273 last_was_nil = true;
00274 } else last_was_nil = false;
00275 }
00276
00277
00278 istring buff = from_unicode_temp(low_buff);
00279 int length = buff.length();
00280 buff.shrink();
00281 tokenizer parser("\1", "=");
00282 parser.parse(buff);
00283 info = parser.table();
00284 return true;
00285 #endif
00286 }
00287
00288 bool ini_configurator::put_section(const istring §ion,
00289 const string_table &info)
00290 {
00291 #ifdef __WIN32__
00292 tokenizer parser("\1", "=");
00293 parser.table() = info;
00294 istring flat = parser.text_form();
00295 flat += "\1\1";
00296 int len = flat.length();
00297 for (int i = 0; i < len; i++) {
00298 if (flat[i] == '\1') {
00299 flat[i] = '\0';
00300 if (flat[i+1] == ' ') {
00301
00302
00303 flat[i] = ' ';
00304 flat[i + 1] = '\0';
00305 }
00306 }
00307 }
00308 return WritePrivateProfileSection(to_unicode_temp(section),
00309 to_unicode_temp(flat), to_unicode_temp(name()));
00310 #else
00311
00312 bool to_return = _parser->put_section(section, info);
00313
00314 write_ini_file();
00315 return to_return;
00316 #endif
00317 }
00318
00319 #ifdef __WIN32__
00320 bool ini_configurator::put_profile_string(const istring §ion,
00321 const istring &entry, const istring &to_store)
00322 {
00323 return bool(WritePrivateProfileString(to_unicode_temp(section),
00324 entry.length() ? (flexichar *)to_unicode_temp(entry) : NIL,
00325 to_store.length() ? (flexichar *)to_unicode_temp(to_store) : NIL,
00326 to_unicode_temp(name())));
00327 }
00328
00329 void ini_configurator::get_profile_string(const istring §ion,
00330 const istring &entry, const istring &default_value,
00331 flexichar *return_buffer, int buffer_size)
00332 {
00333 GetPrivateProfileString(section.length() ?
00334 (flexichar *)to_unicode_temp(section) : NIL,
00335 entry.length() ? (flexichar *)to_unicode_temp(entry) : NIL,
00336 to_unicode_temp(default_value),
00337 return_buffer, buffer_size, to_unicode_temp(name()));
00338 }
00339 #endif
00340
00341 #endif //INI_CONFIG_IMPLEMENTATION_FILE
00342