Jim Flynn / Mbed OS aws-iot-device-sdk-mbed-c
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers aws_iot_json_utils.c Source File

aws_iot_json_utils.c

00001 /*
00002  * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License").
00005  * You may not use this file except in compliance with the License.
00006  * A copy of the License is located at
00007  *
00008  *  http://aws.amazon.com/apache2.0
00009  *
00010  * or in the "license" file accompanying this file. This file is distributed
00011  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
00012  * express or implied. See the License for the specific language governing
00013  * permissions and limitations under the License.
00014  */
00015 
00016 /**
00017  * @file aws_json_utils.c
00018  * @brief Utilities for manipulating JSON
00019  *
00020  * json_utils provides JSON parsing utilities for use with the IoT SDK.
00021  * Underlying JSON parsing relies on the Jasmine JSON parser.
00022  *
00023  */
00024 
00025 #ifdef __cplusplus
00026 extern "C" {
00027 #endif
00028 
00029 #include "aws_iot_json_utils.h"
00030 
00031 #include <stdio.h>
00032 #include <stdint.h>
00033 #include <string.h>
00034 
00035 #include "aws_iot_log.h"
00036 
00037 int8_t jsoneq(const char *json, jsmntok_t *tok, const char *s) {
00038     if(tok->type == JSMN_STRING) {
00039         if((int) strlen(s) == tok->end - tok->start) {
00040             if(strncmp(json + tok->start, s, (size_t) (tok->end - tok->start)) == 0) {
00041                 return 0;
00042             }
00043         }
00044     }
00045     return -1;
00046 }
00047 
00048 IoT_Error_t parseUnsignedInteger32Value(uint32_t *i, const char *jsonString, jsmntok_t *token) {
00049     if(token->type != JSMN_PRIMITIVE) {
00050         IOT_WARN("Token was not an integer");
00051         return JSON_PARSE_ERROR;
00052     }
00053 
00054     if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%lu", i))) {
00055         IOT_WARN("Token was not an unsigned integer.");
00056         return JSON_PARSE_ERROR;
00057     }
00058 
00059     return AWS_SUCCESS;
00060 }
00061 
00062 IoT_Error_t parseUnsignedInteger16Value(uint16_t *i, const char *jsonString, jsmntok_t *token) {
00063     if(token->type != JSMN_PRIMITIVE) {
00064         IOT_WARN("Token was not an integer");
00065         return JSON_PARSE_ERROR;
00066     }
00067 
00068     if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%hu", i))) {
00069         IOT_WARN("Token was not an unsigned integer.");
00070         return JSON_PARSE_ERROR;
00071     }
00072 
00073     return AWS_SUCCESS;
00074 }
00075 
00076 IoT_Error_t parseUnsignedInteger8Value(uint8_t *i, const char *jsonString, jsmntok_t *token) {
00077     if(token->type != JSMN_PRIMITIVE) {
00078         IOT_WARN("Token was not an integer");
00079         return JSON_PARSE_ERROR;
00080     }
00081 
00082     if(('-' == (char) (jsonString[token->start])) || (1 != sscanf(jsonString + token->start, "%hhu", i))) {
00083         IOT_WARN("Token was not an unsigned integer.");
00084         return JSON_PARSE_ERROR;
00085     }
00086 
00087     return AWS_SUCCESS;
00088 }
00089 
00090 IoT_Error_t parseInteger32Value(int32_t *i, const char *jsonString, jsmntok_t *token) {
00091     if(token->type != JSMN_PRIMITIVE) {
00092         IOT_WARN("Token was not an integer");
00093         return JSON_PARSE_ERROR;
00094     }
00095 
00096     if(1 != sscanf(jsonString + token->start, "%li", i)) {
00097         IOT_WARN("Token was not an integer.");
00098         return JSON_PARSE_ERROR;
00099     }
00100 
00101     return AWS_SUCCESS;
00102 }
00103 
00104 IoT_Error_t parseInteger16Value(int16_t *i, const char *jsonString, jsmntok_t *token) {
00105     if(token->type != JSMN_PRIMITIVE) {
00106         IOT_WARN("Token was not an integer");
00107         return JSON_PARSE_ERROR;
00108     }
00109 
00110     if(1 != sscanf(jsonString + token->start, "%hi", i)) {
00111         IOT_WARN("Token was not an integer.");
00112         return JSON_PARSE_ERROR;
00113     }
00114 
00115     return AWS_SUCCESS;
00116 }
00117 
00118 IoT_Error_t parseInteger8Value(int8_t *i, const char *jsonString, jsmntok_t *token) {
00119     if(token->type != JSMN_PRIMITIVE) {
00120         IOT_WARN("Token was not an integer");
00121         return JSON_PARSE_ERROR;
00122     }
00123 
00124     if(1 != sscanf(jsonString + token->start, "%hhi", i)) {
00125         IOT_WARN("Token was not an integer.");
00126         return JSON_PARSE_ERROR;
00127     }
00128 
00129     return AWS_SUCCESS;
00130 }
00131 
00132 IoT_Error_t parseFloatValue(float *f, const char *jsonString, jsmntok_t *token) {
00133     if(token->type != JSMN_PRIMITIVE) {
00134         IOT_WARN("Token was not a float.");
00135         return JSON_PARSE_ERROR;
00136     }
00137 
00138     if(1 != sscanf(jsonString + token->start, "%f", f)) {
00139         IOT_WARN("Token was not a float.");
00140         return JSON_PARSE_ERROR;
00141     }
00142 
00143     return AWS_SUCCESS;
00144 }
00145 
00146 IoT_Error_t parseDoubleValue(double *d, const char *jsonString, jsmntok_t *token) {
00147     if(token->type != JSMN_PRIMITIVE) {
00148         IOT_WARN("Token was not a double.");
00149         return JSON_PARSE_ERROR;
00150     }
00151 
00152     if(1 != sscanf(jsonString + token->start, "%lf", d)) {
00153         IOT_WARN("Token was not a double.");
00154         return JSON_PARSE_ERROR;
00155     }
00156 
00157     return AWS_SUCCESS;
00158 }
00159 
00160 IoT_Error_t parseBooleanValue(bool *b, const char *jsonString, jsmntok_t *token) {
00161     if(token->type != JSMN_PRIMITIVE) {
00162         IOT_WARN("Token was not a primitive.");
00163         return JSON_PARSE_ERROR;
00164     }
00165     if(strncmp(jsonString + token->start, "true", 4) == 0) {
00166         *b = true;
00167     } else if(strncmp(jsonString + token->start, "false", 5) == 0) {
00168         *b = false;
00169     } else {
00170         IOT_WARN("Token was not a bool.");
00171         return JSON_PARSE_ERROR;
00172     }
00173     return AWS_SUCCESS;
00174 }
00175 
00176 IoT_Error_t parseStringValue(char *buf, size_t bufLen, const char *jsonString, jsmntok_t *token) {
00177     /* This length does not include a null-terminator. */
00178     size_t stringLength = (size_t)(token->end - token->start);
00179 
00180     if(token->type != JSMN_STRING) {
00181         IOT_WARN("Token was not a string.");
00182         return JSON_PARSE_ERROR;
00183     }
00184 
00185     if (stringLength+1 > bufLen) {
00186         IOT_WARN("Buffer too small to hold string value.");
00187         return SHADOW_JSON_ERROR;
00188     }
00189 
00190     strncpy(buf, jsonString + token->start, stringLength);
00191     buf[stringLength] = '\0';
00192 
00193     return AWS_SUCCESS;
00194 }
00195 
00196 jsmntok_t *findToken(const char *key, const char *jsonString, jsmntok_t *token) {
00197     jsmntok_t *result = token;
00198     int i;
00199 
00200     if(token->type != JSMN_OBJECT) {
00201         IOT_WARN("Token was not an object.");
00202         return NULL;
00203     }
00204 
00205     if(token->size == 0) {
00206         return NULL;
00207     }
00208 
00209     result = token + 1;
00210 
00211     for (i = 0; i < token->size; i++) {
00212         if (0 == jsoneq(jsonString, result, key)) {
00213             return result + 1;
00214         }
00215 
00216         int propertyEnd = (result + 1)->end;
00217         result += 2;
00218         while (result->start < propertyEnd)
00219             result++;
00220     }
00221 
00222     return NULL;
00223 }
00224 
00225 #ifdef __cplusplus
00226 }
00227 #endif