Skip to content

Instantly share code, notes, and snippets.

@fbstj
Last active December 11, 2015 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fbstj/4674888 to your computer and use it in GitHub Desktop.
Save fbstj/4674888 to your computer and use it in GitHub Desktop.
ini file parsing
#include <string.h>
#include <stdio.h>
enum ini_parts {
ini_section, ini_key, ini_value,
ini_section_start = '[', ini_section_end=']',
ini_key_value = '=',
ini_comment = ';'
};
static char valid_token(const char token[])
{
return strchr(token, ini_section_start) == NULL
&& strchr(token, ini_section_end) == NULL
&& strchr(token, ini_comment) == NULL;
}
// find the start and length of the next section title
char *ini_next_section(char * const file, int * const length)
{
char * start, * end;
start = strchr(file, ini_section_start);
if (start == NULL) return NULL;
end = strchr(++start, ini_section_end);
if (end == NULL) return NULL;
*length = end - start;
return start;
}
int ini_find_value(const char file[], const char section[], const char key[], char * const value)
{
size_t _sl = strlen(section) + 2, _kl = strlen(key) + 1, _end;
char _section[_sl], _key[_kl];
const char * _start, * _next, * _value;
if (!valid_token(section) || !valid_token(key))
return -1;
sprintf(_section, "%c%s%c", ini_section_start, section, ini_section_end);
sprintf(_key, "%s%c", key, ini_key_value);
_start = strstr(file, _section);
if (_start == NULL) return -2; // no '[section]'
_value = strstr(_start + _sl, _key);
if (_value == NULL) return -3; // no 'key='
_value += _kl;
_next = strchr(_start + _sl, ini_section_start);
if (_next == NULL) _next = file + strlen(file);
if (_value > _next) return -4; // 'key=' is after the next '[section]'
_end = strcspn(_value, "\n\r;");
memcpy(value, _value, _end);
value[_end] = 0;
return _end;
}
/* test ini.c */
#include <stdio.h>
#include <stdlib.h>
size_t fsize(FILE * const file)
{
size_t size = -1;
fseek(file, 0, SEEK_END);
size = ftell(file);
rewind(file);
return size;
}
char * fgeta(FILE * const file)
{
char * buffer = NULL;
size_t string_size, read_size;
if (file)
{
string_size = fsize(file);
buffer = (char*) malloc(sizeof(char) * (string_size + 1));
read_size = fread(buffer, sizeof(char), string_size, file);
buffer[string_size + 1] = '\0';
if (string_size != read_size)
{
free(buffer);
buffer = NULL;
}
}
return buffer;
}
extern int ini_find_value(const char file[], const char section[], const char key[], char * const value);
void test_ini(const char file[], const char section[], const char key[])
{
static char value[200];
if (ini_find_value(file, section, key, value) < 0)
fprintf(stderr, "![%s]%s not found\n", section, key);
else
printf("[%s]%s=%s\n", section, key, value);
}
int main(int argc, char **argv)
{
char * file = fgeta(fopen(argv[1], "r"));
test_ini(file, "section","key");
test_ini(file, "section","key2");
test_ini(file, "section","key3");
test_ini(file, "section","bcde");
test_ini(file, "section","prev");
test_ini(file, "next","prev");
test_ini(file, "next","test");
test_ini(file, "test","test");
test_ini(file, "test=0","test");
}
[section]
key=1
key2=3;comment
bcde=fghi
[next];section comment
prev=four;comment;with;comments
[test]
[test=0]
test=3
;end comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment