
Fixed string truncation warnings by reducing max parameter lengths by one where applicable. The binlogrouter filename lengths are slightly different so using memcpy to work around the warnings is an adequate "solution" until the root of the problem is solved. Removed unnecessary CMake policy settings from qc_sqlite. Adding a self-dependency on the source file of an external project has no effect and only caused warnings to be logged.
177 lines
4.9 KiB
C
177 lines
4.9 KiB
C
/* inih -- simple .INI file parser
|
|
|
|
inih is released under the New BSD license (see LICENSE.txt). Go to the project
|
|
home page for more info:
|
|
|
|
http://code.google.com/p/inih/
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#include "ini.h"
|
|
|
|
#if !INI_USE_STACK
|
|
#include <stdlib.h>
|
|
#endif
|
|
|
|
#define MAX_SECTION 50
|
|
#define MAX_NAME 50
|
|
|
|
/* Strip whitespace chars off end of given string, in place. Return s. */
|
|
static char* rstrip(char* s)
|
|
{
|
|
char* p = s + strlen(s);
|
|
while (p > s && isspace((unsigned char)(*--p)))
|
|
*p = '\0';
|
|
return s;
|
|
}
|
|
|
|
/* Return pointer to first non-whitespace char in given string. */
|
|
static char* lskip(const char* s)
|
|
{
|
|
while (*s && isspace((unsigned char)(*s)))
|
|
s++;
|
|
return (char*)s;
|
|
}
|
|
|
|
/* Return pointer to first char c or ';' comment in given string, or pointer to
|
|
null at end of string if neither found. ';' must be prefixed by a whitespace
|
|
character to register as a comment. */
|
|
static char* find_char_or_comment(const char* s, char c)
|
|
{
|
|
int was_whitespace = 0;
|
|
while (*s && *s != c && !(was_whitespace && *s == ';')) {
|
|
was_whitespace = isspace((unsigned char)(*s));
|
|
s++;
|
|
}
|
|
return (char*)s;
|
|
}
|
|
|
|
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
|
|
static char* strncpy0(char* dest, const char* src, size_t size)
|
|
{
|
|
strncpy(dest, src, size);
|
|
dest[size - 1] = '\0';
|
|
return dest;
|
|
}
|
|
|
|
/* See documentation in header file. */
|
|
int ini_parse_file(FILE* file,
|
|
int (*handler)(void*, const char*, const char*,
|
|
const char*),
|
|
void* user)
|
|
{
|
|
/* Uses a fair bit of stack (use heap instead if you need to) */
|
|
#if INI_USE_STACK
|
|
char line[INI_MAX_LINE];
|
|
#else
|
|
char* line;
|
|
#endif
|
|
char section[MAX_SECTION] = "";
|
|
char prev_name[MAX_NAME] = "";
|
|
|
|
char* start;
|
|
char* end;
|
|
char* name;
|
|
char* value;
|
|
int lineno = 0;
|
|
int error = 0;
|
|
|
|
#if !INI_USE_STACK
|
|
line = (char*)malloc(INI_MAX_LINE);
|
|
if (!line) {
|
|
return -2;
|
|
}
|
|
#endif
|
|
|
|
/* Scan through file line by line */
|
|
while (fgets(line, INI_MAX_LINE, file) != NULL) {
|
|
lineno++;
|
|
|
|
start = line;
|
|
#if INI_ALLOW_BOM
|
|
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
|
|
(unsigned char)start[1] == 0xBB &&
|
|
(unsigned char)start[2] == 0xBF) {
|
|
start += 3;
|
|
}
|
|
#endif
|
|
start = lskip(rstrip(start));
|
|
|
|
if (*start == ';' || *start == '#') {
|
|
/* Per Python ConfigParser, allow '#' comments at start of line */
|
|
}
|
|
#if INI_ALLOW_MULTILINE
|
|
else if (*prev_name && *start && start > line) {
|
|
/* Non-black line with leading whitespace, treat as continuation
|
|
of previous name's value (as per Python ConfigParser). */
|
|
if (!handler(user, section, prev_name, start) && !error)
|
|
error = lineno;
|
|
}
|
|
#endif
|
|
else if (*start == '[') {
|
|
/* A "[section]" line */
|
|
end = find_char_or_comment(start + 1, ']');
|
|
if (*end == ']') {
|
|
*end = '\0';
|
|
strncpy0(section, start + 1, sizeof(section) - 1);
|
|
*prev_name = '\0';
|
|
}
|
|
else if (!error) {
|
|
/* No ']' found on section line */
|
|
error = lineno;
|
|
}
|
|
}
|
|
else if (*start && *start != ';') {
|
|
/* Not a comment, must be a name[=:]value pair */
|
|
end = find_char_or_comment(start, '=');
|
|
if (*end != '=') {
|
|
end = find_char_or_comment(start, ':');
|
|
}
|
|
if (*end == '=' || *end == ':') {
|
|
*end = '\0';
|
|
name = rstrip(start);
|
|
value = lskip(end + 1);
|
|
end = find_char_or_comment(value, '\0');
|
|
if (*end == ';')
|
|
*end = '\0';
|
|
rstrip(value);
|
|
|
|
/* Valid name[=:]value pair found, call handler */
|
|
strncpy0(prev_name, name, sizeof(prev_name) - 1);
|
|
if (!handler(user, section, name, value) && !error)
|
|
error = lineno;
|
|
}
|
|
else if (!error) {
|
|
/* No '=' or ':' found on name[=:]value line */
|
|
error = lineno;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if !INI_USE_STACK
|
|
free(line);
|
|
#endif
|
|
|
|
return error;
|
|
}
|
|
|
|
/* See documentation in header file. */
|
|
int ini_parse(const char* filename,
|
|
int (*handler)(void*, const char*, const char*, const char*),
|
|
void* user)
|
|
{
|
|
FILE* file;
|
|
int error;
|
|
|
|
file = fopen(filename, "r");
|
|
if (!file)
|
|
return -1;
|
|
error = ini_parse_file(file, handler, user);
|
|
fclose(file);
|
|
return error;
|
|
}
|