📄 ini.cpp
字号:
//
// Copyright (c) 2005, Wei Mingzhi <whistler@openoffice.org>
// All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301, USA
//
#include "ini.h"
void CIniFile::trim(char *str)
{
int pos = 0;
char *dest = str;
// skip leading blanks
while (str[pos] <= ' ' && str[pos] > 0)
pos++;
while (str[pos]) {
*(dest++) = str[pos];
pos++;
}
*(dest--) = '\0'; // store the null
// remove trailing blanks
while (dest >= str && *dest <= ' ' && *dest > 0)
*(dest--) = '\0';
}
CIniFile::CIniFile():
ini(NULL), key_count(0), current_size(0)
{
#ifdef WITH_HASH
m_Hash = (ini_key_t **)calloc(INI_HASH_KEY_SIZE, sizeof(ini_key_t *));
if (m_Hash == NULL) {
printf("Memory allocation error !\n");
exit(1);
}
#endif
}
CIniFile::CIniFile(const char *filename):
ini(NULL), key_count(0), current_size(0)
{
#ifdef WITH_HASH
m_Hash = (ini_key_t **)calloc(INI_HASH_KEY_SIZE, sizeof(ini_key_t *));
if (m_Hash == NULL) {
printf("Memory allocation error !\n");
exit(1);
}
#endif
Load(filename);
}
CIniFile::~CIniFile()
{
FreeAllTheStuff();
#ifdef WITH_HASH
free(m_Hash);
#endif
}
void CIniFile::FreeAllTheStuff()
{
int i, j;
if (ini) {
// free all the memory allocated for this ini file
for (i = 0; i < key_count; i++) {
// delete all the values in this key...
for (j = 0; j < ini[i].value_count; j++) {
free(ini[i].values[j].value);
free(ini[i].values[j].value_name);
}
free(ini[i].values);
free(ini[i].key_name);
}
free(ini);
ini = NULL;
}
#ifdef WITH_HASH
// null out the hash table
memset(m_Hash, 0, sizeof(ini_key_t *) * INI_HASH_KEY_SIZE);
#endif
}
void CIniFile::Load(const char *filename)
{
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
printf("cannot load ini file %s\n", filename);
return;
}
// if we already have a file loaded, free it first
if (Valid()) {
FreeAllTheStuff();
}
char str[256], section[256];
section[0] = '\0';
while (fgets(str, 256, fp)) {
trim(str); // trim all the blanks or linefeeds
// skip all comment lines or empty lines
if (!str[0] || str[0] == ';' || str[0] == '/' || str[0] == '#')
continue;
int length = strlen(str);
char *p;
// check if this is a session line (e.g., [SECTION])
if (str[0] == '[' && str[length - 1] == ']') {
strcpy(section, &str[1]);
section[length - 2] = 0; // remove the ]
trim(section); // trim section name after removing []
} else if ((p = strchr(str, '=')) != NULL) {
*(p++) = '\0';
trim(str);
trim(p);
Set(section, str, p);
}
}
fclose(fp); // load completed; close the file
}
void CIniFile::Save(const char *filename)
{
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
printf("cannot save to INI file: %s\n", filename);
return;
}
fprintf(fp, "; %s\n\n", filename);
for (int i = 0; i < key_count; i++) {
fprintf(fp, "[%s]\n", ini[i].key_name); // write the key name
// write all the values...
for (int j = 0; j < ini[i].value_count; j++) {
fprintf(fp, "%s=%s\n", ini[i].values[j].value_name, ini[i].values[j].value);
}
fprintf(fp, "\n"); // add a line feed
}
fclose(fp); // save completed; close the file
}
// set the value in ini file
void CIniFile::Set(const char *key, const char *value, const char *set)
{
ini_key_t *pKey = NULL;
ini_value_t *pValue = NULL;
int i;
#ifdef WITH_HASH
// search if this key already exists...
// first search in the hash table...
unsigned short vhash = GetHashValue(key) % INI_HASH_KEY_SIZE;
if (m_Hash[vhash] != NULL && strcasecmp(key, m_Hash[vhash]->key_name) == 0) {
pKey = m_Hash[vhash]; // found this value in the hash table
}
#endif
if (pKey == NULL) {
// not found in the hash table, do a normal search...
for (i = 0; i < key_count; i++) {
if (strcasecmp(ini[i].key_name, key) == 0) {
pKey = &ini[i];
break;
}
}
}
// if this is a new key, try to allocate memory for it
if (pKey == NULL) {
key_count++;
// if we don't have enough room for this new key, try to allocate more memory
if (key_count > current_size) {
current_size += INI_SIZE_INCREMENT;
if (ini) {
ini = (ini_key_t *)realloc(ini, sizeof(ini_key_t) * current_size);
} else {
ini = (ini_key_t *)malloc(sizeof(ini_key_t) * current_size);
}
if (!ini) {
printf("Memory allocation error !");
exit(1);
}
}
pKey = &ini[key_count - 1];
pKey->key_name = strdup(key);
pKey->values = NULL;
pKey->value_count = 0;
pKey->current_size = 0;
#ifdef WITH_HASH
memset(pKey->hash, 0, sizeof(pKey->hash)); // zero out the hash table
// store this new key in the hash table...
unsigned short vhash = GetHashValue(pKey->key_name) % INI_HASH_KEY_SIZE;
m_Hash[vhash] = pKey;
#endif
}
#ifdef WITH_HASH
// search if the value is already in the key...
vhash = GetHashValue(value) % INI_HASH_VALUE_SIZE;
if (pKey->hash[vhash] != NULL && strcasecmp(value, pKey->hash[vhash]->value_name) == 0) {
pValue = pKey->hash[vhash]; // we have found the value in the hash table
}
#endif
if (pValue == NULL) {
// value is not found in the hash table, do a normal search...
for (i = 0; i < pKey->value_count; i++) {
if (strcasecmp(value, pKey->values[i].value_name) == 0) {
// we have found the value
pValue = &pKey->values[i];
break;
}
}
}
if (pValue != NULL) {
// this value already exists in the key...
free(pValue->value);
pValue->value = strdup(set);
if (pValue->value == NULL) {
printf("Memory allocation error !");
exit(1);
}
} else {
// this is a new value...
pKey->value_count++;
// if we don't have enough room for this new value, try to allocate more memory
if (pKey->value_count > pKey->current_size) {
pKey->current_size += INI_SIZE_INCREMENT;
if (pKey->values) {
pKey->values = (ini_value_t *)realloc(pKey->values, sizeof(ini_value_t) * pKey->current_size);
} else {
pKey->values = (ini_value_t *)malloc(sizeof(ini_value_t) * pKey->current_size);
}
if (pKey->values == NULL) {
printf("Memory allocation error !");
exit(1);
}
}
pKey->values[pKey->value_count - 1].value_name = strdup(value);
pKey->values[pKey->value_count - 1].value = strdup(set);
if (pKey->values[pKey->value_count - 1].value == NULL ||
pKey->values[pKey->value_count - 1].value_name == NULL) {
printf("Memory allocation error !");
exit(1);
}
trim(pKey->values[pKey->value_count - 1].value);
trim(pKey->values[pKey->value_count - 1].value_name);
#ifdef WITH_HASH
// store this new value in the hash table
unsigned short vhash = GetHashValue(pKey->values[pKey->value_count - 1].value_name) % INI_HASH_VALUE_SIZE;
pKey->hash[vhash] = &pKey->values[pKey->value_count - 1];
#endif
}
}
// get a value from the ini file
const char *CIniFile::Get(const char *key, const char *value, const char *def)
{
ini_key_t *pKey = NULL;
int i;
#ifdef WITH_HASH
// search for the key name...
// first search in the hash table...
unsigned short vhash = GetHashValue(key) % INI_HASH_KEY_SIZE;
if (m_Hash[vhash] != NULL && strcasecmp(key, m_Hash[vhash]->key_name) == 0) {
pKey = m_Hash[vhash]; // found this value in the hash table
}
#endif
if (pKey == NULL) {
// Not found in the hash table, do a normal search...
for (i = 0; i < key_count; i++) {
if (strcasecmp(ini[i].key_name, key) == 0) {
pKey = &ini[i];
break;
}
}
}
if (pKey != NULL) {
#ifdef WITH_HASH
// key found, search for the value in this key...
vhash = GetHashValue(value) % INI_HASH_VALUE_SIZE;
if (pKey->hash[vhash] != NULL && strcasecmp(value, pKey->hash[vhash]->value_name) == 0) {
return pKey->hash[vhash]->value;
}
#endif
// not found in the hash table, do a normal linear search...
for (i = 0; i < pKey->value_count; i++) {
if (strcasecmp(pKey->values[i].value_name, value) == 0) {
return pKey->values[i].value;
}
}
}
return def; // value is not found; use default value
}
#ifdef WITH_HASH
/**
* This hash function has been taken from an Article in Dr Dobbs Journal.
* This is normally a collision-free function, distributing keys evenly.
* Collision can be avoided by comparing the key itself in last resort.
*/
unsigned short CIniFile::GetHashValue(const char *sz)
{
unsigned short hash = 0;
while (*sz) {
// convert all the characters to be upper case, so
// that it will be case insensitive
char a = *sz;
if (a >= 'a' && a <= 'z') {
a -= 'a' - 'A';
}
hash += (unsigned short)a;
hash += (hash << 10);
hash ^= (hash >> 6);
sz++;
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -