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

Dependents:   RPC_mbed_client WebSocket_test pseudo_comet RPC_Wifly_HelloWorld ... more

Committer:
samux
Date:
Thu Sep 22 10:57:37 2011 +0000
Revision:
4:10a99cdf7846
Parent:
3:f2ffae08b963

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 0:0cf0e27feaad 1 #include "MbedJSONValue.h"
samux 0:0cf0e27feaad 2
samux 0:0cf0e27feaad 3 # include <stdlib.h>
samux 0:0cf0e27feaad 4 # include <stdio.h>
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];
samux 0:0cf0e27feaad 61 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];
samux 0:0cf0e27feaad 86 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];
samux 0:0cf0e27feaad 91 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 }
samux 0:0cf0e27feaad 243 return -1;
samux 0:0cf0e27feaad 244 }
samux 0:0cf0e27feaad 245