/* Example: parse an INI file using a custom ini_reader and a string buffer for I/O This example was provided by Grzegorz Sokół (https://github.com/greg-sokol) in pull request https://github.com/benhoyt/inih/pull/38 */ #include #include #include #include "../ini.h" typedef struct { int version; const char* name; const char* email; } configuration; typedef struct { const char* ptr; int bytes_left; } buffer_ctx; static char* ini_buffer_reader(char* str, int num, void* stream) { buffer_ctx* ctx = (buffer_ctx*)stream; int idx = 0; char newline = 0; if (ctx->bytes_left <= 0) return NULL; for (idx = 0; idx < num - 1; ++idx) { if (idx == ctx->bytes_left) break; if (ctx->ptr[idx] == '\n') newline = '\n'; else if (ctx->ptr[idx] == '\r') newline = '\r'; if (newline) break; } memcpy(str, ctx->ptr, idx); str[idx] = 0; ctx->ptr += idx + 1; ctx->bytes_left -= idx + 1; if (newline && ctx->bytes_left > 0 && ((newline == '\r' && ctx->ptr[0] == '\n') || (newline == '\n' && ctx->ptr[0] == '\r'))) { ctx->bytes_left--; ctx->ptr++; } return str; } static int handler(void* user, const char* section, const char* name, const char* value) { configuration* pconfig = (configuration*)user; #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 if (MATCH("protocol", "version")) { pconfig->version = atoi(value); } else if (MATCH("user", "name")) { pconfig->name = strdup(value); } else if (MATCH("user", "email")) { pconfig->email = strdup(value); } else { return 0; /* unknown section/name, error */ } return 1; } int main(int argc, char* argv[]) { configuration config; buffer_ctx ctx; ctx.ptr = "; Test ini buffer\n" "\n" "[protocol]\n" "version=42\n" "\n" "[user]\n" "name = Jane Smith\n" "email = jane@smith.com\n"; ctx.bytes_left = strlen(ctx.ptr); if (ini_parse_stream((ini_reader)ini_buffer_reader, &ctx, handler, &config) < 0) { printf("Can't load buffer\n"); return 1; } printf("Config loaded from buffer: version=%d, name=%s, email=%s\n", config.version, config.name, config.email); return 0; }