diff options
author | alberth <alberth@openttd.org> | 2011-03-03 20:50:24 +0000 |
---|---|---|
committer | alberth <alberth@openttd.org> | 2011-03-03 20:50:24 +0000 |
commit | d19a9f5df5ca670857ae82ae8e02e065a0035974 (patch) | |
tree | b255320cccd5f987d03f0900186b7c5159ef2cc0 /src/ini.cpp | |
parent | b74de9ff7223b4402abdc1e0e8aad68a5187009e (diff) | |
download | openttd-d19a9f5df5ca670857ae82ae8e02e065a0035974.tar.xz |
(svn r22167) -Codechange: Extract IniLoadFile base class for loading ini files out of IniFile.
Diffstat (limited to 'src/ini.cpp')
-rw-r--r-- | src/ini.cpp | 292 |
1 files changed, 1 insertions, 291 deletions
diff --git a/src/ini.cpp b/src/ini.cpp index 35d8910c8..3dc1219bb 100644 --- a/src/ini.cpp +++ b/src/ini.cpp @@ -10,8 +10,6 @@ /** @file ini.cpp Definition of the IniItem class, related to reading/writing '*.ini' files. */ #include "stdafx.h" -#include "core/alloc_func.hpp" -#include "core/mem_func.hpp" #include "debug.h" #include "ini_type.h" #include "string_func.h" @@ -26,296 +24,8 @@ # include <shellapi.h> #endif -/** - * Construct a new in-memory item of an Ini file. - * @param parent the group we belong to - * @param name the name of the item - * @param len the length of the name of the item - */ -IniItem::IniItem(IniGroup *parent, const char *name, size_t len) : next(NULL), value(NULL), comment(NULL) -{ - if (len == 0) len = strlen(name); - - this->name = strndup(name, len); - *parent->last_item = this; - parent->last_item = &this->next; -} - -/** Free everything we loaded. */ -IniItem::~IniItem() -{ - free(this->name); - free(this->value); - free(this->comment); - - delete this->next; -} - -/** - * Replace the current value with another value. - * @param value the value to replace with. - */ -void IniItem::SetValue(const char *value) -{ - free(this->value); - this->value = strdup(value); -} - -/** - * Construct a new in-memory group of an Ini file. - * @param parent the file we belong to - * @param name the name of the group - * @param len the length of the name of the group - */ -IniGroup::IniGroup(IniFile *parent, const char *name, size_t len) : next(NULL), type(IGT_VARIABLES), item(NULL), comment(NULL) -{ - if (len == 0) len = strlen(name); - - this->name = strndup(name, len); - this->last_item = &this->item; - *parent->last_group = this; - parent->last_group = &this->next; - - if (parent->list_group_names == NULL) return; - - for (uint i = 0; parent->list_group_names[i] != NULL; i++) { - if (strcmp(this->name, parent->list_group_names[i]) == 0) { - this->type = IGT_LIST; - return; - } - } -} - -/** Free everything we loaded. */ -IniGroup::~IniGroup() -{ - free(this->name); - free(this->comment); - - delete this->item; - delete this->next; -} - -/** - * Get the item with the given name, and if it doesn't exist - * and create is true it creates a new item. - * @param name name of the item to find. - * @param create whether to create an item when not found or not. - * @return the requested item or NULL if not found. - */ -IniItem *IniGroup::GetItem(const char *name, bool create) -{ - for (IniItem *item = this->item; item != NULL; item = item->next) { - if (strcmp(item->name, name) == 0) return item; - } - - if (!create) return NULL; - - /* otherwise make a new one */ - return new IniItem(this, name, strlen(name)); -} - -/** - * Clear all items in the group - */ -void IniGroup::Clear() -{ - delete this->item; - this->item = NULL; - this->last_item = &this->item; -} - -/** - * Construct a new in-memory Ini file representation. - * @param list_group_names A NULL terminated list with groups that should be - * loaded as lists instead of variables. - */ -IniFile::IniFile(const char * const *list_group_names) : group(NULL), comment(NULL), list_group_names(list_group_names) -{ - this->last_group = &this->group; -} - -/** Free everything we loaded. */ -IniFile::~IniFile() -{ - free(this->comment); - delete this->group; -} - -/** - * Get the group with the given name, and if it doesn't exist - * create a new group. - * @param name name of the group to find. - * @param len the maximum length of said name. - * @return the requested group. - */ -IniGroup *IniFile::GetGroup(const char *name, size_t len) +IniFile::IniFile(const char * const *list_group_names) : IniLoadFile(list_group_names) { - if (len == 0) len = strlen(name); - - /* does it exist already? */ - for (IniGroup *group = this->group; group != NULL; group = group->next) { - if (!strncmp(group->name, name, len) && group->name[len] == 0) { - return group; - } - } - - /* otherwise make a new one */ - IniGroup *group = new IniGroup(this, name, len); - group->comment = strdup("\n"); - return group; -} - -/** - * Remove the group with the given name. - * @param name name of the group to remove. - */ -void IniFile::RemoveGroup(const char *name) -{ - size_t len = strlen(name); - IniGroup *prev = NULL; - IniGroup *group; - - /* does it exist already? */ - for (group = this->group; group != NULL; prev = group, group = group->next) { - if (strncmp(group->name, name, len) == 0) { - break; - } - } - - if (group == NULL) return; - - if (prev != NULL) { - prev->next = prev->next->next; - if (this->last_group == &group->next) this->last_group = &prev->next; - } else { - this->group = this->group->next; - if (this->last_group == &group->next) this->last_group = &this->group; - } - - group->next = NULL; - delete group; -} - -/** - * Load the Ini file's data from the disk. - * @param filename the file to load. - * @pre nothing has been loaded yet. - */ -void IniFile::LoadFromDisk(const char *filename) -{ - assert(this->last_group == &this->group); - - char buffer[1024]; - IniGroup *group = NULL; - - char *comment = NULL; - uint comment_size = 0; - uint comment_alloc = 0; - - size_t end; - /* - * Now we are going to open a file that contains no more than simple - * plain text. That would raise the question: "why open the file as - * if it is a binary file?". That's simple... Microsoft, in all - * their greatness and wisdom decided it would be useful if ftell - * is aware of '\r\n' and "sees" that as a single character. The - * easiest way to test for that situation is by searching for '\n' - * and decrease the value every time you encounter a '\n'. This will - * thus also make ftell "see" the '\r' when it is not there, so the - * result of ftell will be highly unreliable. So to work around this - * marvel of wisdom we have to open in as a binary file. - */ - FILE *in = FioFOpenFile(filename, "rb", DATA_DIR, &end); - if (in == NULL) return; - - end += ftell(in); - - /* for each line in the file */ - while ((size_t)ftell(in) < end && fgets(buffer, sizeof(buffer), in)) { - char c, *s; - /* trim whitespace from the left side */ - for (s = buffer; *s == ' ' || *s == '\t'; s++) {} - - /* trim whitespace from right side. */ - char *e = s + strlen(s); - while (e > s && ((c = e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--; - *e = '\0'; - - /* skip comments and empty lines */ - if (*s == '#' || *s == ';' || *s == '\0') { - uint ns = comment_size + (e - s + 1); - uint a = comment_alloc; - /* add to comment */ - if (ns > a) { - a = max(a, 128U); - do a *= 2; while (a < ns); - comment = ReallocT(comment, comment_alloc = a); - } - uint pos = comment_size; - comment_size += (e - s + 1); - comment[pos + e - s] = '\n'; // comment newline - memcpy(comment + pos, s, e - s); // copy comment contents - continue; - } - - /* it's a group? */ - if (s[0] == '[') { - if (e[-1] != ']') { - ShowInfoF("ini: invalid group name '%s'", buffer); - } else { - e--; - } - s++; // skip [ - group = new IniGroup(this, s, e - s); - if (comment_size != 0) { - group->comment = strndup(comment, comment_size); - comment_size = 0; - } - } else if (group != NULL) { - char *t; - /* find end of keyname */ - if (*s == '\"') { - s++; - for (t = s; *t != '\0' && *t != '\"'; t++) {} - if (*t == '\"') *t = ' '; - } else { - for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++) {} - } - - /* it's an item in an existing group */ - IniItem *item = new IniItem(group, s, t - s); - if (comment_size != 0) { - item->comment = strndup(comment, comment_size); - comment_size = 0; - } - - /* find start of parameter */ - while (*t == '=' || *t == ' ' || *t == '\t') t++; - - bool quoted = (*t == '\"'); - /* remove starting quotation marks */ - if (*t == '\"') t++; - /* remove ending quotation marks */ - e = t + strlen(t); - if (e > t && e[-1] == '\"') e--; - *e = '\0'; - - /* If the value was not quoted and empty, it must be NULL */ - item->value = (!quoted && e == t) ? NULL : strndup(t, e - t); - } else { - /* it's an orphan item */ - ShowInfoF("ini: '%s' outside of group", buffer); - } - } - - if (comment_size > 0) { - this->comment = strndup(comment, comment_size); - comment_size = 0; - } - - free(comment); - fclose(in); } /** |