[PATCH 2/2] Generate correct json
Salvo 'LtWorf' Tomaselli
tiposchi at tiscali.it
Tue Aug 26 10:56:20 PDT 2014
Not quite the solution I'd want, but the json generation would need
to be re-done from scratch to generate valid json code.
Instead, I wrote this, to find and remove the guilty commas. It tries to
move as little bytes around as possible, and writing it felt like
interviewing for a position at Facebook.
---
save-html.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 100 insertions(+)
diff --git a/save-html.c b/save-html.c
index c3d5073..987bc59 100644
--- a/save-html.c
+++ b/save-html.c
@@ -1,7 +1,106 @@
+#include <string.h>
+
#include "save-html.h"
#include "gettext.h"
#include "stdio.h"
+/**
+ * Marks invalid commas inside a json for deletion.
+ *
+ * buf: json string
+ * buf_len: strlen(buf)
+ * marked: pointer to int array, where the positions of the
+ * commas to delete are marked
+ * marked_size: initially contains the size of the array.
+ * When returning will contain the amount of marked commas
+ *
+ * Returns false if there was not enough space inside the array
+ **/
+static bool mark_invalid_commas(char *buf, size_t buf_len, int *marked, size_t *marked_size) {
+ size_t size = *marked_size;
+ size_t used = 0;
+ int i;
+ bool string = false;
+ bool escape = false;
+
+ for (i = 0; i < buf_len; i++) {
+ char c = buf[i];
+
+ if (c == ',' && (!string)) {
+ /*
+ * If the next non-whitespace symbol is a } or ]
+ * mark for deletion
+ **/
+ int inc = 1;
+
+ //Skip whitespace
+ while (buf[i + inc] == ' ' || buf[i + inc] == '\n')
+ inc++;
+
+ switch (buf[i + inc]) {
+ case ']':
+ case '}':
+ if (size>used) {
+ marked[used++] = i;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ else if (c == '"' && (!escape) ) {
+ string = !string;
+ }
+
+ if (c == '\\')
+ escape = true;
+ else
+ escape = false; //Reset escape state
+ }
+
+ *marked_size = used;
+ return true;
+}
+
+/**
+ * Deletes the chars at the given positions inside a string,
+ * operates in-place
+ *
+ * buf: the string
+ * buf_len: strlen(buf)
+ * marked: array with the positions of the chars to delete
+ * marked_size: size of the array
+ *
+ * Returns the new size of the string.
+ **/
+static size_t delete_at_position(char *buf, size_t buf_len, int *marked, size_t marked_size) {
+ int i;
+ int distance;
+
+ for (i = 0; i < marked_size; i++) {
+ if (i + 1< marked_size)
+ distance = marked[i + 1] - marked[i];
+ else
+ distance = buf_len - marked[i] + 1;
+ memmove(buf + marked[i] - i, buf + marked[i] + 1, distance - 1);
+ }
+ return buf_len - i;
+}
+
+/**
+ * Removes the wrong commas from a json
+ *
+ * [[1,2,3,],] will become [[1,2,3]]
+ * as it should be.
+ **/
+static void clean_json(struct membuffer *b) {
+ size_t items = b->len / 10;
+ int *marked = calloc(items , sizeof(int));
+ mark_invalid_commas(b->buffer, b->len, marked, &items);
+ b->len = delete_at_position(b->buffer, b->len, marked, items);
+ free(marked);
+}
+
void write_attribute(struct membuffer *b, const char *att_name, const char *value)
{
if (!value)
@@ -335,6 +434,7 @@ void export_HTML(const char *file_name, const char *photos_dir, const bool selec
struct membuffer buf = { 0 };
export_list(&buf, photos_dir, selected_only, list_only);
+ clean_json(&buf);
f = subsurface_fopen(file_name, "w+");
if (!f)
--
2.1.0
More information about the subsurface
mailing list