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 **************************************************************************/
27 // File: vogl_value.cpp
28 #include "vogl_core.h"
29 #include "vogl_value.h"
34 const char *g_value_data_type_strings[cDTTotal + 1] =
58 value_data_type string_to_value_data_type(const char *pStr)
60 for (uint i = 0; i < cDTTotal; i++)
61 if (!vogl_stricmp(pStr, g_value_data_type_strings[i]))
62 return static_cast<value_data_type>(i);
66 value &value::operator=(const value &other)
71 change_type(other.m_type);
72 m_user_data = other.m_user_data;
73 m_flags = other.m_flags;
78 m_pStr->set(*other.m_pStr);
81 m_pVec3F->set(*other.m_pVec3F);
84 m_pVec3I->set(*other.m_pVec3I);
87 (*m_pBlob) = (*other.m_pBlob);
90 (*m_pJSONDoc) = (*other.m_pJSONDoc);
93 m_uint64 = other.m_uint64;
99 bool value::operator==(const value &other) const
104 if (m_flags != other.m_flags)
106 if (m_flags & cFlagsHasUserData)
108 if (m_user_data != other.m_user_data)
112 if (m_type != other.m_type)
115 if (m_type == cDTInvalid)
117 else if (is_json_document())
118 return *m_pJSONDoc == *other.m_pJSONDoc;
120 if (get_data_size_in_bytes() != other.get_data_size_in_bytes())
123 return memcmp(get_data_ptr(), other.get_data_ptr(), other.get_data_size_in_bytes()) == 0;
126 bool value::operator<(const value &other) const
131 if (m_flags < other.m_flags)
133 else if (m_flags != other.m_flags)
136 if (m_flags & cFlagsHasUserData)
138 if (m_user_data < other.m_user_data)
140 else if (m_user_data != other.m_user_data)
144 if (m_type < other.m_type)
146 else if (m_type == other.m_type)
153 return m_pStr->compare(*other.m_pStr, true) < 0;
155 return m_bool < other.m_bool;
157 return m_int8 < other.m_int8;
159 return m_uint8 < other.m_uint8;
161 return m_int16 < other.m_int16;
163 return m_uint16 < other.m_uint16;
165 return m_int < other.m_int;
168 return m_uint < other.m_uint;
170 return m_float < other.m_float;
172 return m_double < other.m_double;
174 return m_int64 < other.m_int64;
176 return m_uint64 < other.m_uint64;
178 return m_pPtr < other.m_pPtr;
180 return (*m_pVec3F) < (*other.m_pVec3F);
182 return (*m_pVec3I) < (*other.m_pVec3I);
184 return (*m_pBlob) < (*other.m_pBlob);
187 // This is brain dead slow, but I doubt we'll be using this path much if at all.
189 m_pJSONDoc->binary_serialize(doc);
192 other.m_pJSONDoc->binary_serialize(other_doc);
194 return doc < other_doc;
205 bool value::parse(const char *p)
213 size_t str_len = strlen(p);
215 if (vogl_stricmp(p, "false") == 0)
220 else if (vogl_stricmp(p, "true") == 0)
232 if (str[str.get_len() - 1] == '\"')
234 str.left(str.get_len() - 1);
244 if (p[str_len - 1] == ']')
247 for (i = 1; i < (str_len - 1); i++)
249 if (((static_cast<int>(i) - 1) % 3) == 2)
254 else if (utils::from_hex(p[i]) < 0)
258 if (i == (str_len - 1))
260 size_t size = str_len - 2;
266 size = (size / 3) + 1;
269 if (size > cUINT32_MAX)
275 change_type(cDTBlob);
276 if (!m_pBlob->try_resize(static_cast<uint>(size)))
284 uint8 *pDst = m_pBlob->get_ptr();
286 for (i = 1; i < (str_len - 1); i += 3)
288 int h = utils::from_hex(p[i]);
289 int l = utils::from_hex(p[i + 1]);
291 *pDst++ = ((h << 4) | l);
300 if (strchr(p, ',') != NULL)
302 float fx = 0, fy = 0, fz = 0;
304 if (sscanf_s(p, "%f,%f,%f", &fx, &fy, &fz) == 3)
306 if (sscanf(p, "%f,%f,%f", &fx, &fy, &fz) == 3)
309 bool as_float = true;
310 int ix = 0, iy = 0, iz = 0;
312 if (sscanf_s(p, "%i,%i,%i", &ix, &iy, &iz) == 3)
314 if (sscanf(p, "%i,%i,%i", &ix, &iy, &iz) == 3)
317 if ((ix == fx) && (iy == fy) && (iz == fz))
322 set_vec(vec3F(fx, fy, fz));
324 set_vec(vec3I(ix, iy, iz));
332 if ((p[0] == '{') && (p[str_len - 1] == '}'))
335 if (doc.deserialize(p))
337 set_json_document_take_ownership(doc);
344 bool success = string_ptr_to_uint64(q, m_uint64);
345 if ((success) && (*q == 0))
347 if (m_uint64 <= cUINT8_MAX)
348 set_uint8(static_cast<uint8>(m_uint64));
349 else if (m_uint64 <= cUINT16_MAX)
350 set_uint16(static_cast<uint16>(m_uint64));
351 else if (m_uint64 <= cUINT32_MAX)
352 set_uint(static_cast<uint>(m_uint64));
354 set_uint64(m_uint64);
359 success = string_ptr_to_int64(q, m_int64);
360 if ((success) && (*q == 0))
362 if ((m_int64 >= cINT16_MIN) && (m_int64 <= cINT16_MAX))
363 set_int16(static_cast<int16>(m_int64));
364 else if ((m_int64 >= cINT32_MIN) && (m_int64 <= cINT32_MAX))
365 set_int(static_cast<int>(m_int64));
372 success = string_ptr_to_double(q, m_double);
373 if ((success) && (*q == 0))
375 float value_as_float = static_cast<float>(m_double);
376 if (value_as_float == m_double)
377 set_float(value_as_float);
379 set_double(m_double);
388 // rename quote_strings to parsable? or add another method?
389 // TODO: Get rid of quote_strings and add flags field
390 dynamic_string &value::get_string(dynamic_string &dst, bool quote_strings) const
411 dst = m_bool ? "TRUE" : "FALSE";
414 dst.format("%i", m_int8);
417 dst.format("%u", m_uint8);
420 dst.format("%i", m_int16);
423 dst.format("%u", m_uint16);
426 dst.format("%i", m_int);
430 dst.format("%u", m_uint);
433 dst.format("%" PRIi64, m_int64);
436 dst.format("%" PRIu64, m_uint64);
439 dst.format("0x%" PRIxPTR, reinterpret_cast<uintptr_t>(m_pPtr));
442 dst.format("%1.8f", m_float);
445 dst.format("%1.17f", m_double);
448 dst.format("%1.8f,%1.8f,%1.8f", (*m_pVec3F)[0], (*m_pVec3F)[1], (*m_pVec3F)[2]);
451 dst.format("%i,%i,%i", (*m_pVec3I)[0], (*m_pVec3I)[1], (*m_pVec3I)[2]);
455 uint blob_size = m_pBlob->size();
456 const uint8 *pSrc = m_pBlob->get_ptr();
462 dst.set_len(blob_size * 3 + 2 - 1);
463 dst.set_char(0, '[');
464 dst.set_char(dst.get_len() - 1, ']');
466 for (uint i = 0; i < blob_size; i++)
469 dst.set_char(1 + i * 3 + 0, utils::to_hex(v >> 4));
470 dst.set_char(1 + i * 3 + 1, utils::to_hex(v & 0xF));
471 if (i < (blob_size - 1))
472 dst.set_char(1 + i * 3 + 2, ',');
480 m_pJSONDoc->serialize(dst);
491 bool value::get_int8_or_fail(int8 &val, uint component) const
494 bool success = get_int64_or_fail(i64_val, component);
495 if ((!success) || (i64_val < cINT8_MIN) || (i64_val > cINT8_MAX))
498 val = static_cast<int8>(i64_val);
502 bool value::get_uint8_or_fail(uint8 &val, uint component) const
505 bool success = get_uint64_or_fail(u64_val, component);
506 if ((!success) || (u64_val > cUINT8_MAX))
509 val = static_cast<uint8>(u64_val);
513 bool value::get_int16_or_fail(int16 &val, uint component) const
516 bool success = get_int64_or_fail(i64_val, component);
517 if ((!success) || (i64_val < cINT16_MIN) || (i64_val > cINT16_MAX))
520 val = static_cast<int16>(i64_val);
524 bool value::get_uint16_or_fail(uint16 &val, uint component) const
527 bool success = get_uint64_or_fail(u64_val, component);
528 if ((!success) || (u64_val > cUINT16_MAX))
531 val = static_cast<uint16>(u64_val);
535 bool value::get_int_or_fail(int &val, uint component) const
538 bool success = get_int64_or_fail(i64_val, component);
539 if ((!success) || (i64_val < cINT32_MIN) || (i64_val > cINT32_MAX))
542 val = static_cast<int>(i64_val);
546 bool value::get_int64_or_fail(int64_t &val, uint component) const
556 const char *p = m_pStr->get_ptr();
557 return string_ptr_to_int64(p, val);
602 if (m_uint64 > static_cast<uint64_t>(cINT64_MAX))
604 val = static_cast<int64_t>(m_uint64);
609 if ((m_float < cINT64_MIN) || (m_float > cINT64_MAX))
611 val = static_cast<int64_t>(m_float);
616 if ((m_double < cINT64_MIN) || (m_double > cINT64_MAX))
618 val = static_cast<int64_t>(m_double);
625 if (((*m_pVec3F)[component] < cINT64_MIN) || ((*m_pVec3F)[component] > cINT64_MAX))
627 val = static_cast<int64_t>((*m_pVec3F)[component]);
634 val = (*m_pVec3I)[component];
639 if (component >= m_pBlob->size())
641 val = m_pBlob->at(component);
646 val = reinterpret_cast<int64_t>(m_pPtr);
651 if (m_pJSONDoc->is_node())
653 val = m_pJSONDoc->as_int64();
665 bool value::get_uint_or_fail(uint &val, uint component) const
668 bool success = get_uint64_or_fail(u64_val, component);
669 if (u64_val > cUINT32_MAX)
671 val = static_cast<uint>(u64_val);
675 bool value::get_uint64_or_fail(uint64_t &val, uint component) const
685 const char *p = m_pStr->get_ptr();
686 return string_ptr_to_uint64(p, val);
709 val = static_cast<uint64_t>(m_int16);
721 val = static_cast<uint64_t>(m_int);
734 val = static_cast<uint64_t>(m_int64);
739 val = static_cast<uint64_t>(m_uint64);
744 if ((m_float < 0) || (m_float > cUINT64_MAX))
746 val = static_cast<uint64_t>(m_float);
751 if ((m_double < 0) || (m_double > cUINT64_MAX))
753 val = static_cast<uint64_t>(m_double);
760 if (((*m_pVec3F)[component] < 0) || ((*m_pVec3F)[component] > cUINT64_MAX))
764 val = static_cast<uint64_t>((*m_pVec3F)[component]);
771 if ((*m_pVec3I)[component] < 0)
775 val = static_cast<uint64_t>((*m_pVec3I)[component]);
780 if (component >= m_pBlob->size())
782 val = m_pBlob->at(component);
787 val = reinterpret_cast<uint64_t>(m_pPtr);
792 if (m_pJSONDoc->is_node())
794 val = m_pJSONDoc->as_uint64();
804 bool value::get_bool_or_fail(bool &val, uint component) const
814 const char *p = m_pStr->get_ptr();
815 return string_ptr_to_bool(p, val);
825 val = (m_uint8 != 0);
831 val = (m_uint16 != 0);
844 val = (m_uint64 != 0);
849 val = (m_float != 0);
854 val = (m_double != 0);
861 val = ((*m_pVec3F)[component] != 0);
868 val = ((*m_pVec3I)[component] != 0);
873 if (component >= m_pBlob->size())
875 val = m_pBlob->at(component) != 0;
880 val = (m_pPtr != NULL);
885 if (m_pJSONDoc->is_node())
887 val = m_pJSONDoc->as_bool();
898 bool value::get_double_or_fail(double &val, uint component) const
908 const char *p = m_pStr->get_ptr();
909 return string_ptr_to_double(p, val);
918 val = static_cast<double>(m_int8);
923 val = static_cast<double>(m_uint8);
928 val = static_cast<double>(m_int16);
933 val = static_cast<double>(m_uint16);
938 val = static_cast<double>(m_int);
944 val = static_cast<double>(m_uint);
949 val = static_cast<double>(m_int64);
954 val = static_cast<double>(m_uint64);
971 val = (*m_pVec3F)[component];
978 val = static_cast<double>((*m_pVec3I)[component]);
983 if (component >= m_pBlob->size())
985 val = static_cast<double>(m_pBlob->at(component));
995 if (m_pJSONDoc->is_node())
997 val = m_pJSONDoc->as_double();
1007 bool value::get_float_or_fail(float &val, uint component) const
1010 bool success = get_double_or_fail(dbl_val, component);
1012 if ((dbl_val < -FLT_MAX) || (dbl_val > FLT_MAX))
1018 val = static_cast<float>(dbl_val);
1022 bool value::get_vec3F_or_fail(vec3F &val) const
1032 const char *p = m_pStr->get_ptr();
1033 float x = 0, y = 0, z = 0;
1035 if (sscanf_s(p, "%f,%f,%f", &x, &y, &z) == 3)
1037 if (sscanf(p, "%f,%f,%f", &x, &y, &z) == 3)
1055 val.set(static_cast<float>(m_uint8));
1060 val.set(static_cast<float>(m_int16));
1065 val.set(static_cast<float>(m_uint16));
1070 val.set(static_cast<float>(m_int));
1076 val.set(static_cast<float>(m_uint));
1081 val.set(static_cast<float>(m_int64));
1086 val.set(static_cast<float>(m_uint64));
1096 val.set(static_cast<float>(m_double));
1106 val.set(static_cast<float>((*m_pVec3I)[0]), static_cast<float>((*m_pVec3I)[1]), static_cast<float>((*m_pVec3I)[2]));
1111 if (!m_pBlob->size())
1113 val.set(static_cast<float>(m_pBlob->at(0)));
1123 if (m_pJSONDoc->is_node())
1125 val.set(m_pJSONDoc->as_double());
1135 bool value::get_vec3I_or_fail(vec3I &val) const
1145 const char *p = m_pStr->get_ptr();
1146 float x = 0, y = 0, z = 0;
1148 if (sscanf_s(p, "%f,%f,%f", &x, &y, &z) == 3)
1150 if (sscanf(p, "%f,%f,%f", &x, &y, &z) == 3)
1153 if ((x < INT_MIN) || (x > INT_MAX) || (y < INT_MIN) || (y > INT_MAX) || (z < INT_MIN) || (z > INT_MAX))
1155 val.set((int)x, (int)y, (int)z);
1191 if (m_uint > static_cast<uint>(cINT32_MAX))
1198 if ((m_int64 < cINT32_MIN) || (m_int64 > cINT32_MAX))
1200 val.set(static_cast<int>(m_int64));
1205 if (m_uint64 > static_cast<uint64_t>(cINT32_MAX))
1207 val.set(static_cast<int>(m_uint64));
1212 val.set(static_cast<int>(m_float));
1217 val.set(static_cast<int>(m_double));
1222 val.set((int)(*m_pVec3F)[0], (int)(*m_pVec3F)[1], (int)(*m_pVec3F)[2]);
1232 if (!m_pBlob->size())
1234 val.set(m_pBlob->at(0));
1244 if (m_pJSONDoc->is_node())
1246 val.set(m_pJSONDoc->as_int());
1256 bool value::get_string_hash_or_fail(string_hash &hash) const
1258 if (m_type == cDTString)
1261 hash.set(m_pStr->get_ptr());
1264 else if (m_type == cDTStringHash)
1266 hash = get_string_hash_ref();
1269 else if (m_type == cDTBlob)
1271 // Just hash the blob and hope for the best
1272 hash.set(reinterpret_cast<const char *>(m_pBlob->get_ptr()), m_pBlob->size());
1275 else if (m_type == cDTJSONDoc)
1277 // This is slow but it's better than nothing.
1279 m_pJSONDoc->binary_serialize(data);
1280 hash.set(reinterpret_cast<const char *>(data.get_ptr()), data.size());
1284 // Convert to uint32 and hope for the best
1286 bool success = get_uint_or_fail(val, 0);
1294 uint value::get_serialize_size(bool serialize_user_data) const
1296 uint size = sizeof(uint8);
1298 if (serialize_user_data)
1299 size += sizeof(m_user_data);
1305 size += m_pStr->get_serialize_size();
1310 size += sizeof(m_bool);
1315 size += sizeof(m_uint8);
1321 size += sizeof(m_uint16);
1329 size += sizeof(m_uint);
1337 size += sizeof(m_uint64);
1342 size += sizeof(vec3F);
1347 size += sizeof(vec3I);
1352 size += sizeof(uint) + m_pBlob->size();
1357 // TODO: This binary serializes the sucker and tosses the data to get the serialization size.
1359 m_pJSONDoc->binary_serialize(data);
1360 size += sizeof(uint) + data.size();
1371 int value::serialize(void *pBuf, uint buf_size, bool little_endian, bool serialize_user_data) const
1373 uint buf_left = buf_size;
1375 uint8 t = (uint8)m_type;
1376 if (!utils::write_obj(t, pBuf, buf_left, little_endian))
1379 if (serialize_user_data)
1381 if (!utils::write_obj(m_user_data, pBuf, buf_left, little_endian))
1389 int bytes_written = m_pStr->serialize(pBuf, buf_left, little_endian);
1390 if (bytes_written < 0)
1393 pBuf = static_cast<uint8 *>(pBuf) + bytes_written;
1394 buf_left -= bytes_written;
1400 if (!utils::write_obj(m_bool, pBuf, buf_left, little_endian))
1406 if (!utils::write_obj(m_uint8, pBuf, buf_left, little_endian))
1413 if (!utils::write_obj(m_uint16, pBuf, buf_left, little_endian))
1422 if (!utils::write_obj(m_uint, pBuf, buf_left, little_endian))
1431 if (!utils::write_obj(m_uint64, pBuf, buf_left, little_endian))
1437 for (uint i = 0; i < 3; i++)
1438 if (!utils::write_obj((*m_pVec3F)[i], pBuf, buf_left, little_endian))
1444 for (uint i = 0; i < 3; i++)
1445 if (!utils::write_obj((*m_pVec3I)[i], pBuf, buf_left, little_endian))
1451 uint size = m_pBlob->size();
1453 if (buf_left < (size + sizeof(uint)))
1456 if (!utils::write_obj(size, pBuf, buf_left, little_endian))
1461 memcpy(pBuf, m_pBlob->get_ptr(), size);
1462 pBuf = static_cast<uint8 *>(pBuf) + size;
1471 m_pJSONDoc->binary_serialize(data);
1473 uint size = data.size();
1475 if (buf_left < (size + sizeof(uint)))
1478 if (!utils::write_obj(size, pBuf, buf_left, little_endian))
1483 memcpy(pBuf, data.get_ptr(), size);
1484 pBuf = static_cast<uint8 *>(pBuf) + size;
1495 return buf_size - buf_left;
1498 int value::deserialize(const void *pBuf, uint buf_size, bool little_endian, bool serialize_user_data)
1500 uint buf_left = buf_size;
1503 if (!utils::read_obj(t, pBuf, buf_left, little_endian))
1509 if (serialize_user_data)
1511 if (!utils::read_obj(m_user_data, pBuf, buf_left, little_endian))
1513 m_flags |= cFlagsHasUserData;
1517 m_flags &= ~cFlagsHasUserData;
1524 change_type(cDTString);
1526 int bytes_read = m_pStr->deserialize(pBuf, buf_left, little_endian);
1530 pBuf = static_cast<const uint8 *>(pBuf) + bytes_read;
1531 buf_left -= bytes_read;
1537 change_type(static_cast<value_data_type>(t));
1539 if (!utils::read_obj(m_bool, pBuf, buf_left, little_endian))
1545 change_type(static_cast<value_data_type>(t));
1547 if (!utils::read_obj(m_uint8, pBuf, buf_left, little_endian))
1554 change_type(static_cast<value_data_type>(t));
1556 if (!utils::read_obj(m_uint16, pBuf, buf_left, little_endian))
1565 change_type(static_cast<value_data_type>(t));
1567 if (!utils::read_obj(m_uint, pBuf, buf_left, little_endian))
1576 change_type(static_cast<value_data_type>(t));
1578 if (!utils::read_obj(m_uint64, pBuf, buf_left, little_endian))
1584 change_type(cDTVec3F);
1586 for (uint i = 0; i < 3; i++)
1587 if (!utils::read_obj((*m_pVec3F)[i], pBuf, buf_left, little_endian))
1593 change_type(cDTVec3I);
1595 for (uint i = 0; i < 3; i++)
1596 if (!utils::read_obj((*m_pVec3I)[i], pBuf, buf_left, little_endian))
1602 change_type(cDTBlob);
1605 if (!utils::read_obj(size, pBuf, buf_left, little_endian))
1608 if (buf_left < size)
1611 if (!m_pBlob->try_resize(size))
1616 memcpy(m_pBlob->get_ptr(), pBuf, size);
1618 pBuf = static_cast<const uint8 *>(pBuf) + size;
1626 change_type(cDTJSONDoc);
1629 if (!utils::read_obj(size, pBuf, buf_left, little_endian))
1632 if (buf_left < size)
1635 if (!m_pJSONDoc->binary_deserialize(static_cast<const uint8 *>(pBuf), size))
1638 pBuf = static_cast<const uint8 *>(pBuf) + size;
1649 return buf_size - buf_left;