Commit dfcd69c544a44cc4751f8cf4013ac6dafbd6d494

Thomas de Grivel 2022-01-02T22:25:10

wip quoting

diff --git a/kv.c b/kv.c
new file mode 100644
index 0000000..55d2a25
--- /dev/null
+++ b/kv.c
@@ -0,0 +1,62 @@
+/*
+ * kv - key value text file format
+ *
+ * Copyright 2022 Thomas de Grivel
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <kv.h>
+
+typedef struct kv_paths s_kv_paths;
+
+struct kv_paths {
+  s_kv_path  *k;
+  const char *v;
+  size_t      vsz;
+  s_kv_paths *next;
+};
+
+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, s_kv_paths *keys)
+{
+  FILE *fp = fopen(path, "rb");
+  s_buffer b;
+  if (buffer_init(&b, path, fp, keys) ||
+      kv_parse(&b, on_kv) ||
+      buffer_close(&b))
+    return -1;
+  return 0;
+}
+
+s_kv_paths *kv_paths_new (s_kv_path *k, s_kv_paths *next)
+{
+  s_kv_paths *keys = calloc(sizeof(s_kv_paths), 1);
+  if (keys) {
+    keys->k = k;
+    keys->next = next;
+  }
+  return keys;
+}
+
+s_kv_paths * read_keys (FILE *fp)
+{
+  (void) fp;
+  return NULL;
+}
+
+int main (int argc, char **argv)
+{
+  s_kv_paths *keys = read_keys(stdin);
+  while (--argc > 0)
+    read_file(*++argv, keys);
+  return 0;
+}
diff --git a/kv.h b/kv.h
index c140df9..ce11756 100644
--- a/kv.h
+++ b/kv.h
@@ -26,6 +26,8 @@ int kv_contains_reserved_char (const char *str, size_t str_size);
 int kv_contains_triple_double_quotes (const char *str, size_t str_size);
 int kv_needs_quoting (const char *str, size_t str_size);
 int kv_quote (char **str, size_t *str_size);
+int kv_quote_delim (char **str, size_t *str_size, const char *delim);
+int kv_quote_double_quotes (char **str, size_t *str_size);
 int kv_quote_triple_double_quotes (char **str, size_t *str_size);
 
 #endif
diff --git a/kv_cli.c b/kv_cli.c
deleted file mode 100644
index 55d2a25..0000000
--- a/kv_cli.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * kv - key value text file format
- *
- * Copyright 2022 Thomas de Grivel
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <kv.h>
-
-typedef struct kv_paths s_kv_paths;
-
-struct kv_paths {
-  s_kv_path  *k;
-  const char *v;
-  size_t      vsz;
-  s_kv_paths *next;
-};
-
-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, s_kv_paths *keys)
-{
-  FILE *fp = fopen(path, "rb");
-  s_buffer b;
-  if (buffer_init(&b, path, fp, keys) ||
-      kv_parse(&b, on_kv) ||
-      buffer_close(&b))
-    return -1;
-  return 0;
-}
-
-s_kv_paths *kv_paths_new (s_kv_path *k, s_kv_paths *next)
-{
-  s_kv_paths *keys = calloc(sizeof(s_kv_paths), 1);
-  if (keys) {
-    keys->k = k;
-    keys->next = next;
-  }
-  return keys;
-}
-
-s_kv_paths * read_keys (FILE *fp)
-{
-  (void) fp;
-  return NULL;
-}
-
-int main (int argc, char **argv)
-{
-  s_kv_paths *keys = read_keys(stdin);
-  while (--argc > 0)
-    read_file(*++argv, keys);
-  return 0;
-}
diff --git a/kv_quote.c b/kv_quote.c
index 350080b..b78c847 100644
--- a/kv_quote.c
+++ b/kv_quote.c
@@ -9,6 +9,25 @@
 #include <string.h>
 #include "kv.h"
 
+const char *g_delims[] = {
+  "END",
+  "---",
+  "___",
+  "===",
+  "***",
+  "+++",
+  "!!!",
+  "###",
+  "-END-",
+  "_END_",
+  "=END=",
+  "*END*",
+  "+END+",
+  "!END!",
+  "#END#",
+  NULL
+};
+
 int kv_check_delimiter (const char *delim)
 {
   assert(delim);
@@ -63,61 +82,86 @@ int kv_needs_quoting (const char *str, size_t str_size)
   return 1;
 }
 
-const char *delims[] = {
-  "END",
-  "---",
-  "___",
-  "===",
-  "***",
-  "+++",
-  "!!!",
-  "###",
-  "-END-",
-  "_END_",
-  "=END=",
-  "*END*",
-  "+END+",
-  "!END!",
-  "#END#",
-  NULL
-};
-  
 int kv_quote (char **str, size_t *str_size)
 {
-  int    r;
-  char  *str_delim;
-  size_t str_delim_size;
-  char  *str_triple;
-  size_t str_triple_size;
+  const char **delim;
+  int          delim_r;
+  char        *delim_str;
+  size_t       delim_str_size;
+  int          double_r;
+  char        *double_str;
+  size_t       double_str_size;
+  int          triple_r;
+  char        *triple_str;
+  size_t       triple_str_size;
   assert(str);
   assert(*str);
   assert(str_size);
   if (!kv_needs_quoting(*str, *str_size))
     return 0;
-  str_triple = *str;
-  str_triple_size = *str_size;
-  r = kv_quote_triple_double_quotes(&str_triple, &str_triple_size);
-  if (r <= 0)
-    return r;
-  str_delim = *str;
-  str_delim_size = *str_size;
-  r = kv_quote_delim(&str_delim, &str_delim_size, "END");
-  if (r <= 0)
-    return r;
-  if (r) {
-                      return r;
-                    if (r) {
-                      r = kv_quote_delim(&str_delim, &str_delim_size, "#END#");
-                      if (r <= 0)
-                        return r;
-                      if (r) {
-                        r = kv_quote_delim(&str_delim, &str_delim_size, "+EOF+");
-                        if (r <= 0)
-                          return r;
-                        
+  double_str = *str;
+  double_str_size = *str_size;
+  double_r = kv_quote_double_quotes(&double_str, &double_str_size);
+  if (double_r <= 0)
+    return double_r;
+  triple_str = *str;
+  triple_str_size = *str_size;
+  triple_r = kv_quote_triple_double_quotes(&triple_str, &triple_str_size);
+  if (triple_r <= 0)
+    return triple_r;
+  delim_str = *str;
+  delim_str_size = *str_size;
+  delim = &g_delims[0];
+  delim_r = kv_quote_delim(&delim_str, &delim_str_size, *delim);
+  delim++;
+  while (*delim && delim_r > 0) {
+    delim_r = kv_quote_delim(&delim_str, &delim_str_size, *delim);
+    delim++;
+  }
+  if (delim_r <= 0)
+    return delim_r;
+  
   return -1;
 }
 
+size_t kv_count_reserved_chars (const char *str, size_t str_size)
+{
+  size_t c = 0;
+  while (str_size--)
+    if (kv_is_reserved_char(*str++))
+      c++;
+  return c;
+}
+
+int kv_quote_double_quotes (char **str, size_t *str_size)
+{
+  size_t i = 0;
+  size_t o = 0;
+  size_t res;
+  char  *s;
+  assert(str);
+  assert(str_size);
+  res = kv_count_reserved_chars(*str, *str_size);
+  s = calloc(*str_size + res + 3, 1);
+  if (!s)
+    return -1;
+  s[0] = '"';
+  while (i < *str_size) {
+    int c = (*str)[i];
+    if (kv_is_reserved_char(c))
+      s[o++] = '\\';
+    if (c == 0)
+      s[o++] = '0';
+    else
+      s[o++] = c;
+  }
+  assert(o == *str_size + res + 2);
+  s[o] = 0;
+  *str = s;
+  *str_size = o;
+  return 0;
+}
+
 int kv_quote_triple_double_quotes (char **str, size_t *str_size)
 {
   char *e;
diff --git a/rope.c b/rope.c
index de474f0..2f715a1 100644
--- a/rope.c
+++ b/rope.c
@@ -5,6 +5,7 @@
 */
 
 #include <assert.h>
+#include <stdlib.h>
 #include "rope.h"
 
 void rope_init (s_rope *r, char *str, size_t size, s_rope *next)