src/ini.cpp
author rubidium
Thu, 18 Dec 2008 12:23:08 +0000
changeset 10436 8d3a9fbe8f19
parent 10082 44931aeaa000
permissions -rw-r--r--
(svn r14689) -Change: make configure die on commonly made user mistakes, like not having SDL development files or zlib headers installed; you can still compile a dedicated server or a binary without zlib, but you have to explicitly force it.
9999
d88ba8e0fd38 (svn r14156) -Fix (r14153): missing/wrong comments
smatz
parents: 9996
diff changeset
     1
/* $Id$ */
d88ba8e0fd38 (svn r14156) -Fix (r14153): missing/wrong comments
smatz
parents: 9996
diff changeset
     2
d88ba8e0fd38 (svn r14156) -Fix (r14153): missing/wrong comments
smatz
parents: 9996
diff changeset
     3
/** @file ini.cpp Definition of the IniItem class, related to reading/writing '*.ini' files. */
9996
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
     4
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
     5
#include "stdafx.h"
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
     6
#include "core/alloc_func.hpp"
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
     7
#include "core/math_func.hpp"
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
     8
#include "debug.h"
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
     9
#include "ini_type.h"
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    10
#include "string_func.h"
10039
1f236afd6cd1 (svn r14199) -Codechange: split fileio.h into fileio_type.h and fileio_func.h so not everything that includes saveload.h needs to include everything else too.
rubidium
parents: 10008
diff changeset
    11
#include "fileio_func.h"
9996
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    12
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    13
IniItem::IniItem(IniGroup *parent, const char *name, size_t len) : next(NULL), value(NULL), comment(NULL)
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    14
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    15
	if (len == 0) len = strlen(name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    16
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    17
	this->name = strndup(name, len);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    18
	*parent->last_item = this;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    19
	parent->last_item = &this->next;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    20
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    21
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    22
IniItem::~IniItem()
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    23
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    24
	free(this->name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    25
	free(this->value);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    26
	free(this->comment);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    27
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    28
	delete this->next;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    29
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    30
10008
fca6f9cf02ac (svn r14167) -Fix: items in some ini-groups got duplicated on save.
rubidium
parents: 10005
diff changeset
    31
void IniItem::SetValue(const char *value)
fca6f9cf02ac (svn r14167) -Fix: items in some ini-groups got duplicated on save.
rubidium
parents: 10005
diff changeset
    32
{
fca6f9cf02ac (svn r14167) -Fix: items in some ini-groups got duplicated on save.
rubidium
parents: 10005
diff changeset
    33
	free(this->value);
fca6f9cf02ac (svn r14167) -Fix: items in some ini-groups got duplicated on save.
rubidium
parents: 10005
diff changeset
    34
	this->value = strdup(value);
fca6f9cf02ac (svn r14167) -Fix: items in some ini-groups got duplicated on save.
rubidium
parents: 10005
diff changeset
    35
}
fca6f9cf02ac (svn r14167) -Fix: items in some ini-groups got duplicated on save.
rubidium
parents: 10005
diff changeset
    36
9996
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    37
IniGroup::IniGroup(IniFile *parent, const char *name, size_t len) : next(NULL), type(IGT_VARIABLES), item(NULL), comment(NULL)
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    38
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    39
	if (len == 0) len = strlen(name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    40
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    41
	this->name = strndup(name, len);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    42
	this->last_item = &this->item;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    43
	*parent->last_group = this;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    44
	parent->last_group = &this->next;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    45
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    46
	if (parent->list_group_names == NULL) return;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    47
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    48
	for (uint i = 0; parent->list_group_names[i] != NULL; i++) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    49
		if (strcmp(this->name, parent->list_group_names[i]) == 0) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    50
			this->type = IGT_LIST;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    51
			return;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    52
		}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    53
	}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    54
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    55
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    56
IniGroup::~IniGroup()
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    57
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    58
	free(this->name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    59
	free(this->comment);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    60
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    61
	delete this->item;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    62
	delete this->next;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    63
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    64
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    65
IniItem *IniGroup::GetItem(const char *name, bool create)
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    66
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    67
	IniItem *item;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    68
	size_t len = strlen(name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    69
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    70
	for (item = this->item; item != NULL; item = item->next) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    71
		if (strcmp(item->name, name) == 0) return item;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    72
	}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    73
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    74
	if (!create) return NULL;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    75
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    76
	/* otherwise make a new one */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    77
	return new IniItem(this, name, len);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    78
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    79
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    80
IniFile::IniFile(const char **list_group_names) : group(NULL), comment(NULL), list_group_names(list_group_names)
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    81
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    82
	this->last_group = &this->group;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    83
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    84
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    85
IniFile::~IniFile()
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    86
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    87
	free(this->comment);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    88
	delete this->group;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    89
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    90
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    91
IniGroup *IniFile::GetGroup(const char *name, size_t len)
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    92
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    93
	IniGroup *group;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    94
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    95
	if (len == 0) len = strlen(name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    96
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    97
	/* does it exist already? */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    98
	for (group = this->group; group != NULL; group = group->next) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
    99
		if (!memcmp(group->name, name, len) && group->name[len] == 0) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   100
			return group;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   101
		}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   102
	}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   103
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   104
	/* otherwise make a new one */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   105
	group = new IniGroup(this, name, len);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   106
	group->comment = strdup("\n");
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   107
	return group;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   108
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   109
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   110
void IniFile::RemoveGroup(const char *name)
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   111
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   112
	size_t len = strlen(name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   113
	IniGroup *prev = NULL;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   114
	IniGroup *group;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   115
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   116
	/* does it exist already? */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   117
	for (group = this->group; group != NULL; prev = group, group = group->next) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   118
		if (memcmp(group->name, name, len) == 0) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   119
			break;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   120
		}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   121
	}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   122
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   123
	if (group == NULL) return;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   124
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   125
	if (prev != NULL) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   126
		prev->next = prev->next->next;
