| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799 |
- /*
- * 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
|