[PATCH 2/2] Generate correct json

Gehad Elrobey gehadelrobey at gmail.com
Tue Aug 26 11:24:41 PDT 2014


I think this can be done easily by just checking if the item is the last
item in the array before putting the commas.

Also I think there are other 3rd party JSON parsers for python that can be
more advanced and coup with the trailing commas.

Regards,
Gehad


On Tue, Aug 26, 2014 at 9:08 PM, Dirk Hohndel <dirk at hohndel.org> wrote:

> 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
> _______________________________________________
> subsurface mailing list
> subsurface at hohndel.org
> http://lists.hohndel.org/cgi-bin/mailman/listinfo/subsurface
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.hohndel.org/pipermail/subsurface/attachments/20140826/0685896f/attachment.html>


More information about the subsurface mailing list