diff --git a/Makefile b/Makefile
index 3f5e205..e192bce 100644
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,7 @@ LIBKV_SRC = \
kv_parse.c \
kv_path.c \
kv_quote.c \
+ kv_unquote.c \
rope.c
LIBKV_O = ${LIBKV_SRC:.c=.o}
diff --git a/kv.c b/kv.c
index f836bd1..6f01fb3 100644
--- a/kv.c
+++ b/kv.c
@@ -66,28 +66,36 @@ int get (int argc, char **argv)
return r;
}
-int quote (int argc, char **argv)
+int buffer_read_files (s_buffer *b, int argc, char **argv)
{
- s_buffer in;
- char *q;
- size_t q_size;
- int r;
- if (buffer_init(&in, NULL))
+ int r;
+ if (buffer_init(b, NULL))
return -1;
while (argc--) {
if (!strcmp(*argv, "-")) {
- if (buffer_fp(&in, stdin, "stdin"))
+ if (buffer_fp(b, stdin, "stdin"))
err(1, "stdin");
}
else
- if (buffer_open(&in, *argv))
+ if (buffer_open(b, *argv))
err(1, "%s", *argv);
- while (!(r = buffer_fill(&in)))
+ while (!(r = buffer_fill(b)))
;
if (r != -1)
- err(1, "%s", in.file_path);
+ err(1, "%s", b->file_path);
argv++;
}
+ return 0;
+}
+
+int quote (int argc, char **argv)
+{
+ s_buffer in;
+ char *q;
+ size_t q_size;
+ int r;
+ if (buffer_read_files(&in, argc, argv))
+ return -1;
q = in.chars;
q_size = in.wpos;
if (!(r = kv_quote(&q, &q_size)) &&
@@ -98,12 +106,32 @@ int quote (int argc, char **argv)
return r;
}
+int unquote (int argc, char **argv)
+{
+ s_buffer in;
+ char *str;
+ size_t str_size;
+ int r;
+ if (buffer_read_files(&in, argc, argv))
+ return -1;
+ str = in.chars;
+ str_size = in.wpos;
+ if (!(r = kv_unquote(&str, &str_size)) &&
+ fwrite(str, str_size, 1, stdout) != 1)
+ err(1, "stdout");
+ fflush(stdout);
+ free(str);
+ return r;
+}
+
int usage (const char *argv0)
{
printf("Usage: %s OP [FILE ...]\n"
"OP can be one of :\n"
- " -q | --quote Quote files.\n"
- " -g | --get Get keys passed on stdin in files.\n",
+ " -g | --get Get keys from stdin and print values from "
+ "files.\n"
+ " -q | --quote Quote concatenated files.\n"
+ " -u | --unquote Unquote concatenated files.\n",
argv0);
return 1;
}
@@ -117,15 +145,20 @@ int main (int argc, char **argv)
argc--;
argv++;
if (argc) {
+ if (!strcmp(*argv, "-g") || !strcmp(*argv, "--get")) {
+ argc--;
+ argv++;
+ return get(argc, argv);
+ }
if (!strcmp(*argv, "-q") || !strcmp(*argv, "--quote")) {
argc--;
argv++;
return quote(argc, argv);
}
- if (!strcmp(*argv, "-g") || !strcmp(*argv, "--get")) {
+ if (!strcmp(*argv, "-u") || !strcmp(*argv, "--unquote")) {
argc--;
argv++;
- return get(argc, argv);
+ return unquote(argc, argv);
}
}
return usage(argv0);
diff --git a/kv.h b/kv.h
index ce11756..46203be 100644
--- a/kv.h
+++ b/kv.h
@@ -29,5 +29,9 @@ 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);
+int kv_unquote (char **str, size_t *str_size);
+int kv_unquote_delim (char **str, size_t *str_size, const char *delim);
+int kv_unquote_double_quotes (char **str, size_t *str_size);
+int kv_unquote_triple_double_quotes (char **str, size_t *str_size);
#endif
diff --git a/kv_quote.c b/kv_quote.c
index bb06419..09f99aa 100644
--- a/kv_quote.c
+++ b/kv_quote.c
@@ -98,7 +98,6 @@ int kv_quote (char **str, size_t *str_size)
char *q;
size_t q_size;
assert(str);
- assert(*str);
assert(str_size);
if (!kv_needs_quoting(*str, *str_size))
return 0;
diff --git a/kv_unquote.c b/kv_unquote.c
new file mode 100644
index 0000000..0ca85c5
--- /dev/null
+++ b/kv_unquote.c
@@ -0,0 +1,96 @@
+/*
+ * kv - key value text file format
+ *
+ * Copyright 2022 Thomas de Grivel
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "kv.h"
+
+int kv_unquote (s_buffer *b)
+{
+
+}
+
+int kv_quote_delim (char **str, size_t *str_size, const char *delim)
+{
+ char *s;
+ size_t delim_len;
+ size_t len;
+ assert(str);
+ assert(str_size);
+ assert(delim);
+ if (kv_check_delimiter(delim)) {
+ fprintf(stderr, "bad delimiter: %s\n", delim);
+ return 1;
+ }
+ if (kv_contains_delimiter(*str, *str_size, delim))
+ return 1;
+ delim_len = strlen(delim);
+ len = *str_size + delim_len * 2 + 3;
+ s = calloc(len + 1, 1);
+ if (!s)
+ return -1;
+ s[0] = '<'; s[1] = '<';
+ memcpy(s + 2, delim, delim_len);
+ s[2 + delim_len] = '\n';
+ memcpy(s + delim_len + 3, *str, *str_size);
+ memcpy(s + *str_size + delim_len + 3, delim, delim_len);
+ *str = s;
+ *str_size = len;
+ return 0;
+}
+
+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_quotable_chars(*str, *str_size);
+ s = calloc(*str_size + res + 3, 1);
+ if (!s)
+ return -1;
+ s[o++] = '"';
+ while (i < *str_size) {
+ int c = (*str)[i++];
+ if (kv_is_quotable_char(c))
+ s[o++] = '\\';
+ switch (c) {
+ case 0: s[o++] = '0'; break;
+ case '\n': s[o++] = 'n'; break;
+ case '\r': s[o++] = 'r'; break;
+ case '\t': s[o++] = 't'; break;
+ case '\v': s[o++] = 'v'; break;
+ default: s[o++] = c;
+ }
+ }
+ s[o++] = '"';
+ 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;
+ char *s;
+ if (kv_contains_triple_double_quotes(*str, *str_size))
+ return 1;
+ s = calloc(*str_size + 8, 1);
+ if (!s)
+ return -1;
+ s[0] = '"'; s[1] = '"'; s[2] = '"'; s[3] = '\n';
+ memcpy(s + 4, *str, *str_size);
+ e = s + 4 + *str_size;
+ e[0] = '"'; e[1] = '"'; e[2] = '"'; e[3] = 0;
+ *str = s;
+ *str_size = *str_size + 7;
+ return 0;
+}
diff --git a/test/delim b/test/delim
new file mode 100644
index 0000000..9fcfe3b
--- /dev/null
+++ b/test/delim
@@ -0,0 +1,97 @@
+Hello world !
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"""
+
+
+
+
+
+
+
+
+
+
+
+
+
+"""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hello world !!