|
|
@@ -1,799 +0,0 @@
|
|
|
-/*
|
|
|
- * Copyright (c) 2012-2018 Daniele Bartolini and individual contributors.
|
|
|
- * License: https://github.com/dbartolini/crown/blob/master/LICENSE
|
|
|
- */
|
|
|
-
|
|
|
-#include "core/strings/string.h"
|
|
|
-#include "core/types.h"
|
|
|
-#include "core/guid.h"
|
|
|
-#include "core/memory/allocator.h"
|
|
|
-#include "core/math/types.h"
|
|
|
-#include "core/memory/memory.h"
|
|
|
-#include "core/containers/hash_map.h"
|
|
|
-#include "core/strings/string_stream.h"
|
|
|
-#include "core/memory/temp_allocator.h"
|
|
|
-#include "core/strings/dynamic_string.h"
|
|
|
-#include "core/math/quaternion.h"
|
|
|
-#include "core/math/vector3.h"
|
|
|
-#include "core/json/types.h"
|
|
|
-#include "core/json/sjson.h"
|
|
|
-#include "core/json/json_object.h"
|
|
|
-#include "core/containers/vector.h"
|
|
|
-#include "core/filesystem/filesystem_disk.h"
|
|
|
-#include "core/filesystem/file.h"
|
|
|
-#include "core/containers/hash_set.h"
|
|
|
-
|
|
|
-namespace crown
|
|
|
-{
|
|
|
- struct ActionType
|
|
|
- {
|
|
|
- enum Enum
|
|
|
- {
|
|
|
- CREATE,
|
|
|
- DESTROY,
|
|
|
- SET_PROPERTY_NULL,
|
|
|
- SET_PROPERTY_BOOL,
|
|
|
- SET_PROPERTY_DOUBLE,
|
|
|
- SET_PROPERTY_STRING,
|
|
|
- SET_PROPERTY_GUID,
|
|
|
- SET_PROPERTY_VECTOR3,
|
|
|
- SET_PROPERTY_QUATERNION,
|
|
|
- ADD_TO_SET,
|
|
|
- REMOVE_FROM_SET,
|
|
|
- RESTORE_POINT
|
|
|
- };
|
|
|
- };
|
|
|
-
|
|
|
- struct ValueType
|
|
|
- {
|
|
|
- enum Enum
|
|
|
- {
|
|
|
- NIL,
|
|
|
- BOOL,
|
|
|
- DOUBLE,
|
|
|
- STRING,
|
|
|
- GUID,
|
|
|
- VECTOR3,
|
|
|
- QUATERNION,
|
|
|
- SET,
|
|
|
- };
|
|
|
- };
|
|
|
-
|
|
|
- struct Ledger
|
|
|
- {
|
|
|
- Allocator* _allocator;
|
|
|
- u8* _data;
|
|
|
- u32 _read;
|
|
|
-
|
|
|
- Ledger(Allocator& a)
|
|
|
- : _allocator(&a)
|
|
|
- , _data(NULL)
|
|
|
- , _read(0)
|
|
|
- {
|
|
|
- _data = (u8*)a.allocate(1024*1024);
|
|
|
- _read = 0;
|
|
|
- }
|
|
|
-
|
|
|
- ~Ledger()
|
|
|
- {
|
|
|
- _allocator->deallocate(_data);
|
|
|
- }
|
|
|
-
|
|
|
- void clear()
|
|
|
- {
|
|
|
- _read = 0;
|
|
|
- }
|
|
|
-
|
|
|
- u32 size()
|
|
|
- {
|
|
|
- return _read;
|
|
|
- }
|
|
|
-
|
|
|
- void write(const void* data, u32 size)
|
|
|
- {
|
|
|
- memcpy(&_data[_read], data, size);
|
|
|
- _read += size;
|
|
|
- }
|
|
|
-
|
|
|
- template <typename T>
|
|
|
- void write(const T& data)
|
|
|
- {
|
|
|
- write(&data, sizeof(T));
|
|
|
- }
|
|
|
-
|
|
|
- void read(void* data, u32 size)
|
|
|
- {
|
|
|
- _read -= size;
|
|
|
- memcpy(data, &_data[_read], size);
|
|
|
- }
|
|
|
-
|
|
|
- template <typename T>
|
|
|
- void read(T& data)
|
|
|
- {
|
|
|
- read(&data, sizeof(T));
|
|
|
- }
|
|
|
-
|
|
|
- ValueType::Enum read_value_type()
|
|
|
- {
|
|
|
- _read -= (u32)sizeof(u32);
|
|
|
- u32 a = *(u32*)(&_data[_read]);
|
|
|
- return (ValueType::Enum)a;
|
|
|
- }
|
|
|
-
|
|
|
- void write_create_action(Guid id)
|
|
|
- {
|
|
|
- write(id);
|
|
|
- write(ActionType::CREATE);
|
|
|
- }
|
|
|
-
|
|
|
- void write_destroy_action(Guid id)
|
|
|
- {
|
|
|
- write(id);
|
|
|
- write(ActionType::DESTROY);
|
|
|
- }
|
|
|
-
|
|
|
- void write_set_property_null(Guid id, const char* key)
|
|
|
- {
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::SET_PROPERTY_NULL);
|
|
|
- }
|
|
|
-
|
|
|
- void write_set_property_bool(Guid id, const char* key, bool value)
|
|
|
- {
|
|
|
- write(value);
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::SET_PROPERTY_BOOL);
|
|
|
- }
|
|
|
-
|
|
|
- void write_set_property_double(Guid id, const char* key, double value)
|
|
|
- {
|
|
|
- write(value);
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::SET_PROPERTY_DOUBLE);
|
|
|
- }
|
|
|
-
|
|
|
- void write_set_property_string(Guid id, const char* key, const char* value)
|
|
|
- {
|
|
|
- const u32 value_len = strlen32(value) + 1;
|
|
|
- write(value, value_len);
|
|
|
- write(value_len);
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::SET_PROPERTY_STRING);
|
|
|
- }
|
|
|
-
|
|
|
- void write_set_property_guid(Guid id, const char* key, const Guid& value)
|
|
|
- {
|
|
|
- write(value);
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::SET_PROPERTY_GUID);
|
|
|
- }
|
|
|
-
|
|
|
- void write_set_property_vector3(Guid id, const char* key, const Vector3& value)
|
|
|
- {
|
|
|
- write(value);
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::SET_PROPERTY_VECTOR3);
|
|
|
- }
|
|
|
-
|
|
|
- void write_set_property_quaternion(Guid id, const char* key, const Quaternion& value)
|
|
|
- {
|
|
|
- write(value);
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::SET_PROPERTY_QUATERNION);
|
|
|
- }
|
|
|
-
|
|
|
- void write_add_to_set_action(Guid id, const char* key, Guid item_id)
|
|
|
- {
|
|
|
- write(item_id);
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::ADD_TO_SET);
|
|
|
- }
|
|
|
-
|
|
|
- void write_remove_from_set_action(Guid id, const char* key, Guid item_id)
|
|
|
- {
|
|
|
- write(item_id);
|
|
|
- const u32 key_len = strlen32(key) + 1;
|
|
|
- write(key, key_len);
|
|
|
- write(key_len);
|
|
|
- write(id);
|
|
|
- write(ActionType::REMOVE_FROM_SET);
|
|
|
- }
|
|
|
-
|
|
|
- void write_restore_point(int id, u32 size, Guid* begin, Guid* end)
|
|
|
- {
|
|
|
- const u32 num_guids = end - begin;
|
|
|
- for (u32 i = 0; i < num_guids; ++i)
|
|
|
- write(begin[i]);
|
|
|
- write(num_guids);
|
|
|
- write(size);
|
|
|
- write(id);
|
|
|
- write(ActionType::RESTORE_POINT);
|
|
|
- }
|
|
|
-
|
|
|
- u32 peek_type()
|
|
|
- {
|
|
|
- return *(u32*)(&_data[_read - (u32)sizeof(u32)]);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- struct Value
|
|
|
- {
|
|
|
- Value()
|
|
|
- : allocator(NULL)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- ~Value()
|
|
|
- {
|
|
|
- if (allocator != NULL)
|
|
|
- allocator->deallocate(value_string);
|
|
|
- }
|
|
|
-
|
|
|
- Value(const Value& other)
|
|
|
- {
|
|
|
- if (type == ValueType::STRING)
|
|
|
- allocator->deallocate(value_string);
|
|
|
-
|
|
|
- type = other.type;
|
|
|
-
|
|
|
- switch (type)
|
|
|
- {
|
|
|
- case ValueType::NIL:
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::BOOL:
|
|
|
- value_bool = other.value_bool;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::DOUBLE:
|
|
|
- value_double = other.value_double;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::STRING:
|
|
|
- allocator = other.allocator;
|
|
|
- value_string = (char*)allocator->allocate(strlen32(other.value_string) + 1);
|
|
|
- strcpy(value_string, other.value_string);
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::GUID:
|
|
|
- value_guid = other.value_guid;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::VECTOR3:
|
|
|
- value_vector3 = other.value_vector3;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::QUATERNION:
|
|
|
- value_quaternion = other.value_quaternion;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Value& operator=(const Value& other)
|
|
|
- {
|
|
|
- if (type == ValueType::STRING)
|
|
|
- allocator->deallocate(value_string);
|
|
|
-
|
|
|
- type = other.type;
|
|
|
-
|
|
|
- switch (type)
|
|
|
- {
|
|
|
- case ValueType::NIL:
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::BOOL:
|
|
|
- value_bool = other.value_bool;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::DOUBLE:
|
|
|
- value_double = other.value_double;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::STRING:
|
|
|
- allocator = other.allocator;
|
|
|
- value_string = (char*)allocator->allocate(strlen32(other.value_string) + 1);
|
|
|
- strcpy(value_string, other.value_string);
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::GUID:
|
|
|
- value_guid = other.value_guid;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::VECTOR3:
|
|
|
- value_vector3 = other.value_vector3;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::QUATERNION:
|
|
|
- value_quaternion = other.value_quaternion;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- Allocator* allocator;
|
|
|
- ValueType::Enum type;
|
|
|
- union
|
|
|
- {
|
|
|
- bool value_bool;
|
|
|
- f64 value_double;
|
|
|
- char* value_string;
|
|
|
- Guid value_guid;
|
|
|
- Vector3 value_vector3;
|
|
|
- Quaternion value_quaternion;
|
|
|
- };
|
|
|
- };
|
|
|
-
|
|
|
- struct Object
|
|
|
- {
|
|
|
- ALLOCATOR_AWARE;
|
|
|
-
|
|
|
- HashMap<const char*, Value> _data;
|
|
|
-
|
|
|
- Object(Allocator& a)
|
|
|
- : _data(a)
|
|
|
- {
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- template<>
|
|
|
- struct hash<Guid>
|
|
|
- {
|
|
|
- u32 operator()(const Guid val) const
|
|
|
- {
|
|
|
- return val.data1 ^ val.data2 ^ val.data3 ^ val.data4;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- template<>
|
|
|
- struct hash<const char*>
|
|
|
- {
|
|
|
- u32 operator()(const char* val) const
|
|
|
- {
|
|
|
- return murmur32(val, strlen32(val), 0);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- struct Database
|
|
|
- {
|
|
|
- Allocator* _allocator;
|
|
|
- HashMap<Guid, Object*> _objects;
|
|
|
- const HashMap<StringId32, const char*>& _key_database;
|
|
|
-
|
|
|
- Database(Allocator& a, const HashMap<StringId32, const char*>& key_database)
|
|
|
- : _allocator(&a)
|
|
|
- , _objects(a)
|
|
|
- , _key_database(key_database)
|
|
|
- {
|
|
|
- // This is a special field which stores all objects
|
|
|
- hash_map::set(_objects, GUID_ZERO, CE_NEW(*_allocator, Object)(*_allocator));
|
|
|
- }
|
|
|
-
|
|
|
- ~Database()
|
|
|
- {
|
|
|
- auto cur = hash_map::begin(_objects);
|
|
|
- auto end = hash_map::end(_objects);
|
|
|
- for (; cur != end; ++cur)
|
|
|
- {
|
|
|
- HASH_MAP_SKIP_HOLE(_objects, cur);
|
|
|
-
|
|
|
- CE_DELETE(*_allocator, cur->second);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void create_internal(Guid id)
|
|
|
- {
|
|
|
- Object* obj = CE_NEW(*_allocator, Object)(*_allocator);
|
|
|
- hash_map::set(_objects, id, obj);
|
|
|
- }
|
|
|
-
|
|
|
- void destroy_internal(Guid id)
|
|
|
- {
|
|
|
- Object* obj = hash_map::get(_objects, id, (Object*)NULL);
|
|
|
- CE_DELETE(*_allocator, obj);
|
|
|
- }
|
|
|
-
|
|
|
- void set_property_bool_internal(Guid guid, const char* key, bool value)
|
|
|
- {
|
|
|
- Object* obj = hash_map::get(_objects, guid, (Object*)NULL);
|
|
|
-
|
|
|
- Value val;
|
|
|
- val.type = ValueType::BOOL;
|
|
|
- val.value_bool = value;
|
|
|
- hash_map::set(obj->_data, key, val);
|
|
|
- }
|
|
|
-
|
|
|
- void set_property_double_internal(Guid guid, const char* key, f64 value)
|
|
|
- {
|
|
|
- Object* obj = hash_map::get(_objects, guid, (Object*)NULL);
|
|
|
-
|
|
|
- Value val;
|
|
|
- val.type = ValueType::DOUBLE;
|
|
|
- val.value_double = value;
|
|
|
- hash_map::set(obj->_data, key, val);
|
|
|
- }
|
|
|
-
|
|
|
- void set_property_string_internal(Guid guid, const char* key, const char* value)
|
|
|
- {
|
|
|
- Object* obj = hash_map::get(_objects, guid, (Object*)NULL);
|
|
|
-
|
|
|
- Value val;
|
|
|
- val.type = ValueType::STRING;
|
|
|
- val.allocator = &default_allocator();
|
|
|
- val.value_string = (char*)val.allocator->allocate(strlen32(value) + 1);
|
|
|
- strcpy(val.value_string, value);
|
|
|
- hash_map::set(obj->_data, key, val);
|
|
|
- }
|
|
|
-
|
|
|
- void set_property_guid_internal(Guid guid, const char* key, Guid value)
|
|
|
- {
|
|
|
- Object* obj = hash_map::get(_objects, guid, (Object*)NULL);
|
|
|
-
|
|
|
- Value val;
|
|
|
- val.type = ValueType::GUID;
|
|
|
- val.value_guid = value;
|
|
|
- hash_map::set(obj->_data, key, val);
|
|
|
- }
|
|
|
-
|
|
|
- void set_property_vector3_internal(Guid guid, const char* key, Vector3 value)
|
|
|
- {
|
|
|
- Object* obj = hash_map::get(_objects, guid, (Object*)NULL);
|
|
|
-
|
|
|
- Value val;
|
|
|
- val.type = ValueType::VECTOR3;
|
|
|
- val.value_vector3 = value;
|
|
|
- hash_map::set(obj->_data, key, val);
|
|
|
- }
|
|
|
-
|
|
|
- void set_property_quaternion_internal(Guid guid, const char* key, Quaternion value)
|
|
|
- {
|
|
|
- Object* obj = hash_map::get(_objects, guid, (Object*)NULL);
|
|
|
-
|
|
|
- Value val;
|
|
|
- val.type = ValueType::QUATERNION;
|
|
|
- val.value_quaternion = value;
|
|
|
- hash_map::set(obj->_data, key, val);
|
|
|
- }
|
|
|
-
|
|
|
- Vector3 get_property_vector3(Guid guid, const char* key)
|
|
|
- {
|
|
|
- Object* obj = hash_map::get(_objects, guid, (Object*)NULL);
|
|
|
-
|
|
|
- Value val;
|
|
|
- val.type = ValueType::NIL;
|
|
|
- val = hash_map::get(obj->_data, key, val);
|
|
|
-
|
|
|
- return val.value_vector3;
|
|
|
- }
|
|
|
-
|
|
|
- void load(const char* json)
|
|
|
- {
|
|
|
- TempAllocator4096 ta;
|
|
|
- JsonObject object(ta);
|
|
|
- sjson::parse(json, object);
|
|
|
- decode(object);
|
|
|
- }
|
|
|
-
|
|
|
- void decode(JsonObject& object)
|
|
|
- {
|
|
|
- // FIXME: reset();
|
|
|
- decode_object(GUID_ZERO, "", object);
|
|
|
- }
|
|
|
-
|
|
|
- void decode_object(Guid id, const char* key, JsonObject& object)
|
|
|
- {
|
|
|
- auto cur = json_object::begin(object);
|
|
|
- auto end = json_object::end(object);
|
|
|
- for (; cur != end; ++cur)
|
|
|
- {
|
|
|
- JSON_OBJECT_SKIP_HOLE(object, cur);
|
|
|
-
|
|
|
- if (cur->first == "id")
|
|
|
- continue;
|
|
|
-
|
|
|
- if (cur->first._data[0] == '#')
|
|
|
- continue;
|
|
|
-
|
|
|
- const char* key_null = NULL;
|
|
|
- const char* key = hash_map::get(_key_database, StringId32(cur->first.data(), cur->first.length()), key_null);
|
|
|
- if (key == key_null)
|
|
|
- {
|
|
|
- printf("KEY NOT IN DATABASE: %.*s\n", cur->first.length(), cur->first.data());
|
|
|
- return;
|
|
|
- }
|
|
|
- const char* value = cur->second;
|
|
|
-
|
|
|
- // Decode value
|
|
|
- switch (sjson::type(cur->second))
|
|
|
- {
|
|
|
- case JsonValueType::NIL:
|
|
|
- break;
|
|
|
-
|
|
|
- case JsonValueType::BOOL:
|
|
|
- set_property_bool_internal(id, key, sjson::parse_bool(value));
|
|
|
- break;
|
|
|
-
|
|
|
- case JsonValueType::NUMBER:
|
|
|
- set_property_double_internal(id, key, sjson::parse_float(value));
|
|
|
- break;
|
|
|
-
|
|
|
- case JsonValueType::STRING:
|
|
|
- {
|
|
|
- TempAllocator256 ta;
|
|
|
- DynamicString str(ta);
|
|
|
- sjson::parse_string(value, str);
|
|
|
- set_property_string_internal(id, key, str.c_str());
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case JsonValueType::ARRAY:
|
|
|
- {
|
|
|
- TempAllocator256 ta;
|
|
|
- JsonArray arr(ta);
|
|
|
- sjson::parse_array(value, arr);
|
|
|
-
|
|
|
- if (array::size(arr) == 3 && sjson::type(arr[0]) == JsonValueType::NUMBER)
|
|
|
- {
|
|
|
- set_property_vector3_internal(id, key, sjson::parse_vector3(value));
|
|
|
- }
|
|
|
- else if (array::size(arr) == 4 && sjson::type(arr[0]) == JsonValueType::NUMBER)
|
|
|
- set_property_quaternion_internal(id, key, sjson::parse_quaternion(value));
|
|
|
- else
|
|
|
- decode_set(id, key, arr);
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case JsonValueType::OBJECT:
|
|
|
- {
|
|
|
- const char* k = key; // FIXME, define k
|
|
|
- TempAllocator256 ta;
|
|
|
- JsonObject sub_object(ta);
|
|
|
- sjson::parse(cur->second, sub_object);
|
|
|
- decode_object(id, k, sub_object);
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- CE_FATAL("Unknown key type");
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void decode_set(Guid id, const char* key, const JsonArray& json)
|
|
|
- {
|
|
|
- // Set should be created even if it is empty.
|
|
|
- create_empty_set(id, key);
|
|
|
-
|
|
|
- for (u32 i = 0; i < array::size(json); ++i)
|
|
|
- {
|
|
|
- TempAllocator128 ta;
|
|
|
- JsonObject obj(ta);
|
|
|
- sjson::parse_object(json[i], obj);
|
|
|
- Guid item_id = sjson::parse_guid(obj["id"]);
|
|
|
- create_internal(item_id);
|
|
|
- decode_object(item_id, "", obj);
|
|
|
- // add_to_set_internal(id, key, item_id);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void create_empty_set(Guid id, const char* key)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- void dump()
|
|
|
- {
|
|
|
- TempAllocator4096 ta;
|
|
|
- StringStream ss(ta);
|
|
|
-
|
|
|
- auto cur = hash_map::begin(_objects);
|
|
|
- auto end = hash_map::end(_objects);
|
|
|
- for (; cur != end; ++cur)
|
|
|
- {
|
|
|
- HASH_MAP_SKIP_HOLE(_objects, cur);
|
|
|
-
|
|
|
- {
|
|
|
- ss << "{\n";
|
|
|
- ss << " id = ";
|
|
|
- {
|
|
|
- TempAllocator128 ta;
|
|
|
- DynamicString str(ta);
|
|
|
- str.from_guid(cur->first);
|
|
|
- ss << '"' << str.c_str() << '"';
|
|
|
- }
|
|
|
- ss << "\n";
|
|
|
- encode_object(ss, cur->second);
|
|
|
- ss << "}\n";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- printf("%s\n", string_stream::c_str(ss));
|
|
|
- }
|
|
|
-
|
|
|
- void encode_object(StringStream& ss, Object* object)
|
|
|
- {
|
|
|
- auto cur = hash_map::begin(object->_data);
|
|
|
- auto end = hash_map::end(object->_data);
|
|
|
- for (; cur != end; ++cur)
|
|
|
- {
|
|
|
- HASH_MAP_SKIP_HOLE(object->_data, cur);
|
|
|
-
|
|
|
- ss << " ";
|
|
|
- ss << cur->first;
|
|
|
- ss << " = ";
|
|
|
- encode_value(ss, cur->second);
|
|
|
- ss << "\n";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void encode_value(StringStream& ss, const Value& value)
|
|
|
- {
|
|
|
- switch (value.type)
|
|
|
- {
|
|
|
- case ValueType::NIL:
|
|
|
- ss << "null";
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::BOOL:
|
|
|
- ss << (value.value_bool ? "true" : "false");
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::DOUBLE:
|
|
|
- ss << value.value_double;
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::STRING:
|
|
|
- ss << '"' << value.value_string << '"';
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::GUID:
|
|
|
- {
|
|
|
- TempAllocator128 ta;
|
|
|
- DynamicString str(ta);
|
|
|
- str.from_guid(value.value_guid);
|
|
|
- ss << '"' << str.c_str() << '"';
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::VECTOR3:
|
|
|
- ss << "[ " << value.value_vector3.x << " " << value.value_vector3.y << " " << value.value_vector3.z << " ]";
|
|
|
- break;
|
|
|
-
|
|
|
- case ValueType::QUATERNION:
|
|
|
- ss << "[ " << value.value_quaternion.x << " " << value.value_quaternion.y << " " << value.value_quaternion.z << " " << value.value_quaternion.w << " ]";
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- template<>
|
|
|
- struct equal_to<const char*>
|
|
|
- {
|
|
|
- bool operator()(const char* a, const char* b) const
|
|
|
- {
|
|
|
- return strcmp(a, b) == 0;
|
|
|
- };
|
|
|
- };
|
|
|
-
|
|
|
- void test_database()
|
|
|
- {
|
|
|
- memory_globals::init();
|
|
|
- {
|
|
|
-#define DATABASE_KEY_SOUNDS "sounds"
|
|
|
-#define DATABASE_KEY_CLASS "class"
|
|
|
-#define DATABASE_KEY_COLLISION_FILTER "collision_filter"
|
|
|
-#define DATABASE_KEY_COMPONENTS "components"
|
|
|
-#define DATABASE_KEY_DATA "data"
|
|
|
-#define DATABASE_KEY_EDITOR "editor"
|
|
|
-#define DATABASE_KEY_GEOMETRY_NAME "geometry_name"
|
|
|
-#define DATABASE_KEY_ID "id"
|
|
|
-#define DATABASE_KEY_MASS "mass"
|
|
|
-#define DATABASE_KEY_MATERIAL "material"
|
|
|
-#define DATABASE_KEY_MESH_RESOURCE "mesh_resource"
|
|
|
-#define DATABASE_KEY_MODIFIED_COMPONENTS "modified_components"
|
|
|
-#define DATABASE_KEY_NAME "name"
|
|
|
-#define DATABASE_KEY_POSITION "position"
|
|
|
-#define DATABASE_KEY_PREFAB "prefab"
|
|
|
-#define DATABASE_KEY_ROTATION "rotation"
|
|
|
-#define DATABASE_KEY_SCALE "scale"
|
|
|
-#define DATABASE_KEY_SCENE "scene"
|
|
|
-#define DATABASE_KEY_SHAPE "shape"
|
|
|
-#define DATABASE_KEY_TYPE "type"
|
|
|
-#define DATABASE_KEY_UNITS "units"
|
|
|
-#define DATABASE_KEY_VISIBLE "visible"
|
|
|
-
|
|
|
- HashMap<StringId32, const char*> key_database(default_allocator());
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_SOUNDS), (const char*)DATABASE_KEY_SOUNDS);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_CLASS), (const char*)DATABASE_KEY_CLASS);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_COLLISION_FILTER), (const char*)DATABASE_KEY_COLLISION_FILTER);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_COMPONENTS), (const char*)DATABASE_KEY_COMPONENTS);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_DATA), (const char*)DATABASE_KEY_DATA);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_EDITOR), (const char*)DATABASE_KEY_EDITOR);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_GEOMETRY_NAME), (const char*)DATABASE_KEY_GEOMETRY_NAME);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_ID), (const char*)DATABASE_KEY_ID);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_MASS), (const char*)DATABASE_KEY_MASS);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_MATERIAL), (const char*)DATABASE_KEY_MATERIAL);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_MESH_RESOURCE), (const char*)DATABASE_KEY_MESH_RESOURCE);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_MODIFIED_COMPONENTS), (const char*)DATABASE_KEY_MODIFIED_COMPONENTS);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_NAME), (const char*)DATABASE_KEY_NAME);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_POSITION), (const char*)DATABASE_KEY_POSITION);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_PREFAB), (const char*)DATABASE_KEY_PREFAB);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_ROTATION), (const char*)DATABASE_KEY_ROTATION);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_SCALE), (const char*)DATABASE_KEY_SCALE);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_SCENE), (const char*)DATABASE_KEY_SCENE);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_SHAPE), (const char*)DATABASE_KEY_SHAPE);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_TYPE), (const char*)DATABASE_KEY_TYPE);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_UNITS), (const char*)DATABASE_KEY_UNITS);
|
|
|
- hash_map::set(key_database, StringId32(DATABASE_KEY_VISIBLE), (const char*)DATABASE_KEY_VISIBLE);
|
|
|
-
|
|
|
- Ledger ledger(default_allocator());
|
|
|
-#if 1
|
|
|
- char* level_json = NULL;
|
|
|
- FilesystemDisk disk(default_allocator());
|
|
|
- File* file = disk.open("/home/dani/git/crown/samples/01-physics/test.level", FileOpenMode::READ);
|
|
|
- if (file)
|
|
|
- {
|
|
|
- u32 size = file->size();
|
|
|
- level_json = (char*)default_allocator().allocate(size + 1);
|
|
|
- file->read(level_json, size);
|
|
|
- level_json[size] = '\0';
|
|
|
- disk.close(*file);
|
|
|
- }
|
|
|
-
|
|
|
- Database db(default_allocator(), key_database);
|
|
|
- db.load(level_json);
|
|
|
- // db.set_property_vector3_internal(guid::parse("f56420ad-7f9c-4cca-aca5-350f366e0dc0"), "position", vector3(1, 2, 3));
|
|
|
- // db.set_property_vector3_internal(guid::parse("f56420ad-7f9c-4cca-aca5-350f366e0dc0"), "position", vector3(4, 5, 6));
|
|
|
- // db.set_property_vector3_internal(guid::parse("f56420ad-7f9c-4cca-aca5-350f366e0dc0"), "position", vector3(7, 8, 9));
|
|
|
- db.dump();
|
|
|
- default_allocator().deallocate(level_json);
|
|
|
-#else
|
|
|
- Database db(default_allocator(), key_database);
|
|
|
- Guid id = guid::new_guid();
|
|
|
- db.create_internal(id);
|
|
|
- db.set_property_vector3_internal(id, DATABASE_KEY_POSITION, vector3(1, 2, 3));
|
|
|
- db.set_property_vector3_internal(id, DATABASE_KEY_POSITION, vector3(4, 5, 6));
|
|
|
- db.set_property_quaternion_internal(id, DATABASE_KEY_ROTATION, quaternion(1, 2, 3, 0));
|
|
|
- db.set_property_string_internal(id, DATABASE_KEY_MASS, "apple");
|
|
|
- db.set_property_string_internal(id, DATABASE_KEY_MASS, "banana");
|
|
|
- db.dump();
|
|
|
- db.destroy_internal(id);
|
|
|
-#endif
|
|
|
- }
|
|
|
- memory_globals::shutdown();
|
|
|
- }
|
|
|
-
|
|
|
-} // namespace crown
|