10082
44931aeaa000 (svn r14257) -Fix (r14153): incorrect update of ini-file group tail pointer causing memory corruption.
rubidium
parents: 10064
diff changeset
   127
		if (this->last_group == &group->next) this->last_group = &prev->next;
9996
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   128
	} else {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   129
		this->group = this->group->next;
10082
44931aeaa000 (svn r14257) -Fix (r14153): incorrect update of ini-file group tail pointer causing memory corruption.
rubidium
parents: 10064
diff changeset
   130
		if (this->last_group == &group->next) this->last_group = &this->group;
9996
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   131
	}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   132
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   133
	group->next = NULL;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   134
	delete group;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   135
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   136
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   137
void IniFile::LoadFromDisk(const char *filename)
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   138
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   139
	assert(this->last_group == &this->group);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   140
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   141
	char buffer[1024], c, *s, *t, *e;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   142
	IniGroup *group = NULL;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   143
	IniItem *item = NULL;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   144
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   145
	char *comment = NULL;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   146
	uint comment_size = 0;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   147
	uint comment_alloc = 0;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   148
10003
7ce0cbe8575f (svn r14161) -Codechange: allow inis to be loaded from tars.
rubidium
parents: 9999
diff changeset
   149
	size_t end;
10064
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   150
	/*
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   151
	 * Now we are going to open a file that contains no more than simple
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   152
	 * plain text. That would raise the question: "why open the file as
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   153
	 * if it is a binary file?". That's simple... Microsoft, in all
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   154
	 * their greatness and wisdom decided it would be useful if ftell
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   155
	 * is aware of '\r\n' and "sees" that as a single character. The
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   156
	 * easiest way to test for that situation is by searching for '\n'
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   157
	 * and decrease the value every time you encounter a '\n'. This will
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   158
	 * thus also make ftell "see" the '\r' when it is not there, so the
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   159
	 * result of ftell will be highly unreliable. So to work around this
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   160
	 * marvel of wisdom we have to open in as a binary file.
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   161
	 */
14763b82c4f4 (svn r14231) -Fix: Windows binaries not able to read non-windows newlines ini files. For more detail read the 'attached' diff.
rubidium
parents: 10039
diff changeset
   162
	FILE *in = FioFOpenFile(filename, "rb", DATA_DIR, &end);
9996
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   163
	if (in == NULL) return;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   164
10003
7ce0cbe8575f (svn r14161) -Codechange: allow inis to be loaded from tars.
rubidium
parents: 9999
diff changeset
   165
	end += ftell(in);
7ce0cbe8575f (svn r14161) -Codechange: allow inis to be loaded from tars.
rubidium
parents: 9999
diff changeset
   166
9996
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   167
	/* for each line in the file */
