xgboost
json_io.h
Go to the documentation of this file.
1 
4 #ifndef XGBOOST_JSON_IO_H_
5 #define XGBOOST_JSON_IO_H_
6 
7 #include <xgboost/base.h>
8 #include <xgboost/byteswap.h> // for ByteSwap
9 #include <xgboost/json.h>
10 
11 #include <cstdint> // for int8_t
12 #include <limits>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 namespace xgboost {
21 class JsonReader {
22  public:
23  using Char = std::int8_t;
24 
25  protected:
26  size_t constexpr static kMaxNumLength = std::numeric_limits<double>::max_digits10 + 1;
27 
28  struct SourceLocation {
29  private:
30  std::size_t pos_{0}; // current position in raw_str_
31 
32  public:
33  SourceLocation() = default;
34  size_t Pos() const { return pos_; }
35 
36  void Forward() { pos_++; }
37  void Forward(uint32_t n) { pos_ += n; }
39 
41 
42  protected:
43  void SkipSpaces();
44 
46  if (XGBOOST_EXPECT((cursor_.Pos() == raw_str_.size()), false)) {
47  return -1;
48  }
49  char ch = raw_str_[cursor_.Pos()];
50  cursor_.Forward();
51  return ch;
52  }
53 
55  if (cursor_.Pos() == raw_str_.size()) {
56  return -1;
57  }
58  Char ch = raw_str_[cursor_.Pos()];
59  return ch;
60  }
61 
62  /* \brief Skip spaces and consume next character. */
64  SkipSpaces();
65  return GetNextChar();
66  }
67  /* \brief Consume next character without first skipping empty space, throw when the next
68  * character is not the expected one.
69  */
70  Char GetConsecutiveChar(char expected_char) {
71  Char result = GetNextChar();
72  if (XGBOOST_EXPECT(result != expected_char, false)) { Expect(expected_char, result); }
73  return result;
74  }
75 
76  void Error(std::string msg) const;
77 
78  // Report expected character
79  void Expect(Char c, Char got) {
80  std::string msg = "Expecting: \"";
81  msg += c;
82  msg += "\", got: \"";
83  if (got == EOF) {
84  msg += "EOF\"";
85  } else if (got == 0) {
86  msg += "\\0\"";
87  } else {
88  msg += std::to_string(got) + " \"";
89  }
90  Error(msg);
91  }
92 
93  virtual Json ParseString();
94  virtual Json ParseObject();
95  virtual Json ParseArray();
96  virtual Json ParseNumber();
97  virtual Json ParseBoolean();
98  virtual Json ParseNull();
99 
101 
102  public:
103  explicit JsonReader(StringView str) :
104  raw_str_{str} {}
105 
106  virtual ~JsonReader() = default;
107 
108  virtual Json Load();
109 };
110 
111 class JsonWriter {
112  template <typename T, std::enable_if_t<!std::is_same_v<Json, T>>* = nullptr>
113  void Save(T const& v) {
114  this->Save(Json{v});
115  }
116  template <typename Array, typename Fn>
117  void WriteArray(Array const* arr, Fn&& fn) {
118  stream_->emplace_back('[');
119  auto const& vec = arr->GetArray();
120  size_t size = vec.size();
121  for (size_t i = 0; i < size; ++i) {
122  auto const& value = vec[i];
123  this->Save(fn(value));
124  if (i != size - 1) {
125  stream_->emplace_back(',');
126  }
127  }
128  stream_->emplace_back(']');
129  }
130 
131  protected:
132  std::vector<char>* stream_;
133 
134  public:
135  explicit JsonWriter(std::vector<char>* stream) : stream_{stream} {}
136 
137  virtual ~JsonWriter() = default;
138 
139  virtual void Save(Json json);
140 
141  virtual void Visit(JsonArray const* arr);
142  virtual void Visit(F32Array const* arr);
143  virtual void Visit(F64Array const*) { LOG(FATAL) << "Only UBJSON format can handle f64 array."; }
144  virtual void Visit(I8Array const* arr);
145  virtual void Visit(U8Array const* arr);
146  virtual void Visit(I16Array const* arr);
147  virtual void Visit(U16Array const* arr);
148  virtual void Visit(I32Array const* arr);
149  virtual void Visit(U32Array const* arr);
150  virtual void Visit(I64Array const* arr);
151  virtual void Visit(U64Array const* arr);
152  virtual void Visit(JsonObject const* obj);
153  virtual void Visit(JsonNumber const* num);
154  virtual void Visit(JsonInteger const* num);
155  virtual void Visit(JsonNull const* null);
156  virtual void Visit(JsonString const* str);
157  virtual void Visit(JsonBoolean const* boolean);
158 };
159 
160 template <typename T, std::enable_if_t<sizeof(T) == 1>* = nullptr>
161 inline T ToBigEndian(T v) {
162  return v;
163 }
164 
165 template <typename T, std::enable_if_t<sizeof(T) != 1>* = nullptr>
166 inline T ToBigEndian(T v) {
167  static_assert(std::is_pod<T>::value, "Only pod is supported.");
168 #if DMLC_LITTLE_ENDIAN
169  auto constexpr kS = sizeof(T);
170  std::conditional_t<kS == 2, uint16_t, std::conditional_t<kS == 4, uint32_t, uint64_t>> u;
171  std::memcpy(&u, &v, sizeof(u));
172  u = ByteSwap(u);
173  std::memcpy(&v, &u, sizeof(u));
174 #endif // DMLC_LITTLE_ENDIAN
175  return v;
176 }
177 
181 class UBJReader : public JsonReader {
182  Json Parse();
183 
184  template <typename T>
185  T ReadStream() {
186  auto ptr = this->raw_str_.c_str() + cursor_.Pos();
187  T v{0};
188  std::memcpy(&v, ptr, sizeof(v));
189  cursor_.Forward(sizeof(v));
190  return v;
191  }
192 
193  template <typename T>
194  T ReadPrimitive() {
195  auto v = ReadStream<T>();
196  v = ToBigEndian(v);
197  return v;
198  }
199 
200  template <typename TypedArray>
201  auto ParseTypedArray(std::int64_t n) {
202  TypedArray results{static_cast<size_t>(n)};
203  for (int64_t i = 0; i < n; ++i) {
204  auto v = this->ReadPrimitive<typename TypedArray::value_type>();
205  results.Set(i, v);
206  }
207  return Json{std::move(results)};
208  }
209 
210  std::string DecodeStr();
211 
212  Json ParseArray() override;
213  Json ParseObject() override;
214 
215  public:
217  Json Load() override;
218 };
219 
223 class UBJWriter : public JsonWriter {
224  void Visit(JsonArray const* arr) override;
225  void Visit(F32Array const* arr) override;
226  void Visit(F64Array const* arr) override;
227  void Visit(I8Array const* arr) override;
228  void Visit(U8Array const* arr) override;
229  void Visit(I16Array const* arr) override;
230  void Visit(I32Array const* arr) override;
231  void Visit(I64Array const* arr) override;
232  void Visit(JsonObject const* obj) override;
233  void Visit(JsonNumber const* num) override;
234  void Visit(JsonInteger const* num) override;
235  void Visit(JsonNull const* null) override;
236  void Visit(JsonString const* str) override;
237  void Visit(JsonBoolean const* boolean) override;
238 
239  public:
241  void Save(Json json) override;
242 };
243 } // namespace xgboost
244 
245 #endif // XGBOOST_JSON_IO_H_
Defines configuration macros and basic types for xgboost.
#define XGBOOST_EXPECT(cond, ret)
Definition: base.h:48
Definition: json.h:120
std::vector< Json > const & GetArray() &&
Definition: json.h:138
Describes both true and false.
Definition: json.h:354
Definition: json.h:299
Definition: json.h:337
Definition: json.h:261
Definition: json.h:223
A json reader, currently error checking and utf-8 is not fully supported.
Definition: json_io.h:21
virtual Json ParseString()
virtual Json Load()
virtual Json ParseNumber()
virtual Json ParseArray()
StringView raw_str_
Definition: json_io.h:40
Char PeekNextChar()
Definition: json_io.h:54
struct xgboost::JsonReader::SourceLocation cursor_
virtual Json ParseBoolean()
Char GetNextChar()
Definition: json_io.h:45
void Expect(Char c, Char got)
Definition: json_io.h:79
virtual Json ParseObject()
Char GetNextNonSpaceChar()
Definition: json_io.h:63
Char GetConsecutiveChar(char expected_char)
Definition: json_io.h:70
std::int8_t Char
Definition: json_io.h:23
void Error(std::string msg) const
virtual ~JsonReader()=default
constexpr static size_t kMaxNumLength
Definition: json_io.h:26
JsonReader(StringView str)
Definition: json_io.h:103
virtual Json ParseNull()
Definition: json.h:93
Typed array for Universal Binary JSON.
Definition: json.h:157
Definition: json_io.h:111
std::vector< char > * stream_
Definition: json_io.h:132
virtual void Save(Json json)
virtual void Visit(F64Array const *)
Definition: json_io.h:143
JsonWriter(std::vector< char > *stream)
Definition: json_io.h:135
virtual void Visit(JsonInteger const *num)
virtual void Visit(JsonNull const *null)
virtual void Visit(U8Array const *arr)
virtual void Visit(JsonArray const *arr)
virtual void Visit(U32Array const *arr)
virtual void Visit(I8Array const *arr)
virtual void Visit(U64Array const *arr)
virtual void Visit(F32Array const *arr)
virtual void Visit(JsonNumber const *num)
virtual ~JsonWriter()=default
virtual void Visit(I64Array const *arr)
virtual void Visit(JsonBoolean const *boolean)
virtual void Visit(I32Array const *arr)
virtual void Visit(JsonObject const *obj)
virtual void Visit(I16Array const *arr)
virtual void Visit(U16Array const *arr)
virtual void Visit(JsonString const *str)
Data structure representing JSON format.
Definition: json.h:396
Reader for UBJSON https://ubjson.org/.
Definition: json_io.h:181
Json Load() override
Writer for UBJSON https://ubjson.org/.
Definition: json_io.h:223
void Save(Json json) override
Learner interface that integrates objective, gbm and evaluation together. This is the user facing XGB...
Definition: base.h:89
T ToBigEndian(T v)
Definition: json_io.h:161
T ByteSwap(T v)
Definition: byteswap.h:94
Definition: json_io.h:28
size_t Pos() const
Definition: json_io.h:34
void Forward()
Definition: json_io.h:36
void Forward(uint32_t n)
Definition: json_io.h:37
Definition: string_view.h:16
value_type const * c_str() const
Definition: string_view.h:50
constexpr std::size_t size() const
Definition: string_view.h:43