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);