10003
7ce0cbe8575f (svn r14161) -Codechange: allow inis to be loaded from tars.
rubidium
parents: 9999
diff changeset
   168
	while ((size_t)ftell(in) < end && fgets(buffer, sizeof(buffer), in)) {
9996
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   169
		/* trim whitespace from the left side */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   170
		for (s = buffer; *s == ' ' || *s == '\t'; s++) {}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   171
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   172
		/* trim whitespace from right side. */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   173
		e = s + strlen(s);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   174
		while (e > s && ((c = e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   175
		*e = '\0';
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   176
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   177
		/* skip comments and empty lines */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   178
		if (*s == '#' || *s == ';' || *s == '\0') {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   179
			uint ns = comment_size + (e - s + 1);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   180
			uint a = comment_alloc;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   181
			uint pos;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   182
			/* add to comment */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   183
			if (ns > a) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   184
				a = max(a, 128U);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   185
				do a *= 2; while (a < ns);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   186
				comment = ReallocT(comment, comment_alloc = a);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   187
			}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   188
			pos = comment_size;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   189
			comment_size += (e - s + 1);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   190
			comment[pos + e - s] = '\n'; // comment newline
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   191
			memcpy(comment + pos, s, e - s); // copy comment contents
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   192
			continue;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   193
		}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   194
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   195
		/* it's a group? */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   196
		if (s[0] == '[') {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   197
			if (e[-1] != ']') {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   198
				ShowInfoF("ini: invalid group name '%s'", buffer);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   199
			} else {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   200
				e--;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   201
			}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   202
			s++; // skip [
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   203
			group = new IniGroup(this, s, e - s);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   204
			if (comment_size) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   205
				group->comment = strndup(comment, comment_size);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   206
				comment_size = 0;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   207
			}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   208
		} else if (group) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   209
			/* find end of keyname */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   210
			if (*s == '\"') {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   211
				s++;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   212
				for (t = s; *t != '\0' && *t != '\"'; t++) {}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   213
				if (*t == '\"') *t = ' ';
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   214
			} else {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   215
				for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++) {}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   216
			}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   217
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   218
			/* it's an item in an existing group */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   219
			item = new IniItem(group, s, t-s);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   220
			if (comment_size) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   221
				item->comment = strndup(comment, comment_size);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   222
				comment_size = 0;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   223
			}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   224
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   225
			/* find start of parameter */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   226
			while (*t == '=' || *t == ' ' || *t == '\t') t++;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   227
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   228
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   229
			/* remove starting quotation marks */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   230
			if (*t == '\"') t++;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   231
			/* remove ending quotation marks */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   232
			e = t + strlen(t);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   233
			if (e > t && e[-1] == '\"') e--;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   234
			*e = '\0';
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   235
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   236
			item->value = strndup(t, e - t);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   237
		} else {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   238
			/* it's an orphan item */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   239
			ShowInfoF("ini: '%s' outside of group", buffer);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   240
		}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   241
	}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   242
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   243
	if (comment_size > 0) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   244
		this->comment = strndup(comment, comment_size);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   245
		comment_size = 0;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   246
	}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   247
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   248
	free(comment);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   249
	fclose(in);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   250
}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   251
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   252
bool IniFile::SaveToDisk(const char *filename)
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   253
{
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   254
	FILE *f;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   255
	IniGroup *group;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   256
	IniItem *item;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   257
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   258
	f = fopen(filename, "w");
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   259
	if (f == NULL) return false;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   260
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   261
	for (group = this->group; group != NULL; group = group->next) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   262
		if (group->comment) fputs(group->comment, f);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   263
		fprintf(f, "[%s]\n", group->name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   264
		for (item = group->item; item != NULL; item = item->next) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   265
			assert(item->value != NULL);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   266
			if (item->comment != NULL) fputs(item->comment, f);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   267
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   268
			/* protect item->name with quotes if needed */
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   269
			if (strchr(item->name, ' ') != NULL) {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   270
				fprintf(f, "\"%s\"", item->name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   271
			} else {
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   272
				fprintf(f, "%s", item->name);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   273
			}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   274
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   275
			fprintf(f, " = %s\n", item->value);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   276
		}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   277
	}
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   278
	if (this->comment) fputs(this->comment, f);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   279
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   280
	fclose(f);
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   281
	return true;
fceaf224b2f0 (svn r14153) -Codechange: split ini file reading/saving from settings.cpp.
rubidium
parents:
diff changeset
   282
}