[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