Tileson  1.3.0
A helpful json parser for Tiled maps
PicoJson.hpp
Go to the documentation of this file.
1 //
2 // Created by robin on 11.01.2021.
3 //
4 
5 #ifdef picojson_h
6 #ifndef TILESON_PICOJSON_HPP
7 #define TILESON_PICOJSON_HPP
8 
9 namespace tson
10 {
11  class PicoJson : public tson::IJson
12  {
13  public:
14  inline PicoJson() = default;
15 
16  IJson &operator[](std::string_view key) override
17  {
18  if(m_arrayCache.count(key.data()) == 0)
19  {
20  if(m_json->is<picojson::object>())
21  {
22  picojson::object &o = m_json->get<picojson::object>();
23  m_arrayCache[key.data()] = std::make_unique<PicoJson>(&o[key.data()]);
24  }
25  }
26 
27  return *m_arrayCache[key.data()].get();
28  }
29 
30  inline explicit PicoJson(picojson::value *json) : m_json {json}
31  {
32 
33  }
34 
35  inline IJson& at(std::string_view key) override
36  {
37  if(m_arrayCache.count(key.data()) == 0)
38  {
39  if(m_json->is<picojson::object>())
40  {
41  picojson::object &o = m_json->get<picojson::object>();
42  m_arrayCache[key.data()] = std::make_unique<PicoJson>(&o[key.data()]);
43  }
44  }
45  return *m_arrayCache[key.data()].get();
46  }
47 
48  inline IJson& at(size_t pos) override
49  {
50  if(m_arrayPosCache.count(pos) == 0)
51  {
52  picojson::array &a = m_json->get<picojson::array>();
53  m_arrayPosCache[pos] = std::make_unique<PicoJson>(&a.at(pos));
54  }
55 
56  return *m_arrayPosCache[pos];
57  }
58 
59  std::vector<std::unique_ptr<IJson>> array() override
60  {
61  std::vector<std::unique_ptr<IJson>> vec;
62  if(m_json->is<picojson::array>())
63  {
64  picojson::array &a = m_json->get<picojson::array>();
65  for (auto &item : a)
66  {
67  picojson::value *ptr = &item;
68  vec.emplace_back(std::make_unique<PicoJson>(ptr));
69  }
70  }
71 
72  return vec;
73  }
74 
75  inline std::vector<std::unique_ptr<IJson>> &array(std::string_view key) override
76  {
77  if(m_arrayListDataCache.count(key.data()) == 0)
78  {
79  if(count(key.data()) > 0)
80  {
81  if (isObject())
82  {
83  picojson::object &obj = m_json->get<picojson::object>();
84  picojson::value &v = obj.at(key.data());
85  bool isArray = v.is<picojson::array>();
86  if (isArray)
87  {
88  picojson::array &a = v.get<picojson::array>();
89 
90  std::for_each(a.begin(), a.end(), [&](picojson::value &item)
91  {
92  picojson::value *ptr = &item;
93  m_arrayListDataCache[key.data()].emplace_back(std::make_unique<PicoJson>(ptr));
94  });
95  }
96  }
97  }
98  }
99 
100 
101  return m_arrayListDataCache[key.data()];
102  }
103 
104  [[nodiscard]] inline size_t size() const override
105  {
106  if (m_json->is<picojson::object>())
107  {
108  picojson::object obj = m_json->get<picojson::object>();
109  return obj.size();
110  }
111  return 0;
112  }
113 
114  inline bool parse(const fs::path &path) override
115  {
116  clearCache();
117  m_data = nullptr;
118  m_json = nullptr;
119  if (fs::exists(path) && fs::is_regular_file(path))
120  {
121  m_path = path.parent_path();
122  m_data = std::make_unique<picojson::value>();
123  std::ifstream i(path.u8string());
124  try
125  {
126  std::string error = picojson::parse(*m_data, i);
127  if(!error.empty())
128  {
129  std::cerr << "PicoJson parse error: " << error << "\n";
130  return false;
131  }
132  //i >> *m_data;
133  m_json = m_data.get();
134  }
135  catch (const std::exception &error)
136  {
137  std::string message = "Parse error: ";
138  message += std::string(error.what());
139  message += std::string("\n");
140  std::cerr << message;
141  return false;
142  }
143  return true;
144  }
145  return false;
146  }
147 
148  inline bool parse(const void *data, size_t size) override
149  {
150  clearCache();
151  m_json = nullptr;
152  m_data = std::make_unique<picojson::value>();
153  tson::MemoryStream mem{(uint8_t *) data, size};
154  try
155  {
156  std::string error = picojson::parse(*m_data, mem);
157  if(!error.empty())
158  {
159  std::cerr << "PicoJson parse error: " << error << "\n";
160  return false;
161  }
162  //mem >> *m_data;
163  m_json = m_data.get();
164  }
165  catch (const std::exception &error)
166  {
167  std::string message = "Parse error: ";
168  message += std::string(error.what());
169  message += std::string("\n");
170  std::cerr << message;
171  return false;
172  }
173  return true;
174  }
175 
176  [[nodiscard]] inline size_t count(std::string_view key) const override
177  {
178  if (isObject())
179  {
180  picojson::object obj = m_json->get<picojson::object>();
181  return obj.count(key.data());
182  }
183 
184  return m_json->contains(key.data()) ? 1 : 0;
185  }
186 
187  [[nodiscard]] inline bool any(std::string_view key) const override
188  {
189  return count(key) > 0;
190  }
191 
192  [[nodiscard]] inline bool isArray() const override
193  {
194  return m_json->is<picojson::array>();
195  }
196 
197  [[nodiscard]] inline bool isObject() const override
198  {
199  return m_json->is<picojson::object>();
200  }
201 
202  [[nodiscard]] inline bool isNull() const override
203  {
204  return m_json->is<picojson::null>();
205  }
206 
207  fs::path directory() const override
208  {
209  return m_path;
210  }
211 
212  void directory(const fs::path &directory) override
213  {
214  m_path = directory;
215  }
216 
217  protected:
218  [[nodiscard]] inline int32_t getInt32(std::string_view key) override
219  {
220  picojson::object obj = m_json->get<picojson::object>();
221  return static_cast<int32_t>(getDouble(key));
222  }
223 
224  [[nodiscard]] inline uint32_t getUInt32(std::string_view key) override
225  {
226  picojson::object obj = m_json->get<picojson::object>();
227  return static_cast<uint32_t>(getDouble(key));
228  }
229 
230  [[nodiscard]] inline int64_t getInt64(std::string_view key) override
231  {
232  picojson::object obj = m_json->get<picojson::object>();
233  return static_cast<int64_t>(getDouble(key));
234  }
235 
236  [[nodiscard]] inline uint64_t getUInt64(std::string_view key) override
237  {
238  picojson::object obj = m_json->get<picojson::object>();
239  return static_cast<uint64_t>(getDouble(key));
240  }
241 
242  [[nodiscard]] inline double getDouble(std::string_view key) override
243  {
244  picojson::object obj = m_json->get<picojson::object>();
245  return obj[key.data()].get<double>();
246  }
247 
248  [[nodiscard]] inline std::string getString(std::string_view key) override
249  {
250  picojson::object obj = m_json->get<picojson::object>();
251  return obj[key.data()].get<std::string>();
252  }
253 
254  [[nodiscard]] inline bool getBool(std::string_view key) override
255  {
256  picojson::object obj = m_json->get<picojson::object>();
257  return obj[key.data()].get<bool>();
258  }
259 
260  [[nodiscard]] float getFloat(std::string_view key) override
261  {
262  picojson::object obj = m_json->get<picojson::object>();
263  return static_cast<float>(getDouble(key));
264  }
265 
266  [[nodiscard]] inline int32_t getInt32() override
267  {
268  return static_cast<int32_t>(getDouble());
269  }
270 
271  [[nodiscard]] inline uint32_t getUInt32() override
272  {
273  return static_cast<uint32_t>(getDouble());
274  }
275 
276  [[nodiscard]] inline int64_t getInt64() override
277  {
278  return static_cast<int64_t>(getDouble());
279  }
280 
281  [[nodiscard]] inline uint64_t getUInt64() override
282  {
283  return static_cast<uint64_t>(getDouble());
284  }
285 
286  [[nodiscard]] inline double getDouble() override
287  {
288  return m_json->get<double>();
289  }
290 
291  [[nodiscard]] inline std::string getString() override
292  {
293  return m_json->get<std::string>();
294  }
295 
296  [[nodiscard]] inline bool getBool() override
297  {
298  return m_json->get<bool>();
299  }
300 
301  [[nodiscard]] float getFloat() override
302  {
303  return static_cast<float>(getDouble());
304  }
305 
306  private:
307  inline void clearCache()
308  {
309  m_arrayCache.clear();
310  m_arrayPosCache.clear();
311  m_arrayListDataCache.clear();
312  }
313 
314  picojson::value *m_json = nullptr;
315  std::unique_ptr<picojson::value> m_data = nullptr; //Only used if this is the owner json!
316  fs::path m_path;
317 
318  //Cache!
319  std::map<std::string, std::unique_ptr<IJson>> m_arrayCache;
320  std::map<size_t, std::unique_ptr<IJson>> m_arrayPosCache;
321  std::map<std::string, std::vector<std::unique_ptr<IJson>>> m_arrayListDataCache;
322 
323  };
324 }
325 #endif //TILESON_PICOJSON_HPP
326 #endif
Definition: IJson.hpp:11
T get(std::string_view key)
Definition: IJson.hpp:72
Definition: MemoryStream.hpp:12
Definition: Base64.hpp:12