1 /* 2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 #include <vector> 26 #include <iterator> 27 28 #include <string.h> 29 #include <map> 30 #include <iostream> 31 #include <regex> 32 #include "json.h" 33 #include "buffer_cursor.h" 34 35 36 JSonNode::JSonNode(Type type, JSonObjectNode *parent, std::string name) 37 : type(type), parent(parent), name(name) { 38 39 } 40 41 bool JSonNode::hasNode(std::string name) { return false; } 42 43 JSonNode *JSonNode::getNode(std::string name) { return nullptr; } 44 45 46 47 48 bool JSonNode::isList(){return type==LIST;} 49 bool JSonNode::isObject(){return type==OBJECT;} 50 bool JSonNode::isValue(){return type==VALUE;} 51 52 JSonNode::~JSonNode() {} 53 JSonValueNode::JSonValueNode(JSonObjectNode *parent, std::string name, JSonValueNode::ValueType valueType, std::string value) 54 : JSonNode( 55 JSonNode::Type::VALUE, parent, name), valueType(valueType), value(value) {} 56 57 JSonValueNode::~JSonValueNode() {} 58 59 JSonObjectNode::JSonObjectNode(JSonNode::Type type, JSonObjectNode *parent, std::string name) 60 : JSonNode(type, parent, 61 name) {} 62 63 JSonObjectNode::JSonObjectNode(JSonObjectNode *parent, std::string name) 64 : JSonNode(JSonNode::Type::OBJECT, parent, 65 name) {} 66 67 JSonObjectNode::~JSonObjectNode() { 68 for (auto c:childArray) { 69 delete c; 70 } 71 childArray.clear(); 72 nameToChildMap.clear(); 73 } 74 75 JSonNode *JSonObjectNode::add(JSonNode *newOne) { 76 nameToChildMap[newOne->name] = newOne; 77 childArray.push_back(newOne); 78 return newOne; 79 } 80 81 int JSonListNode::size() { 82 return nameToChildMap.size(); 83 } 84 85 JSonListNode::JSonListNode(JSonObjectNode *parent, std::string name) 86 : JSonObjectNode(JSonNode::Type::LIST, parent, 87 name) {} 88 89 JSonListNode::~JSonListNode() { 90 // JsonObjectNode parent should deal with this 91 } 92 93 94 JSonValueNode *JSonNode::asValue() { 95 return dynamic_cast<JSonValueNode *>(this); 96 } 97 98 JSonListNode *JSonNode::asList() { 99 return dynamic_cast<JSonListNode *>(this); 100 } 101 102 JSonObjectNode *JSonNode::asObject() { 103 return dynamic_cast<JSonObjectNode *>(this); 104 } 105 106 void JSonObjectNode::visit(JSonNodeVisitor visitor) { 107 for (auto n:childArray) { 108 visitor(n); 109 } 110 } 111 112 bool JSonObjectNode::hasNode(std::string name) { return nameToChildMap.find(name) != nameToChildMap.end(); } 113 114 JSonNode *JSonObjectNode::getNode(std::string name) { return nameToChildMap[name]; } 115 116 std::string JSonNode::parseString(BufferCursor *cursor) { 117 cursor->advance(); // step over " 118 std::string content; 119 //https://www.json.org/json-en.html 120 while (!cursor->isLookingAt('"')) { 121 if (cursor->isLookingAt('\\')){ 122 cursor->advance(); 123 char c = cursor->ch(); 124 switch (c){ 125 case 'n':content+='\n';break ; 126 case 'r':content+='\r';break ; 127 case 't':content+='\t';break ; 128 case 'b':content+='\b';break ; 129 case 'f':content+='\f';break ; 130 case '"':content+='"';break ; 131 case '/':content+='/';break ; 132 case '\\':content+='\\';break ; 133 case 'u':{ 134 cursor->advance(); 135 int value = 0; 136 while (cursor->isLookingAtHexDigit()){ 137 c = cursor->ch(); 138 value =value *16 + (::isdigit(c) )?c-'0':(c>='a'&&c<='f')?c-'a'+10:c-'A'+10; 139 } 140 if (value < 127){ 141 content+=(char)value; 142 }else{ 143 std::cerr << "skipping unicode "<< std::hex<< value << std::endl;std::exit(1); 144 } 145 break; 146 } 147 default: 148 149 std::cerr << "skipping escape of char '"<< c << std::endl; 150 content+=c; 151 }; 152 }else{ 153 content+=cursor->ch(); 154 } 155 cursor->advance(); 156 } 157 158 cursor->advance(); // step over " 159 return content; 160 } 161 162 JSonNode *JSonObjectNode::parse(BufferCursor *cursor) { 163 // we are 'passed the open curly' 164 Mark *objectStart = cursor->mark(); 165 cursor->skipWhiteSpaceOrNewLine(); 166 while (!cursor->isLookingAt("}")) { 167 if (cursor->isLookingAt('\"')) { 168 std::string parsedName = JSonNode::parseString(cursor); 169 cursor->skipWhiteSpaceOrNewLine(); 170 if (cursor->isLookingAt(':')) { 171 cursor->advance(); 172 cursor->skipWhiteSpaceOrNewLine(); 173 174 if (cursor->isLookingAt("{")) { 175 cursor->advance(); 176 object(parsedName, [&](auto o) { 177 o->parse(cursor); 178 }); 179 } else if (cursor->isLookingAt("[")) { 180 cursor->advance(); 181 // std::cerr << "into Arr"<<std::endl; 182 list(parsedName, [&](auto l) { 183 l->parse(cursor); 184 }); 185 // std::cerr << "outof Arr"<<std::endl; 186 } else { 187 if (cursor->isLookingAt('\"')) { 188 std::string parsedValue = JSonNode::parseString(cursor); 189 this->string(parsedName, parsedValue); 190 } else if (cursor->isLookingAt("true")) { 191 cursor->stepOver("true"); 192 this->boolean(parsedName, "true"); 193 } else if (cursor->isLookingAt("false")) { 194 cursor->stepOver("false"); 195 this->boolean(parsedName, "false"); 196 } else { 197 Mark *start = cursor->mark(); 198 bool number = true; 199 bool integer = true; 200 bool first = true; 201 bool hasDot = false; 202 while (cursor->isLookingAtAlphaNumOr("_-.")) { 203 number = number && ((first && cursor->isLookingAt('-')) || cursor->isLookingAtDigit() || (!hasDot && cursor->isLookingAt('.'))); 204 integer = integer && ((first && cursor->isLookingAt('-')) || (cursor->isLookingAtDigit())); 205 hasDot = hasDot | cursor->isLookingAt('.'); 206 cursor->advance(); 207 first = false; 208 209 } 210 std::string parsedValue = start->str(); 211 if (parsedValue == "x") { 212 std::cerr << "x!" << std::endl; 213 } 214 if (integer) { 215 this->integer(parsedName, parsedValue); 216 } else if (number) { 217 this->number(parsedName, parsedValue); 218 } else { 219 this->string(parsedName, parsedValue); 220 } 221 } 222 223 } 224 cursor->skipWhiteSpaceOrNewLine(); 225 if (cursor->isLookingAt(",")) { 226 cursor->advance(); 227 cursor->skipWhiteSpaceOrNewLine(); 228 } else if (!cursor->isLookingAt('}')) { 229 std::cerr << "expecting , for }" << std::endl; 230 } 231 } else { 232 std::cerr << "expecting colon name!" << std::endl; 233 } 234 235 } else { 236 std::cerr << "expecting literal name!" << std::endl; 237 } 238 } 239 cursor->advance(); 240 cursor->skipWhiteSpaceOrNewLine(); 241 return this; 242 } 243 244 JSonNode *JSonListNode::parse(BufferCursor *cursor) { 245 // we are passed the open '[' 246 cursor->skipWhiteSpaceOrNewLine(); 247 248 Mark *listStart = cursor->mark(); 249 cursor->skipWhiteSpaceOrNewLine(); 250 while (!cursor->isLookingAt("]")) { 251 if (cursor->isLookingAt("{")) { 252 cursor->advance(); 253 item([&](auto n) { 254 n->parse(cursor); 255 }); 256 } else if (cursor->isLookingAt("[")) { 257 cursor->advance(); 258 list([&](auto l) { 259 l->parse(cursor); 260 }); 261 } else { 262 if (cursor->isLookingAt('\"')) { 263 std::string parsedValue = JSonNode::parseString(cursor); 264 this->string(parsedValue); 265 } else if (cursor->isLookingAt("true")) { 266 cursor->stepOver("true"); 267 this->boolean("true"); 268 } else if (cursor->isLookingAt("false")) { 269 cursor->stepOver("false"); 270 this->boolean("false"); 271 } else { 272 Mark *start = cursor->mark(); 273 bool number = true; 274 bool integer = true; 275 bool first = true; 276 bool hasDot = false; 277 while (cursor->isLookingAtAlphaNumOr("_-.")) { 278 number = number && ((first && cursor->isLookingAt('-')) || cursor->isLookingAtDigit() || (!hasDot && cursor->isLookingAt('.'))); 279 integer = integer && ((first && cursor->isLookingAt('-')) || (cursor->isLookingAtDigit())); 280 hasDot = hasDot | cursor->isLookingAt('.'); 281 cursor->advance(); 282 first = false; 283 284 } 285 std::string parsedValue = start->str(); 286 if (parsedValue == "x") { 287 std::cerr << "x!" << std::endl; 288 } 289 if (integer) { 290 this->integer(parsedValue); 291 } else if (number) { 292 this->number(parsedValue); 293 } else { 294 this->string(parsedValue); 295 } 296 297 } 298 } 299 300 cursor->skipWhiteSpaceOrNewLine(); 301 if (cursor->isLookingAt(",")) { 302 cursor->advance(); 303 cursor->skipWhiteSpaceOrNewLine(); 304 } else if (!cursor->isLookingAt(']')) { 305 std::cerr << "expecting , for [" << std::endl; 306 } 307 } 308 cursor->advance(); 309 cursor->skipWhiteSpaceOrNewLine(); 310 return this; 311 } 312 313 JSonNode *JSonNode::parse(char *text) { 314 BufferCursor *cursor = new BufferCursor((char *) text); 315 cursor->skipWhiteSpace(); 316 if (cursor->isLookingAt("{")) { 317 cursor->advance(); 318 JSonObjectNode *doc = new JSonObjectNode(nullptr, ""); 319 doc->parse(cursor); 320 return doc; 321 } else if (cursor->isLookingAt("[")) { 322 cursor->advance(); 323 JSonObjectNode *doc = new JSonListNode(nullptr, ""); 324 doc->parse(cursor); 325 return doc; 326 } 327 delete cursor; 328 return nullptr; 329 } 330 JSonObjectNode * JSonNode::remove(){ 331 return parent->remove(this); 332 } 333 334 JSonNode *JSonNode::collect(std::string s, std::vector<JSonNode *> &list) { 335 std::cout << "collecting "<< s << std::endl; 336 if (s == "") { 337 list.push_back(this); 338 } else { 339 auto slashpos = s.find_first_of('/'); 340 std::string head = (slashpos == std::string::npos) ? s : s.substr(0, slashpos); 341 std::string tail = (slashpos == std::string::npos) ? "" : s.substr(slashpos + 1); 342 if (head == "..") { 343 parent->collect(tail, list); 344 } else { 345 if (head[0]=='{'){ 346 auto eqpos = head.find_first_of('='); 347 auto tildepos = head.find_first_of('~'); 348 auto ccbracepos = head.find_last_of('}'); 349 auto notpos = head.find_first_of('!'); 350 if (eqpos != std::string::npos && (tildepos==std::string::npos || tildepos>eqpos ) && ccbracepos != std::string::npos && ccbracepos>eqpos){ 351 bool invert = (notpos != std::string::npos && notpos+1 == eqpos); 352 std::string listName = head.substr(1, eqpos-1 - (invert?1:0)); 353 std::string re = head.substr(eqpos+1, ccbracepos-eqpos-1); 354 JSonObjectNode *node = asObject(); 355 if (node) { 356 auto n = node->nameToChildMap[listName]; 357 if (n && n->isValue()) { 358 std::string svalue = n->asValue()->value; 359 if (invert && svalue != re) { 360 list.push_back(this); 361 } else if (!invert && svalue == re) { 362 list.push_back(this); 363 } 364 } 365 } 366 }else if (tildepos != std::string::npos && (eqpos==std::string::npos || eqpos>tildepos ) && ccbracepos != std::string::npos && ccbracepos>tildepos){ 367 bool invert = (notpos != std::string::npos && notpos+1 ==tildepos); 368 std::string listName = head.substr(1, tildepos-1 - (invert?1:0)); 369 std::string re = head.substr(tildepos+1, ccbracepos-tildepos-1); 370 JSonObjectNode *node = asObject(); 371 if (node) { 372 auto n = node->nameToChildMap[listName]; 373 if (n && n->isValue()){ 374 std::string svalue = n->asValue()->value; 375 std::regex r(re); 376 bool matched = std::regex_match(svalue, r); 377 if (invert && !matched){ 378 list.push_back(this); 379 }else if (!invert && matched) { 380 list.push_back(this); 381 } 382 } 383 } 384 } 385 }else { 386 auto osbracepos = head.find_first_of('['); 387 auto csbracepos = head.find_last_of(']'); 388 if (osbracepos != std::string::npos && csbracepos != std::string::npos && csbracepos>osbracepos) { 389 // we have something akin to map[...] 390 std::string listName = s.substr(0, osbracepos); 391 std::string listSuffix = s.substr(osbracepos + 1, csbracepos - osbracepos - 1); 392 JSonObjectNode *node = asObject(); 393 if (node) { 394 std::regex r(listName); 395 for (auto spair: node->nameToChildMap) { 396 if (std::regex_match(spair.first, r)) { 397 if (tail == ""){ 398 spair.second->collect(listSuffix, list); 399 }else { 400 spair.second->collect(listSuffix + "/" + tail, list); 401 } 402 403 } 404 } 405 } 406 } else { 407 // auto ocbracepos = s.find_first_of('{'); 408 JSonObjectNode *node = asObject(); 409 if (node) { 410 std::regex r(head); 411 for (auto spair: node->nameToChildMap) { 412 if (std::regex_match(spair.first, r)) { 413 spair.second->collect(tail, list); 414 } 415 } 416 } else { 417 list.push_back(this); 418 } 419 } 420 } 421 } 422 } 423 return this; 424 } 425 426 427 JSonNode *JSonNode::get(std::string s, JSonNodeVisitor visitor) { 428 if (s == "") { 429 visitor(this); 430 } else { 431 auto slashpos = s.find_first_of('/'); 432 std::string head = (slashpos == std::string::npos) ? s : s.substr(0, slashpos); 433 std::string tail = (slashpos == std::string::npos) ? "" : s.substr(slashpos + 1); 434 if (head == "..") { 435 parent->get(tail, visitor); 436 } else { 437 if (head[0]=='{'){ 438 auto eqpos = head.find_first_of('='); 439 auto tildepos = head.find_first_of('~'); 440 auto ccbracepos = head.find_last_of('}'); 441 auto notpos = head.find_first_of('!'); 442 if (eqpos != std::string::npos && (tildepos==std::string::npos || tildepos>eqpos ) && ccbracepos != std::string::npos && ccbracepos>eqpos){ 443 bool invert = (notpos != std::string::npos && notpos+1 == eqpos); 444 std::string listName = head.substr(1, eqpos-1 - (invert?1:0)); 445 std::string re = head.substr(eqpos+1, ccbracepos-eqpos-1); 446 JSonObjectNode *node = asObject(); 447 if (node) { 448 auto n = node->nameToChildMap[listName]; 449 if (n && n->isValue()) { 450 std::string svalue = n->asValue()->value; 451 if (invert && svalue != re) { 452 visitor(this); 453 } else if (!invert && svalue == re) { 454 visitor(this); 455 } 456 } 457 } 458 }else if (tildepos != std::string::npos && (eqpos==std::string::npos || eqpos>tildepos ) && ccbracepos != std::string::npos && ccbracepos>tildepos){ 459 bool invert = (notpos != std::string::npos && notpos+1 == tildepos); 460 std::string listName = head.substr(1, tildepos-1 - (invert?1:0)); 461 std::string re = head.substr(tildepos+1, ccbracepos-tildepos-1); 462 JSonObjectNode *node = asObject(); 463 if (node) { 464 auto n = node->nameToChildMap[listName]; 465 if (n && n->isValue()){ 466 std::string svalue = n->asValue()->value; 467 std::regex r(re); 468 bool matched = std::regex_match(svalue, r); 469 if (invert && !matched){ 470 visitor(this); 471 }else if (!invert && matched) { 472 visitor(this); 473 } 474 } 475 } 476 } 477 }else { 478 auto osbracepos = head.find_first_of('['); 479 auto csbracepos = head.find_last_of(']'); 480 if (osbracepos != std::string::npos && csbracepos != std::string::npos && csbracepos>osbracepos) { 481 // we have something akin to map[...] 482 std::string listName = s.substr(0, osbracepos); 483 std::string listSuffix = s.substr(osbracepos + 1, csbracepos - osbracepos - 1); 484 JSonObjectNode *node = asObject(); 485 if (node) { 486 std::regex r(listName); 487 for (auto spair: node->nameToChildMap) { 488 if (std::regex_match(spair.first, r)) { 489 if (tail == ""){ 490 spair.second->get(listSuffix, visitor); 491 }else { 492 spair.second->get(listSuffix + "/" + tail, visitor); 493 } 494 } 495 } 496 } 497 } else { 498 // auto ocbracepos = s.find_first_of('{'); 499 JSonObjectNode *node = asObject(); 500 if (node) { 501 std::regex r(head); 502 for (auto spair: node->nameToChildMap) { 503 if (std::regex_match(spair.first, r)) { 504 spair.second->get(tail, visitor); 505 } 506 } 507 } else { 508 visitor(this); 509 } 510 } 511 } 512 } 513 } 514 return this; 515 } 516 JSonObjectNode* JSonObjectNode::remove(JSonNode *n){ 517 nameToChildMap.erase(n->name); 518 for (auto i=childArray.begin(); i!=childArray.end(); i++){ 519 if (*i == n){ 520 childArray.erase(i); 521 break; 522 } 523 } 524 return this; 525 } 526 JSonObjectNode* JSonObjectNode::remove(std::string name){ 527 return remove(getNode(name)); 528 } 529 JSonObjectNode *JSonObjectNode::object(std::string name, JSonObjectNodeVisitor visitor) { 530 JSonObjectNode *newOne = new JSonObjectNode(this, name); 531 visitor(newOne); 532 add(newOne); 533 return this; 534 } 535 536 JSonObjectNode *JSonObjectNode::list(std::string name, JSonListNodeVisitor visitor) { 537 538 JSonListNode *newOne = new JSonListNode(this, name); 539 visitor(newOne); 540 add(newOne); 541 return this; 542 } 543 544 JSonObjectNode *JSonListNode::item(JSonObjectNodeVisitor visitor) { 545 JSonObjectNode *newOne = new JSonObjectNode(this, std::to_string(childArray.size())); 546 visitor(newOne); 547 add(newOne); 548 return this; 549 } 550 551 JSonObjectNode *JSonObjectNode::boolean(std::string name, std::string value) { 552 JSonValueNode *newOne = new JSonValueNode(this, name, BOOLEAN, value); 553 add(newOne); 554 return this; 555 } 556 557 JSonObjectNode *JSonObjectNode::boolean(std::string name, bool value) { 558 JSonValueNode *newOne = new JSonValueNode(this, name, BOOLEAN, std::to_string(value)); 559 add(newOne); 560 return this; 561 } 562 563 JSonObjectNode *JSonObjectNode::string(std::string name, std::string value) { 564 JSonValueNode *newOne = new JSonValueNode(this, name, STRING, value); 565 add(newOne); 566 return this; 567 } 568 569 JSonObjectNode *JSonObjectNode::integer(std::string name, std::string value) { 570 JSonValueNode *newOne = new JSonValueNode(this, name, INTEGER, value); 571 add(newOne); 572 return this; 573 } 574 575 JSonObjectNode *JSonObjectNode::integer(std::string name, int value) { 576 JSonValueNode *newOne = new JSonValueNode(this, name, INTEGER, std::to_string(value)); 577 add(newOne); 578 return this; 579 } 580 581 JSonObjectNode *JSonObjectNode::number(std::string name, std::string value) { 582 JSonValueNode *newOne = new JSonValueNode(this, name, NUMBER, value); 583 add(newOne); 584 return this; 585 } 586 587 JSonObjectNode *JSonListNode::boolean(std::string value) { 588 JSonValueNode *newOne = new JSonValueNode(this, std::to_string(childArray.size()), ValueType::BOOLEAN, value); 589 add(newOne); 590 return this; 591 } 592 593 JSonObjectNode *JSonListNode::boolean(bool value) { 594 JSonValueNode *newOne = new JSonValueNode(this, std::to_string(childArray.size()), ValueType::BOOLEAN, std::to_string(value)); 595 add(newOne); 596 return this; 597 } 598 599 JSonObjectNode *JSonListNode::integer(std::string value) { 600 JSonValueNode *newOne = new JSonValueNode(this, std::to_string(childArray.size()), ValueType::INTEGER, value); 601 add(newOne); 602 return this; 603 } 604 605 JSonObjectNode *JSonListNode::integer(int value) { 606 JSonValueNode *newOne = new JSonValueNode(this, std::to_string(childArray.size()), ValueType::INTEGER, std::to_string(value)); 607 add(newOne); 608 return this; 609 } 610 611 JSonObjectNode *JSonListNode::number(std::string value) { 612 JSonValueNode *newOne = new JSonValueNode(this, std::to_string(childArray.size()), ValueType::NUMBER, value); 613 add(newOne); 614 return this; 615 } 616 bool JSonNode::write(std::ostream o){ 617 JSonWriter w(o); 618 w.write(this, nullptr); 619 return true; 620 } 621 bool JSonNode::write(std::string filename){ 622 std::ofstream all(filename, std::ios::trunc); 623 JSonWriter w(all); 624 w.write(this, nullptr); 625 all.close(); 626 return true; 627 } 628 629 630 JSonObjectNode *JSonListNode::string(std::string value) { 631 JSonValueNode *newOne = new JSonValueNode(this, std::to_string(childArray.size()), ValueType::STRING, value); 632 add(newOne); 633 return this; 634 } 635 636 JSonObjectNode *JSonListNode::list(JSonListNodeVisitor visitor) { 637 JSonListNode *newOne = new JSonListNode(this, std::to_string(childArray.size())); 638 add(newOne); 639 visitor(newOne); 640 return this; 641 } 642 643 644 JSonWriter *JSonWriter::write(JSonNode *n){ 645 return write(n, nullptr); 646 } 647 JSonWriter *JSonWriter::write(JSonNode *n, Filter filter){ 648 if (filter == nullptr || filter(n)) { 649 if (n->isObject()) { 650 JSonObjectNode *object = n->asObject(); 651 obrace(); 652 in(); 653 nl(); 654 bool first = true; 655 for (auto c: object->childArray) { 656 if (filter== nullptr || filter(c)) { 657 if (first) { 658 first = false; 659 } else { 660 comma(); 661 nl(); 662 } 663 name(c->name); 664 write(c, filter); 665 } 666 } 667 out(); 668 nl(); 669 cbrace(); 670 } else if (n->isList()) { 671 JSonListNode *list = n->asList(); 672 osbrace(); 673 in(); 674 nl(); 675 bool first = true; 676 for (auto c: list->childArray) { 677 if (first) { 678 first = false; 679 } else { 680 comma(); 681 if (!c->isObject()) { 682 nl(); 683 } 684 } 685 write(c, filter); 686 } 687 out(); 688 nl(); 689 csbrace(); 690 } else if (n->isValue()) { 691 JSonValueNode *value = n->asValue(); 692 if (value->valueType == JSonNode::ValueType::STRING) { 693 oquote(); 694 } 695 std::size_t n = value->value.length(); 696 std::string escaped; 697 escaped.reserve(n * 2); // pessimistic preallocation 698 699 for (std::size_t i = 0; i < n; ++i) { 700 switch (value->value[i]) { 701 case '\n': 702 escaped += "\\n"; 703 break; 704 case '"': 705 escaped += "\\\""; 706 break; 707 case '\\': 708 escaped += "\\\\"; 709 break; 710 case '\r': 711 escaped += "\\r"; 712 break; 713 case '\t': 714 escaped += "\\t"; 715 break; 716 default: 717 escaped += value->value[i]; 718 break; 719 } 720 } 721 put(escaped); 722 if (value->valueType == JSonNode::ValueType::STRING) { 723 cquote(); 724 } 725 } else { 726 std::cerr << "what type is this!" << std::endl; 727 } 728 } 729 return this; 730 } 731 732 JSonWriter::JSonWriter(std::ostream &o) 733 : o(o) , indent(0){ 734 } 735 736 JSonWriter *JSonWriter::put(std::string s) { 737 o << s; 738 return this; 739 } 740 741 JSonWriter *JSonWriter::comma() { 742 return put(","); 743 } 744 JSonWriter *JSonWriter::nl(){ 745 o<<std::endl; 746 std::fill_n(std::ostream_iterator<char>(o), indent, ' '); 747 return this; 748 } 749 JSonWriter *JSonWriter::in(){ 750 indent++; 751 return this; 752 } 753 JSonWriter *JSonWriter::out(){ 754 indent--; 755 return this; 756 } 757 JSonWriter *JSonWriter::colon() { 758 return put(":"); 759 } 760 JSonWriter *JSonWriter::oquote() { 761 return put("\""); 762 } 763 JSonWriter *JSonWriter::cquote() { 764 return put("\""); 765 } 766 JSonWriter *JSonWriter::obrace() { 767 return put("{"); 768 } 769 JSonWriter *JSonWriter::cbrace() { 770 return put("}"); 771 } 772 JSonWriter *JSonWriter::osbrace() { 773 return put("["); 774 } 775 JSonWriter *JSonWriter::csbrace() { 776 return put("]"); 777 } 778 JSonWriter *JSonWriter::name(std::string n){ 779 return oquote()->put(n)->cquote()->colon(); 780 } 781 782 JSonObjectNode *JSon::create(std::function<void(JSonObjectNode *)> builder){ 783 JSonObjectNode * root = new JSonObjectNode(nullptr, ""); 784 builder(root); 785 return root; 786 } 787 788 789 JSonNode *JSon::parseFile(std::string filename){ 790 if (fsutil::isFile(filename)) { 791 792 struct stat st; 793 stat(filename.c_str(), &st); 794 if (S_ISREG(st.st_mode)) { 795 int fd = ::open(filename.c_str(), O_RDONLY); 796 char *memory= new char[st.st_size]; 797 size_t bytesRead = 0; 798 size_t bytes = 0; 799 while (bytesRead < st.st_size && (bytes = ::read(fd, memory + bytesRead, st.st_size - bytesRead)) >= 0) { 800 bytesRead -= bytes; 801 } 802 ::close(fd); 803 JSonNode *json = JSonNode::parse(memory); 804 delete []memory; 805 return json; 806 }else{ 807 std::cout << "not reg file!"<< std::endl; 808 } 809 } 810 811 return nullptr; 812 }