mxnet
json.h
Go to the documentation of this file.
1 
7 #ifndef DMLC_JSON_H_
8 #define DMLC_JSON_H_
9 
10 // This code requires C++11 to compile
11 #include <vector>
12 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
13 #include <iostream>
14 #include <sstream>
15 #endif
16 #include <cctype>
17 #include <string>
18 #include <algorithm>
19 #include <map>
20 #include <list>
21 #include <utility>
22 
23 #include "./base.h"
24 #include "./logging.h"
25 #include "./type_traits.h"
26 
27 #if DMLC_USE_CXX11
28 #include <typeindex>
29 #include <typeinfo>
30 #include <unordered_map>
31 #if DMLC_STRICT_CXX11
32 #if DMLC_ENABLE_RTTI
33 #include "./any.h"
34 #endif // DMLC_ENABLE_RTTI
35 #endif // DMLC_STRICT_CXX11
36 #endif // DMLC_USE_CXX11
37 
38 namespace dmlc {
44 class JSONReader {
45  public:
50 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
51  explicit JSONReader(std::istream *is)
52 #else
53  explicit JSONReader(std::string *is)
54 #endif
55  : is_(is),
56  line_count_r_(0),
57  line_count_n_(0) {}
63  inline void ReadString(std::string *out_str);
70  template<typename ValueType>
71  inline void ReadNumber(ValueType *out_value);
85  inline void BeginObject();
97  inline void BeginArray();
105  inline bool NextObjectItem(std::string *out_key);
112  inline bool NextArrayItem();
119  template<typename ValueType>
120  inline void Read(ValueType *out_value);
121 
123  inline std::string line_info() const {
124 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
125  char temp[64];
126  std::ostringstream os;
127  os << " Line " << std::max(line_count_r_, line_count_n_);
128  is_->getline(temp, 64);
129  os << ", around ^`" << temp << "`";
130  return os.str();
131 #else
132  std::string info = " Line ";
133  info += std::to_string(std::max(line_count_r_, line_count_n_));
134 
135  // string getline
136  size_t end_pos = is_->find('\n');
137  end_pos = std::min((size_t)64,
138  end_pos == std::string::npos ? is_->size() : end_pos);
139  std::string line = is_->substr(0, end_pos);
140  is_->erase(0, line.size() + 1); // +1 for \n
141 
142  info += ", around ^`" + line + "`";
143  return info;
144 #endif
145  }
146 
147  private:
148 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
149 
150  std::istream *is_;
151 #else
152 
153  std::string *is_;
154 #endif
155 
156  size_t line_count_r_;
158  size_t line_count_n_;
163  std::vector<size_t> scope_counter_;
168  inline int NextNonSpace();
173  inline int PeekNextNonSpace();
178  inline int NextChar();
183  inline int PeekNextChar();
184 };
185 
189 class JSONWriter {
190  public:
195 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
196  explicit JSONWriter(std::ostream *os)
197 #else
198  explicit JSONWriter(std::string *os)
199 #endif
200  : os_(os) {}
205  inline void WriteNoEscape(const std::string &s);
210  inline void WriteString(const std::string &s);
216  template<typename ValueType>
217  inline void WriteNumber(const ValueType &v);
229  inline void BeginArray(bool multi_line = true);
231  inline void EndArray();
243  inline void BeginObject(bool multi_line = true);
245  inline void EndObject();
252  template<typename ValueType>
253  inline void WriteObjectKeyValue(const std::string &key,
254  const ValueType &value);
259  inline void WriteArraySeperator();
265  template<typename ValueType>
266  inline void WriteArrayItem(const ValueType &value);
272  template<typename ValueType>
273  inline void Write(const ValueType &value);
274 
275  private:
276 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
277 
278  std::ostream *os_;
279 #else
280  std::string *os_;
281 #endif
282 
286  std::vector<size_t> scope_counter_;
288  std::vector<bool> scope_multi_line_;
292  inline void WriteSeperator();
293 };
294 
312  public:
319  template<typename T>
320  inline void DeclareField(const std::string &key, T *addr) {
321  DeclareFieldInternal(key, addr, false);
322  }
329  template<typename T>
330  inline void DeclareOptionalField(const std::string &key, T *addr) {
331  DeclareFieldInternal(key, addr, true);
332  }
337  inline void ReadAllFields(JSONReader *reader);
338 
339  private:
347  template<typename T>
348  inline void DeclareFieldInternal(const std::string &key, T *addr, bool optional);
354  template<typename T>
355  inline static void ReaderFunction(JSONReader *reader, void *addr);
357  typedef void (*ReadFunction)(JSONReader *reader, void *addr);
359  struct Entry {
361  ReadFunction func;
363  void *addr;
365  bool optional;
366  };
368  std::map<std::string, Entry> map_;
369 };
370 
371 #define DMLC_JSON_ENABLE_ANY_VAR_DEF(KeyName) \
372  static DMLC_ATTRIBUTE_UNUSED ::dmlc::json::AnyJSONManager& \
373  __make_AnyJSONType ## _ ## KeyName ## __
374 
383 #define DMLC_JSON_ENABLE_ANY(Type, KeyName) \
384  DMLC_STR_CONCAT(DMLC_JSON_ENABLE_ANY_VAR_DEF(KeyName), __COUNTER__) = \
385  ::dmlc::json::AnyJSONManager::Global()->EnableType<Type>(#KeyName) \
386 
387 namespace json {
389 
394 template<typename T>
395 struct Handler;
396 
397 template<typename ValueType>
398 struct NumericHandler {
399  inline static void Write(JSONWriter *writer, const ValueType &value) {
400  writer->WriteNumber<ValueType>(value);
401  }
402  inline static void Read(JSONReader *reader, ValueType *value) {
403  reader->ReadNumber<ValueType>(value);
404  }
405 };
406 
407 template<typename ContainerType>
408 struct ArrayHandler {
409  inline static void Write(JSONWriter *writer, const ContainerType &array) {
410  typedef typename ContainerType::value_type ElemType;
411  writer->BeginArray(array.size() > 10 || !dmlc::is_pod<ElemType>::value);
412  for (typename ContainerType::const_iterator it = array.begin();
413  it != array.end(); ++it) {
414  writer->WriteArrayItem(*it);
415  }
416  writer->EndArray();
417  }
418  inline static void Read(JSONReader *reader, ContainerType *array) {
419  typedef typename ContainerType::value_type ElemType;
420  array->clear();
421  reader->BeginArray();
422  while (reader->NextArrayItem()) {
423  ElemType value;
424  Handler<ElemType>::Read(reader, &value);
425  array->insert(array->end(), value);
426  }
427  }
428 };
429 
430 template<typename ContainerType>
431 struct MapHandler{
432  inline static void Write(JSONWriter *writer, const ContainerType &map) {
433  writer->BeginObject(map.size() > 1);
434  for (typename ContainerType::const_iterator it = map.begin(); it != map.end(); ++it) {
435  writer->WriteObjectKeyValue(it->first, it->second);
436  }
437  writer->EndObject();
438  }
439  inline static void Read(JSONReader *reader, ContainerType *map) {
440  typedef typename ContainerType::mapped_type ElemType;
441  map->clear();
442  reader->BeginObject();
443  std::string key;
444  while (reader->NextObjectItem(&key)) {
445  ElemType value;
446  reader->Read(&value);
447  (*map)[key] = value;
448  }
449  }
450 };
451 
452 template<typename T>
453 struct CommonJSONSerializer {
454  inline static void Write(JSONWriter *writer, const T &value) {
455  value.Save(writer);
456  }
457  inline static void Read(JSONReader *reader, T *value) {
458  value->Load(reader);
459  }
460 };
461 
462 template<>
463 struct Handler<std::string> {
464  inline static void Write(JSONWriter *writer, const std::string &value) {
465  writer->WriteString(value);
466  }
467  inline static void Read(JSONReader *reader, std::string *str) {
468  reader->ReadString(str);
469  }
470 };
471 
472 template<typename T>
473 struct Handler<std::vector<T> > : public ArrayHandler<std::vector<T> > {
474 };
475 
476 template<typename K, typename V>
477 struct Handler<std::pair<K, V> > {
478  inline static void Write(JSONWriter *writer, const std::pair<K, V> &kv) {
479  writer->BeginArray();
480  writer->WriteArrayItem(kv.first);
481  writer->WriteArrayItem(kv.second);
482  writer->EndArray();
483  }
484  inline static void Read(JSONReader *reader, std::pair<K, V> *kv) {
485  reader->BeginArray();
486  CHECK(reader->NextArrayItem())
487  << "Expect array of length 2";
488  Handler<K>::Read(reader, &(kv->first));
489  CHECK(reader->NextArrayItem())
490  << "Expect array of length 2";
491  Handler<V>::Read(reader, &(kv->second));
492  CHECK(!reader->NextArrayItem())
493  << "Expect array of length 2";
494  }
495 };
496 
497 template<typename T>
498 struct Handler<std::list<T> > : public ArrayHandler<std::list<T> > {
499 };
500 
501 template<typename V>
502 struct Handler<std::map<std::string, V> > : public MapHandler<std::map<std::string, V> > {
503 };
504 
505 #if DMLC_USE_CXX11
506 template<typename V>
507 struct Handler<std::unordered_map<std::string, V> >
508  : public MapHandler<std::unordered_map<std::string, V> > {
509 };
510 #endif // DMLC_USE_CXX11
511 
512 template<typename T>
513 struct Handler {
514  inline static void Write(JSONWriter *writer, const T &data) {
516  NumericHandler<T>,
517  CommonJSONSerializer<T> >::Type THandler;
518  THandler::Write(writer, data);
519  }
520  inline static void Read(JSONReader *reader, T *data) {
522  NumericHandler<T>,
523  CommonJSONSerializer<T> >::Type THandler;
524  THandler::Read(reader, data);
525  }
526 };
527 
528 #if DMLC_STRICT_CXX11
529 #if DMLC_ENABLE_RTTI
530 // Manager to store json serialization strategy.
531 class AnyJSONManager {
532  public:
533  template<typename T>
534  inline AnyJSONManager& EnableType(const std::string& type_name) { // NOLINT(*)
535  std::type_index tp = std::type_index(typeid(T));
536  if (type_name_.count(tp) != 0) {
537  CHECK(type_name_.at(tp) == type_name)
538  << "Type has already been registered as another typename " << type_name_.at(tp);
539  return *this;
540  }
541  CHECK(type_map_.count(type_name) == 0)
542  << "Type name " << type_name << " already registered in registry";
543  Entry e;
544  e.read = ReadAny<T>;
545  e.write = WriteAny<T>;
546  type_name_[tp] = type_name;
547  type_map_[type_name] = e;
548  return *this;
549  }
550  // return global singleton
551  inline static AnyJSONManager* Global() {
552  static AnyJSONManager inst;
553  return &inst;
554  }
555 
556  private:
557  AnyJSONManager() {}
558 
559  template<typename T>
560  inline static void WriteAny(JSONWriter *writer, const any &data) {
561  writer->Write(dmlc::unsafe_get<T>(data));
562  }
563  template<typename T>
564  inline static void ReadAny(JSONReader *reader, any* data) {
565  T temp;
566  reader->Read(&temp);
567  *data = std::move(temp);
568  }
569  // data entry to store vtable for any type
570  struct Entry {
571  void (*read)(JSONReader* reader, any *data);
572  void (*write)(JSONWriter* reader, const any& data);
573  };
574 
575  template<typename T>
576  friend struct Handler;
577 
578  std::unordered_map<std::type_index, std::string> type_name_;
579  std::unordered_map<std::string, Entry> type_map_;
580 };
581 
582 template<>
583 struct Handler<any> {
584  inline static void Write(JSONWriter *writer, const any &data) {
585  std::unordered_map<std::type_index, std::string>&
586  nmap = AnyJSONManager::Global()->type_name_;
587  std::type_index id = std::type_index(data.type());
588  auto it = nmap.find(id);
589  CHECK(it != nmap.end() && it->first == id)
590  << "Type " << id.name() << " has not been registered via DMLC_JSON_ENABLE_ANY";
591  std::string type_name = it->second;
592  AnyJSONManager::Entry e = AnyJSONManager::Global()->type_map_.at(type_name);
593  writer->BeginArray(false);
594  writer->WriteArrayItem(type_name);
595  writer->WriteArraySeperator();
596  e.write(writer, data);
597  writer->EndArray();
598  }
599  inline static void Read(JSONReader *reader, any *data) {
600  std::string type_name;
601  reader->BeginArray();
602  CHECK(reader->NextArrayItem()) << "invalid any json format";
603  Handler<std::string>::Read(reader, &type_name);
604  std::unordered_map<std::string, AnyJSONManager::Entry>&
605  tmap = AnyJSONManager::Global()->type_map_;
606  auto it = tmap.find(type_name);
607  CHECK(it != tmap.end() && it->first == type_name)
608  << "Typename " << type_name << " has not been registered via DMLC_JSON_ENABLE_ANY";
609  AnyJSONManager::Entry e = it->second;
610  CHECK(reader->NextArrayItem()) << "invalid any json format";
611  e.read(reader, data);
612  CHECK(!reader->NextArrayItem()) << "invalid any json format";
613  }
614 };
615 #endif // DMLC_ENABLE_RTTI
616 #endif // DMLC_STRICT_CXX11
617 
618 } // namespace json
619 
620 // implementations of JSONReader/Writer
621 inline int JSONReader::NextChar() {
622 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
623  return is_->get();
624 #else
625  int ch = is_->at(0);
626  is_->erase(0, 1);
627  return ch;
628 #endif
629 }
630 
631 inline int JSONReader::PeekNextChar() {
632 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
633  return is_->peek();
634 #else
635  return is_->at(0);
636 #endif
637 }
638 
639 inline int JSONReader::NextNonSpace() {
640  int ch;
641  do {
642  ch = NextChar();
643  if (ch == '\n') ++line_count_n_;
644  if (ch == '\r') ++line_count_r_;
645  } while (isspace(ch));
646  return ch;
647 }
648 
649 inline int JSONReader::PeekNextNonSpace() {
650  int ch;
651  while (true) {
652  ch = PeekNextChar();
653  if (ch == '\n') ++line_count_n_;
654  if (ch == '\r') ++line_count_r_;
655  if (!isspace(ch)) break;
656  NextChar();
657  }
658  return ch;
659 }
660 
661 namespace {
662  template<typename T>
663 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
664  void Extend(std::ostream *os, T item) {
665  *os << item;
666  }
667 #else
668  void Extend(std::string *ostr, T item) {
669  *ostr += item;
670  }
671 #endif
672 } // namespace
673 
674 inline void JSONReader::ReadString(std::string *out_str) {
675  int ch = NextNonSpace();
676  CHECK_EQ(ch, '\"')
677  << "Error at" << line_info()
678  << ", Expect \'\"\' but get \'" << static_cast<char>(ch) << '\'';
679 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
680  std::ostringstream output;
681 #else
682  std::string output = "";
683 #endif
684  while (true) {
685  ch = NextChar();
686  if (ch == '\\') {
687  char sch = static_cast<char>(NextChar());
688  switch (sch) {
689  case 'r': Extend(&output, "\r"); break;
690  case 'n': Extend(&output, "\n"); break;
691  case '\\': Extend(&output, "\\"); break;
692  case 't': Extend(&output, "\t"); break;
693  case '\"': Extend(&output, "\""); break;
694  default: LOG(FATAL) << "unknown string escape \\" << sch;
695  }
696  } else {
697  if (ch == '\"') break;
698  Extend(&output, static_cast<char>(ch));
699  }
700  if (ch == EOF || ch == '\r' || ch == '\n') {
701  LOG(FATAL)
702  << "Error at" << line_info()
703  << ", Expect \'\"\' but reach end of line ";
704  }
705  }
706 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
707  *out_str = output.str();
708 #else
709  *out_str = output;
710 #endif
711 }
712 
713 template<typename ValueType>
714 inline void JSONReader::ReadNumber(ValueType *out_value) {
715 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
716  *is_ >> *out_value;
717  CHECK(!is_->fail())
718  << "Error at" << line_info()
719  << ", Expect number";
720 #else
721  char* endptr;
722  const char* icstr = is_->c_str();
723  unsigned number = strtol(icstr, &endptr, 10);
724  is_->erase(0, endptr - icstr);
725  *out_value = static_cast<ValueType>(number);
726 #endif
727 }
728 
729 inline void JSONReader::BeginObject() {
730  int ch = NextNonSpace();
731  CHECK_EQ(ch, '{')
732  << "Error at" << line_info()
733  << ", Expect \'{\' but get \'" << static_cast<char>(ch) << '\'';
734  scope_counter_.push_back(0);
735 }
736 
737 inline void JSONReader::BeginArray() {
738  int ch = NextNonSpace();
739  CHECK_EQ(ch, '[')
740  << "Error at" << line_info()
741  << ", Expect \'{\' but get \'" << static_cast<char>(ch) << '\'';
742  scope_counter_.push_back(0);
743 }
744 
745 inline bool JSONReader::NextObjectItem(std::string *out_key) {
746  bool next = true;
747  if (scope_counter_.back() != 0) {
748  int ch = NextNonSpace();
749  if (ch == EOF) {
750  next = false;
751  } else if (ch == '}') {
752  next = false;
753  } else {
754  CHECK_EQ(ch, ',')
755  << "Error at" << line_info()
756  << ", JSON object expect \'}\' or \',\' \'" << static_cast<char>(ch) << '\'';
757  }
758  } else {
759  int ch = PeekNextNonSpace();
760  if (ch == '}') {
761  NextChar();
762  next = false;
763  }
764  }
765  if (!next) {
766  scope_counter_.pop_back();
767  return false;
768  } else {
769  scope_counter_.back() += 1;
770  ReadString(out_key);
771  int ch = NextNonSpace();
772  CHECK_EQ(ch, ':')
773  << "Error at" << line_info()
774  << ", Expect \':\' but get \'" << static_cast<char>(ch) << '\'';
775  return true;
776  }
777 }
778 
779 inline bool JSONReader::NextArrayItem() {
780  bool next = true;
781  if (scope_counter_.back() != 0) {
782  int ch = NextNonSpace();
783  if (ch == EOF) {
784  next = false;
785  } else if (ch == ']') {
786  next = false;
787  } else {
788  CHECK_EQ(ch, ',')
789  << "Error at" << line_info()
790  << ", JSON array expect \']\' or \',\'. Get \'" << static_cast<char>(ch) << "\' instead";
791  }
792  } else {
793  int ch = PeekNextNonSpace();
794  if (ch == ']') {
795  NextChar();
796  next = false;
797  }
798  }
799  if (!next) {
800  scope_counter_.pop_back();
801  return false;
802  } else {
803  scope_counter_.back() += 1;
804  return true;
805  }
806 }
807 
808 template<typename ValueType>
809 inline void JSONReader::Read(ValueType *out_value) {
810  json::Handler<ValueType>::Read(this, out_value);
811 }
812 
813 inline void JSONWriter::WriteNoEscape(const std::string &s) {
814  Extend(os_, '\"');
815  Extend(os_, s);
816  Extend(os_, '\"');
817 }
818 
819 inline void JSONWriter::WriteString(const std::string &s) {
820  Extend(os_, '\"');
821  for (size_t i = 0; i < s.length(); ++i) {
822  char ch = s[i];
823  switch (ch) {
824  case '\r': Extend(os_, "\\r"); break;
825  case '\n': Extend(os_, "\\n"); break;
826  case '\\': Extend(os_, "\\\\"); break;
827  case '\t': Extend(os_, "\\t"); break;
828  case '\"': Extend(os_, "\\\""); break;
829  default: Extend(os_, ch);
830  }
831  }
832  Extend(os_, '\"');
833 }
834 
835 template<typename ValueType>
836 inline void JSONWriter::WriteNumber(const ValueType &v) {
837 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
838  Extend(os_, v);
839 #else
840  Extend(os_, std::to_string(v));
841 #endif
842 }
843 
844 inline void JSONWriter::BeginArray(bool multi_line) {
845  Extend(os_, '[');
846  scope_multi_line_.push_back(multi_line);
847  scope_counter_.push_back(0);
848 }
849 
850 inline void JSONWriter::EndArray() {
851  CHECK_NE(scope_multi_line_.size(), 0U);
852  CHECK_NE(scope_counter_.size(), 0U);
853  bool newline = scope_multi_line_.back();
854  size_t nelem = scope_counter_.back();
855  scope_multi_line_.pop_back();
856  scope_counter_.pop_back();
857  if (newline && nelem != 0) WriteSeperator();
858  Extend(os_, ']');
859 }
860 
861 inline void JSONWriter::BeginObject(bool multi_line) {
862  Extend(os_, '{');
863  scope_multi_line_.push_back(multi_line);
864  scope_counter_.push_back(0);
865 }
866 
867 inline void JSONWriter::EndObject() {
868  CHECK_NE(scope_multi_line_.size(), 0U);
869  CHECK_NE(scope_counter_.size(), 0U);
870  bool newline = scope_multi_line_.back();
871  size_t nelem = scope_counter_.back();
872  scope_multi_line_.pop_back();
873  scope_counter_.pop_back();
874  if (newline && nelem != 0) WriteSeperator();
875  Extend(os_, '}');
876 }
877 
878 template<typename ValueType>
879 inline void JSONWriter::WriteObjectKeyValue(const std::string &key,
880  const ValueType &value) {
881  if (scope_counter_.back() > 0) {
882  Extend(os_, ", ");
883  }
884  WriteSeperator();
885  Extend(os_, '\"');
886  Extend(os_, key);
887  Extend(os_, "\": ");
888  scope_counter_.back() += 1;
889  json::Handler<ValueType>::Write(this, value);
890 }
891 
892 inline void JSONWriter::WriteArraySeperator() {
893  if (scope_counter_.back() != 0) {
894  Extend(os_, ", ");
895  }
896  scope_counter_.back() += 1;
897  WriteSeperator();
898 }
899 
900 template<typename ValueType>
901 inline void JSONWriter::WriteArrayItem(const ValueType &value) {
902  this->WriteArraySeperator();
903  json::Handler<ValueType>::Write(this, value);
904 }
905 
906 template<typename ValueType>
907 inline void JSONWriter::Write(const ValueType &value) {
908  size_t nscope = scope_multi_line_.size();
909  json::Handler<ValueType>::Write(this, value);
910  CHECK_EQ(nscope, scope_multi_line_.size())
911  << "Uneven scope, did you call EndArray/EndObject after each BeginObject/Array?";
912 }
913 
914 inline void JSONWriter::WriteSeperator() {
915  if (scope_multi_line_.size() == 0 || scope_multi_line_.back()) {
916  Extend(os_, '\n');
917  Extend(os_, std::string(scope_multi_line_.size() * 2, ' '));
918  }
919 }
920 
921 inline void JSONObjectReadHelper::ReadAllFields(JSONReader *reader) {
922  reader->BeginObject();
923  std::map<std::string, int> visited;
924  std::string key;
925  while (reader->NextObjectItem(&key)) {
926  if (map_.count(key) != 0) {
927  Entry e = map_[key];
928  (*e.func)(reader, e.addr);
929  visited[key] = 0;
930  } else {
931 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
932  std::ostringstream err;
933 #else
934  std::string err("");
935 #endif
936  Extend(&err, "JSONReader: Unknown field ");
937  Extend(&err, key);
938  Extend(&err, ", candidates are: \n");
939  for (std::map<std::string, Entry>::iterator
940  it = map_.begin(); it != map_.end(); ++it) {
941  Extend(&err, '\"');
942  Extend(&err, it->first);
943  Extend(&err, "\"\n");
944  }
945 #ifndef _LIBCPP_SGX_NO_IOSTREAMS
946  LOG(FATAL) << err.str();
947 #else
948  LOG(FATAL) << err;
949 #endif
950  }
951  }
952  if (visited.size() != map_.size()) {
953  for (std::map<std::string, Entry>::iterator
954  it = map_.begin(); it != map_.end(); ++it) {
955  if (it->second.optional) continue;
956  CHECK_NE(visited.count(it->first), 0U)
957  << "JSONReader: Missing field \"" << it->first << "\"\n At "
958  << reader->line_info();
959  }
960  }
961 }
962 
963 template<typename T>
964 inline void JSONObjectReadHelper::ReaderFunction(JSONReader *reader, void *addr) {
965  json::Handler<T>::Read(reader, static_cast<T*>(addr));
966 }
967 
968 template<typename T>
969 inline void JSONObjectReadHelper::
970 DeclareFieldInternal(const std::string &key, T *addr, bool optional) {
971  CHECK_EQ(map_.count(key), 0U)
972  << "Adding duplicate field " << key;
973  Entry e;
974  e.func = ReaderFunction<T>;
975  e.addr = static_cast<void*>(addr);
976  e.optional = optional;
977  map_[key] = e;
978 }
979 
981 } // namespace dmlc
982 #endif // DMLC_JSON_H_
JSONWriter(std::ostream *os)
Constructor.
Definition: json.h:196
void BeginObject(bool multi_line=true)
Start beginning of array.
std::string line_info() const
Definition: json.h:123
whether a type is pod type
Definition: type_traits.h:21
void WriteArraySeperator()
Write seperator of array, before writing next element. User can proceed to call writer->Write to writ...
c++17 compatible optional class.
Definition: optional.h:43
void WriteString(const std::string &s)
Write a string that can contain escape characters.
void WriteNoEscape(const std::string &s)
Write a string that do not contain escape characters.
void WriteObjectKeyValue(const std::string &key, const ValueType &value)
Write key value pair in the object.
void BeginObject()
Begin parsing an object.
void DeclareField(const std::string &key, T *addr)
Declare field of type T.
Definition: json.h:320
void ReadNumber(ValueType *out_value)
Read Number.
void ReadAllFields(JSONReader *reader)
Read in all the declared fields.
void EndArray()
Finish writing an array.
void BeginArray()
Begin parsing an array.
Helper class to read JSON into a class or struct object.
Definition: json.h:311
Lightweight JSON Reader to read any STL compositions and structs. The user need to know the schema of...
Definition: json.h:44
bool isspace(char c)
Inline implementation of isspace(). Tests whether the given character is a whitespace letter...
Definition: strtonum.h:26
Container to hold any data type.
void EndObject()
Finish writing object.
namespace for dmlc
Definition: array_view.h:12
void Write(const ValueType &value)
Write value to json.
void WriteNumber(const ValueType &v)
Write a string that can contain escape characters.
template to select type based on condition For example, IfThenElseType<true, int, float>::Type will g...
Definition: type_traits.h:123
void DeclareOptionalField(const std::string &key, T *addr)
Declare optional field of type T.
Definition: json.h:330
JSONReader(std::istream *is)
Constructor.
Definition: json.h:51
void WriteArrayItem(const ValueType &value)
Write value into array.
void Read(ValueType *out_value)
Read next ValueType.
void BeginArray(bool multi_line=true)
Start beginning of array.
bool NextArrayItem()
Try to read the next element in the array. If this call is successful, user can proceed to call reade...
void ReadString(std::string *out_str)
Parse next JSON string.
bool NextObjectItem(std::string *out_key)
Try to move to next object item. If this call is successful, user can proceed to call reader->Read to...
type traits information header
Lightweight json to write any STL compositions.
Definition: json.h:189
std::string type_name()
the string representation of type name
Definition: type_traits.h:101