Commit b82e6676808c8f0fa276d0db17aa62fda1ed7c01

Thomas de Grivel 2022-01-03T09:41:46

wip quoting

diff --git a/kv_quote.c b/kv_quote.c
index b78c847..a25a091 100644
--- a/kv_quote.c
+++ b/kv_quote.c
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "kv.h"
+#include "rope.h"
 
 const char *g_delims[] = {
   "END",
@@ -85,43 +86,54 @@ int kv_needs_quoting (const char *str, size_t str_size)
 int kv_quote (char **str, size_t *str_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;
+  int          r;
+  s_rope      *rope = NULL;
+  char        *q;
+  size_t       q_size;
   assert(str);
   assert(*str);
   assert(str_size);
   if (!kv_needs_quoting(*str, *str_size))
     return 0;
-  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;
+  q = *str;
+  q_size = *str_size;
+  r = kv_quote_double_quotes(&q, &q_size);
+  if (r < 0)
+    return r;
+  if (r == 0 && rope_push(&rope, q, q_size))
+    return -3;
+  q = *str;
+  q_size = *str_size;
+  r = kv_quote_triple_double_quotes(&q, &q_size);
+  if (r < 0)
+    return r;
+  if (r == 0 && rope_push(&rope, q, q_size)) {
+    rope_delete_all_free(rope);
+    return -3;
+  }
+  q = *str;
+  q_size = *str_size;
   delim = &g_delims[0];
-  delim_r = kv_quote_delim(&delim_str, &delim_str_size, *delim);
+  r = kv_quote_delim(&q, &q_size, *delim);
   delim++;
-  while (*delim && delim_r > 0) {
-    delim_r = kv_quote_delim(&delim_str, &delim_str_size, *delim);
+  while (*delim && r > 0) {
+    r = kv_quote_delim(&q, &q_size, *delim);
     delim++;
   }
-  if (delim_r <= 0)
-    return delim_r;
-  
-  return -1;
+  if (r < 0)
+    return r;
+  if (r == 0 && rope_push(&rope, q, q_size)) {
+    rope_delete_all_free(rope);
+    return -3;
+  }
+  if (!rope)
+    return 1;
+  rope_sort_by_size(rope);
+  *str = rope->str;
+  *str_size = rope->size;
+  rope = rope->next;
+  rope_delete_all_free(rope);
+  return 0;
 }
 
 size_t kv_count_reserved_chars (const char *str, size_t str_size)
diff --git a/rope.c b/rope.c
index 2f715a1..9f519de 100644
--- a/rope.c
+++ b/rope.c
@@ -39,3 +39,75 @@ void rope_delete_all (s_rope *r)
     rope_delete(t);
   }
 }
+
+void rope_delete_all_free (s_rope *r)
+{
+  while (r) {
+    s_rope *t = r;
+    r = r->next;
+    free(t->str);
+    t->str = NULL;
+    t->size = 0;
+    rope_delete(t);
+  }
+}
+
+int rope_push (s_rope **r, char *str, size_t size)
+{
+  s_rope *n;
+  assert(r);
+  n = rope_new(str, size, *r);
+  if (n) {
+    *r = n;
+    return 0;
+  }
+  return -1;
+}
+
+size_t rope_length (const s_rope *r)
+{
+  size_t l = 0;
+  while (r) {
+    l++;
+    r = r->next;
+  }
+  return l;
+}
+
+void rope_swap (s_rope *a, s_rope *b)
+{
+  char  *str;
+  size_t size;
+  assert(a);
+  assert(b);
+  str = a->str;
+  size = a->size;
+  a->str = b->str;
+  a->size = b->size;
+  b->str = str;
+  b->size = size;
+}
+
+void rope_sort_by_size (s_rope *r)
+{
+  s_rope *i;
+  size_t  n;
+  assert(r);
+  n = rope_length(r);
+  while (n > 1) {
+    size_t k = n;
+    int swap = 0;
+    i = r;
+    while (k > 1) {
+      if (i->size > i->next->size) {
+        swap = 1;
+        rope_swap(i, i->next);
+      }
+      k--;
+      i = i->next;
+    }
+    if (!swap)
+      break;
+    n--;
+  }
+}
diff --git a/rope.h b/rope.h
index 41faafc..7c04be9 100644
--- a/rope.h
+++ b/rope.h
@@ -19,5 +19,8 @@ void     rope_init (s_rope *r, char *str, size_t size, s_rope *next);
 s_rope * rope_new (char *str, size_t size, s_rope *next);
 void     rope_delete (s_rope *r);
 void     rope_delete_all (s_rope *r);
+void     rope_delete_all_free (s_rope *r);
+int      rope_push (s_rope **r, char *str, size_t size);
+void     rope_sort_by_size (s_rope *r);
 
 #endif