JsonParser.cpp
1 #include "JsonParser.hpp" 2 3 static jsonType _getPrimitiveType 4 (std::string const& str); 5 static std::string _getStringData 6 (std::string const& text, std::string::iterator& it); 7 static std::string _parseStringKey 8 (std::string const& text, std::string::iterator& it); 9 static std::string _parseStringValue 10 (std::string const& text, std::string::iterator& it); 11 static std::string _parsePrimitive 12 (std::string const& text, std::string::iterator& it, jsonType& type); 13 static bool _checkLineEnd 14 (std::string const& text, std::string::iterator& it); 15 static bool _checkElementEnd 16 (std::string const& text, std::string::iterator& it); 17 18 JsonParser::JsonParser(void) : _json(0) {} 19 20 JsonParser::~JsonParser(void) {} 21 22 JsonData* JsonParser::getJson(void) 23 { 24 return this->_json; 25 } 26 27 void JsonParser::readFile 28 (std::string const& filepath, std::string& output) 29 { 30 std::ifstream file(filepath.c_str()); 31 std::string line; 32 33 while (std::getline(file, line, '\0')) 34 { 35 output.append(line); 36 } 37 } 38 39 std::pair<std::string, JsonData> JsonParser::retriveKeyValuePair 40 (std::string const& text, std::string::iterator& it) 41 { 42 std::string key; 43 JsonData data; 44 45 assert(it != text.end()); 46 47 while (std::isspace(*it)) 48 it++; 49 if (*it == '\"') 50 { 51 key = _parseStringKey(text, it); 52 } 53 else if (*it == '}') 54 { 55 return std::make_pair(key, data); 56 } 57 else 58 { 59 // throw error 60 std::cerr << "Error: Object must have valid key" << std::endl; 61 std::exit(1); 62 } 63 64 while (std::isspace(*it)) 65 it++; 66 67 if (*it == '{') 68 { 69 data = parseObject(text, it); 70 } 71 else if (*it == '\"') 72 { 73 data._type = TYPE_STRING; 74 data._str = _parseStringValue(text, it); 75 } 76 else if (*it == '[') 77 { 78 data._type = TYPE_ARRAY; 79 data._arr = parseArray(text, it); 80 } 81 else if (std::isalnum(*it)) 82 { 83 data._str = _parsePrimitive(text, it, data._type); 84 } 85 else 86 { 87 // throw error 88 std::cerr << "Error: Object must have valid value" << std::endl; 89 std::exit(1); 90 } 91 92 if (_checkLineEnd(text, it) == false) 93 { 94 // throw error 95 std::cerr << "Error: Malformed line end" << std::endl; 96 std::exit(1); 97 } 98 it++; 99 //std::cout << "before it: " << *it << std::endl; 100 while (*it == ',' || std::isspace(*it)) 101 it++; 102 return std::make_pair(key, data); 103 } 104 105 std::vector<JsonData> JsonParser::parseArray 106 (std::string const& text, std::string::iterator& it) 107 { 108 std::vector<JsonData> arr; 109 std::string::iterator nxt; 110 111 it++; 112 while (it != text.end()) 113 { 114 JsonData data; 115 116 while (std::isspace(*it)) 117 it++; 118 if (*it == '{') 119 { 120 data = parseObject(text, it); 121 } 122 else if (*it == '\"') 123 { 124 data._type = TYPE_STRING; 125 data._str = _parseStringValue(text, it); 126 } 127 else if (*it == '[') 128 { 129 data._type = TYPE_ARRAY; 130 data._arr = parseArray(text, it); 131 } 132 else if (*it == ']') 133 { 134 break; 135 } 136 else if (std::isalnum(*it)) 137 { 138 data._str = _parsePrimitive(text, it, data._type); 139 } 140 else 141 { 142 // throw error 143 std::cerr << "Error: Malformed Array 1" << std::endl; 144 std::exit(1); 145 } 146 147 if (_checkElementEnd(text, it) == false) 148 { 149 // throw error 150 std::cerr << "Error: Malformed line end" << std::endl; 151 std::exit(1); 152 } 153 it++; 154 while (*it == ',' || std::isspace(*it)) 155 it++; 156 arr.push_back(data); 157 } 158 return arr; 159 } 160 161 JsonData JsonParser::parseObject 162 (std::string const& text, std::string::iterator& it) 163 { 164 JsonData jsonData; 165 std::vector<std::pair< std::string, JsonData> > jsonObject; 166 167 while (std::isspace(*it)) 168 ++it; 169 170 assert(*it == '{'); 171 it++; 172 173 do { 174 std::pair<std::string, JsonData> keyValuePair 175 = retriveKeyValuePair(text, it); 176 jsonObject.push_back(keyValuePair); 177 178 while (std::isspace(*it)) 179 it++; 180 } while (*it != '}'); 181 182 jsonData._type = TYPE_OBJECT; 183 jsonData._obj = jsonObject; 184 185 return jsonData; 186 } 187 188 JsonData JsonParser::parseJson(std::string const& filepath) 189 { 190 std::string text; 191 std::string::iterator start; 192 193 readFile(filepath, text); 194 start = text.begin(); 195 return parseObject(text, start); 196 } 197 198 /* *************************************************************************** * 199 * Helper Functions * 200 * ****************************************************************************/ 201 202 static bool _checkElementEnd 203 (std::string const& text, std::string::iterator& it) 204 { 205 std::string::iterator cur; 206 bool comma = false; 207 208 if (it == text.end()) 209 { 210 // throw error 211 std::cerr << "Error: Malformed Array format EOF" << std::endl; 212 std::exit(1); 213 } 214 cur = it + 1; 215 // std::cout << "ARR *it: " << *it << " ARR *cur: " << *cur << std::endl; 216 while (*cur == ',' || std::isspace(*cur)) 217 { 218 if (*cur == ',') 219 { 220 if (comma == false) 221 comma = true; 222 else 223 { 224 // throw error 225 std::cerr << "Error: Duplicate comma" << std::endl; 226 std::exit(1); 227 } 228 } 229 cur++; 230 } 231 // std::cout << "ARR after iter cur: " << *cur << std::endl; 232 if (*cur == '\"') 233 { 234 if (comma == true) 235 return true; 236 else 237 { 238 // throw error 239 std::cerr << "Error: No comma before key" << std::endl; 240 std::exit(1); 241 } 242 } 243 else if (*cur == '{') 244 { 245 if (comma == true) 246 return true; 247 else 248 { 249 // throw error 250 std::cerr << "Error: No comma before block" << std::endl; 251 std::exit(1); 252 } 253 } 254 else if (*cur == '[') 255 { 256 if (comma == true) 257 return true; 258 else 259 { 260 // throw error 261 std::cerr << "Error: No comma before array" << std::endl; 262 std::exit(1); 263 } 264 } 265 else if (std::isalnum(*cur)) 266 { 267 if (comma == true) 268 return true; 269 else 270 { 271 // throw error 272 std::cerr << "Error: No comma before primitive" << std::endl; 273 std::exit(1); 274 } 275 } 276 else if (*cur == ']') 277 { 278 if (comma == false) 279 return true; 280 else 281 { 282 // throw error 283 std::cerr << "Error: Comma before end array" << std::endl; 284 std::exit(1); 285 } 286 } 287 return false; 288 } 289 290 static bool _checkLineEnd 291 (std::string const& text, std::string::iterator& it) 292 { 293 std::string::iterator cur; 294 bool comma = false; 295 296 if (it == text.end()) 297 { 298 // throw error 299 std::cerr << "Error: Malformed Json format EOF" << std::endl; 300 std::exit(1); 301 } 302 cur = it + 1; 303 // std::cout << "*it: " << *it << " *cur: " << *cur << std::endl; 304 while (*cur == ',' || std::isspace(*cur)) 305 { 306 if (*cur == ',') 307 { 308 if (comma == false) 309 comma = true; 310 else 311 { 312 // throw error 313 std::cerr << "Error: Duplicate comma" << std::endl; 314 std::exit(1); 315 } 316 } 317 cur++; 318 } 319 // std::cout << "after iter cur: " << *cur << std::endl; 320 if (*cur == '\"') 321 { 322 if (comma == true) 323 return true; 324 else 325 { 326 // throw error 327 std::cerr << "Error: No comma before key" << std::endl; 328 std::exit(1); 329 } 330 } 331 else if (*cur == '}') 332 { 333 if (comma == false) 334 return true; 335 else 336 { 337 // throw error 338 std::cerr << "Error: Comma before end block" << std::endl; 339 std::exit(1); 340 } 341 } 342 return false; 343 } 344 345 static std::string _parsePrimitive 346 (std::string const& text, std::string::iterator& it, jsonType& type) 347 { 348 std::string value; 349 350 while (*it != ',' && *it != '}' && *it != ']' && !std::isspace(*it)) 351 { 352 if (*it == '\"') 353 { 354 // throw error 355 std::cerr << "Error: Malformed Primitive Format" << std::endl; 356 std::exit(1); 357 } 358 value += *it; 359 it++; 360 } 361 it--; 362 type = _getPrimitiveType(value); 363 if (type == TYPE_ERROR) 364 { 365 // throw error 366 std::cerr << "Error: Malformed primitive format" << std::endl; 367 std::exit(1); 368 } 369 return value; 370 } 371 372 static std::string _parseStringKey 373 (std::string const& text, std::string::iterator& it) 374 { 375 std::string key; 376 377 key = _getStringData(text, it); 378 it++; 379 while (std::isspace(*it)) 380 it++; 381 if (*it != ':') 382 { 383 // throw error 384 std::cerr << "Error: Colon not found after key" << std::endl; 385 std::exit(1); 386 } 387 it++; 388 return key; 389 } 390 391 static std::string _parseStringValue 392 (std::string const& text, std::string::iterator& it) 393 { 394 std::string value; 395 std::string::iterator cur; 396 397 value = _getStringData(text, it); 398 // it++; 399 // while (std::isspace(*it)) 400 // it++; 401 return value; 402 } 403 404 static std::string _getStringData 405 (std::string const& text, std::string::iterator& it) 406 { 407 std::string str; 408 bool insideQuote = false; 409 bool escape = false; 410 char ch; 411 412 while (it != text.end()) 413 { 414 ch = *it; 415 if (insideQuote) 416 { 417 if (ch == '\n') 418 { 419 // throw error 420 std::cerr << "Error: Malformed String Data type" << std::endl; 421 std::exit(1); 422 } 423 if (escape) 424 { 425 str += ch; 426 escape = false; 427 } 428 else if (ch == '\\') 429 escape = true; 430 else if (ch == '\"') 431 { 432 insideQuote = false; 433 break; 434 } 435 else 436 str += ch; 437 } 438 else if (ch == '\"') 439 insideQuote = true; 440 else if (ch == '\\') 441 escape = true; 442 else 443 { 444 // throw error 445 std::cerr << "Error: Malformed String Data type" << std::endl; 446 std::exit(1); 447 } 448 it++; 449 } 450 if ((it == text.end()) || insideQuote) 451 { 452 // throw error 453 std::cerr << "Error: Malformed Key value" << std::endl; 454 std::exit(1); 455 } 456 return str; 457 } 458 459 static jsonType _getPrimitiveType(std::string const& str) 460 { 461 char* endptr; 462 463 static_cast<void>(strtol(str.c_str(), &endptr, 10)); 464 if (*endptr == '\0') 465 return TYPE_INTEGER; 466 static_cast<void>(strtod(str.c_str(), &endptr)); 467 if (*endptr == '\0') 468 return TYPE_FLOAT; 469 if (str == "true" || str == "false") 470 return TYPE_BOOLEAN; 471 if (str == "null") 472 return TYPE_NULL; 473 return TYPE_ERROR; 474 }