You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/01/12 22:34:14 UTC

[1/2] incubator-mynewt-larva git commit: add json parsing and encoding libraries.

Repository: incubator-mynewt-larva
Updated Branches:
  refs/heads/master 83801d4c9 -> 4628d6bb1


add json parsing and encoding libraries.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/4628d6bb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/4628d6bb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/4628d6bb

Branch: refs/heads/master
Commit: 4628d6bb14a14f9a721aadd37a6727e403e59e73
Parents: 37e081d
Author: Sterling Hughes <st...@apache.org>
Authored: Tue Jan 12 13:33:58 2016 -0800
Committer: Sterling Hughes <st...@apache.org>
Committed: Tue Jan 12 13:34:09 2016 -0800

----------------------------------------------------------------------
 libs/json/MSJSON_COPYING      |  28 ++
 libs/json/egg.yml             |   2 +
 libs/json/include/json/json.h | 230 +++++++++++++
 libs/json/src/json_decode.c   | 664 +++++++++++++++++++++++++++++++++++++
 libs/json/src/json_encode.c   | 136 ++++++++
 libs/newtmgr/egg.yml          |   1 +
 libs/newtmgr/src/newtmgr.c    |  39 ---
 7 files changed, 1061 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/4628d6bb/libs/json/MSJSON_COPYING
