shithub: libini

ref: e922ef10cc79b48a7085ec76f343bee5859be94b
dir: /ini.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>

void
tolowercase(char *c)
{
	while (*c != 0) {
		*c = tolower(*c);
		c++;
	}
}

int
extractsection(char *line, char **section)
{
	char *start, *end;
	
	start = strchr(line, '[');
	end = strchr(line, ']');
	
	if (start == nil || end == nil)
		return 0;
	
	*section = malloc(end-start);
	if (!section)
		sysfatal("error allocating section string: %r");
	
	if (!memcpy(*section, start+1, end-start-1))
		sysfatal("error copying section string: %r");
	
	(*section)[end-start-1] = 0;
	return 1;
}

int
extractkeyvalue(char *line, char **key, char **value)
{
	char *arg[2];
	
	arg[0] = nil;
	arg[1] = nil;
	
	if (getfields(line, arg, 2, 1, "=") == 0)
		return 0;
	
	*key = arg[0] ? strdup(arg[0]) : nil;
	*value = arg[1] ? strdup(arg[1]) : nil;
	
	if (!(key && value))
		sysfatal("error copying key/value strings: %r");
	return 1;
}

int
parseini(char *file, void (*f)(char*,char*,char*), int forcelower)
{
	char *line;
	int callback;
	Biobuf *bio = Bopen(file, OREAD);
	
	char *section = nil;
	char *key = nil;
	char *value = nil;
	
	if (!bio)
		return 0;
	
	while (line = Brdstr(bio, '\n', 1)) {
		if (!line)
			return 1;
		
		if (forcelower)
			tolowercase(line);
		
		callback = 0;
		if (*line == ';')
			goto endline;
		
		if (extractsection(line, &section))
			goto endline;
		
		if (callback = extractkeyvalue(line, &key, &value))
			goto endline;
			
endline:
		free(line);
		if (callback && f)
			f(section, key, value);
	}
	Bterm(bio);
	
	return 1;
}