Honeycomb  0.1
Component-Model Framework
Json.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
4 #include "Honey/String/Id.h"
5 #include "Honey/Misc/Variant.h"
7 
8 namespace honey
9 {
11 namespace json
12 {
13 
15 enum class ValueType { Null, Int, Real, Bool, String, Array, Object };
17 struct null_t {};
19 static null_t null;
20 
22 
23 template<class Config> class Value_;
24 
26 
30 template<bool ordered = false, template<class> class Alloc = SmallAllocator>
31 struct Config
32 {
36  typedef vector<value_wrap, Alloc<value_wrap>> Array;
38 
39  struct ObjectOrdered : ObjectUnordered
40  {
41  typedef typename ObjectUnordered::iterator Iter;
42  typedef typename ObjectUnordered::const_iterator ConstIter;
43 
44  template<class Pair>
45  pair<Iter, bool> insert(Pair&& pair)
46  {
47  auto res = ObjectUnordered::insert(forward<Pair>(pair));
48  if (res.second) orderedNames.push_back(res.first->first);
49  return res;
50  }
51 
53  Iter erase(ConstIter pos) { stdutil::eraseVal(orderedNames, pos->first); return ObjectUnordered::erase(pos); }
54  void clear() { orderedNames.clear(); ObjectUnordered::clear(); }
55 
57  const String& name(const Id& id) const
58  {
59  auto it = this->find(NameId(id));
60  if (it == this->end()) throw_ ValueError() << "Value not found. Id: " << id;
61  return it->first.name();
62  }
63 
65  vector<Id, Alloc<Id>> orderedNames;
66  };
67 
68  typedef typename std::conditional<ordered, ObjectOrdered, ObjectUnordered>::type Object;
69 
71 };
72 
74 template<class Config_>
75 class Value_ : public Config_::Variant
76 {
77 public:
78  typedef Config_ Config;
80  typedef typename Config::Array Array;
82  typedef typename Config::Object Object;
88  typedef typename Config::Variant Variant;
89 
91  Value_() : Value_(null) {}
93  template<class T>
94  Value_(T&& val) : Variant(forward<T>(val)) {}
95  Value_(const Value_& rhs) : Value_(static_cast<const Variant&>(rhs)) {}
96  Value_(Value_& rhs) : Value_(static_cast<Variant&>(rhs)) {}
97  Value_(Value_&& rhs) : Value_(move(static_cast<Variant&>(rhs))) {}
98 
100  template<class T>
101  Value_& operator=(T&& val) { Variant::operator=(forward<T>(val)); return *this; }
102  Value_& operator=(const Value_& rhs) { Variant::operator=(static_cast<const Variant&>(rhs)); return *this; }
103  Value_& operator=(Value_& rhs) { Variant::operator=(static_cast<Variant&>(rhs)); return *this; }
104  Value_& operator=(Value_&& rhs) { Variant::operator=(move(static_cast<Variant&>(rhs))); return *this; }
105 
108  {
110  auto& arr = get_<Array>();
111  assert(i < arr.size());
112  return arr[i];
113  }
114  const Value_& operator[](szt i) const { return const_cast<Value_&>(*this)[i]; }
115 
117  Value_& operator[](const String& name)
118  {
120  auto& obj = get_<Object>();
121  Id id = name;
122  auto it = obj.find(NameId(id));
123  if (it == obj.end()) it = obj.insert(make_pair(NameId(name, id), Value_())).first;
124  return it->second;
125  }
126  //resolves ambiguity between String and built-in asymmetric operator[](int, const Char*)
127  Value_& operator[](const Char* name) { return (*this)[String(name)]; }
128  Value_& operator[](const char* name) { return (*this)[String(name)]; }
129 
131  Value_& operator[](const Id& id)
132  {
134  auto& obj = get_<Object>();
135  auto it = obj.find(NameId(id));
136  if (it == obj.end()) throw_ ValueError() << "Value not found. Id: " << id;
137  return it->second;
138  }
139  const Value_& operator[](const Id& id) const { return const_cast<Value_&>(this)[id]; }
140  //resolves ambiguity between Id and int
141  Value_& operator[](const IdLiteral& id) { return (*this)[Id(id)]; }
142  const Value_& operator[](const IdLiteral& id) const { return (*this)[Id(id)]; }
143 
145  ValueType type() const { return static_cast<ValueType>(Variant::type()); }
146 
148  typename Array::iterator begin() { assert(type() == ValueType::Array); return get_<Array>().begin(); }
150  typename Array::const_iterator begin() const { assert(type() == ValueType::Array); return get_<Array>().begin(); }
151 
153  typename Array::iterator end() { assert(type() == ValueType::Array); return get_<Array>().end(); }
155  typename Array::const_iterator end() const { assert(type() == ValueType::Array); return get_<Array>().end(); }
156 
158  Value_& front() { assert(!empty()); return get_<Array>().front(); }
159  const Value_& front() const { assert(!empty()); return get_<Array>().front(); }
161  Value_& back() { assert(!empty()); return get_<Array>().back(); }
162  const Value_& back() const { assert(!empty()); return get_<Array>().back(); }
163 
165  template<class T>
166  void push_back(T&& val) { assert(type() == ValueType::Array); get_<Array>().push_back(Value_(forward<T>(val))); }
168  void pop_back() { assert(type() == ValueType::Array); get_<Array>().pop_back(); }
169 
171  bool contains(const Id& id) { assert(type() == ValueType::Object); return get_<Object>().count(NameId(id)); }
172 
174  template<class T>
175  void insert(szt i, T&& val)
176  {
178  auto& arr = get_<Array>();
179  assert(i <= arr.size());
180  arr.insert(arr.begin() + i, Value_(forward<T>(val)));
181  }
182 
184 
188  template<class T>
189  pair<typename Object::iterator, bool> insert(const String& name, T&& val)
190  {
192  return get_<Object>().insert(make_pair(NameId(name), Value_(forward<T>(val))));
193  }
194 
196  void erase(szt i)
197  {
199  auto& arr = get_<Array>();
200  assert(i < arr.size());
201  arr.erase(arr.begin() + i);
202  }
203 
205  bool erase(const Id& id)
206  {
208  auto& obj = get_<Object>();
209  auto it = obj.find(NameId(id));
210  if (it == obj.end()) return false;
211  obj.erase(it);
212  return true;
213  }
214  bool erase(const IdLiteral& id) { return erase(Id(id)); }
215 
217  void clear()
218  {
220  return visit(overload(
221  [](Array& arr) { arr.clear(); },
222  [](Object& obj) { obj.clear(); }
223  ));
224  }
225 
227  bool empty() const { return !size(); }
228 
230  szt size() const
231  {
233  return this->template visit<szt>(overload(
234  [](const Array& arr) { return arr.size(); },
235  [](const Object& obj) { return obj.size(); }
236  ));
237  }
238 
239 private:
241  template<class T> T& get_() { return this->template get<T>(); }
242  template<class T> const T& get_() const { return this->template get<T>(); }
243 };
244 
247 
249 
254 template<class Config> istream& operator>>(istream& is, Value_<Config>& val);
255 
257 namespace priv
258 {
259  struct WriterManip : Manip<WriterManip>
260  {
261  bool beautify = false;
262  bool escapeSlash = false;
263  };
264 }
267 inline ostream& beautify(ostream& os) { priv::WriterManip::inst(os).beautify = true; return os; }
270 inline ostream& escapeSlash(ostream& os) { priv::WriterManip::inst(os).escapeSlash = true; return os; }
271 
273 template<class Config> ostream& operator<<(ostream& os, const Value_<Config>& val);
274 
275 }
276 
277 extern template class Manip<json::priv::WriterManip>;
278 
279 }
const Value_ & operator[](const IdLiteral &id) const
Definition: Json.h:142
Value_(Value_ &&rhs)
Definition: Json.h:97
Definition: Json.h:21
Value_ & front()
Get first value in array.
Definition: Json.h:158
Array::iterator begin()
Get iterator to first value in array.
Definition: Json.h:148
Holds both a name string and its hashed value, and unlike Id the name is never compiled out...
Definition: Id.h:144
vector< value_wrap, Alloc< value_wrap > > Array
Definition: Json.h:36
Allows for recursive type definitions, eg. class Object : vector>.
Definition: StdUtil.h:173
ObjectUnordered::const_iterator ConstIter
Definition: Json.h:42
Multi-typed value. A variant is a value of any type from a fixed set of bounded types, the active bounded type may be changed dynamically.
Definition: Variant.h:230
vector< Id, Alloc< Id > > orderedNames
List of names in order of name/value pair insertion.
Definition: Json.h:65
istream & operator>>(istream &is, Value_< Config > &val)
Convert a string to a json value tree. Returns either a tree with val as the root array/object...
Definition: Json.cpp:171
Id created from a string literal at compile-time.
Definition: Id.h:81
static null_t null
Json null value.
Definition: Json.h:19
Array::const_iterator begin() const
Get iterator to first value in array.
Definition: Json.h:150
ostream & escapeSlash(ostream &os)
Escape forward slash characters in json output so it is suitable for embedding in HTML...
Definition: Json.h:270
Value_< Config > Value
Definition: Json.h:33
List::reverse_iterator erase(List &list, const typename List::reverse_iterator &iter)
Erase using reverse iterator. Returns reverse iterator to element after erased element.
Definition: StdUtil.h:45
Iter find(Range &&, Seqs &&..., Func &&pred)
Find an element in a series of sequences.
Value_()
Construct with null value.
Definition: Json.h:91
Json null value type.
Definition: Json.h:17
Value_ & operator=(Value_ &&rhs)
Definition: Json.h:104
bool empty() const
Check if array/object contains any values.
Definition: Json.h:227
String & insert(szt pos, const String &str, szt subpos=0, szt sublen=npos)
Definition: String.cpp:9
void clear()
Definition: Json.h:54
Value_ & operator=(T &&val)
Attempts to copy/move-assign any json value type, otherwise first json value type assignable to val i...
Definition: Json.h:101
Value_ & operator[](szt i)
Get value at index in array.
Definition: Json.h:107
Value_(const Value_ &rhs)
Definition: Json.h:95
std::unordered_map< Key, Value, std::hash< Key >, std::equal_to< Key >, Alloc< pair< const Key, Value >>> unordered_map
std::unordered_map with custom allocator
Definition: StdUtil.h:83
szt size() const
Get number of values in array/object.
Definition: Json.h:230
Iter erase(ConstIter pos)
This function is O(n)
Definition: Json.h:53
pair< typename Object::iterator, bool > insert(const String &name, T &&val)
Create Value from val and insert name/value pair into object.
Definition: Json.h:189
std::conditional< ordered, ObjectOrdered, ObjectUnordered >::type Object
Definition: Json.h:68
const Value_ & operator[](const Id &id) const
Definition: Json.h:139
Value_< Config<> > Value
Json value with default config.
Definition: Json.h:246
stdutil::unordered_map< NameId, value_wrap, Alloc > ObjectUnordered
Definition: Json.h:37
overload_< Funcs... > overload(Funcs &&...fs)
Create an overloaded visitor functor.
Definition: Variant.h:346
pair< Iter, bool > insert(Pair &&pair)
Definition: Json.h:45
ValueType type() const
Get active json value type.
Definition: Json.h:145
Value_(T &&val)
Attempts to copy/move construct any json value type, otherwise first json value type constructible wi...
Definition: Json.h:94
#define EXCEPTION(Class)
Declares methods required for every subclass of honey::Exception.
Definition: Exception.h:17
Value_ & back()
Get last value in array.
Definition: Json.h:161
bool contains(const Id &id)
Check if object contains value with id.
Definition: Json.h:171
void erase(szt i)
Erase value at index in array.
Definition: Json.h:196
ostream & beautify(ostream &os)
Output easily readable json with line breaks and indentation.
Definition: Json.h:268
const String & name() const
Get name string that this id represents.
Definition: Id.h:57
char16_t Char
Represents a single code unit (not code point) for class String.
Definition: String.h:13
Value_ & operator[](const Id &id)
Get value with id in object. Throws ValueError if it doesn't exist.
Definition: Json.h:131
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
Configuration for json value variant.
Definition: Json.h:31
variant & operator=(T &&val)
Attempts to copy/move-assign to any bounded type, otherwise first bounded type assignable to val is s...
Definition: Variant.h:267
const Value_ & front() const
Definition: Json.h:159
Value_ & operator[](const IdLiteral &id)
Definition: Json.h:141
Unicode UTF-16 string class, wrapper around std::u16string.
Definition: String.h:23
const String & name(const Id &id) const
Get name for id.
Definition: Json.h:57
ObjectUnordered::iterator Iter
Definition: Json.h:41
Base exception class. Exceptions inherited from this class provide debug info and can be thrown polym...
Definition: Exception.h:45
bool erase(const Id &id)
Erase value with id in object. Returns true if found and erased.
Definition: Json.h:205
#define throw_
Use in place of throw keyword to throw a honey::Exception object polymorphically and provide debug in...
Definition: Exception.h:11
size_t szt
Size type, shorthand for size_t.
Definition: Core.h:90
Value_(Value_ &rhs)
Definition: Json.h:96
recursive_wrap< Value, Alloc< Value > > value_wrap
Holds a value in an array/object.
Definition: Json.h:35
Config::Array Array
Json value array.
Definition: Json.h:80
void pop_back()
Remove last value from array.
Definition: Json.h:168
Global allocator for small memory blocks. To provide a custom pool define SmallAllocator_createSingle...
Definition: SmallAllocator.h:23
Value_ & operator[](const char *name)
Definition: Json.h:128
Config_ Config
Definition: Json.h:78
ValueType
Json value type, corresponds to Value::Variant bounded type id.
Definition: Json.h:15
szt type() const
Get active bounded type id, range [0, size)
Definition: Variant.h:280
List::iterator eraseVal(List &list, const typename List::value_type &val)
Erase first occurrence of value. Returns iterator to next element after the erased element...
Definition: StdUtil.h:52
Value_ & operator[](const Char *name)
Definition: Json.h:127
Config::Object Object
Json object, map of json name/value pairs. May be ObjectUnordered (default) or ObjectOrdered dependin...
Definition: Json.h:82
Base class to hold iostream manipulator state. Inherit from this class and call Subclass::inst(ios) t...
Definition: StdUtil.h:206
Array::iterator end()
Get iterator to position after the last value in array.
Definition: Json.h:153
void clear()
Clear all values in array/object.
Definition: Json.h:217
void push_back(T &&val)
Create Value from val and add value to back of array.
Definition: Json.h:166
const Value_ & back() const
Definition: Json.h:162
Config::Variant Variant
Base class, the underlying variant.
Definition: Json.h:88
Holds a name string and its hashed value for fast comparison ops. See String Identifier.
Definition: Id.h:25
void insert(szt i, T &&val)
Create Value from val and insert value into array at index.
Definition: Json.h:175
Base class for objects.
Definition: Object.h:12
Value_ & operator[](const String &name)
Get value with name in object. Adds null value if it doesn't exist.
Definition: Json.h:117
const Value_ & operator[](szt i) const
Definition: Json.h:114
Global Honeycomb namespace.
bool erase(const IdLiteral &id)
Definition: Json.h:214
Config::ObjectUnordered ObjectUnordered
Object with unordered name/value pairs.
Definition: Json.h:84
variant< null_t, int64, double, bool, String, Array, Object > Variant
Definition: Json.h:70
Json value variant. Provide a Config to customize the variant's bounded types.
Definition: Json.h:23
Value_ & operator=(Value_ &rhs)
Definition: Json.h:103
Array::const_iterator end() const
Get iterator to position after the last value in array.
Definition: Json.h:155
Config::ObjectOrdered ObjectOrdered
Object with ordered name/value pairs.
Definition: Json.h:86
Value_ & operator=(const Value_ &rhs)
Definition: Json.h:102