Minimalist JSON parser and serializer (inspired by picojson). Used by MbedJSONRpc. (Original by Samuel Mokrani)

Dependents:   City_Game_JSON City_Game_JSON

Fork of MbedJSONValue by Samuel Mokrani

Committer:
dwini
Date:
Thu Nov 24 20:25:42 2016 +0000
Revision:
6:c21b9ffd9628
Parent:
5:ba03a74f9119
Child:
7:a2fabe322eff
Replace stdio.h and stdlib.h with cstdio and cstdlib to fix problem of library not compiling with offline toolchain.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 0:0cf0e27feaad 1 #include "MbedJSONValue.h"
samux 0:0cf0e27feaad 2
dwini 6:c21b9ffd9628 3 #include <cstdio>
dwini 6:c21b9ffd9628 4 #include <cstdlib>
samux 0:0cf0e27feaad 5
samux 0:0cf0e27feaad 6 // Clean up
samux 0:0cf0e27feaad 7 void MbedJSONValue::clean() {
samux 0:0cf0e27feaad 8 switch (_type) {
samux 0:0cf0e27feaad 9 case TypeString:
samux 0:0cf0e27feaad 10 delete _value.asString;
samux 0:0cf0e27feaad 11 break;
samux 0:0cf0e27feaad 12 case TypeArray:
samux 0:0cf0e27feaad 13 for (int i = 0; i < index_array; i++)
samux 0:0cf0e27feaad 14 delete array[i];
samux 0:0cf0e27feaad 15 index_array = 0;
samux 0:0cf0e27feaad 16 break;
samux 0:0cf0e27feaad 17 case TypeObject:
samux 0:0cf0e27feaad 18 for (int i = 0; i < index_token; i++) {
samux 0:0cf0e27feaad 19 delete token[i];
samux 0:0cf0e27feaad 20 delete token_name[i];
samux 0:0cf0e27feaad 21 }
samux 0:0cf0e27feaad 22 index_token = 0;
samux 0:0cf0e27feaad 23 break;
samux 0:0cf0e27feaad 24 default:
samux 0:0cf0e27feaad 25 break;
samux 0:0cf0e27feaad 26 }
samux 0:0cf0e27feaad 27 _type = TypeNull;
samux 0:0cf0e27feaad 28 _type = TypeNull;
samux 0:0cf0e27feaad 29 }
samux 0:0cf0e27feaad 30
samux 0:0cf0e27feaad 31 bool MbedJSONValue::hasMember(char * name)
samux 0:0cf0e27feaad 32 {
samux 0:0cf0e27feaad 33 for(int i = 0; i < index_token; i++)
samux 0:0cf0e27feaad 34 if( !strcmp(name, (*(token_name[i])).c_str() ))
samux 0:0cf0e27feaad 35 return true;
samux 0:0cf0e27feaad 36 return false;
samux 0:0cf0e27feaad 37 }
samux 0:0cf0e27feaad 38
samux 0:0cf0e27feaad 39
samux 0:0cf0e27feaad 40 void copy(const std::string& s, std::back_insert_iterator<std::string> oi) {
samux 0:0cf0e27feaad 41 std::copy(s.begin(), s.end(), oi);
samux 0:0cf0e27feaad 42 }
samux 0:0cf0e27feaad 43
samux 0:0cf0e27feaad 44 void serialize_str(const std::string& s, std::back_insert_iterator<std::string> oi) {
samux 0:0cf0e27feaad 45 *oi++ = '"';
samux 0:0cf0e27feaad 46 for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
samux 0:0cf0e27feaad 47 switch (*i) {
samux 0:0cf0e27feaad 48 #define MAP(val, sym) case val: copy(sym, oi); break
samux 0:0cf0e27feaad 49 MAP('"', "\\\"");
samux 0:0cf0e27feaad 50 MAP('\\', "\\\\");
samux 0:0cf0e27feaad 51 MAP('/', "\\/");
samux 0:0cf0e27feaad 52 MAP('\b', "\\b");
samux 0:0cf0e27feaad 53 MAP('\f', "\\f");
samux 0:0cf0e27feaad 54 MAP('\n', "\\n");
samux 0:0cf0e27feaad 55 MAP('\r', "\\r");
samux 0:0cf0e27feaad 56 MAP('\t', "\\t");
samux 0:0cf0e27feaad 57 #undef MAP
samux 0:0cf0e27feaad 58 default:
samux 0:0cf0e27feaad 59 if ((unsigned char)*i < 0x20 || *i == 0x7f) {
samux 0:0cf0e27feaad 60 char buf[7];
dwini 6:c21b9ffd9628 61 std::sprintf(buf, "\\u%04x", *i & 0xff);
samux 0:0cf0e27feaad 62 copy(buf, buf + 6, oi);
samux 0:0cf0e27feaad 63 } else {
samux 0:0cf0e27feaad 64 *oi++ = *i;
samux 0:0cf0e27feaad 65 }
samux 0:0cf0e27feaad 66 break;
samux 0:0cf0e27feaad 67 }
samux 0:0cf0e27feaad 68 }
samux 0:0cf0e27feaad 69 *oi++ = '"';
samux 0:0cf0e27feaad 70 }
samux 0:0cf0e27feaad 71
samux 0:0cf0e27feaad 72 std::string MbedJSONValue::serialize(){
samux 0:0cf0e27feaad 73 std::string s;
samux 0:0cf0e27feaad 74 serialize(std::back_inserter(s));
samux 0:0cf0e27feaad 75 return s;
samux 0:0cf0e27feaad 76 }
samux 0:0cf0e27feaad 77
samux 0:0cf0e27feaad 78 std::string MbedJSONValue::to_str(){
samux 0:0cf0e27feaad 79 switch (_type) {
samux 0:0cf0e27feaad 80 case TypeNull:
samux 0:0cf0e27feaad 81 return "null";
samux 0:0cf0e27feaad 82 case TypeBoolean:
samux 0:0cf0e27feaad 83 return _value.asBool ? "true" : "false";
samux 0:0cf0e27feaad 84 case TypeInt: {
samux 0:0cf0e27feaad 85 char buf[10];
dwini 6:c21b9ffd9628 86 std::sprintf(buf, "%d", _value.asInt);
samux 0:0cf0e27feaad 87 return buf;
samux 0:0cf0e27feaad 88 }
samux 0:0cf0e27feaad 89 case TypeDouble: {
samux 0:0cf0e27feaad 90 char buf[10];
dwini 6:c21b9ffd9628 91 std::sprintf(buf, "%f", _value.asDouble);
samux 0:0cf0e27feaad 92 return buf;
samux 0:0cf0e27feaad 93 }
samux 0:0cf0e27feaad 94 default:
samux 0:0cf0e27feaad 95 break;
samux 0:0cf0e27feaad 96 }
samux 0:0cf0e27feaad 97 return NULL;
samux 0:0cf0e27feaad 98 }
samux 0:0cf0e27feaad 99
samux 0:0cf0e27feaad 100
samux 0:0cf0e27feaad 101
samux 0:0cf0e27feaad 102 void MbedJSONValue::serialize(std::back_insert_iterator<std::string> oi) {
samux 0:0cf0e27feaad 103 switch (_type) {
samux 0:0cf0e27feaad 104 case TypeString:
samux 0:0cf0e27feaad 105 serialize_str(*_value.asString, oi);
samux 0:0cf0e27feaad 106 break;
samux 0:0cf0e27feaad 107 case TypeArray: {
samux 0:0cf0e27feaad 108 *oi++ = '[';
samux 0:0cf0e27feaad 109 for (int i = 0; i < index_array; i++) {
samux 0:0cf0e27feaad 110 if (i)
samux 0:0cf0e27feaad 111 *oi++ = ',';
samux 0:0cf0e27feaad 112 (*this)[i].serialize(oi);
samux 0:0cf0e27feaad 113 }
samux 0:0cf0e27feaad 114 *oi++ = ']';
samux 0:0cf0e27feaad 115 break;
samux 0:0cf0e27feaad 116 }
samux 0:0cf0e27feaad 117 case TypeObject: {
samux 0:0cf0e27feaad 118 *oi++ = '{';
samux 0:0cf0e27feaad 119 for (int i = 0; i < index_token; i++) {
samux 0:0cf0e27feaad 120 if (i)
samux 0:0cf0e27feaad 121 *oi++ = ',';
samux 0:0cf0e27feaad 122 serialize_str(*(token_name[i]), oi);
samux 0:0cf0e27feaad 123 *oi++ = ':';
samux 0:0cf0e27feaad 124 (*(token[i])).serialize(oi);
samux 0:0cf0e27feaad 125 }
samux 0:0cf0e27feaad 126 *oi++ = '}';
samux 0:0cf0e27feaad 127 break;
samux 0:0cf0e27feaad 128 }
samux 0:0cf0e27feaad 129 default:
samux 0:0cf0e27feaad 130 copy(to_str(), oi);
samux 0:0cf0e27feaad 131 break;
samux 0:0cf0e27feaad 132 }
samux 0:0cf0e27feaad 133 }
samux 0:0cf0e27feaad 134
samux 0:0cf0e27feaad 135
samux 0:0cf0e27feaad 136
samux 0:0cf0e27feaad 137 MbedJSONValue& MbedJSONValue::operator[](int i) {
samux 0:0cf0e27feaad 138 _type = TypeArray;
samux 0:0cf0e27feaad 139 if (i < NB_TOKEN && index_array == i ) {
samux 0:0cf0e27feaad 140 #ifdef DEBUG
samux 0:0cf0e27feaad 141 printf("will add an element to the array\r\n");
samux 0:0cf0e27feaad 142 #endif
samux 0:0cf0e27feaad 143 array[i] = new MbedJSONValue();
samux 0:0cf0e27feaad 144 index_array++;
samux 0:0cf0e27feaad 145 return *(array[i]);
samux 0:0cf0e27feaad 146 }
samux 0:0cf0e27feaad 147 if (i < NB_TOKEN && index_array > i)
samux 0:0cf0e27feaad 148 return *(array[i]);
samux 0:0cf0e27feaad 149
samux 0:0cf0e27feaad 150 //if the user is not doing something wrong, this code is never executed!!
samux 0:0cf0e27feaad 151 return *(new MbedJSONValue());
samux 0:0cf0e27feaad 152 }
samux 0:0cf0e27feaad 153
samux 0:0cf0e27feaad 154 MbedJSONValue& MbedJSONValue::operator[](std::string k) {
samux 0:0cf0e27feaad 155 _type = TypeObject;
samux 0:0cf0e27feaad 156 for (int i = 0; i < index_token; i++) {
samux 0:0cf0e27feaad 157 #ifdef DEBUG
samux 0:0cf0e27feaad 158 printf("k: %s\r\n", k.c_str());
samux 0:0cf0e27feaad 159 printf("str: %s\r\n", token_name[i]->c_str());
samux 0:0cf0e27feaad 160 #endif
samux 0:0cf0e27feaad 161 //existing token
samux 0:0cf0e27feaad 162 if (!strcmp(k.c_str(), token_name[i]->c_str())) {
samux 0:0cf0e27feaad 163 #ifdef DEBUG
samux 0:0cf0e27feaad 164 printf("token found: %d\r\n", i);
samux 0:0cf0e27feaad 165 #endif
samux 0:0cf0e27feaad 166 return *(token[i]);
samux 0:0cf0e27feaad 167 }
samux 0:0cf0e27feaad 168 }
samux 0:0cf0e27feaad 169
samux 0:0cf0e27feaad 170 if(index_token >= NB_TOKEN)
samux 0:0cf0e27feaad 171 index_token = NB_TOKEN - 1;
samux 0:0cf0e27feaad 172 //non existing token
samux 0:0cf0e27feaad 173 token_name[index_token] = new std::string(k);
samux 0:0cf0e27feaad 174 token[index_token] = new MbedJSONValue();
samux 0:0cf0e27feaad 175 index_token++;
samux 0:0cf0e27feaad 176 return *(token[index_token - 1]);
samux 0:0cf0e27feaad 177 }
samux 0:0cf0e27feaad 178
samux 0:0cf0e27feaad 179 MbedJSONValue& MbedJSONValue::operator[](std::string k) const
samux 0:0cf0e27feaad 180 {
samux 0:0cf0e27feaad 181 for (int i = 0; i < index_token; i++) {
samux 0:0cf0e27feaad 182 #ifdef DEBUG
samux 0:0cf0e27feaad 183 printf("k: %s\r\n", k.c_str());
samux 0:0cf0e27feaad 184 printf("str: %s\r\n", token_name[i]->c_str());
samux 0:0cf0e27feaad 185 #endif
samux 0:0cf0e27feaad 186 if (!strcmp(k.c_str(), token_name[i]->c_str())) {
samux 0:0cf0e27feaad 187 #ifdef DEBUG
samux 0:0cf0e27feaad 188 printf("token found: %d\r\n", i);
samux 0:0cf0e27feaad 189 #endif
samux 0:0cf0e27feaad 190 return *(token[i]);
samux 0:0cf0e27feaad 191 }
samux 0:0cf0e27feaad 192 }
samux 0:0cf0e27feaad 193
samux 0:0cf0e27feaad 194 //if the user is not doing something wrong, this code is never executed!!
samux 0:0cf0e27feaad 195 return *(new MbedJSONValue());
samux 0:0cf0e27feaad 196 }
samux 0:0cf0e27feaad 197
samux 0:0cf0e27feaad 198
samux 0:0cf0e27feaad 199 // Operators
samux 0:0cf0e27feaad 200 MbedJSONValue& MbedJSONValue::operator=(MbedJSONValue const& rhs) {
samux 0:0cf0e27feaad 201 if (this != &rhs) {
samux 0:0cf0e27feaad 202 clean();
samux 0:0cf0e27feaad 203 _type = rhs._type;
samux 0:0cf0e27feaad 204 switch (_type) {
samux 0:0cf0e27feaad 205 case TypeBoolean:
samux 0:0cf0e27feaad 206 _value.asBool = rhs._value.asBool;
samux 0:0cf0e27feaad 207 break;
samux 0:0cf0e27feaad 208 case TypeInt:
samux 0:0cf0e27feaad 209 _value.asInt = rhs._value.asInt;
samux 0:0cf0e27feaad 210 break;
samux 0:0cf0e27feaad 211 case TypeDouble:
samux 0:0cf0e27feaad 212 _value.asDouble = rhs._value.asDouble;
samux 0:0cf0e27feaad 213 break;
samux 0:0cf0e27feaad 214 case TypeString:
samux 0:0cf0e27feaad 215 _value.asString = new std::string(*rhs._value.asString);
samux 0:0cf0e27feaad 216 break;
samux 0:0cf0e27feaad 217 case TypeArray:
samux 0:0cf0e27feaad 218 for (int i = 0; i < rhs.index_array; i++)
samux 0:0cf0e27feaad 219 (*this)[i] = rhs[i];
samux 0:0cf0e27feaad 220 case TypeObject:
samux 0:0cf0e27feaad 221 for (int i = 0; i < rhs.index_token; i++)
samux 0:0cf0e27feaad 222 (*this)[*(rhs.token_name[i])] = rhs[*(rhs.token_name[i])];
samux 0:0cf0e27feaad 223 default:
samux 0:0cf0e27feaad 224 break;
samux 0:0cf0e27feaad 225 }
samux 0:0cf0e27feaad 226 }
samux 0:0cf0e27feaad 227 return *this;
samux 0:0cf0e27feaad 228 }
samux 0:0cf0e27feaad 229
samux 0:0cf0e27feaad 230
samux 0:0cf0e27feaad 231 // Works for strings, arrays, and structs.
samux 0:0cf0e27feaad 232 int MbedJSONValue::size() const {
samux 0:0cf0e27feaad 233 switch (_type) {
samux 0:0cf0e27feaad 234 case TypeString:
samux 0:0cf0e27feaad 235 return int(_value.asString->size());
samux 0:0cf0e27feaad 236 case TypeArray:
samux 0:0cf0e27feaad 237 return index_array;
samux 0:0cf0e27feaad 238 case TypeObject:
samux 0:0cf0e27feaad 239 return index_token;
samux 0:0cf0e27feaad 240 default:
samux 0:0cf0e27feaad 241 break;
samux 0:0cf0e27feaad 242 }
dwini 5:ba03a74f9119 243 return 0; // 0 is better than -1 for for-loops
samux 0:0cf0e27feaad 244 }
samux 0:0cf0e27feaad 245