28typedef int (*ini_handler)(
void* user,
const char* section,
const char* name,
const char* value);
31typedef char* (*ini_reader)(
char* str,
int num,
void* stream);
46int ini_parse(
const char* filename, ini_handler handler,
void* user);
50int ini_parse_file(FILE* file, ini_handler handler,
void* user);
54int ini_parse_stream(ini_reader reader,
void* stream, ini_handler handler,
void* user);
59#ifndef INI_ALLOW_MULTILINE
60#define INI_ALLOW_MULTILINE 1
66#define INI_ALLOW_BOM 1
72#ifndef INI_ALLOW_INLINE_COMMENTS
73#define INI_ALLOW_INLINE_COMMENTS 1
75#ifndef INI_INLINE_COMMENT_PREFIXES
76#define INI_INLINE_COMMENT_PREFIXES ";"
81#define INI_USE_STACK 1
85#ifndef INI_STOP_ON_FIRST_ERROR
86#define INI_STOP_ON_FIRST_ERROR 0
91#define INI_MAX_LINE 200
107#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
108#define _CRT_SECURE_NO_WARNINGS
119#define MAX_SECTION 50
123inline static char* rstrip(
char* s)
125 char* p = s + strlen(s);
126 while (p > s && isspace((
unsigned char)(*--p)))
134inline static char* lskip(
const char* s)
136 while (*s && isspace((
unsigned char)(*s)))
146inline static char* find_chars_or_comment(
const char* s,
const char* chars)
148#if INI_ALLOW_INLINE_COMMENTS
150 while (*s && (!chars || !strchr(chars, *s))
151 && !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s)))
153 was_space = isspace((
unsigned char)(*s));
157 while (*s && (!chars || !strchr(chars, *s)))
166inline static char* strncpy0(
char* dest,
const char* src,
size_t size)
168 strncpy(dest, src, size);
169 dest[size - 1] =
'\0';
174inline int ini_parse_stream(ini_reader reader,
void* stream, ini_handler handler,
void* user)
178 char line[INI_MAX_LINE];
182 char section[MAX_SECTION] =
"";
183 char prev_name[MAX_NAME] =
"";
193 line = (
char*)malloc(INI_MAX_LINE);
201 while (reader(line, INI_MAX_LINE, stream) != NULL)
207 if (lineno == 1 && (
unsigned char)start[0] == 0xEF && (
unsigned char)start[1] == 0xBB
208 && (
unsigned char)start[2] == 0xBF)
213 start = lskip(rstrip(start));
215 if (*start ==
';' || *start ==
'#')
220#if INI_ALLOW_MULTILINE
221 else if (*prev_name && *start && start > line)
223#if INI_ALLOW_INLINE_COMMENTS
224 end = find_chars_or_comment(start, NULL);
234 if (!handler(user, section, prev_name, start) && !error)
240 else if (*start ==
'[')
243 end = find_chars_or_comment(start + 1,
"]");
247 strncpy0(section, start + 1,
sizeof(section));
259 end = find_chars_or_comment(start,
"=:");
260 if (*end ==
'=' || *end ==
':')
263 name = rstrip(start);
264 value = lskip(end + 1);
265#if INI_ALLOW_INLINE_COMMENTS
266 end = find_chars_or_comment(value, NULL);
275 strncpy0(prev_name, name,
sizeof(prev_name));
276 if (!handler(user, section, name, value) && !error)
288#if INI_STOP_ON_FIRST_ERROR
304inline int ini_parse_file(FILE* file, ini_handler handler,
void* user)
306 return ini_parse_stream((ini_reader)fgets, file, handler, user);
310inline int ini_parse(
const char* filename, ini_handler handler,
void* user)
315 file = fopen(filename,
"r");
320 error = ini_parse_file(file, handler, user);
327#ifndef __INIREADER_H__
328#define __INIREADER_H__
352 int ParseError()
const;
355 const std::set<std::string>& Sections()
const;
358 std::string Get(std::string section, std::string name, std::string default_value)
const;
362 long GetInteger(std::string section, std::string name,
long default_value)
const;
367 double GetReal(std::string section, std::string name,
double default_value)
const;
373 bool GetBoolean(std::string section, std::string name,
bool default_value)
const;
377 std::map<std::string, std::string> _values;
378 std::set<std::string> _sections;
379 static std::string MakeKey(std::string section, std::string name);
380 static int ValueHandler(
void* user,
const char* section,
const char* name,
const char* value);
392inline INIReader::INIReader(std::string filename)
394 _error = ini_parse(filename.c_str(), ValueHandler,
this);
397inline INIReader::INIReader(FILE* file)
399 _error = ini_parse_file(file, ValueHandler,
this);
402inline int INIReader::ParseError()
const
407inline const std::set<std::string>& INIReader::Sections()
const
412inline std::string INIReader::Get(std::string section,
414 std::string default_value)
const
416 std::string key = MakeKey(section, name);
417 return _values.count(key) ? _values.at(key) : default_value;
420inline long INIReader::GetInteger(std::string section, std::string name,
long default_value)
const
422 std::string valstr = Get(section, name,
"");
423 const char* value = valstr.c_str();
426 long n = strtol(value, &end, 0);
427 return end > value ? n : default_value;
430inline double INIReader::GetReal(std::string section, std::string name,
double default_value)
const
432 std::string valstr = Get(section, name,
"");
433 const char* value = valstr.c_str();
435 double n = strtod(value, &end);
436 return end > value ? n : default_value;
439inline bool INIReader::GetBoolean(std::string section, std::string name,
bool default_value)
const
441 std::string valstr = Get(section, name,
"");
443 std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);
444 if (valstr ==
"true" || valstr ==
"yes" || valstr ==
"on" || valstr ==
"1")
448 else if (valstr ==
"false" || valstr ==
"no" || valstr ==
"off" || valstr ==
"0")
454 return default_value;
458inline std::string INIReader::MakeKey(std::string section, std::string name)
460 std::string key = section +
"=" + name;
462 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
466inline int INIReader::ValueHandler(
void* user,
472 std::string key = MakeKey(section, name);
473 if (reader->_values[key].size() > 0)
475 reader->_values[key] +=
"\n";
477 reader->_values[key] += value;
478 reader->_sections.insert(section);
Definition INIReader.h:337