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 }