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