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