源自发布跨平台INI文件读写API(C++版本) V0.2.1
使用说明请参考该链接。
下面的版本对源码做了改进:
1. 修改了等号两边不能有空格或~t的问题
2. 增加了readBool方法
#include <string>
class IniFile
{
public:
IniFile(const std::string & fileName);
public:
virtual ~IniFile(void);
const std::string &getFileName() const;
const std::string &getSection() const;
void setSection(const std::string §ion);
bool write(const std::string &key, const std::string & value) const ;
bool write(const std::string &key, int value) const ;
std::string readStr(const std::string &key, const std::string &default_value) const;
int readInt(const std::string &key, int default_value) const;
bool readBool(const std::string &key, bool default_value) const;
public:
static int read_profile_string(const char *section, const char *key, char *value,
int size, const char *default_value, const char *file);
static int read_profile_int(const char *section, const char *key, int default_value,
const char *file);
static bool read_profile_bool(const char *section, const char *key, bool default_value,
const char *file);
static int write_profile_string(const char *section, const char *key,
const char *value, const char *file);
private:
static int load_ini_file(const char *file, char *buf, int *file_size);
static int newline(char c);
static int end_of_string(char c);
static int left_barce(char c);
static int right_brace(char c);
static int parse_file(const char *section, const char *key, const char *buf, int *sec_s, int *sec_e,
int *key_s, int *key_e, int *value_s, int *value_e);
private:
std::string m_fileName;
std::string m_section;
};
#endif
const int MAX_INI_FILE_SIZE = 1024 * 16;
IniFile::IniFile(const std::string & fileName)
{
m_fileName = fileName;
}
IniFile::~IniFile(void)
{
}
const std::string & IniFile::getFileName() const
{
return m_fileName;
}
void IniFile::setSection(const std::string §ion)
{
m_section = section;
}
bool IniFile::write(const std::string &key, const std::string & value) const
{
return write_profile_string(m_section.c_str(), key.c_str(), value.c_str(), m_fileName.c_str()) == 1 ? true : false;
}
bool IniFile::write(const std::string &key, int value) const
{
char tmp[64];
_snprintf(tmp, strlen(tmp) - 1, "%d", value);
return write(key, tmp);
}
std::string IniFile::readStr(const std::string &key, const std::string &default_value) const
{
char buf[4096];
read_profile_string(m_section.c_str(), key.c_str(), buf, sizeof(buf), default_value.c_str(), m_fileName.c_str());
return buf;
}
int IniFile::readInt(const std::string &key, int default_value) const
{
return read_profile_int(m_section.c_str(), key.c_str(), default_value, m_fileName.c_str());
}
bool IniFile::readBool(const std::string &key, bool default_value) const
{
return read_profile_bool(m_section.c_str(), key.c_str(), default_value, m_fileName.c_str());
}
const std::string &IniFile::getSection() const
{
return m_section;
}
int IniFile::load_ini_file(const char *file, char *buf, int *file_size)
{
FILE *in = NULL;
int i = 0;
*file_size = 0;
assert(file != NULL);
assert(buf != NULL);
in = fopen(file, "r");
if (NULL == in)
{
return 0;
}
buf[i] = fgetc(in);
// load initialization file
while (buf[i] != (char)EOF)
{
++i;
assert(i < MAX_INI_FILE_SIZE); // file too big, you can redefine MAX_INI_FILE_SIZE to fit the big file
buf[i] = fgetc(in);
}
buf[i] = '/0';
*file_size = i;
fclose(in);
return 1;
}
int IniFile::newline(char c)
{
return ('/n' == c || '/r' == c) ? 1 : 0;
}
int IniFile::end_of_string(char c)
{
return '/0' == c ? 1 : 0;
}
int IniFile::left_barce(char c)
{
return '[' == c ? 1 : 0;
}
int IniFile::right_brace(char c)
{
return ']' == c ? 1 : 0;
}
int IniFile::parse_file(const char *section, const char *key, const char *buf, int *sec_s, int *sec_e,
int *key_s, int *key_e, int *value_s, int *value_e)
{
const char *p = buf;
int i = 0;
assert(buf != NULL);
assert(section != NULL && strlen(section));
assert(key != NULL && strlen(key));
*sec_e = *sec_s = *key_e = *key_s = *value_s = *value_e = - 1;
while (!end_of_string(p[i]))
{
// find the section
if ((0 == i || newline(p[i - 1])) && left_barce(p[i]))
{
int section_start = i + 1;
// find the ']'
do
{
++i;
}
while (!right_brace(p[i]) && !end_of_string(p[i]));
//////////////////////////////////////////////////////////////////////////
if (i - section_start == strlen(section) && 0 == strncmp(p + section_start, section, strlen(section)))
{
int newline_start = 0;
++i;
// Skip over space char after ']'
while (isspace(p[i]))
{
++i;
}
// find the section
*sec_s = section_start;
*sec_e = i;
while (!(newline(p[i - 1]) && left_barce(p[i]))
&& !end_of_string(p[i]))
{
int j = 0;
// get a new line
newline_start = i;
while (!newline(p[i]) && !end_of_string(p[i]))
{
++i;
}
// now i is equal to end of the line
j = newline_start;
int valid = j;
if ('#' != p[j]) // skip over comment
{
while (j < i && p[j] != '=')
{
++j;
if (' ' != p[j] && '/t' != p[j] && '=' != p[j])
valid = j;
if ('=' == p[j])
{
if (j - newline_start == strlen(key) && strncmp(key, p + newline_start, strlen(key)) == 0)
{
// find the key ok
*key_s = newline_start;
*key_e = j - 1;
valid = j + 1;
while (' ' == p[valid] || '/t' == p[valid])
valid++;
*value_s = valid;
*value_e = i;
return 1;
}
}
}
}
++i;
}
}
}
else
{
++i;
}
}
return 0;
}
/**
*@brief read string in initialization file/n
* retrieves a string from the specified section in an initialization file
*@param section[in] name of the section containing the key name
*@param key[in] name of the key pairs to value
*@param value[in] pointer to the buffer that receives the retrieved string
*@param size[in] size of result's buffer
*@param default_value[in] default value of result
*@param file[in] path of the initialization file
*@return 1 : read success; /n 0 : read fail
*/
int IniFile::read_profile_string(const char *section, const char *key, char *value,
int size, const char *default_value, const char *file)
{
char buf[MAX_INI_FILE_SIZE] = {0};
int file_size;
int sec_s, sec_e, key_s, key_e, value_s, value_e;
// check parameters
assert(section != NULL && strlen(section));
assert(key != NULL && strlen(key));
assert(value != NULL);
assert(size > 0);
assert(file != NULL && strlen(key));
if (!load_ini_file(file, buf, &file_size))
{
if (default_value != NULL)
{
strncpy(value, default_value, size);
}
return 0;
}
if (!parse_file(section, key, buf, &sec_s, &sec_e, &key_s, &key_e, &value_s, &value_e))
{
if (default_value != NULL)
{
strncpy(value, default_value, size);
}
return 0; // not find the key
}
else
{
int cpcount = value_e - value_s;
if (size - 1 < cpcount)
{
cpcount = size - 1;
}
memset(value, 0, size);
memcpy(value, buf + value_s, cpcount);
value[cpcount] = '/0';
return 1;
}
}
/**
*@brief read int value in initialization file/n
* retrieves int value from the specified section in an initialization file
*@param section[in] name of the section containing the key name
*@param key[in] name of the key pairs to value
*@param default_value[in] default value of result
*@param file[in] path of the initialization file
*@return profile int value, if read fail, return default value
*/
int IniFile::read_profile_int(const char *section, const char *key, int default_value,
const char *file)
{
char value[32] = {0};
if (!read_profile_string(section, key, value, sizeof(value), NULL, file))
{
return default_value;
}
else
{
return atoi(value);
}
}
bool IniFile::read_profile_bool(const char *section, const char *key, bool default_value,
const char *file)
{
char value[32] = {0};
if (!read_profile_string(section, key, value, sizeof(value), NULL, file))
{
return default_value;
}
else
{
for(int i = 0; i < sizeof(value); ++i)
value[i]=tolower(value[i]);
std::string boolValue = static_cast<std::string>(value);
if ("true" == boolValue)
{
return true;
}
else
{
return false;
}
}
}
/**
* @brief write a profile string to a ini file
* @param section[in] name of the section, can't be NULL and empty string
* @param key[in] name of the key pairs to value, can't be NULL and empty string
* @param value[in] profile string value
* @param file[in] path of ini file
* @return 1 : success/n 0 : failure
*/
int IniFile::write_profile_string(const char *section, const char *key,
const char *value, const char *file)
{
char buf[MAX_INI_FILE_SIZE] = {0};
char w_buf[MAX_INI_FILE_SIZE] = {0};
int sec_s, sec_e, key_s, key_e, value_s, value_e;
int value_len = (int)strlen(value);
int file_size;
FILE *out;
// check parameters
assert(section != NULL && strlen(section));
assert(key != NULL && strlen(key));
assert(value != NULL);
assert(file != NULL && strlen(key));
if (!load_ini_file(file, buf, &file_size))
{
sec_s = - 1;
}
else
{
parse_file(section, key, buf, &sec_s, &sec_e, &key_s, &key_e, &value_s, &value_e);
}
if (-1 == sec_s)
{
if (0 == file_size)
{
sprintf(w_buf + file_size, "[%s]/n%s=%s/n", section, key, value);
}
else
{
// not find the section, then add the new section at end of the file
memcpy(w_buf, buf, file_size);
sprintf(w_buf + file_size, "/n[%s]/n%s=%s/n", section, key, value);
}
}
else if (-1 == key_s)
{
// not find the key, then add the new key=value at end of the section
memcpy(w_buf, buf, sec_e);
sprintf(w_buf + sec_e, "%s=%s/n", key, value);
sprintf(w_buf + sec_e + strlen(key) + strlen(value) + 2, buf + sec_e, file_size - sec_e);
}
else
{
// update value with new value
memcpy(w_buf, buf, value_s);
memcpy(w_buf + value_s, value, value_len);
memcpy(w_buf + value_s + value_len, buf + value_e, file_size - value_e);
}
out = fopen(file, "w");
if (NULL == out)
{
return 0;
}
if (-1 == fputs(w_buf, out))
{
fclose(out);
return 0;
}
fclose(out);
return 1;
}