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@hohndel.org
> http://lists.hohndel.org/cgi-bin/mailman/listinfo/subsurface
_______________________________________________
subsurface mailing list
subsurface@hohndel.org
http://lists.hohndel.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to