1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
30 #include "vogl_core.h"
31 #include "vogl_strutils.h"
32 #include "vogl_dynamic_string.h"
34 #include "vogl_hash_map.h"
35 #include "vogl_data_stream.h"
36 #include "vogl_json.h"
40 // adding: uint8, int64_t, uint64_t, double, blob
58 cDTString = cDTFirstDynamic,
66 extern const char *g_value_data_type_strings[cDTTotal + 1];
68 value_data_type string_to_value_data_type(const char *pStr);
84 VOGL_ASSUME(sizeof(float) == sizeof(int));
85 VOGL_ASSUME(sizeof(double) == sizeof(uint64_t));
88 inline value(const char *pStr)
89 : m_pStr(vogl_new(dynamic_string, pStr)), m_user_data(0), m_type(cDTString), m_flags(0)
93 inline value(const dynamic_string &str)
94 : m_pStr(vogl_new(dynamic_string, str)), m_user_data(0), m_type(cDTString), m_flags(0)
98 inline value(const uint8 *pBuf, uint size)
99 : m_pBlob(vogl_new(uint8_vec, size)), m_user_data(0), m_type(cDTBlob), m_flags(0)
102 memcpy(m_pBlob->get_ptr(), pBuf, size);
105 inline value(const uint8_vec &blob)
106 : m_pBlob(vogl_new(uint8_vec, blob)), m_user_data(0), m_type(cDTBlob), m_flags(0)
110 inline value(const json_document &doc)
111 : m_pJSONDoc(vogl_new(json_document, doc)), m_user_data(0), m_type(cDTJSONDoc), m_flags(0)
115 inline explicit value(bool v)
116 : m_bool(v), m_user_data(0), m_type(cDTBool), m_flags(0)
120 inline explicit value(void *p)
121 : m_pPtr(p), m_user_data(0), m_type(cDTVoidPtr), m_flags(0)
126 : m_int8(v), m_user_data(0), m_type(cDTInt8), m_flags(0)
130 inline value(uint8 v)
131 : m_uint8(v), m_user_data(0), m_type(cDTUInt8), m_flags(0)
135 inline value(int16 v)
136 : m_int16(v), m_user_data(0), m_type(cDTInt16), m_flags(0)
140 inline value(uint16 v)
141 : m_uint16(v), m_user_data(0), m_type(cDTUInt16), m_flags(0)
146 : m_int(v), m_user_data(0), m_type(cDTInt), m_flags(0)
151 : m_uint(v), m_user_data(0), m_type(cDTUInt), m_flags(0)
155 inline value(int64_t v)
156 : m_int64(v), m_user_data(0), m_type(cDTInt64), m_flags(0)
160 inline value(uint64_t v)
161 : m_uint64(v), m_user_data(0), m_type(cDTUInt64), m_flags(0)
165 inline value(float v)
166 : m_float(v), m_user_data(0), m_type(cDTFloat), m_flags(0)
170 inline value(double v)
171 : m_double(v), m_user_data(0), m_type(cDTDouble), m_flags(0)
175 inline value(const vec3F &v)
176 : m_pVec3F(vogl_new(vec3F, v)), m_user_data(0), m_type(cDTVec3F), m_flags(0)
180 inline value(const vec3I &v)
181 : m_pVec3I(vogl_new(vec3I, v)), m_user_data(0), m_type(cDTVec3I), m_flags(0)
185 inline value(const value &other)
186 : m_type(cDTInvalid),
192 inline value(const string_hash &hash)
193 : m_user_data(0), m_type(cDTStringHash), m_flags(0)
195 get_string_hash_ref() = hash;
203 value &operator=(const value &other);
205 bool operator==(const value &other) const;
206 bool operator!=(const value &other) const
208 return !(*this == other);
211 bool operator<(const value &other) const;
213 inline value_data_type get_data_type() const
228 inline void set_bool(bool v)
235 inline void set_int8(int8 v)
242 inline void set_uint8(uint8 v)
249 inline void set_int16(int16 v)
256 inline void set_uint16(uint16 v)
263 inline void set_int(int v)
270 inline void set_uint(uint v)
277 inline void set_int64(int64_t v)
284 inline void set_uint64(uint64_t v)
291 inline void set_float(float v)
298 inline void set_double(double v)
305 inline void set_void_ptr(void *p)
312 inline void set_vec(const vec3F &v)
314 change_type(cDTVec3F);
318 inline void set_vec(const vec3I &v)
320 change_type(cDTVec3I);
324 inline void set_string(const char *pStr)
329 inline bool set_blob(const uint8 *pBlob, uint size)
331 change_type(cDTBlob);
332 if (!m_pBlob->try_resize(size))
335 memcpy(m_pBlob->get_ptr(), pBlob, size);
339 inline bool set_blob(const uint8_vec &v)
341 return set_blob(v.get_ptr(), v.size());
344 inline void set_blob_take_ownership(uint8_vec &v)
346 change_type(cDTBlob);
350 inline bool set_json_document(const json_document &doc)
352 change_type(cDTJSONDoc);
357 inline bool set_json_document_take_ownership(json_document &doc)
359 change_type(cDTJSONDoc);
360 m_pJSONDoc->swap(doc);
364 inline json_document *init_json_document()
366 change_type(cDTJSONDoc);
370 inline void set_string_hash(const string_hash &hash)
372 change_type(cDTStringHash);
373 m_type = cDTStringHash;
374 get_string_hash_ref() = hash;
377 inline value &operator=(bool value)
382 inline value &operator=(uint8 value)
387 inline value &operator=(int16 value)
392 inline value &operator=(uint16 value)
397 inline value &operator=(int value)
402 inline value &operator=(uint value)
407 inline value &operator=(int64_t value)
412 inline value &operator=(uint64_t value)
417 inline value &operator=(float value)
422 inline value &operator=(double value)
427 inline value &operator=(void *pPtr)
432 inline value &operator=(const vec3F &value)
437 inline value &operator=(const vec3I &value)
442 inline value &operator=(const uint8_vec &value)
447 inline value &operator=(const dynamic_string &value)
449 set_string(value.get_ptr());
452 inline value &operator=(const char *pStr)
457 inline value &operator=(const string_hash &hash)
459 set_string_hash(hash);
462 inline value &operator=(const json_document &doc)
464 set_json_document(doc);
468 bool parse(const char *p);
470 dynamic_string &get_string(dynamic_string &dst, bool quote_strings = false) const;
472 inline dynamic_string get_string(bool quote_strings = false) const
475 get_string(str, quote_strings);
478 inline dynamic_string *get_string_ptr() const
480 return (m_type == cDTString) ? m_pStr : NULL;
483 // on failure, the destination val is NOT modified
484 bool get_int8_or_fail(int8 &val, uint component) const;
485 bool get_uint8_or_fail(uint8 &val, uint component) const;
486 bool get_int16_or_fail(int16 &val, uint component) const;
487 bool get_uint16_or_fail(uint16 &val, uint component) const;
488 bool get_int_or_fail(int &val, uint component = 0) const;
489 bool get_int64_or_fail(int64_t &val, uint component = 0) const;
490 bool get_uint_or_fail(uint &val, uint component = 0) const;
491 bool get_uint64_or_fail(uint64_t &val, uint component = 0) const;
492 bool get_bool_or_fail(bool &val, uint component = 0) const;
493 bool get_double_or_fail(double &val, uint component = 0) const;
494 bool get_float_or_fail(float &val, uint component = 0) const;
495 bool get_vec3F_or_fail(vec3F &val) const;
496 bool get_vec3I_or_fail(vec3I &val) const;
497 bool get_string_hash_or_fail(string_hash &hash) const;
499 inline int8 get_int8(int8 def = 0, uint component = 0) const
502 get_int8_or_fail(result, component);
505 inline int16 get_int16(int16 def = 0, uint component = 0) const
508 get_int16_or_fail(result, component);
511 inline uint8 get_uint8(uint8 def = 0, uint component = 0) const
514 get_uint8_or_fail(result, component);
517 inline uint16 get_uint16(uint16 def = 0, uint component = 0) const
520 get_uint16_or_fail(result, component);
523 inline int get_int(int def = 0, uint component = 0) const
526 get_int_or_fail(result, component);
529 inline int64_t get_int64(int64_t def = 0, uint component = 0) const
531 int64_t result = def;
532 get_int64_or_fail(result, component);
535 inline uint get_uint(uint def = 0, uint component = 0) const
538 get_uint_or_fail(result, component);
541 inline uint64_t get_uint64(uint64_t def = 0, uint component = 0) const
543 uint64_t result = def;
544 get_uint64_or_fail(result, component);
548 inline bool get_bool(bool def = false, uint component = 0) const
551 get_bool_or_fail(result, component);
554 inline double get_double(double def = 0.0f, uint component = 0) const
557 get_double_or_fail(result, component);
560 inline float get_float(float def = 0.0f, uint component = 0) const
563 get_float_or_fail(result, component);
566 inline vec3F get_vec3F(const vec3F &def = vec3F(0)) const
569 get_vec3F_or_fail(result);
572 inline vec3I get_vec3I(const vec3I &def = vec3I(0)) const
575 get_vec3I_or_fail(result);
578 inline string_hash get_string_hash(const string_hash &def = string_hash(0U)) const
580 string_hash result(def);
581 get_string_hash_or_fail(result);
585 inline const uint8_vec *get_blob() const
587 return (m_type == cDTBlob) ? m_pBlob : NULL;
590 inline uint8_vec *get_blob()
592 return (m_type == cDTBlob) ? m_pBlob : NULL;
595 inline void *get_void_ptr() const
597 return (m_type == cDTVoidPtr) ? m_pPtr : NULL;
600 inline const json_document *get_json_document() const
602 return (m_type == cDTJSONDoc) ? m_pJSONDoc : NULL;
605 inline json_document *get_json_document()
607 return (m_type == cDTJSONDoc) ? m_pJSONDoc : NULL;
610 inline bool set_zero()
670 inline bool is_valid() const
672 return m_type != cDTInvalid;
675 inline bool is_dynamic() const
677 return m_type >= cDTFirstDynamic;
680 inline bool is_vector() const
693 inline uint get_num_components() const
701 return m_pBlob->size();
708 inline bool is_numeric() const
732 inline const void *get_data_ptr() const
734 if (m_type >= cDTFirstDynamic)
739 return m_pStr->get_ptr();
745 return m_pBlob->get_ptr();
757 inline uint get_data_size_in_bytes() const
766 return sizeof(uint8);
769 return sizeof(uint16);
774 return sizeof(uint32);
778 return sizeof(uint64_t);
780 return sizeof(void *);
782 return (m_pStr->get_len() + 1);
784 return sizeof(vec3F);
786 return sizeof(vec3I);
788 return m_pBlob->size_in_bytes();
798 inline bool is_float() const
812 inline bool is_integer() const
833 inline bool is_unsigned() const
849 inline bool is_signed() const
868 inline bool is_string() const
870 return m_type == cDTString;
873 inline bool is_blob() const
875 return m_type == cDTBlob;
878 inline bool is_string_hash() const
880 return m_type == cDTStringHash;
883 inline bool is_json_document() const
885 return m_type == cDTJSONDoc;
888 uint get_serialize_size(bool serialize_user_data) const;
889 int serialize(void *pBuf, uint buf_size, bool little_endian, bool serialize_user_data) const;
890 int deserialize(const void *pBuf, uint buf_size, bool little_endian, bool serialize_user_data);
892 inline value &swap(value &other)
894 std::swap(m_uint64, other.m_uint64);
895 std::swap(m_type, other.m_type);
896 std::swap(m_user_data, other.m_user_data);
897 std::swap(m_flags, other.m_flags);
901 inline bool has_user_data() const
903 return (m_flags & cFlagsHasUserData) != 0;
905 inline uint get_user_data() const
909 inline void set_user_data(uint16 v)
912 m_flags |= cFlagsHasUserData;
914 inline void clear_user_data()
916 m_flags &= ~cFlagsHasUserData;
919 inline size_t get_hash() const
921 if (m_type == cDTJSONDoc)
924 m_pJSONDoc->binary_serialize(data);
925 return (((fast_hash(data.get_ptr(), data.size_in_bytes()) + m_type) ^ (m_type << 20)) - bitmix32(m_user_data)) ^ bitmix32(m_flags);
929 return (((fast_hash(get_data_ptr(), get_data_size_in_bytes()) + m_type) ^ (m_type << 20)) - bitmix32(m_user_data)) ^ bitmix32(m_flags);
934 inline void clear_dynamic()
936 if (m_type >= cDTFirstDynamic)
938 if (m_type == cDTVec3F)
939 vogl_delete(m_pVec3F);
940 else if (m_type == cDTVec3I)
941 vogl_delete(m_pVec3I);
942 else if (m_type == cDTString)
944 else if (m_type == cDTBlob)
945 vogl_delete(m_pBlob);
946 else if (m_type == cDTJSONDoc)
947 vogl_delete(m_pJSONDoc);
958 inline void change_type(value_data_type type)
965 if (m_type >= cDTFirstDynamic)
970 m_pStr = vogl_new(dynamic_string);
973 m_pVec3F = vogl_new(vec3F);
976 m_pVec3I = vogl_new(vec3I);
979 m_pBlob = vogl_new(uint8_vec);
982 m_pJSONDoc = vogl_new(json_document);
991 inline void set_str(const dynamic_string &s)
993 if (m_type == cDTString)
1000 m_pStr = vogl_new(dynamic_string, s);
1004 inline void set_str(const char *p)
1006 if (m_type == cDTString)
1013 m_pStr = vogl_new(dynamic_string, p);
1039 dynamic_string *m_pStr;
1041 json_document *m_pJSONDoc;
1044 const string_hash &get_string_hash_ref() const
1046 VOGL_ASSUME(sizeof(string_hash) == sizeof(uint));
1047 return *reinterpret_cast<const string_hash *>(&m_uint);
1049 string_hash &get_string_hash_ref()
1051 VOGL_ASSUME(sizeof(string_hash) == sizeof(uint));
1052 return *reinterpret_cast<string_hash *>(&m_uint);
1055 // I'm torn about m_user_data/m_flags - may not be useful, but there's room for it due to alignment.
1057 value_data_type m_type;
1061 typedef vogl::vector<value> value_vector;
1064 struct hasher<value>
1066 inline size_t operator()(const value &key) const
1068 return key.get_hash();
1072 typedef hash_map<value, value> value_to_value_hash_map;
1077 typedef value_to_value_hash_map::iterator iterator;
1078 typedef value_to_value_hash_map::const_iterator const_iterator;
1080 inline key_value_map()
1084 inline ~key_value_map()
1089 inline key_value_map(const key_value_map &other)
1094 inline key_value_map &operator=(const key_value_map &rhs)
1098 m_key_values = rhs.m_key_values;
1102 inline bool operator==(const key_value_map &other) const
1104 if (m_key_values.size() != other.m_key_values.size())
1107 for (const_iterator it = begin(); it != end(); ++it)
1109 const_iterator other_it = other.find(it->first);
1110 if (other_it == other.end())
1112 if (it->second != other_it->second)
1119 inline bool operator!=(const key_value_map &other) const
1121 return !(*this == other);
1124 inline size_t get_hash() const
1126 size_t h = 0xDEADBEEF ^ bitmix32(get_num_key_values());
1128 for (const_iterator it = begin(); it != end(); ++it)
1130 h ^= it->first.get_hash();
1131 h -= it->second.get_hash();
1139 m_key_values.clear();
1144 m_key_values.reset();
1147 inline void reserve(uint new_capacity)
1149 m_key_values.reserve(new_capacity);
1152 inline uint size() const
1154 return m_key_values.size();
1157 inline uint64_t get_serialize_size(bool serialize_user_data) const
1159 uint64_t l = sizeof(uint) * 2;
1161 for (const_iterator it = begin(); it != end(); ++it)
1162 l += it->first.get_serialize_size(serialize_user_data) + it->second.get_serialize_size(serialize_user_data);
1167 inline int serialize_to_buffer(void *pBuf, uint buf_size, bool little_endian, bool serialize_user_data) const
1169 if (buf_size < sizeof(uint) * 2)
1172 uint buf_left = buf_size;
1174 void *pSize = reinterpret_cast<uint *>(pBuf);
1175 if (!utils::write_obj(buf_left, pBuf, buf_left, little_endian))
1178 uint n = get_num_key_values();
1179 if (!utils::write_obj(n, pBuf, buf_left, little_endian))
1182 for (const_iterator it = begin(); it != end(); ++it)
1184 int num_bytes_written = it->first.serialize(pBuf, buf_left, little_endian, serialize_user_data);
1185 if (num_bytes_written < 0)
1188 pBuf = static_cast<uint8 *>(pBuf) + num_bytes_written;
1189 buf_left -= num_bytes_written;
1191 num_bytes_written = it->second.serialize(pBuf, buf_left, little_endian, serialize_user_data);
1192 if (num_bytes_written < 0)
1195 pBuf = static_cast<uint8 *>(pBuf) + num_bytes_written;
1196 buf_left -= num_bytes_written;
1199 uint total_bytes_written = buf_size - buf_left;
1202 utils::write_obj(total_bytes_written, pSize, n, little_endian);
1204 return total_bytes_written;
1207 inline int deserialize_from_buffer(const void *pBuf, uint buf_size, bool little_endian, bool serialize_user_data)
1209 m_key_values.reset();
1211 uint buf_left = buf_size;
1214 if (!utils::read_obj(len, pBuf, buf_left, little_endian))
1217 if (len < sizeof(uint) * 2)
1220 if ((buf_left + sizeof(uint)) < len)
1224 if (!utils::read_obj(n, pBuf, buf_left, little_endian))
1227 for (uint i = 0; i < n; ++i)
1230 int num_bytes_read = key.deserialize(pBuf, buf_left, little_endian, serialize_user_data);
1231 if (num_bytes_read < 0)
1234 pBuf = static_cast<const uint8 *>(pBuf) + num_bytes_read;
1235 buf_left -= num_bytes_read;
1238 num_bytes_read = val.deserialize(pBuf, buf_left, little_endian, serialize_user_data);
1239 if (num_bytes_read < 0)
1242 pBuf = static_cast<const uint8 *>(pBuf) + num_bytes_read;
1243 buf_left -= num_bytes_read;
1245 if (!insert(key, val).second)
1249 uint total_bytes_read = buf_size - buf_left;
1250 if (total_bytes_read != len)
1252 return total_bytes_read;
1255 inline int serialize_to_stream(data_stream &stream, bool little_endian, bool serialize_user_data) const
1257 uint64_t num_bytes_needed = get_serialize_size(serialize_user_data);
1258 if (num_bytes_needed > static_cast<uint64_t>(cINT32_MAX))
1265 if (num_bytes_needed > sizeof(buf))
1267 dyn_buf.resize(static_cast<uint>(num_bytes_needed));
1268 pBuf = dyn_buf.get_ptr();
1271 int num_bytes_written = serialize_to_buffer(pBuf, static_cast<uint>(num_bytes_needed), little_endian, serialize_user_data);
1272 if (num_bytes_written < 0)
1274 VOGL_ASSERT(num_bytes_needed == static_cast<uint64_t>(num_bytes_written));
1276 uint num_bytes_streamed = stream.write(pBuf, num_bytes_written);
1277 if (num_bytes_streamed != static_cast<uint>(num_bytes_written))
1280 return num_bytes_written;
1283 inline int deserialize_from_stream(data_stream &stream, bool little_endian, bool serialize_user_data)
1285 uint num_bytes_read = sizeof(uint) * 2;
1286 VOGL_NOTE_UNUSED(num_bytes_read);
1289 if (stream.read(&raw_size, sizeof(raw_size)) != sizeof(raw_size))
1292 uint size = raw_size;
1293 if (little_endian != c_vogl_little_endian_platform)
1294 size = utils::swap32(size);
1296 if ((size < sizeof(uint) * 2) || (size > static_cast<uint>(cINT32_MAX)))
1299 uint8_vec buf(size);
1300 *reinterpret_cast<uint *>(buf.get_ptr()) = raw_size;
1302 if (stream.read(buf.get_ptr() + sizeof(uint), buf.size() - sizeof(uint)) != (buf.size() - sizeof(uint)))
1305 return deserialize_from_buffer(buf.get_ptr(), buf.size(), little_endian, serialize_user_data);
1308 // result.first will be an iterator
1309 // result.second will be true if the key was inserted, or false if the key already exists (in which case it will not be modified).
1310 inline value_to_value_hash_map::insert_result insert(const value &key, const value &val)
1312 return m_key_values.insert(key, val);
1315 inline iterator find(const value &key)
1317 return m_key_values.find(key);
1319 inline const_iterator find(const value &key) const
1321 return m_key_values.find(key);
1324 // TODO: add more/easier to use gets
1325 inline value get_value(const value &key, const value &def) const
1327 const_iterator it = m_key_values.find(key);
1328 return (it == m_key_values.end()) ? def : it->second;
1331 // On failure, the destination val is NOT modified
1332 inline bool get_string_if_found(const value &key, dynamic_string &dst, bool quote_strings = false) const;
1333 inline bool get_int_if_found(const value &key, int &val, uint component = 0) const;
1334 inline bool get_int64_if_found(const value &key, int64_t &val, uint component = 0) const;
1335 inline bool get_uint_if_found(const value &key, uint &val, uint component = 0) const;
1336 inline bool get_uint64_if_found(const value &key, uint64_t &val, uint component = 0) const;
1337 inline bool get_bool_if_found(const value &key, bool &val, uint component = 0) const;
1338 inline bool get_double_if_found(const value &key, double &val, uint component = 0) const;
1339 inline bool get_float_if_found(const value &key, float &val, uint component = 0) const;
1340 inline bool get_vec3F_if_found(const value &key, vec3F &val) const;
1341 inline bool get_vec3I_if_found(const value &key, vec3I &val) const;
1342 inline bool get_string_hash_if_found(const value &key, string_hash &val) const;
1344 inline dynamic_string get_string(const value &key, const char *pDef = "", bool quote_strings = false) const
1346 dynamic_string result = pDef;
1347 get_string_if_found(key, result, quote_strings);
1350 inline int get_int(const value &key, int32 def = 0, uint component = 0) const
1353 get_int_if_found(key, result, component);
1356 inline int64_t get_int64(const value &key, int64_t def = 0, uint component = 0) const
1358 int64_t result = def;
1359 get_int64_if_found(key, result, component);
1362 inline uint get_uint(const value &key, uint def = 0, uint component = 0) const
1365 get_uint_if_found(key, result, component);
1368 inline uint64_t get_uint64(const value &key, uint64_t def = 0, uint component = 0) const
1370 uint64_t result = def;
1371 get_uint64_if_found(key, result, component);
1374 inline bool get_bool(const value &key, bool def = false, uint component = 0) const
1377 get_bool_if_found(key, result, component);
1380 inline float get_float(const value &key, float def = 0.0f, uint component = 0) const
1383 get_float_if_found(key, result, component);
1386 inline double get_double(const value &key, double def = 0.0f, uint component = 0) const
1388 double result = def;
1389 get_double_if_found(key, result, component);
1392 inline vec3F get_vec3F(const value &key, const vec3F &def = vec3F(0.0f)) const
1395 get_vec3F_if_found(key, result);
1398 inline vec3I get_vecI(const value &key, const vec3I &def = vec3I(0)) const
1401 get_vec3I_if_found(key, result);
1404 inline string_hash get_string_hash(const value &key, const string_hash &def = string_hash(0U)) const
1406 string_hash result(def);
1407 get_string_hash_if_found(key, result);
1411 inline dynamic_string *get_string_ptr(const value &key) const;
1413 inline const uint8_vec *get_blob(const value &key) const;
1414 inline uint8_vec *get_blob(const value &key);
1416 inline const json_document *get_json_document(const value &key) const;
1417 inline json_document *get_json_document(const value &key);
1419 inline bool does_key_exist(const value &key) const
1421 return find(key) != end();
1424 inline void set(const value &key, const value &val)
1426 iterator it = find(key);
1433 // erase() invalidates any active iterators
1434 inline bool erase(const value &key)
1436 return m_key_values.erase(key);
1439 inline uint get_num_key_values() const
1441 return m_key_values.size();
1444 inline iterator begin()
1446 return m_key_values.begin();
1448 inline const_iterator begin() const
1450 return m_key_values.begin();
1453 inline iterator end()
1455 return m_key_values.end();
1457 inline const_iterator end() const
1459 return m_key_values.end();
1462 inline value_to_value_hash_map &get_map()
1464 return m_key_values;
1466 inline const value_to_value_hash_map &get_map() const
1468 return m_key_values;
1472 value_to_value_hash_map m_key_values;
1475 inline bool key_value_map::get_string_if_found(const value &key, dynamic_string &dst, bool quote_strings) const
1477 const_iterator it = m_key_values.find(key);
1478 if (it == m_key_values.end())
1480 it->second.get_string(dst, quote_strings);
1484 inline bool key_value_map::get_int_if_found(const value &key, int &val, uint component) const
1486 const_iterator it = m_key_values.find(key);
1487 if (it == m_key_values.end())
1489 return it->second.get_int_or_fail(val, component);
1492 inline bool key_value_map::get_int64_if_found(const value &key, int64_t &val, uint component) const
1494 const_iterator it = m_key_values.find(key);
1495 if (it == m_key_values.end())
1497 return it->second.get_int64_or_fail(val, component);
1500 inline bool key_value_map::get_uint_if_found(const value &key, uint &val, uint component) const
1502 const_iterator it = m_key_values.find(key);
1503 if (it == m_key_values.end())
1505 return it->second.get_uint_or_fail(val, component);
1508 inline bool key_value_map::get_uint64_if_found(const value &key, uint64_t &val, uint component) const
1510 const_iterator it = m_key_values.find(key);
1511 if (it == m_key_values.end())
1513 return it->second.get_uint64_or_fail(val, component);
1516 inline bool key_value_map::get_bool_if_found(const value &key, bool &val, uint component) const
1518 const_iterator it = m_key_values.find(key);
1519 if (it == m_key_values.end())
1521 return it->second.get_bool_or_fail(val, component);
1524 inline bool key_value_map::get_double_if_found(const value &key, double &val, uint component) const
1526 const_iterator it = m_key_values.find(key);
1527 if (it == m_key_values.end())
1529 return it->second.get_double_or_fail(val, component);
1532 inline bool key_value_map::get_float_if_found(const value &key, float &val, uint component) const
1534 const_iterator it = m_key_values.find(key);
1535 if (it == m_key_values.end())
1537 return it->second.get_float_or_fail(val, component);
1540 inline bool key_value_map::get_vec3F_if_found(const value &key, vec3F &val) const
1542 const_iterator it = m_key_values.find(key);
1543 if (it == m_key_values.end())
1545 return it->second.get_vec3F_or_fail(val);
1548 inline bool key_value_map::get_vec3I_if_found(const value &key, vec3I &val) const
1550 const_iterator it = m_key_values.find(key);
1551 if (it == m_key_values.end())
1553 return it->second.get_vec3I_or_fail(val);
1556 inline bool key_value_map::get_string_hash_if_found(const value &key, string_hash &val) const
1558 const_iterator it = m_key_values.find(key);
1559 if (it == m_key_values.end())
1561 return it->second.get_string_hash_or_fail(val);
1564 inline dynamic_string *key_value_map::get_string_ptr(const value &key) const
1566 const_iterator it = m_key_values.find(key);
1567 if (it == m_key_values.end())
1569 return it->second.get_string_ptr();
1572 inline const uint8_vec *key_value_map::get_blob(const value &key) const
1574 const_iterator it = m_key_values.find(key);
1575 if (it == m_key_values.end())
1577 return it->second.get_blob();
1580 inline uint8_vec *key_value_map::get_blob(const value &key)
1582 iterator it = m_key_values.find(key);
1583 if (it == m_key_values.end())
1585 return it->second.get_blob();
1588 inline const json_document *key_value_map::get_json_document(const value &key) const
1590 const_iterator it = m_key_values.find(key);
1591 if (it == m_key_values.end())
1593 return it->second.get_json_document();
1596 inline json_document *key_value_map::get_json_document(const value &key)
1598 iterator it = m_key_values.find(key);
1599 if (it == m_key_values.end())
1601 return it->second.get_json_document();