aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-05-22 00:05:23 +0200
committerFederico Angelilli <code@fedang.net>2024-05-22 00:05:23 +0200
commit2881783a6d7bc37e03c8639caf8ac0b0876a01c6 (patch)
treee8d473cd4c94184d0f701ddad8ac9f6c5f10b4a0
parent08cce5d434620275a1b0a7b8726837714d479f01 (diff)
Handle lines longer than ANY_INI_BUFFER_SIZE
-rw-r--r--Makefile4
-rw-r--r--any_ini.h158
-rw-r--r--test/test.ini17
3 files changed, 136 insertions, 43 deletions
diff --git a/Makefile b/Makefile
index 5387d1f..b4f457c 100644
--- a/Makefile
+++ b/Makefile
@@ -2,12 +2,14 @@
SRCS = $(wildcard test/*.c)
TESTS = $(SRCS:.c=)
+.PHONY: all
+
all: tests
tests: $(TESTS)
%: %.c
- $(CC) -I. $< -o $@
+ $(CC) -I. $< -o $@ -ggdb
clean:
rm -rf $(TESTS)
diff --git a/any_ini.h b/any_ini.h
index aecdcd1..8efce03 100644
--- a/any_ini.h
+++ b/any_ini.h
@@ -20,11 +20,6 @@
#ifndef ANY_INI_INCLUDE
#define ANY_INI_INCLUDE
-#ifndef ANY_INI_MALLOC
-#include <stdlib.h>
-#define ANY_INI_MALLOC malloc
-#endif
-
#include <stddef.h>
#include <stdbool.h>
@@ -48,7 +43,7 @@ char *any_ini_next_value(any_ini_t *ini);
#ifndef ANY_INI_NO_STREAM
#ifndef ANY_INI_BUFFER_SIZE
-#define ANY_INI_BUFFER_SIZE 4096
+#define ANY_INI_BUFFER_SIZE 512
#endif
typedef char *(*any_ini_stream_read_t)(char *string, int size, void *stream);
@@ -84,6 +79,13 @@ char *any_ini_stream_next_value(any_ini_stream_t *ini);
#include <stdbool.h>
#include <ctype.h>
+
+#ifndef ANY_INI_MALLOC
+#include <stdlib.h>
+#define ANY_INI_MALLOC malloc
+#define ANY_INI_REALLOC realloc
+#endif
+
#ifndef ANY_INI_DELIM_COMMENT
#define ANY_INI_DELIM_COMMENT ';'
#endif
@@ -104,7 +106,6 @@ static size_t any_ini_trim(const char *source, size_t start, size_t end)
{
while (isspace(source[end - 1]))
end--;
-
return end - start;
}
@@ -242,7 +243,25 @@ static void any_ini_stream_read(any_ini_stream_t *ini)
ini->cursor = 0;
}
-static void any_ini_stream_skip(any_ini_stream_t *ini)
+static void any_ini_stream_skip_line(any_ini_stream_t *ini)
+{
+ while (true) {
+ switch (ini->buffer[ini->cursor]) {
+ case '\n':
+ return;
+
+ case '\0':
+ any_ini_stream_read(ini);
+ break;
+
+ default:
+ ini->cursor++;
+ break;
+ }
+ }
+}
+
+static void any_ini_stream_skip(any_ini_stream_t *ini, bool comment)
{
while (!ini->eof) {
switch (ini->buffer[ini->cursor]) {
@@ -252,12 +271,22 @@ static void any_ini_stream_skip(any_ini_stream_t *ini)
case '\r':
break;
- // Discard the current line
- case '\n':
+ case '\0':
+ any_ini_stream_read(ini);
+ continue;
+
case ANY_INI_DELIM_COMMENT:
#ifdef ANY_INI_DELIM_COMMENT2
case ANY_INI_DELIM_COMMENT2:
#endif
+ if (!comment)
+ return;
+
+ any_ini_stream_skip_line(ini);
+ // fallthrough
+
+ // Discard the current line
+ case '\n':
ini->line++;
any_ini_stream_read(ini);
continue;
@@ -269,13 +298,74 @@ static void any_ini_stream_skip(any_ini_stream_t *ini)
}
}
+static char *any_ini_stream_until(any_ini_stream_t *ini, size_t start, char c)
+{
+ char *tmp, *value = NULL;
+ size_t size = 0;
+ char prev = '\0';
+
+ bool done = false;
+ while (!ini->eof && !done) {
+ switch (ini->buffer[ini->cursor]) {
+ case '\0':
+ tmp = ANY_INI_REALLOC(value, size + ini->cursor - start);
+ if (!tmp) return value;
+
+ memcpy(tmp + size, ini->buffer + start, ini->cursor - start);
+ size += ini->cursor - start;
+ value = tmp;
+
+ any_ini_stream_read(ini);
+ start = 0;
+ break;
+
+ // Stop at line boundaries
+ case '\n':
+ done = true;
+ break;
+
+#ifndef ANY_INI_NO_INLINE_COMMENT
+ case ANY_INI_DELIM_COMMENT:
+#ifdef ANY_INI_DELIM_COMMENT2
+ case ANY_INI_DELIM_COMMENT2:
+#endif
+ if (isspace(prev)) {
+ done = true;
+ break;
+ }
+ // fallthrough
+#endif
+ default:
+ if (ini->buffer[ini->cursor] == c) {
+ done = true;
+ break;
+ }
+
+ prev = ini->buffer[ini->cursor];
+ ini->cursor++;
+ break;
+
+ }
+ }
+
+ tmp = ANY_INI_REALLOC(value, size + ini->cursor - start);
+ if (!tmp) return value;
+
+ memcpy(tmp + size, ini->buffer + start, ini->cursor - start);
+ size = any_ini_trim(tmp, 0, size + ini->cursor - start);
+ tmp[size] = '\0';
+ return tmp;
+}
+
void any_ini_stream_init(any_ini_stream_t *ini, any_ini_stream_read_t read, void *stream)
{
- ini->cursor = 0;
ini->line = 1;
ini->read = read;
ini->stream = stream;
- ini->eof = read(ini->buffer, ANY_INI_BUFFER_SIZE, stream) == NULL;
+
+ // Init buffer
+ memset(ini->buffer, 0, ANY_INI_BUFFER_SIZE);
+ any_ini_stream_read(ini);
}
void any_ini_file_init(any_ini_stream_t *ini, FILE *file)
@@ -290,38 +380,29 @@ bool any_ini_stream_eof(any_ini_stream_t *ini)
char *any_ini_stream_next_section(any_ini_stream_t *ini)
{
- any_ini_stream_skip(ini);
+ any_ini_stream_skip(ini, true);
if (ini->eof || ini->buffer[ini->cursor] != ANY_INI_SECTION_START)
return NULL;
- size_t start = ++ini->cursor;
- while (isspace(ini->buffer[ini->cursor])) ++start;
-
- while (ini->buffer[ini->cursor] != '\n') ini->cursor++;
+ // Skip padding
+ ini->cursor++;
+ any_ini_stream_skip(ini, false);
- // NOTE: Does not handle the case where ANY_INI_SECTION_END is not found
- size_t end = ini->cursor;
- while (end > start && ini->buffer[end] != ANY_INI_SECTION_END)
- end--;
-
- size_t length = any_ini_trim(ini->buffer, start, end);
- return any_ini_copy(ini->buffer + start, length);
+ char *section = any_ini_stream_until(ini, ini->cursor, ANY_INI_SECTION_END);
+ any_ini_stream_skip_line(ini);
+ return section;
}
char *any_ini_stream_next_key(any_ini_stream_t *ini)
{
- any_ini_stream_skip(ini);
+ any_ini_stream_skip(ini, true);
- if (ini->eof || ini->buffer[ini->cursor] == ANY_INI_SECTION_START)
+ if (ini->eof || ini->buffer[ini->cursor] == ANY_INI_SECTION_START
+ || ini->buffer[ini->cursor] == ANY_INI_DELIM_PAIR)
return NULL;
- size_t start = ini->cursor;
- while (any_ini_skip_pair(ini->buffer, ini->cursor, true))
- ini->cursor++;
-
- size_t length = any_ini_trim(ini->buffer, start, ini->cursor);
- return any_ini_copy(ini->buffer + start, length);
+ return any_ini_stream_until(ini, ini->cursor, ANY_INI_DELIM_PAIR);
}
char *any_ini_stream_next_value(any_ini_stream_t *ini)
@@ -329,15 +410,10 @@ char *any_ini_stream_next_value(any_ini_stream_t *ini)
if (ini->eof || ini->buffer[ini->cursor] != ANY_INI_DELIM_PAIR)
return NULL;
- ++ini->cursor;
- any_ini_stream_skip(ini);
-
- size_t start = ini->cursor;
- while (any_ini_skip_pair(ini->buffer, ini->cursor, false))
- ini->cursor++;
-
- size_t length = any_ini_trim(ini->buffer, start, ini->cursor);
- return any_ini_copy(ini->buffer + start, length);
+ // Skip padding
+ ini->cursor++;
+ any_ini_stream_skip(ini, false);
+ return any_ini_stream_until(ini, ini->cursor, '\n');
}
#endif
diff --git a/test/test.ini b/test/test.ini
index c09d7e6..e575371 100644
--- a/test/test.ini
+++ b/test/test.ini
@@ -1,3 +1,10 @@
+[ciao]
+[ sus ]
+[ ; sus ]
+[ ; ciao
+
+ [ bogus section -- name 234<F9><F8>r32
+
ciao=sus
[hello]
@@ -5,13 +12,18 @@ world=true
this=is sparta
-my name is = slim shady
+my name is = slim shady
+my idea is = wrong but
+
+sus ; sus
123 = 456
; comment
; another
crazy = stuff ; here
+
+crumped=stuff;nocomment
; x = 1
;
xx = 123
@@ -28,3 +40,6 @@ crazy = stuff ; here
;
; indeed
+[bro]
+
+I know that this is long = but it really is really long you know but maybe even longer now I know that this is long = but it really is really long you know but maybe even longer now