[PATCH 2/2] Generate correct json
Dirk Hohndel
dirk at hohndel.org
Tue Aug 26 11:08:39 PDT 2014
On Tue, Aug 26, 2014 at 07:56:20PM +0200, Salvo 'LtWorf' Tomaselli wrote:
> Not quite the solution I'd want, but the json generation would need
> to be re-done from scratch to generate valid json code.
... and that is considered not worth it?
> 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.
I don't know about Facebook's interview process... but I don't think this
is the way I would have done this. Why not just do the memmove on the fly
while you scan the string?
This seems rather fragile to me.
/D
> ---
> 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
>
> _______________________________________________
> subsurface mailing list
> subsurface at hohndel.org
> http://lists.hohndel.org/cgi-bin/mailman/listinfo/subsurface
More information about the subsurface
mailing list