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 #include <dmlc/endian.h>
7 #include <xgboost/base.h>
8 #include <xgboost/json.h>
9 
10 #include <cinttypes>
11 #include <limits>
12 #include <map>
13 #include <memory>
14 #include <sstream>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 namespace xgboost {
20 namespace detail {
21 // Whether char is signed is undefined, as a result we might or might not need
22 // static_cast and std::to_string.
23 template <typename Char, std::enable_if_t<std::is_signed<Char>::value>* = nullptr>
24 std::string CharToStr(Char c) {
25  static_assert(std::is_same<Char, char>::value, "");
26  return std::string{c};
27 }
28 
29 template <typename Char, std::enable_if_t<!std::is_signed<Char>::value>* = nullptr>
30 std::string CharToStr(Char c) {
31  static_assert(std::is_same<Char, char>::value, "");
32  return (c <= static_cast<char>(127) ? std::string{c} : std::to_string(c));
33 }
34 } // namespace detail
35 
36 /*
37  * \brief A json reader, currently error checking and utf-8 is not fully supported.
38  */
39 class JsonReader {
40  protected:
41  size_t constexpr static kMaxNumLength =
42  std::numeric_limits<double>::max_digits10 + 1;
43 
44  struct SourceLocation {
45  private:
46  size_t pos_ { 0 }; // current position in raw_str_
47 
48  public:
49  SourceLocation() = default;
50  size_t Pos() const { return pos_; }
51 
52  void Forward() {
53  pos_++;
54  }
55  void Forward(uint32_t n) {
56  pos_ += n;
57  }
59 
61 
62  protected:
63  void SkipSpaces();
64 
65  char GetNextChar() {
66  if (XGBOOST_EXPECT((cursor_.Pos() == raw_str_.size()), false)) {
67  return -1;
68  }
69  char ch = raw_str_[cursor_.Pos()];
70  cursor_.Forward();
71  return ch;
72  }
73 
74  char PeekNextChar() {
75  if (cursor_.Pos() == raw_str_.size()) {
76  return -1;
77  }
78  char ch = raw_str_[cursor_.Pos()];
79  return ch;
80  }
81 
82  /* \brief Skip spaces and consume next character. */
84  SkipSpaces();
85  return GetNextChar();
86  }
87  /* \brief Consume next character without first skipping empty space, throw when the next
88  * character is not the expected one.
89  */
90  char GetConsecutiveChar(char expected_char) {
91  char result = GetNextChar();
92  if (XGBOOST_EXPECT(result != expected_char, false)) { Expect(expected_char, result); }
93  return result;
94  }
95 
96  void Error(std::string msg) const;
97 
98  // Report expected character
99  void Expect(char c, char got) {
100  std::string msg = "Expecting: \"";
101  msg += c;
102  msg += "\", got: \"";
103  if (got == EOF) {
104  msg += "EOF\"";
105  } else if (got == 0) {
106  msg += "\\0\"";
107  } else {
108  msg += detail::CharToStr(got) + " \"";
109  }
110  Error(msg);
111  }
112 
113  virtual Json ParseString();
114  virtual Json ParseObject();
115  virtual Json ParseArray();
116  virtual Json ParseNumber();
117  virtual Json ParseBoolean();
118  virtual Json ParseNull();
119 
121 
122  public:
123  explicit JsonReader(StringView str) :
124  raw_str_{str} {}
125 
126  virtual ~JsonReader() = default;
127 
128  virtual Json Load();
129 };
130 
131 class JsonWriter {
132  template <typename T, std::enable_if_t<!std::is_same<Json, T>::value>* = nullptr>
133  void Save(T const& v) {
134  this->Save(Json{v});
135  }
136  template <typename Array, typename Fn>
137  void WriteArray(Array const* arr, Fn&& fn) {
138  stream_->emplace_back('[');
139  auto const& vec = arr->GetArray();
140  size_t size = vec.size();
141  for (size_t i = 0; i < size; ++i) {
142  auto const& value = vec[i];
143  this->Save(fn(value));
144  if (i != size - 1) {
145  stream_->emplace_back(',');
146  }
147  }
148  stream_->emplace_back(']');
149  }
150 
151  protected:
152  std::vector<char>* stream_;
153 
154  public:
155  explicit JsonWriter(std::vector<char>* stream) : stream_{stream} {}
156 
157  virtual ~JsonWriter() = default;
158 
159  virtual void Save(Json json);
160 
161  virtual void Visit(JsonArray const* arr);
162  virtual void Visit(F32Array const* arr);
163  virtual void Visit(U8Array const* arr);
164  virtual void Visit(I32Array const* arr);
165  virtual void Visit(I64Array const* arr);
166  virtual void Visit(JsonObject const* obj);
167  virtual void Visit(JsonNumber const* num);
168  virtual void Visit(JsonInteger const* num);
169  virtual void Visit(JsonNull const* null);
170  virtual void Visit(JsonString const* str);
171  virtual void Visit(JsonBoolean const* boolean);
172 };
173 
174 #if defined(__GLIBC__)
175 template <typename T>
176 T BuiltinBSwap(T v);
177 
178 template <>
179 inline uint16_t BuiltinBSwap(uint16_t v) {
180  return __builtin_bswap16(v);
181 }
182 
183 template <>
184 inline uint32_t BuiltinBSwap(uint32_t v) {
185  return __builtin_bswap32(v);
186 }
187 
188 template <>
189 inline uint64_t BuiltinBSwap(uint64_t v) {
190  return __builtin_bswap64(v);
191 }
192 #else
193 template <typename T>
194 T BuiltinBSwap(T v) {
195  dmlc::ByteSwap(&v, sizeof(v), 1);
196  return v;
197 }
198 #endif // defined(__GLIBC__)
199 
200 template <typename T, std::enable_if_t<sizeof(T) == 1>* = nullptr>
201 inline T ToBigEndian(T v) {
202  return v;
203 }
204 
205 template <typename T, std::enable_if_t<sizeof(T) != 1>* = nullptr>
206 inline T ToBigEndian(T v) {
207  static_assert(std::is_pod<T>::value, "Only pod is supported.");
208 #if DMLC_LITTLE_ENDIAN
209  auto constexpr kS = sizeof(T);
210  std::conditional_t<kS == 2, uint16_t, std::conditional_t<kS == 4, uint32_t, uint64_t>> u;
211  std::memcpy(&u, &v, sizeof(u));
212  u = BuiltinBSwap(u);
213  std::memcpy(&v, &u, sizeof(u));
214 #endif // DMLC_LITTLE_ENDIAN
215  return v;
216 }
217 
221 class UBJReader : public JsonReader {
222  Json Parse();
223 
224  template <typename T>
225  T ReadStream() {
226  auto ptr = this->raw_str_.c_str() + cursor_.Pos();
227  T v{0};
228  std::memcpy(&v, ptr, sizeof(v));
229  cursor_.Forward(sizeof(v));
230  return v;
231  }
232 
233  template <typename T>
234  T ReadPrimitive() {
235  auto v = ReadStream<T>();
236  v = ToBigEndian(v);
237  return v;
238  }
239 
240  template <typename TypedArray>
241  auto ParseTypedArray(int64_t n) {
242  TypedArray results{static_cast<size_t>(n)};
243  for (int64_t i = 0; i < n; ++i) {
244  auto v = this->ReadPrimitive<typename TypedArray::Type>();
245  results.Set(i, v);
246  }
247  return Json{std::move(results)};
248  }
249 
250  std::string DecodeStr();
251 
252  Json ParseArray() override;
253  Json ParseObject() override;
254 
255  public:
257  Json Load() override;
258 };
259 
263 class UBJWriter : public JsonWriter {
264  void Visit(JsonArray const* arr) override;
265  void Visit(F32Array const* arr) override;
266  void Visit(U8Array const* arr) override;
267  void Visit(I32Array const* arr) override;
268  void Visit(I64Array const* arr) override;
269  void Visit(JsonObject const* obj) override;
270  void Visit(JsonNumber const* num) override;
271  void Visit(JsonInteger const* num) override;
272  void Visit(JsonNull const* null) override;
273  void Visit(JsonString const* str) override;
274  void Visit(JsonBoolean const* boolean) override;
275 
276  public:
278  void Save(Json json) override;
279 };
280 } // namespace xgboost
281 
282 #endif // XGBOOST_JSON_IO_H_
defines configuration macros of xgboost.
#define XGBOOST_EXPECT(cond, ret)
Definition: base.h:75
Definition: json.h:112
std::vector< Json > const & GetArray() &&
Definition: json.h:130
Describes both true and false.
Definition: json.h:311
Definition: json.h:252
Definition: json.h:295
Definition: json.h:218
Definition: json.h:189
Definition: json_io.h:39
virtual Json ParseString()
virtual Json Load()
virtual Json ParseNumber()
virtual Json ParseArray()
StringView raw_str_
Definition: json_io.h:60
char PeekNextChar()
Definition: json_io.h:74
struct xgboost::JsonReader::SourceLocation cursor_
virtual Json ParseBoolean()
virtual Json ParseObject()
void Error(std::string msg) const
char GetNextNonSpaceChar()
Definition: json_io.h:83
virtual ~JsonReader()=default
constexpr static size_t kMaxNumLength
Definition: json_io.h:41
void Expect(char c, char got)
Definition: json_io.h:99
char GetConsecutiveChar(char expected_char)
Definition: json_io.h:90
char GetNextChar()
Definition: json_io.h:65
JsonReader(StringView str)
Definition: json_io.h:123
virtual Json ParseNull()
Definition: json.h:86
Typed array for Universal Binary JSON.
Definition: json.h:148
Definition: json_io.h:131
std::vector< char > * stream_
Definition: json_io.h:152
virtual void Save(Json json)
JsonWriter(std::vector< char > *stream)
Definition: json_io.h:155
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(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(JsonString const *str)
Data structure representing JSON format.
Definition: json.h:356
Reader for UBJSON https://ubjson.org/.
Definition: json_io.h:221
Json Load() override
Writer for UBJSON https://ubjson.org/.
Definition: json_io.h:263
void Save(Json json) override
std::string CharToStr(Char c)
Definition: json_io.h:24
namespace of xgboost
Definition: base.h:110
T BuiltinBSwap(T v)
Definition: json_io.h:194
T ToBigEndian(T v)
Definition: json_io.h:201
Definition: json_io.h:44
size_t Pos() const
Definition: json_io.h:50
void Forward()
Definition: json_io.h:52
void Forward(uint32_t n)
Definition: json_io.h:55
Definition: string_view.h:15
CharT const * c_str() const
Definition: string_view.h:46
constexpr size_t size() const
Definition: string_view.h:40