----------------------------------------------------------------------
diff --git a/libs/json/MSJSON_COPYING b/libs/json/MSJSON_COPYING
new file mode 100644
index 0000000..2267ff2
--- /dev/null
+++ b/libs/json/MSJSON_COPYING
@@ -0,0 +1,28 @@
+			BSD LICENSE
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+Neither name of the GPSD project nor the names of its contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/4628d6bb/libs/json/egg.yml
----------------------------------------------------------------------
diff --git a/libs/json/egg.yml b/libs/json/egg.yml
new file mode 100644
index 0000000..e45648a
--- /dev/null
+++ b/libs/json/egg.yml
@@ -0,0 +1,2 @@
+egg.name: libs/json 
+egg.vers: 0.1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/4628d6bb/libs/json/include/json/json.h
----------------------------------------------------------------------
diff --git a/libs/json/include/json/json.h b/libs/json/include/json/json.h
new file mode 100644
index 0000000..346fc59
--- /dev/null
+++ b/libs/json/include/json/json.h
@@ -0,0 +1,230 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _JSON_H_
+#define _JSON_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+
+#define JSON_VALUE_TYPE_BOOL   (0)
+#define JSON_VALUE_TYPE_UINT64 (1)
+#define JSON_VALUE_TYPE_INT64  (2)
+#define JSON_VALUE_TYPE_STRING (3)
+#define JSON_VALUE_TYPE_ARRAY  (4)
+#define JSON_VALUE_TYPE_OBJECT (5)
+
+/**
+ * For JSON decode, descriptions of the JSON values that 
+ * need to be parsed.
+ */
+struct json_value_desc {
+    char *jv_name;
+    void *jv_ptr;
+    uint16_t jv_len;
+    uint8_t jv_type;
+    uint8_t jv_matched;
+};
+
+/** 
+ * For encode.  The contents of a JSON value to encode.
+ */
+struct json_value {
+    uint8_t jv_pad1;
+    uint8_t jv_type;
+    uint16_t jv_len;
+
+    union {
+        uint64_t u;
+        float fl;
+        char *str;
+        struct {
+            char **keys;
+            struct json_value **values;
+        } composite;
+    } jv_val;
+};
+
+#define JSON_VALUE_STRING(__jv, __str)        \
+    (__jv)->jv_type = JSON_VALUE_TYPE_STRING; \
+    (__jv)->jv_len = strlen(__str);           \
+    (__jv)->jv_val.str = str;
+
+#define JSON_VALUE_STRINGN(__jv, __str, __len) \
+    (__jv)->jv_type = JSON_VALUE_TYPE_STRING;  \
+    (__jv)->jv_len = __len;                    \
+    (__jv)->jv_val.str = str;
+
+#define JSON_VALUE_BOOL(__jv, __v)            \
+    (__jv)->jv_type = JSON_VALUE_TYPE_BOOL;   \
+    (__jv)->jv_val.u = __v;
+
+#define JSON_VALUE_INT(__jv, __v)             \
+    (__jv)->jv_type = JSON_VALUE_TYPE_INT64;  \
+    (__jv)->jv_val.u = (uint64_t) __v;
+
+#define JSON_VALUE_UINT(__jv, __v)            \
+    (__jv)->jv_type = JSON_VALUE_TYPE_UINT64; \
+    (__jv)->jv_val.u = (uint64_t) __v;
+
+/* Encoding functions */
+typedef int (*json_write_func_t)(void *buf, char *data, 
+        int len);
+
+struct json_encoder {
+    json_write_func_t je_write;
+    void *je_arg;
+    char je_encode_buf[64];
+};
+
+
+#define JSON_NITEMS(x) (int)(sizeof(x)/sizeof(x[0]))
+
+int json_encode_object_start(struct json_encoder *, void *, json_write_func_t);
+int json_encode_object_entry(struct json_encoder *, char *, 
+        struct json_value *);
+int json_encode_object_finish(struct json_encoder *);
+
+/* Json parser definitions */
+typedef enum {
+    t_integer, 
+    t_uinteger, 
+    t_real,
+    t_string, 
+    t_boolean, 
+    t_character,
+    t_object, 
+    t_structobject, 
+    t_array, 
+    t_check, 
+    t_ignore
+} json_type;
+
+struct json_enum_t {
+    char        *name;
+    int                value;
+};
+
+struct json_array_t {
+    json_type element_type;
+    union {
+        struct {
+            const struct json_attr_t *subtype;
+            char *base;
+            size_t stride;
+        } objects;
+        struct {
+            char **ptrs;
+            char *store;
+            int storelen;
+        } strings;
+        struct {
+            int *store;
+        } integers;
+        struct {
+            unsigned int *store;
+        } uintegers;
+        struct {
+            double *store;
+        } reals;
+        struct {
+            bool *store;
+        } booleans;
+    } arr;
+    int *count;
+    int maxlen;
+};
+
+struct json_attr_t {
+    char *attribute;
+    json_type type;
+    union {
+        int *integer;
+        unsigned int *uinteger;
+        double *real;
+        char *string;
+        bool *boolean;
+        char *character;
+        struct json_array_t array;
+        size_t offset;
+    } addr;
+    union {
+        int integer;
+        unsigned int uinteger;
+        double real;
+        bool boolean;
+        char character;
+        char *check;
+    } dflt;
+    size_t len;
+    const struct json_enum_t *map;
+    bool nodefault;
+};
+
+#define JSON_ATTR_MAX        31        /* max chars in JSON attribute name */
+#define JSON_VAL_MAX        512        /* max chars in JSON value part */
+
+int json_read_object(const char *, const struct json_attr_t *, const char **);
+int json_read_array(const char *, const struct json_array_t *, const char **);
+
+#define JSON_ERR_OBSTART     1   /* non-WS when expecting object start */
+#define JSON_ERR_ATTRSTART   2   /* non-WS when expecting attrib start */
+#define JSON_ERR_BADATTR     3   /* unknown attribute name */
+#define JSON_ERR_ATTRLEN     4   /* attribute name too long */
+#define JSON_ERR_NOARRAY     5   /* saw [ when not expecting array */
+#define JSON_ERR_NOBRAK      6   /* array element specified, but no [ */
+#define JSON_ERR_STRLONG     7   /* string value too long */
+#define JSON_ERR_TOKLONG     8   /* token value too long */
+#define JSON_ERR_BADTRAIL    9   /* garbage while expecting comma or } or ] */
+#define JSON_ERR_ARRAYSTART  10  /* didn't find expected array start */
+#define JSON_ERR_OBJARR      11  /* error while parsing object array */
+#define JSON_ERR_SUBTOOLONG  12  /* too many array elements */
+#define JSON_ERR_BADSUBTRAIL 13  /* garbage while expecting array comma */
+#define JSON_ERR_SUBTYPE     14  /* unsupported array element type */
+#define JSON_ERR_BADSTRING   15  /* error while string parsing */
+#define JSON_ERR_CHECKFAIL   16  /* check attribute not matched */
+#define JSON_ERR_NOPARSTR    17  /* can't support strings in parallel arrays */
+#define JSON_ERR_BADENUM     18  /* invalid enumerated value */
+#define JSON_ERR_QNONSTRING  19  /* saw quoted value when expecting nonstring */
+#define JSON_ERR_NONQSTRING  19  /* didn't see quoted value when expecting string */
+#define JSON_ERR_MISC        20  /* other data conversion error */
+#define JSON_ERR_BADNUM      21  /* error while parsing a numerical argument */
+#define JSON_ERR_NULLPTR     22  /* unexpected null value or attribute pointer */
+
+/*
+ * Use the following macros to declare template initializers for structobject
+ * arrays.  Writing the equivalents out by hand is error-prone.
+ *
+ * JSON_STRUCT_OBJECT takes a structure name s, and a fieldname f in s.
+ *
+ * JSON_STRUCT_ARRAY takes the name of a structure array, a pointer to a an
+ * initializer defining the subobject type, and the address of an integer to
+ * store the length in.
+ */
+#define JSON_STRUCT_OBJECT(s, f)        .addr.offset = offsetof(s, f)
+#define JSON_STRUCT_ARRAY(a, e, n) \
+        .addr.array.element_type = t_structobject, \
+        .addr.array.arr.objects.subtype = e, \
+        .addr.array.arr.objects.base = (char*)a, \
+        .addr.array.arr.objects.stride = sizeof(a[0]), \
+        .addr.array.count = n, \
+        .addr.array.maxlen = (int)(sizeof(a)/sizeof(a[0]))
+
+#endif /* _JSON_H_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/4628d6bb/libs/json/src/json_decode.c
----------------------------------------------------------------------
diff --git a/libs/json/src/json_decode.c b/libs/json/src/json_decode.c
new file mode 100644
index 0000000..bd2d0f5
--- /dev/null
+++ b/libs/json/src/json_decode.c
@@ -0,0 +1,664 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+
+#include <json/json.h>
+
+/** 
+ * This file is based upon microjson, from Eric S Raymond. 
+ *
+ * License information for MicroJSON is in the package file MSJSON_COPYING, 
+ * it is BSD licensed source code. 
+ */
+
+
+/****************************************************************************
+
+NAME
+   mjson.c - parse JSON into fixed-extent data structures
+
+DESCRIPTION
+   This module parses a large subset of JSON (JavaScript Object
+Notation).  Unlike more general JSON parsers, it doesn't use malloc(3)
+and doesn't support polymorphism; you need to give it a set of
+template structures describing the expected shape of the incoming
+JSON, and it will error out if that shape is not matched.  When the
+parse succeeds, attribute values will be extracted into static
+locations specified in the template structures.
+
+   The "shape" of a JSON object in the type signature of its
+attributes (and attribute values, and so on recursively down through
+all nestings of objects and arrays).  This parser is indifferent to
+the order of attributes at any level, but you have to tell it in
+advance what the type of each attribute value will be and where the
+parsed value will be stored. The template structures may supply
+default values to be used when an expected attribute is omitted.
+
+   The preceding paragraph told one fib.  A single attribute may
+actually have a span of multiple specifications with different
+syntactically distinguishable types (e.g. string vs. real vs. integer
+vs. boolean, but not signed integer vs. unsigned integer).  The parser
+will match the right spec against the actual data.
+
+   The dialect this parses has some limitations.  First, it cannot
+recognize the JSON "null" value. Second, all elements of an array must
+be of the same type. Third, characters may not be array elements (this
+restriction could be lifted)
+
+   There are separate entry points for beginning a parse of either
+JSON object or a JSON array. JSON "float" quantities are actually
+stored as doubles.
+
+   This parser processes object arrays in one of two different ways,
+defending on whether the array subtype is declared as object or
+structobject.
+
+   Object arrays take one base address per object subfield, and are
+mapped into parallel C arrays (one per subfield).  Strings are not
+supported in this kind of array, as they don't have a "natural" size
+to use as an offset multiplier.
+
+   Structobjects arrays are a way to parse a list of objects to a set
+of modifications to a corresponding array of C structs.  The trick is
+that the array object initialization has to specify both the C struct
+array's base address and the stride length (the size of the C struct).
+If you initialize the offset fields with the correct offsetof calls,
+everything will work. Strings are supported but all string storage
+has to be inline in the struct.
+
+PERMISSIONS
+   This file is Copyright (c) 2014 by Eric S. Raymond
+   BSD terms apply: see the file COPYING in the distribution root for details.
+
+***************************************************************************/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>        /* for HUGE_VAL */
+
+static char *
+json_target_address(const struct json_attr_t *cursor, 
+        const struct json_array_t *parent, int offset)
+{
+    char *targetaddr = NULL;
+    if (parent == NULL || parent->element_type != t_structobject) {
+        /* ordinary case - use the address in the cursor structure */
+        switch (cursor->type) {
+        case t_ignore:
+            targetaddr = NULL;
+            break;
+        case t_integer:
+            targetaddr = (char *)&cursor->addr.integer[offset];
+            break;
+        case t_uinteger:
+            targetaddr = (char *)&cursor->addr.uinteger[offset];
+            break;
+        case t_real:
+            targetaddr = (char *)&cursor->addr.real[offset];
+            break;
+        case t_string:
+            targetaddr = cursor->addr.string;
+            break;
+        case t_boolean:
+            targetaddr = (char *)&cursor->addr.boolean[offset];
+            break;
+        case t_character:
+            targetaddr = (char *)&cursor->addr.character[offset];
+            break;
+        default:
+            targetaddr = NULL;
+            break;
+        }
+    } else {
+        /* tricky case - hacking a member in an array of structures */
+        targetaddr =
+            parent->arr.objects.base + (offset * parent->arr.objects.stride) +
+            cursor->addr.offset;
+    }
+    return targetaddr;
+}
+
+static int 
+json_internal_read_object(const char *cp, const struct json_attr_t *attrs, 
+        const struct json_array_t *parent, int offset, const char **end)
+{
+    enum { 
+        init, await_attr, in_attr, await_value, in_val_string,
+        in_escape, in_val_token, post_val, post_array
+    } state = 0;
+    char attrbuf[JSON_ATTR_MAX + 1], *pattr = NULL;
+    char valbuf[JSON_VAL_MAX + 1], *pval = NULL;
+    bool value_quoted = false;
+    char uescape[5];                /* enough space for 4 hex digits and a NUL */
+    const struct json_attr_t *cursor;
+    int substatus, n, maxlen = 0;
+    unsigned int u;
+    const struct json_enum_t *mp;
+    char *lptr;
+
+#ifdef S_SPLINT_S
+    /* prevents gripes about buffers not being completely defined */
+    memset(valbuf, '\0', sizeof(valbuf));
+    memset(attrbuf, '\0', sizeof(attrbuf));
+#endif /* S_SPLINT_S */
+
+    if (end != NULL) { 
+        /* give it a well-defined value on parse failure */
+        *end = NULL; 
+    }
+
+    /* stuff fields with defaults in case they're omitted in the JSON input */
+    for (cursor = attrs; cursor->attribute != NULL; cursor++) {
+        if (!cursor->nodefault) {
+            lptr = json_target_address(cursor, parent, offset);
+            if (lptr != NULL)
+                switch (cursor->type) {
+                case t_integer:
+                    memcpy(lptr, &cursor->dflt.integer, sizeof(int));
+                    break;
+                case t_uinteger:
+                    memcpy(lptr, &cursor->dflt.uinteger, sizeof(unsigned int));
+                    break;
+                case t_real:
+                    memcpy(lptr, &cursor->dflt.real, sizeof(double));
+                    break;
+                case t_string:
+                    if (parent != NULL
+                        && parent->element_type != t_structobject
+                        && offset > 0) {
+                        return JSON_ERR_NOPARSTR;
+                    }
+                    lptr[0] = '\0';
+                    break;
+                case t_boolean:
+                    memcpy(lptr, &cursor->dflt.boolean, sizeof(bool));
+                    break;
+                case t_character:
+                    lptr[0] = cursor->dflt.character;
+                    break;
+                case t_object:        /* silences a compiler warning */
+                case t_structobject:
+                case t_array:
+                case t_check:
+                case t_ignore:
+                    break;
+                }
+        }
+    }
+
+    /* parse input JSON */
+    for (; *cp != '\0'; cp++) {
+        switch (state) {
+        case init:
+            if (isspace((unsigned char) *cp)) {
+                continue;
+            } else if (*cp == '{') {
+                state = await_attr;
+            } else {
+                if (end != NULL) {
+                    *end = cp;
+                }
+                return JSON_ERR_OBSTART;
+            }
+            break;
+        case await_attr:
+            if (isspace((unsigned char) *cp)) {
+                continue;
+            } else if (*cp == '"') {
+                state = in_attr;
+                pattr = attrbuf;
+                if (end != NULL) {
+                    *end = cp;
+                }
+            } else if (*cp == '}') {
+                break;
+            } else {
+                if (end != NULL) {
+                    *end = cp;
+                }
+                return JSON_ERR_ATTRSTART;
+            }
+            break;
+        case in_attr:
+            if (pattr == NULL) {
+                /* don't update end here, leave at attribute start */
+                return JSON_ERR_NULLPTR;
+            }
+            if (*cp == '"') {
+                *pattr++ = '\0';
+                for (cursor = attrs; cursor->attribute != NULL; cursor++) {
+                    if (strcmp(cursor->attribute, attrbuf) == 0) {
+                        break;
+                    }
+                }
+                if (cursor->attribute == NULL) {
+                    /* don't update end here, leave at attribute start */
+                    return JSON_ERR_BADATTR;
+                }
+                state = await_value;
+                if (cursor->type == t_string) {
+                    maxlen = (int)cursor->len - 1;
+                } else if (cursor->type == t_check) {
+                    maxlen = (int)strlen(cursor->dflt.check);
+                } else if (cursor->type == t_ignore) {
+                    maxlen = JSON_VAL_MAX;
+                } else if (cursor->map != NULL) {
+                    maxlen = (int)sizeof(valbuf) - 1;
+                }
+                pval = valbuf;
+            } else if (pattr >= attrbuf + JSON_ATTR_MAX - 1) {
+                /* don't update end here, leave at attribute start */
+                return JSON_ERR_ATTRLEN;
+            } else {
+                *pattr++ = *cp;
+            }
+            break;
+        case await_value:
+            if (isspace((unsigned char) *cp) || *cp == ':') {
+                continue;
+            } else if (*cp == '[') {
+                if (cursor->type != t_array) {
+                    if (end != NULL) {
+                        *end = cp;
+                    }
+                    return JSON_ERR_NOARRAY;
+                }
+                substatus = json_read_array(cp, &cursor->addr.array, &cp);
+                if (substatus != 0) {
+                    return substatus;
+                }
+                state = post_array;
+            } else if (cursor->type == t_array) {
+                if (end != NULL) {
+                    *end = cp;
+                }
+                return JSON_ERR_NOBRAK;
+            } else if (*cp == '"') {
+                value_quoted = true;
+                state = in_val_string;
+                pval = valbuf;
+            } else {
+                value_quoted = false;
+                state = in_val_token;
+                pval = valbuf;
+                *pval++ = *cp;
+            }
+            break;
+        case in_val_string:
+            if (pval == NULL) {
+                /* don't update end here, leave at value start */
+                return JSON_ERR_NULLPTR;
+            }
+            if (*cp == '\\') {
+                state = in_escape;
+            } else if (*cp == '"') {
+                *pval++ = '\0';
+                state = post_val;
+            } else if (pval > valbuf + JSON_VAL_MAX - 1
+                       || pval > valbuf + maxlen) {
+                /* don't update end here, leave at value start */
+                return JSON_ERR_STRLONG;        /*  */
+            } else {
+                *pval++ = *cp;
+            }
+            break;
+        case in_escape:
+            if (pval == NULL) {
+                /* don't update end here, leave at value start */
+                return JSON_ERR_NULLPTR;
+            }
+            switch (*cp) {
+            case 'b':
+                *pval++ = '\b';
+                break;
+            case 'f':
+                *pval++ = '\f';
+                break;
+            case 'n':
+                *pval++ = '\n';
+                break;
+            case 'r':
+                *pval++ = '\r';
+                break;
+            case 't':
+                *pval++ = '\t';
+                break;
+            case 'u':
+                for (n = 0; n < 4 && cp[n] != '\0'; n++) {
+                    uescape[n] = *cp++;
+                }
+                --cp;
+                (void)sscanf(uescape, "%04x", &u);
+                *pval++ = (char)u;        /* will truncate values above 0xff */
+                break;
+            default:                /* handles double quote and solidus */
+                *pval++ = *cp;
+                break;
+            }
+            state = in_val_string;
+            break;
+        case in_val_token:
+            if (pval == NULL) {
+                /* don't update end here, leave at value start */
+                return JSON_ERR_NULLPTR;
+            }
+            if (isspace((unsigned char) *cp) || *cp == ',' || *cp == '}') {
+                *pval = '\0';
+                state = post_val;
+                if (*cp == '}' || *cp == ',') {
+                    --cp;
+                }
+            } else if (pval > valbuf + JSON_VAL_MAX - 1) {
+                /* don't update end here, leave at value start */
+                return JSON_ERR_TOKLONG;
+            } else {
+                *pval++ = *cp;
+            }
+            break;
+        case post_val:
+            /*
+             * We know that cursor points at the first spec matching
+             * the current attribute.  We don't know that it's *the*
+             * correct spec; our dialect allows there to be any number
+             * of adjacent ones with the same attrname but different
+             * types.  Here's where we try to seek forward for a
+             * matching type/attr pair if we're not looking at one.
+             */
+            for (;;) {
+                int seeking = cursor->type;
+                if (value_quoted && (cursor->type == t_string)) {
+                    break;
+                }
+                if ((strcmp(valbuf, "true")==0 || strcmp(valbuf, "false")==0)
+                        && seeking == t_boolean) {
+                    break;
+                }
+                if (isdigit((unsigned char) valbuf[0])) {
+                    bool decimal = strchr(valbuf, '.') != NULL;
+                    if (decimal && seeking == t_real) {
+                        break;
+                    }
+                    if (!decimal && (seeking == t_integer || seeking == t_uinteger)) {
+                        break;
+                    }
+                }
+                if (cursor[1].attribute==NULL) {       /* out of possiblities */
+                    break;
+                }
+                if (strcmp(cursor[1].attribute, attrbuf)!=0) {
+                    break;
+                }
+                ++cursor;
+            }
+            if (value_quoted
+                && (cursor->type != t_string && cursor->type != t_character
+                    && cursor->type != t_check && cursor->type != t_ignore 
+                    && cursor->map == 0)) {
+                return JSON_ERR_QNONSTRING;
+            }
+            if (!value_quoted
+                && (cursor->type == t_string || cursor->type == t_check
+                    || cursor->map != 0)) {
+                return JSON_ERR_NONQSTRING;
+            }
+            if (cursor->map != 0) {
+                for (mp = cursor->map; mp->name != NULL; mp++) {
+                    if (strcmp(mp->name, valbuf) == 0) {
+                        goto foundit;
+                    }
+                }
+                return JSON_ERR_BADENUM;
+              foundit:
+                (void)snprintf(valbuf, sizeof(valbuf), "%d", mp->value);
+            }
+            lptr = json_target_address(cursor, parent, offset);
+            if (lptr != NULL) {
+                switch (cursor->type) {
+                case t_integer: {
+                        int tmp = atoi(valbuf);
+                        memcpy(lptr, &tmp, sizeof(int));
+                    }
+                    break;
+                case t_uinteger: {
+                        unsigned int tmp = (unsigned int)atoi(valbuf);
+                        memcpy(lptr, &tmp, sizeof(unsigned int));
+                    }
+                    break;
+                case t_real: {
+                        double tmp = atof(valbuf);
+                        memcpy(lptr, &tmp, sizeof(double));
+                    }
+                    break;
+                case t_string:
+                    if (parent != NULL
+                        && parent->element_type != t_structobject
+                        && offset > 0) {
+                        return JSON_ERR_NOPARSTR;
+                    }
+                    (void)strncpy(lptr, valbuf, cursor->len);
+                    valbuf[sizeof(valbuf)-1] = '\0';
+                    break;
+                case t_boolean: {
+                        bool tmp = (strcmp(valbuf, "true") == 0);
+                        memcpy(lptr, &tmp, sizeof(bool));
+                    }
+                    break;
+                case t_character:
+                    if (strlen(valbuf) > 1) {
+                        /* don't update end here, leave at value start */
+                        return JSON_ERR_STRLONG;
+                    } else {
+                        lptr[0] = valbuf[0];
+                    }
+                    break;
+                case t_ignore:        /* silences a compiler warning */
+                case t_object:        /* silences a compiler warning */
+                case t_structobject:
+                case t_array:
+                    break;
+                case t_check:
+                    if (strcmp(cursor->dflt.check, valbuf) != 0) {
+                        /* don't update end here, leave at start of attribute */
+                        return JSON_ERR_CHECKFAIL;
+                    }
+                    break;
+                }
+            }
+            /*@fallthrough@*/
+        case post_array:
+            if (isspace((unsigned char) *cp)) {
+                continue;
+            } else if (*cp == ',') {
+                state = await_attr;
+            } else if (*cp == '}') {
+                ++cp;
+                goto good_parse;
+            } else {
+                if (end != NULL) {
+                    *end = cp;
+                }
+                return JSON_ERR_BADTRAIL;
+            }
+            break;
+        }
+    }
+
+  good_parse:
+    /* in case there's another object following, consume trailing WS */
+    while (isspace((unsigned char) *cp)) {
+        ++cp;
+    }
+    if (end != NULL) {
+        *end = cp;
+    }
+    return 0;
+}
+
+int 
+json_read_array(const char *cp, const struct json_array_t *arr, 
+        const char **end)
+{
+    int substatus, offset, arrcount;
+    char *tp;
+
+    if (end != NULL) {
+        /* give it a well-defined value on parse failure */
+        *end = NULL;
+    }
+
+    while (isspace((unsigned char) *cp)) {
+        cp++;
+    }
+
+    if (*cp != '[') {
+        return JSON_ERR_ARRAYSTART;
+    } else {
+        cp++;
+    }
+
+    tp = arr->arr.strings.store;
+    arrcount = 0;
+
+    /* Check for empty array */
+    while (isspace((unsigned char) *cp)) {
+        cp++;
+    }
+    if (*cp == ']') {
+        goto breakout;
+    }
+
+    for (offset = 0; offset < arr->maxlen; offset++) {
+        char *ep = NULL;
+        switch (arr->element_type) {
+        case t_string:
+            if (isspace((unsigned char) *cp)) {
+                cp++;
+            }
+            if (*cp != '"') {
+                return JSON_ERR_BADSTRING;
+            } else {
+                ++cp;
+            }
+            arr->arr.strings.ptrs[offset] = tp;
+            for (; tp - arr->arr.strings.store < arr->arr.strings.storelen;
+                 tp++) {
+                if (*cp == '"') {
+                    ++cp;
+                    *tp++ = '\0';
+                    goto stringend;
+                } else if (*cp == '\0') {
+                    return JSON_ERR_BADSTRING;
+                } else {
+                    *tp = *cp++;
+                }
+            }
+            return JSON_ERR_BADSTRING;
+          stringend:
+            break;
+        case t_object:
+        case t_structobject:
+            substatus =
+                json_internal_read_object(cp, arr->arr.objects.subtype, arr,
+                                          offset, &cp);
+            if (substatus != 0) {
+                if (end != NULL) {
+                    end = &cp;
+                }
+                return substatus;
+            }
+            break;
+        case t_integer:
+            arr->arr.integers.store[offset] = (int)strtol(cp, &ep, 0);
+            if (ep == cp) {
+                return JSON_ERR_BADNUM;
+            } else {
+                cp = ep;
+            }
+            break;
+        case t_uinteger:
+            arr->arr.uintegers.store[offset] = (unsigned int)strtoul(cp, &ep, 0);
+            if (ep == cp) {
+                return JSON_ERR_BADNUM;
+            } else {
+                cp = ep;
+            }
+            break;
+        case t_real:
+            arr->arr.reals.store[offset] = strtod(cp, &ep);
+            if (ep == cp) {
+                return JSON_ERR_BADNUM;
+            } else {
+                cp = ep;
+            }
+            break;
+        case t_boolean:
+            if (strncmp(cp, "true", 4) == 0) {
+                arr->arr.booleans.store[offset] = true;
+                cp += 4;
+            }
+            else if (strncmp(cp, "false", 5) == 0) {
+                arr->arr.booleans.store[offset] = false;
+                cp += 5;
+            }
+            break;
+        case t_character:
+        case t_array:
+        case t_check:
+        case t_ignore:
+            return JSON_ERR_SUBTYPE;
+        }
+        arrcount++;
+        if (isspace((unsigned char) *cp)) {
+            cp++;
+        }
+        if (*cp == ']') {
+            goto breakout;
+        } else if (*cp == ',') {
+            cp++;
+        } else {
+            return JSON_ERR_BADSUBTRAIL;
+        }
+    }
+    if (end != NULL) {
+        *end = cp;
+    }
+    return JSON_ERR_SUBTOOLONG;
+  breakout:
+    if (arr->count != NULL) {
+        *(arr->count) = arrcount;
+    }
+    if (end != NULL) {
+        *end = cp;
+    }
+    return 0;
+}
+
+int 
+json_read_object(const char *cp, const struct json_attr_t *attrs, 
+        const char **end)
+{
+    int st;
+
+    st = json_internal_read_object(cp, attrs, NULL, 0, end);
+    return st;
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/4628d6bb/libs/json/src/json_encode.c
----------------------------------------------------------------------
diff --git a/libs/json/src/json_encode.c b/libs/json/src/json_encode.c
new file mode 100644
index 0000000..ccaf615
--- /dev/null
+++ b/libs/json/src/json_encode.c
@@ -0,0 +1,136 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+
+#include <json/json.h>
+
+#define JSON_ENCODE_OBJECT_START(__e) \
+    (__e)->je_write((__e)->je_arg, "{", sizeof("{")-1);
+
+#define JSON_ENCODE_OBJECT_END(__e) \
+    (__e)->je_write((__e)->je_arg, "}", sizeof("}")-1);
+
+#define JSON_ENCODE_ARRAY_START(__e) \
+    (__e)->je_write((__e)->je_arg, "[", sizeof("[")-1);
+
+#define JSON_ENCODE_ARRAY_END(__e) \
+    (__e)->je_write((__e)->je_arg, "]", sizeof("]")-1);
+
+
+int 
+json_encode_object_start(struct json_encoder *encoder, void *buf, 
+        json_write_func_t wf)
+{
+    encoder->je_write = wf;
+    encoder->je_arg = buf;
+
+    JSON_ENCODE_OBJECT_START(encoder);
+
+    return (0);
+}
+
+static int 
+json_encode_value(struct json_encoder *encoder, struct json_value *jv)
+{
+    int rc;
+    int i;
+    int len;
+
+    switch (jv->jv_type) {
+        case JSON_VALUE_TYPE_BOOL:
+            len = sprintf(encoder->je_encode_buf, "%s", 
+                    jv->jv_val.u > 0 ? "true" : "false");
+            encoder->je_write(encoder->je_arg, encoder->je_encode_buf, len);
+            break;
+        case JSON_VALUE_TYPE_UINT64:
+            len = sprintf(encoder->je_encode_buf, "%llu", jv->jv_val.u);
+            encoder->je_write(encoder->je_arg, encoder->je_encode_buf, len);
+            break;
+        case JSON_VALUE_TYPE_INT64:
+            len = sprintf(encoder->je_encode_buf, "%lld", 
+                    (int64_t) jv->jv_val.u);
+            encoder->je_write(encoder->je_arg, encoder->je_encode_buf, len);
+            break;
+        case JSON_VALUE_TYPE_STRING:
+            encoder->je_write(encoder->je_arg, jv->jv_val.str, jv->jv_len);
+            break;
+        case JSON_VALUE_TYPE_ARRAY:
+            JSON_ENCODE_ARRAY_START(encoder);
+            for (i = 0; i < jv->jv_len; i++) {
+                rc = json_encode_value(encoder, jv->jv_val.composite.values[i]);
+                if (rc != 0) {
+                    goto err;
+                }
+                encoder->je_write(encoder->je_arg, ",", sizeof(",")-1);
+            }
+            JSON_ENCODE_ARRAY_END(encoder);
+            break;
+        case JSON_VALUE_TYPE_OBJECT:
+            JSON_ENCODE_OBJECT_START(encoder);
+            for (i = 0; i < jv->jv_len; i++) {
+                rc = json_encode_object_entry(encoder, 
+                        jv->jv_val.composite.keys[i], 
+                        jv->jv_val.composite.values[i]);
+                if (rc != 0) {
+                    goto err;
+                }
+            }
+            JSON_ENCODE_OBJECT_END(encoder);
+            break;
+        default:
+            rc = -1;
+            goto err;
+    }
+
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+int 
+json_encode_object_entry(struct json_encoder *encoder, char *key, 
+        struct json_value *val)
+{
+    int rc;
+
+    /* Write the key entry */
+    encoder->je_write(encoder->je_arg, "\"", sizeof("\"")-1);
+    encoder->je_write(encoder->je_arg, key, strlen(key));
+    encoder->je_write(encoder->je_arg, "\": ", sizeof("\": ")-1);
+
+    rc = json_encode_value(encoder, val);
+    if (rc != 0) {
+        goto err;
+    }
+    encoder->je_write(encoder->je_arg, ",", sizeof(",")-1);
+
+    return (0);
+err:
+    return (rc);
+}
+
+int 
+json_encode_object_finish(struct json_encoder *encoder)
+{
+    JSON_ENCODE_OBJECT_END(encoder);
+
+    return (0);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/4628d6bb/libs/newtmgr/egg.yml
----------------------------------------------------------------------
diff --git a/libs/newtmgr/egg.yml b/libs/newtmgr/egg.yml
index 719abd2..8f5e6b2 100644
--- a/libs/newtmgr/egg.yml
+++ b/libs/newtmgr/egg.yml
@@ -2,6 +2,7 @@ egg.name: libs/newtmgr
 egg.vers: 0.1
 egg.deps:
     - libs/os
+    - libs/json
     - libs/util
     - libs/testutil
 egg.deps.SHELL:

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/4628d6bb/libs/newtmgr/src/newtmgr.c
----------------------------------------------------------------------
diff --git a/libs/newtmgr/src/newtmgr.c b/libs/newtmgr/src/newtmgr.c
index 72ea06a..951ae8c 100644
--- a/libs/newtmgr/src/newtmgr.c
+++ b/libs/newtmgr/src/newtmgr.c
@@ -46,8 +46,6 @@ static struct nmgr_handler nmgr_def_group_handlers[] = {
 };
 
 
-struct json_encoder json_mbuf_encoder;
-
 static int 
 nmgr_def_echo(struct nmgr_hdr *nmr, struct os_mbuf *req, uint16_t srcoff,
         struct nmgr_hdr *rsp_hdr, struct os_mbuf *rsp)
@@ -60,19 +58,6 @@ nmgr_def_echo(struct nmgr_hdr *nmr, struct os_mbuf *req, uint16_t srcoff,
         goto err;
     }
 
-    rc = nmgr_rsp_init(rsp_hdr, rsp);
-    if (rc != 0) {
-        goto err;
-    }
-
-    // You can write to the mbuf here.
-
-    rc = nmgr_rsp_finish(rsp_hdr, rsp);
-    if (rc != 0) {
-        goto err;
-    }
-
-
     rc = nmgr_rsp_extend(rsp_hdr, rsp, echo_buf, nmr->nh_len);
     if (rc != 0) {
         goto err;
@@ -83,25 +68,6 @@ err:
     return (rc);
 }
 
-static int 
-nmgr_json_write_mbuf(void *buf, uint8_t *data, int len)
-{
-    struct os_mbuf *m;
-    int rc;
-
-    m = (struct os_mbuf *) buf;
-
-    rc = os_mbuf_append(m, data, len);
-    if (rc != 0) {
-        goto err;
-    }
-
-    return (0);
-err:
-    return (rc);
-}
-
-
 int 
 nmgr_group_list_lock(void)
 {
@@ -442,11 +408,6 @@ nmgr_task_init(uint8_t prio, os_stack_t *stack_ptr, uint16_t stack_len)
         goto err;
     }
 
-    rc = json_encoder_init(&json_mbuf_encoder, json_write_mbuf);
-    if (rc != 0) {
-        goto err;
-    }
-
     return (0);
 err:
     return (rc);



[2/2] incubator-mynewt-larva git commit: initial json mbuf code, commiting for local merge.

Posted by st...@apache.org.
initial json mbuf code, commiting for local merge.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/37e081d6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/37e081d6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/37e081d6

Branch: refs/heads/master
Commit: 37e081d6b0fd807662e1bb531852910d5bfbce99
Parents: 83801d4
Author: Sterling Hughes <st...@apache.org>
Authored: Fri Jan 8 18:12:25 2016 +0200
Committer: Sterling Hughes <st...@apache.org>
Committed: Tue Jan 12 13:34:09 2016 -0800

----------------------------------------------------------------------
 libs/newtmgr/src/newtmgr.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/37e081d6/libs/newtmgr/src/newtmgr.c
----------------------------------------------------------------------
diff --git a/libs/newtmgr/src/newtmgr.c b/libs/newtmgr/src/newtmgr.c
index 951ae8c..72ea06a 100644
--- a/libs/newtmgr/src/newtmgr.c
+++ b/libs/newtmgr/src/newtmgr.c
@@ -46,6 +46,8 @@ static struct nmgr_handler nmgr_def_group_handlers[] = {
 };
 
 
+struct json_encoder json_mbuf_encoder;
+
 static int 
 nmgr_def_echo(struct nmgr_hdr *nmr, struct os_mbuf *req, uint16_t srcoff,
         struct nmgr_hdr *rsp_hdr, struct os_mbuf *rsp)
@@ -58,6 +60,19 @@ nmgr_def_echo(struct nmgr_hdr *nmr, struct os_mbuf *req, uint16_t srcoff,
         goto err;
     }
 
+    rc = nmgr_rsp_init(rsp_hdr, rsp);
+    if (rc != 0) {
+        goto err;
+    }
+
+    // You can write to the mbuf here.
+
+    rc = nmgr_rsp_finish(rsp_hdr, rsp);
+    if (rc != 0) {
+        goto err;
+    }
+
+
     rc = nmgr_rsp_extend(rsp_hdr, rsp, echo_buf, nmr->nh_len);
     if (rc != 0) {
         goto err;
@@ -68,6 +83,25 @@ err:
     return (rc);
 }
 
+static int 
+nmgr_json_write_mbuf(void *buf, uint8_t *data, int len)
+{
+    struct os_mbuf *m;
+    int rc;
+
+    m = (struct os_mbuf *) buf;
+
+    rc = os_mbuf_append(m, data, len);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
 int 
 nmgr_group_list_lock(void)
 {
@@ -408,6 +442,11 @@ nmgr_task_init(uint8_t prio, os_stack_t *stack_ptr, uint16_t stack_len)
         goto err;
     }
 
+    rc = json_encoder_init(&json_mbuf_encoder, json_write_mbuf);
+    if (rc != 0) {
+        goto err;
+    }
+
     return (0);
 err:
     return (rc);