27 typedef int (*ini_handler)(
void* user,
const char* section,
28 const char* name,
const char* value);
31 typedef char* (*ini_reader)(
char* str,
int num,
void* stream);
46 int ini_parse(
const char* filename, ini_handler handler,
void* user);
50 int ini_parse_file(FILE* file, ini_handler handler,
void* user);
54 int ini_parse_stream(ini_reader reader,
void* stream, ini_handler handler,
60 #ifndef INI_ALLOW_MULTILINE
61 #define INI_ALLOW_MULTILINE 1
67 #define INI_ALLOW_BOM 1
73 #ifndef INI_ALLOW_INLINE_COMMENTS
74 #define INI_ALLOW_INLINE_COMMENTS 1
76 #ifndef INI_INLINE_COMMENT_PREFIXES
77 #define INI_INLINE_COMMENT_PREFIXES ";"
82 #define INI_USE_STACK 1
86 #ifndef INI_STOP_ON_FIRST_ERROR
87 #define INI_STOP_ON_FIRST_ERROR 0
92 #define INI_MAX_LINE 200
108 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
109 #define _CRT_SECURE_NO_WARNINGS
120 #define MAX_SECTION 50
124 inline static char* rstrip(
char* s)
126 char* p = s + strlen(s);
127 while (p > s && isspace((
unsigned char)(*--p)))
133 inline static char* lskip(
const char* s)
135 while (*s && isspace((
unsigned char)(*s)))
143 inline static char* find_chars_or_comment(
const char* s,
const char* chars)
145 #if INI_ALLOW_INLINE_COMMENTS
147 while (*s && (!chars || !strchr(chars, *s)) &&
148 !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
149 was_space = isspace((
unsigned char)(*s));
153 while (*s && (!chars || !strchr(chars, *s))) {
161 inline static char* strncpy0(
char* dest,
const char* src,
size_t size)
163 strncpy(dest, src, size);
164 dest[size - 1] =
'\0';
169 inline int ini_parse_stream(ini_reader reader,
void* stream, ini_handler handler,
174 char line[INI_MAX_LINE];
178 char section[MAX_SECTION] =
"";
179 char prev_name[MAX_NAME] =
"";
189 line = (
char*)malloc(INI_MAX_LINE);
196 while (reader(line, INI_MAX_LINE, stream) != NULL) {
201 if (lineno == 1 && (
unsigned char)start[0] == 0xEF &&
202 (
unsigned char)start[1] == 0xBB &&
203 (
unsigned char)start[2] == 0xBF) {
207 start = lskip(rstrip(start));
209 if (*start ==
';' || *start ==
'#') {
213 #if INI_ALLOW_MULTILINE
214 else if (*prev_name && *start && start > line) {
216 #if INI_ALLOW_INLINE_COMMENTS
217 end = find_chars_or_comment(start, NULL);
225 if (!handler(user, section, prev_name, start) && !error)
229 else if (*start ==
'[') {
231 end = find_chars_or_comment(start + 1,
"]");
234 strncpy0(section, start + 1,
sizeof(section));
244 end = find_chars_or_comment(start,
"=:");
245 if (*end ==
'=' || *end ==
':') {
247 name = rstrip(start);
248 value = lskip(end + 1);
249 #if INI_ALLOW_INLINE_COMMENTS
250 end = find_chars_or_comment(value, NULL);
257 strncpy0(prev_name, name,
sizeof(prev_name));
258 if (!handler(user, section, name, value) && !error)
267 #if INI_STOP_ON_FIRST_ERROR
281 inline int ini_parse_file(FILE* file, ini_handler handler,
void* user)
283 return ini_parse_stream((ini_reader)fgets, file, handler, user);
287 inline int ini_parse(
const char* filename, ini_handler handler,
void* user)
292 file = fopen(filename,
"r");
295 error = ini_parse_file(file, handler, user);
303 #ifndef __INIREADER_H__
304 #define __INIREADER_H__
320 explicit INIReader(
const std::string& filename);
328 int ParseError()
const;
331 const std::set<std::string>& Sections()
const;
334 std::string Get(
const std::string& section,
const std::string& name,
335 const std::string& default_value)
const;
339 long GetInteger(
const std::string& section,
const std::string& name,
long default_value)
const;
344 double GetReal(
const std::string& section,
const std::string& name,
double default_value)
const;
349 float GetFloat(
const std::string& section,
const std::string& name,
float default_value)
const;
354 bool GetBoolean(
const std::string& section,
const std::string& name,
bool default_value)
const;
358 std::map<std::string, std::string> _values;
359 std::set<std::string> _sections;
360 static std::string MakeKey(
const std::string& section,
const std::string& name);
361 static int ValueHandler(
void* user,
const char* section,
const char* name,
365 #endif // __INIREADER_H__
368 #ifndef __INIREADER__
369 #define __INIREADER__
375 inline INIReader::INIReader(
const std::string& filename)
377 _error = ini_parse(filename.c_str(), ValueHandler,
this);
380 inline INIReader::INIReader(FILE *file)
382 _error = ini_parse_file(file, ValueHandler,
this);
385 inline int INIReader::ParseError()
const
390 inline const std::set<std::string>& INIReader::Sections()
const
395 inline std::string INIReader::Get(
const std::string& section,
const std::string& name,
const std::string& default_value)
const
397 std::string key = MakeKey(section, name);
398 return _values.count(key) ? _values.at(key) : default_value;
401 inline long INIReader::GetInteger(
const std::string& section,
const std::string& name,
long default_value)
const
403 std::string valstr = Get(section, name,
"");
404 const char* value = valstr.c_str();
407 long n = strtol(value, &end, 0);
408 return end > value ? n : default_value;
411 inline double INIReader::GetReal(
const std::string& section,
const std::string& name,
double default_value)
const
413 std::string valstr = Get(section, name,
"");
414 const char* value = valstr.c_str();
416 double n = strtod(value, &end);
417 return end > value ? n : default_value;
420 inline float INIReader::GetFloat(
const std::string& section,
const std::string& name,
float default_value)
const
422 std::string valstr = Get(section, name,
"");
423 const char* value = valstr.c_str();
425 float n = strtof(value, &end);
426 return end > value ? n : default_value;
429 inline bool INIReader::GetBoolean(
const std::string& section,
const std::string& name,
bool default_value)
const
431 std::string valstr = Get(section, name,
"");
433 std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);
434 if (valstr ==
"true" || valstr ==
"yes" || valstr ==
"on" || valstr ==
"1")
436 else if (valstr ==
"false" || valstr ==
"no" || valstr ==
"off" || valstr ==
"0")
439 return default_value;
442 inline std::string INIReader::MakeKey(
const std::string& section,
const std::string& name)
444 std::string key = section +
"=" + name;
446 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
450 inline int INIReader::ValueHandler(
void* user,
const char* section,
const char* name,
454 std::string key = MakeKey(section, name);
455 if (reader->_values[key].size() > 0)
456 reader->_values[key] +=
"\n";
457 reader->_values[key] += value;
458 reader->_sections.insert(section);
462 #endif // __INIREADER__
Definition: INIReader.h:312