27typedef int (*ini_handler)(
void* user,
const char* section,
const char* name,
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,
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
124inline static char* rstrip(
char* s) {
125 char* p = s + strlen(s);
126 while (p > s && isspace((
unsigned char)(*--p))) *p =
'\0';
131inline static char* lskip(
const char* s) {
132 while (*s && isspace((
unsigned char)(*s))) s++;
139inline static char* find_chars_or_comment(
const char* s,
const char* chars) {
140#if INI_ALLOW_INLINE_COMMENTS
142 while (*s && (!chars || !strchr(chars, *s)) &&
143 !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
144 was_space = isspace((
unsigned char)(*s));
148 while (*s && (!chars || !strchr(chars, *s))) {
156inline static char* strncpy0(
char* dest,
const char* src,
size_t size) {
157 strncpy(dest, src, size);
158 dest[size - 1] =
'\0';
163inline int ini_parse_stream(ini_reader reader,
void* stream,
164 ini_handler handler,
void* user) {
167 char line[INI_MAX_LINE];
171 char section[MAX_SECTION] =
"";
172 char prev_name[MAX_NAME] =
"";
182 line = (
char*)malloc(INI_MAX_LINE);
189 while (reader(line, INI_MAX_LINE, stream) != NULL) {
194 if (lineno == 1 && (
unsigned char)start[0] == 0xEF &&
195 (
unsigned char)start[1] == 0xBB && (
unsigned char)start[2] == 0xBF) {
199 start = lskip(rstrip(start));
201 if (*start ==
';' || *start ==
'#') {
205#if INI_ALLOW_MULTILINE
206 else if (*prev_name && *start && start > line) {
208#if INI_ALLOW_INLINE_COMMENTS
209 end = find_chars_or_comment(start, NULL);
210 if (*end) *end =
'\0';
216 if (!handler(user, section, prev_name, start) && !error) error = lineno;
219 else if (*start ==
'[') {
221 end = find_chars_or_comment(start + 1,
"]");
224 strncpy0(section, start + 1,
sizeof(section));
232 end = find_chars_or_comment(start,
"=:");
233 if (*end ==
'=' || *end ==
':') {
235 name = rstrip(start);
236 value = lskip(end + 1);
237#if INI_ALLOW_INLINE_COMMENTS
238 end = find_chars_or_comment(value, NULL);
239 if (*end) *end =
'\0';
244 strncpy0(prev_name, name,
sizeof(prev_name));
245 if (!handler(user, section, name, value) && !error) error = lineno;
252#if INI_STOP_ON_FIRST_ERROR
265inline int ini_parse_file(FILE* file, ini_handler handler,
void* user) {
266 return ini_parse_stream((ini_reader)fgets, file, handler, user);
270inline int ini_parse(
const char* filename, ini_handler handler,
void* user) {
274 file = fopen(filename,
"r");
275 if (!file)
return -1;
276 error = ini_parse_file(file, handler, user);
283#ifndef __INIREADER_H__
284#define __INIREADER_H__
307 int ParseError()
const;
310 const std::set<std::string>& Sections()
const;
313 std::string Get(std::string section, std::string name,
314 std::string default_value)
const;
318 long GetInteger(std::string section, std::string name,
319 long default_value)
const;
324 double GetReal(std::string section, std::string name,
325 double default_value)
const;
331 bool GetBoolean(std::string section, std::string name,
332 bool default_value)
const;
336 std::map<std::string, std::string> _values;
337 std::set<std::string> _sections;
338 static std::string MakeKey(std::string section, std::string name);
339 static int ValueHandler(
void* user,
const char* section,
const char* name,
352inline INIReader::INIReader(std::string filename) {
353 _error = ini_parse(filename.c_str(), ValueHandler,
this);
356inline INIReader::INIReader(FILE* file) {
357 _error = ini_parse_file(file, ValueHandler,
this);
360inline int INIReader::ParseError()
const {
return _error; }
362inline const std::set<std::string>& INIReader::Sections()
const {
366inline std::string INIReader::Get(std::string section, std::string name,
367 std::string default_value)
const {
368 std::string key = MakeKey(section, name);
369 return _values.count(key) ? _values.at(key) : default_value;
372inline long INIReader::GetInteger(std::string section, std::string name,
373 long default_value)
const {
374 std::string valstr = Get(section, name,
"");
375 const char* value = valstr.c_str();
378 long n = strtol(value, &end, 0);
379 return end > value ? n : default_value;
382inline double INIReader::GetReal(std::string section, std::string name,
383 double default_value)
const {
384 std::string valstr = Get(section, name,
"");
385 const char* value = valstr.c_str();
387 double n = strtod(value, &end);
388 return end > value ? n : default_value;
391inline bool INIReader::GetBoolean(std::string section, std::string name,
392 bool default_value)
const {
393 std::string valstr = Get(section, name,
"");
395 std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);
396 if (valstr ==
"true" || valstr ==
"yes" || valstr ==
"on" || valstr ==
"1")
398 else if (valstr ==
"false" || valstr ==
"no" || valstr ==
"off" ||
402 return default_value;
405inline std::string INIReader::MakeKey(std::string section, std::string name) {
406 std::string key = section +
"=" + name;
408 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
412inline int INIReader::ValueHandler(
void* user,
const char* section,
413 const char* name,
const char* value) {
415 std::string key = MakeKey(section, name);
416 if (reader->_values[key].size() > 0) reader->_values[key] +=
"\n";
417 reader->_values[key] += value;
418 reader->_sections.insert(section);
Definition INIReader.h:292