Commit c34b4d9286f2fe2463336d64e0e273152c9c959f

Thomas de Grivel 2021-12-29T17:24:14

WIP

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..58d1e23
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/libkv.a
+/kv
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5a43713
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,40 @@
+
+all: build
+
+build: libkv kv
+
+LIBKV_SRC = buffer.c kv_path.c
+LIBKV_O   = buffer.o kv_path.o
+
+KV_SRC = kv.c
+KV_O   = kv.o
+
+CFLAGS ?=
+CFLAGS += -W -Wall -Werror -ansi -pedantic -I.
+
+ifeq ($(DEBUG),)
+CFLAGS += -O2
+else
+CFLAGS += -DDEBUG -O0
+endif
+
+CLEANFILES =
+
+libkv: libkv.a
+
+libkv.a: ${LIBKV_O}
+	ar -cru libkv.a ${LIBKV_O}
+CLEANFILES += libkv.a
+
+.c.o:
+	${CC} ${CPPFLAGS} ${CFLAGS} -c $<
+CLEANFILES += *.o
+
+kv: ${KV_O}
+	${CC} ${CFLAGS} ${LDFLAGS} ${KV_O} -o kv
+CLEANFILES += kv
+
+clean:
+	rm -rf ${CLEANFILES}
+
+.PHONY: all build clean libkv
diff --git a/buffer.c b/buffer.c
new file mode 100644
index 0000000..945fd1a
--- /dev/null
+++ b/buffer.c
@@ -0,0 +1,136 @@
+/*
+ * kv - key value text file format
+ *
+ * Copyright 2022 Thomas de Grivel
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "buffer.h"
+
+int buffer_init (s_buffer *b, FILE *fp, void *state)
+{
+  assert(b);
+  b->chars = calloc(BUFFER_SIZE, 1);
+  if (!b->chars)
+    return -1;
+  b->fp = fp;
+  b->pos = 0;
+  b->size = BUFFER_SIZE;
+  b->state = state;
+  b->wpos = 0;
+  return 0;
+}
+
+s_buffer * buffer_new (FILE *fp, void *state)
+{
+  s_buffer *b = calloc(1, sizeof(s_buffer));
+  if (!b)
+    return NULL;
+  if (buffer_init(b, fp, state))
+    return NULL;
+  return b;
+}
+
+int buffer_resize (s_buffer *b, size_t new_size)
+{
+  void *ptr;
+  assert(b);
+  assert(new_size >= b->size);
+  if (new_size == b->size)
+    return 0;
+  ptr = realloc(b->chars, new_size);
+  if (!ptr)
+    return -1;
+  b->chars = ptr;
+  b->size = new_size;
+  return 0;
+}
+
+int buffer_fill (s_buffer *b)
+{
+  size_t r;
+  assert(b);
+  if (b->wpos == b->size &&
+      buffer_resize(b, b->size + BUFFER_SIZE))
+    return -1;
+  assert(b->wpos < b->size);
+  r = fread(b->chars + b->wpos, 1, b->size - b->wpos, b->fp);
+  if (r <= 0)
+    return -1;
+  b->wpos += r;
+  return 0;
+}
+
+int buffer_peek (s_buffer *b)
+{
+  assert(b);
+  if (b->pos == b->wpos &&
+      buffer_fill(b))
+    return -1;
+  assert(b->pos < b->wpos);
+  return b->chars[b->pos];
+}
+
+int buffer_peek_n (s_buffer *b, size_t n)
+{
+  assert(b);
+  if (n == 0)
+    return 0;
+  while (b->pos + n >= b->wpos)
+    if (buffer_fill(b))
+      return -1;
+  assert(b->pos + n < b->wpos);
+  return 0;
+}
+
+int buffer_read (s_buffer *b)
+{
+  int c = buffer_peek(b);
+  if (c >= 0)
+    b->pos++;
+  return c;
+}
+
+int buffer_read_n (s_buffer *b, size_t n)
+{
+  if (buffer_peek_n(b, n))
+    return -1;
+  b->pos += n;
+  return 0;
+}
+
+int buffer_flush (s_buffer *b)
+{
+  assert(b);
+  if (b->pos == 0)
+    return 0;
+  memmove(b->chars, b->chars + b->pos, b->wpos - b->pos);
+  b->pos = 0;
+  b->wpos -= b->pos;
+  return 0;
+}
+
+int buffer_close (s_buffer *b)
+{
+  if (!b)
+    return 0;
+  fclose(b->fp);
+  free(b->chars);
+  b->chars = NULL;
+  b->pos = 0;
+  b->size = 0;
+  b->state = NULL;
+  b->wpos = 0;
+  return 0;
+}
+
+int buffer_delete (s_buffer *b)
+{
+  if (buffer_close(b))
+    return -1;
+  free(b);
+  return 0;
+}
diff --git a/buffer.h b/buffer.h
new file mode 100644
index 0000000..fd95a4d
--- /dev/null
+++ b/buffer.h
@@ -0,0 +1,38 @@
+/*
+ * kv - key value text file format
+ *
+ * Copyright 2022 Thomas de Grivel
+*/
+
+#ifndef BUFFER_H
+#define BUFFER_H
+
+#ifdef DEBUG
+# define BUFFER_SIZE 64
+#else
+# define BUFFER_SIZE (1024 * 1024)
+#endif
+
+typedef struct buffer
+{
+  char  *chars;
+  FILE  *fp;
+  size_t pos;
+  size_t size;
+  void  *state;
+  size_t wpos;
+} s_buffer;
+
+int        buffer_init (s_buffer *b, FILE *fp, void *state);
+s_buffer * buffer_new (FILE *fp, void *state);
+int        buffer_resize (s_buffer *b, size_t new_size);
+int        buffer_fill (s_buffer *b);
+int        buffer_peek (s_buffer *b);
+int        buffer_peek_n (s_buffer *b, size_t n);
+int        buffer_read (s_buffer *b);
+int        buffer_read_n (s_buffer *b, size_t n);
+int        buffer_flush (s_buffer *b);
+int        buffer_close (s_buffer *b);
+int        buffer_delete (s_buffer *b);
+
+#endif
diff --git a/kv.c b/kv.c
new file mode 100644
index 0000000..9d67a5e
--- /dev/null
+++ b/kv.c
@@ -0,0 +1,36 @@
+/*
+ * kv - key value text file format
+ *
+ * Copyright 2022 Thomas de Grivel
+*/
+
+#include <stdio.h>
+#include <kv.h>
+
+int on_kv (s_buffer *b, const char *v, size_t vsz)
+{
+  (void) b;
+  (void) v;
+  (void) vsz;
+  printf("--- v: %s\n", v);
+  return 0;
+}
+
+int read_file (const char *path)
+{
+  FILE *fp = fopen(path, "rb");
+  s_buffer b;
+  if (buffer_init(&b, fp, NULL) ||
+      kv_parse(&b, on_kv) ||
+      buffer_close(&b))
+    return -1;
+  return 0;
+}
+  
+
+int main (int argc, char **argv)
+{
+  while (--argc > 0)
+    read_file(*++argv);
+  return 0;
+}
diff --git a/kv.h b/kv.h
new file mode 100644
index 0000000..fd703db
--- /dev/null
+++ b/kv.h
@@ -0,0 +1,12 @@
+/*
+ * kv - key value text file format
+ *
+ * Copyright 2022 Thomas de Grivel
+*/
+
+#ifndef KV_H
+#define KV_H
+
+#include "buffer.h"
+
+#endif
diff --git a/kv_path.c b/kv_path.c
new file mode 100644
index 0000000..63e5ad4
--- /dev/null
+++ b/kv_path.c
@@ -0,0 +1,50 @@
+/*
+ * kv - key value text file format
+ *
+ * Copyright 2022 Thomas de Grivel
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "kv_path.h"
+
+void kv_path_init (s_kv_path *p, const char *k, size_t ks,
+                   s_kv_path *parent)
+{
+  assert(p);
+  p->k = k;
+  p->ks = ks;
+  p->parent = parent;
+}
+
+s_kv_path * kv_path_new (const char *k, size_t ks, s_kv_path *parent)
+{
+  s_kv_path *p = calloc(sizeof(s_kv_path), 1);
+  if (p)
+    kv_path_init(p, k, ks, parent);
+  return p;
+}
+
+void kv_path_delete (s_kv_path *p)
+{
+  free(p);
+}
+
+size_t kv_path_print (s_kv_path *p, FILE *fp)
+{
+  s_kv_path *acc;
+  size_t r = 0;
+  while (p) {
+    acc = kv_path_new(p->k, p->ks, acc);
+    p = p->parent;
+  }
+  while (acc) {
+    r += fprintf(fp, "%s", acc->k);
+    kv_path_delete(acc);
+    acc = acc->parent;
+    if (acc)
+      r += fprintf(fp, " ");
+  }
+  return r;
+}
diff --git a/kv_path.h b/kv_path.h
new file mode 100644
index 0000000..1895648
--- /dev/null
+++ b/kv_path.h
@@ -0,0 +1,24 @@
+/*
+ * kv - key value text file format
+ *
+ * Copyright 2022 Thomas de Grivel
+*/
+
+#ifndef KV_PATH_H
+#define KV_PATH_H
+
+typedef struct kv_path s_kv_path;
+
+struct kv_path {
+  const char *k;
+  size_t      ks;
+  s_kv_path  *parent;
+};
+
+void        kv_path_init (s_kv_path *p, const char *k, size_t ks,
+                          s_kv_path *parent);
+s_kv_path * kv_path_new (const char *k, size_t ks, s_kv_path *parent);
+void        kv_path_delete (s_kv_path *p);
+size_t      kv_path_print (s_kv_path *p, FILE *fp);
+
+#endif