diff --git a/easy2d/2d/Node.cpp b/easy2d/2d/Node.cpp index 737bc9d5..e460686e 100644 --- a/easy2d/2d/Node.cpp +++ b/easy2d/2d/Node.cpp @@ -62,7 +62,7 @@ namespace easy2d return; UpdateActions(this, dt); - UpdateTasks(dt); + UpdateTimers(dt); if (cb_update_) cb_update_(dt); diff --git a/easy2d/2d/Node.h b/easy2d/2d/Node.h index 7a84aad7..d3cf7eaf 100644 --- a/easy2d/2d/Node.h +++ b/easy2d/2d/Node.h @@ -22,7 +22,7 @@ #include "include-forwards.h" #include "Transform.hpp" #include "ActionManager.h" -#include "../base/TaskManager.h" +#include "../base/TimerManager.h" #include "../base/EventDispatcher.h" namespace easy2d @@ -32,7 +32,7 @@ namespace easy2d // 节点 class E2D_API Node : public virtual Object - , public TaskManager + , public TimerManager , public ActionManager , public EventDispatcher , public IntrusiveListItem diff --git a/easy2d/Easy2D.vcxproj b/easy2d/Easy2D.vcxproj index 889c46cf..df865420 100644 --- a/easy2d/Easy2D.vcxproj +++ b/easy2d/Easy2D.vcxproj @@ -38,8 +38,8 @@ - - + + @@ -101,8 +101,8 @@ - - + + diff --git a/easy2d/Easy2D.vcxproj.filters b/easy2d/Easy2D.vcxproj.filters index 9ea89d7c..396f9859 100644 --- a/easy2d/Easy2D.vcxproj.filters +++ b/easy2d/Easy2D.vcxproj.filters @@ -153,12 +153,6 @@ base - - base - - - base - base @@ -243,6 +237,12 @@ common + + base + + + base + @@ -317,12 +317,6 @@ base - - base - - - base - base @@ -368,5 +362,11 @@ utils + + base + + + base + \ No newline at end of file diff --git a/easy2d/base/Object.h b/easy2d/base/Object.h index 82e936af..5d1597da 100644 --- a/easy2d/base/Object.h +++ b/easy2d/base/Object.h @@ -21,7 +21,6 @@ #pragma once #include "../macros.h" #include "../common/helper.h" -#include "../common/Json.h" #include "RefCounter.hpp" #include "SmartPtr.hpp" diff --git a/easy2d/base/TaskManager.cpp b/easy2d/base/TaskManager.cpp deleted file mode 100644 index 9ab7e9a4..00000000 --- a/easy2d/base/TaskManager.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2016-2018 Easy2D - Nomango -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include "TaskManager.h" -#include "../base/logs.h" - -namespace easy2d -{ - void TaskManager::UpdateTasks(Duration dt) - { - if (tasks_.IsEmpty()) - return; - - TaskPtr next; - for (auto task = tasks_.First(); task; task = next) - { - next = task->NextItem(); - - bool remove_after_update = false; - task->Update(dt, remove_after_update); - - if (remove_after_update) - tasks_.Remove(task); - } - } - - void TaskManager::AddTask(TaskPtr const& task) - { - E2D_ASSERT(task && "AddTask failed, NULL pointer exception"); - - if (task) - { - task->Reset(); - tasks_.PushBack(task); - } - } - - void TaskManager::StopTasks(String const& name) - { - if (tasks_.IsEmpty()) - return; - - for (auto task = tasks_.First().Get(); task; task = task->NextItem().Get()) - { - if (task->IsName(name)) - { - task->Stop(); - } - } - } - - void TaskManager::StartTasks(String const& name) - { - if (tasks_.IsEmpty()) - return; - - for (auto task = tasks_.First().Get(); task; task = task->NextItem().Get()) - { - if (task->IsName(name)) - { - task->Start(); - } - } - } - - void TaskManager::RemoveTasks(String const& name) - { - if (tasks_.IsEmpty()) - return; - - TaskPtr next; - for (auto task = tasks_.First(); task; task = next) - { - next = task->NextItem(); - if (task->IsName(name)) - { - tasks_.Remove(task); - } - } - } - - void TaskManager::StopAllTasks() - { - if (tasks_.IsEmpty()) - return; - - for (auto task = tasks_.First().Get(); task; task = task->NextItem().Get()) - { - task->Stop(); - } - } - - void TaskManager::StartAllTasks() - { - if (tasks_.IsEmpty()) - return; - - for (auto task = tasks_.First().Get(); task; task = task->NextItem().Get()) - { - task->Start(); - } - } - - void TaskManager::RemoveAllTasks() - { - tasks_.Clear(); - } - - const TaskManager::Tasks & TaskManager::GetAllTasks() const - { - return tasks_; - } -} diff --git a/easy2d/base/Task.cpp b/easy2d/base/Timer.cpp similarity index 83% rename from easy2d/base/Task.cpp rename to easy2d/base/Timer.cpp index 94fb5554..6938642a 100644 --- a/easy2d/base/Task.cpp +++ b/easy2d/base/Timer.cpp @@ -18,16 +18,16 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "Task.h" +#include "Timer.h" namespace easy2d { - Task::Task(Callback const& func, String const& name) - : Task(func, Duration{}, -1, name) + Timer::Timer(Callback const& func, String const& name) + : Timer(func, Duration{}, -1, name) { } - Task::Task(Callback const& func, Duration delay, int times, String const& name) + Timer::Timer(Callback const& func, Duration delay, int times, String const& name) : running_(true) , run_times_(0) , total_times_(times) @@ -38,17 +38,17 @@ namespace easy2d SetName(name); } - void Task::Start() + void Timer::Start() { running_ = true; } - void Task::Stop() + void Timer::Stop() { running_ = false; } - void Task::Update(Duration dt, bool& remove_after_update) + void Timer::Update(Duration dt, bool& remove_after_update) { if (!running_) return; @@ -80,13 +80,13 @@ namespace easy2d } } - void Task::Reset() + void Timer::Reset() { delta_ = Duration{}; run_times_ = 0; } - bool Task::IsRunning() const + bool Timer::IsRunning() const { return running_; } diff --git a/easy2d/base/Task.h b/easy2d/base/Timer.h similarity index 90% rename from easy2d/base/Task.h rename to easy2d/base/Timer.h index 73880664..568d5412 100644 --- a/easy2d/base/Task.h +++ b/easy2d/base/Timer.h @@ -27,27 +27,27 @@ namespace easy2d { - class TaskManager; + class TimerManager; - E2D_DECLARE_SMART_PTR(Task); + E2D_DECLARE_SMART_PTR(Timer); // 定时任务 - class E2D_API Task + class E2D_API Timer : public virtual Object - , protected IntrusiveListItem + , protected IntrusiveListItem { - friend class TaskManager; - friend class IntrusiveList; + friend class TimerManager; + friend class IntrusiveList; using Callback = std::function; public: - explicit Task( + explicit Timer( Callback const& func, /* 执行函数 */ String const& name = L"" /* 任务名称 */ ); - explicit Task( + explicit Timer( Callback const& func, /* 执行函数 */ Duration delay, /* 时间间隔(秒) */ int times = -1, /* 执行次数(设 -1 为永久执行) */ diff --git a/easy2d/base/TimerManager.cpp b/easy2d/base/TimerManager.cpp new file mode 100644 index 00000000..a90b3310 --- /dev/null +++ b/easy2d/base/TimerManager.cpp @@ -0,0 +1,130 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "TimerManager.h" +#include "../base/logs.h" + +namespace easy2d +{ + void TimerManager::UpdateTimers(Duration dt) + { + if (timers_.IsEmpty()) + return; + + TimerPtr next; + for (auto timer = timers_.First(); timer; timer = next) + { + next = timer->NextItem(); + + bool remove_after_update = false; + timer->Update(dt, remove_after_update); + + if (remove_after_update) + timers_.Remove(timer); + } + } + + void TimerManager::AddTimer(TimerPtr const& timer) + { + E2D_ASSERT(timer && "AddTimer failed, NULL pointer exception"); + + if (timer) + { + timer->Reset(); + timers_.PushBack(timer); + } + } + + void TimerManager::StopTimers(String const& name) + { + if (timers_.IsEmpty()) + return; + + for (auto timer = timers_.First().Get(); timer; timer = timer->NextItem().Get()) + { + if (timer->IsName(name)) + { + timer->Stop(); + } + } + } + + void TimerManager::StartTimers(String const& name) + { + if (timers_.IsEmpty()) + return; + + for (auto timer = timers_.First().Get(); timer; timer = timer->NextItem().Get()) + { + if (timer->IsName(name)) + { + timer->Start(); + } + } + } + + void TimerManager::RemoveTimers(String const& name) + { + if (timers_.IsEmpty()) + return; + + TimerPtr next; + for (auto timer = timers_.First(); timer; timer = next) + { + next = timer->NextItem(); + if (timer->IsName(name)) + { + timers_.Remove(timer); + } + } + } + + void TimerManager::StopAllTimers() + { + if (timers_.IsEmpty()) + return; + + for (auto timer = timers_.First().Get(); timer; timer = timer->NextItem().Get()) + { + timer->Stop(); + } + } + + void TimerManager::StartAllTimers() + { + if (timers_.IsEmpty()) + return; + + for (auto timer = timers_.First().Get(); timer; timer = timer->NextItem().Get()) + { + timer->Start(); + } + } + + void TimerManager::RemoveAllTimers() + { + timers_.Clear(); + } + + const TimerManager::Timers & TimerManager::GetAllTimers() const + { + return timers_; + } +} diff --git a/easy2d/base/TaskManager.h b/easy2d/base/TimerManager.h similarity index 75% rename from easy2d/base/TaskManager.h rename to easy2d/base/TimerManager.h index 00e5360c..fd601194 100644 --- a/easy2d/base/TaskManager.h +++ b/easy2d/base/TimerManager.h @@ -19,51 +19,51 @@ // THE SOFTWARE. #pragma once -#include "Task.h" +#include "Timer.h" namespace easy2d { - class E2D_API TaskManager + class E2D_API TimerManager { - using Tasks = IntrusiveList; + using Timers = IntrusiveList; public: // 添加任务 - void AddTask( - TaskPtr const& task + void AddTimer( + TimerPtr const& timer ); // 启动任务 - void StartTasks( - String const& task_name + void StartTimers( + String const& timer_name ); // 停止任务 - void StopTasks( - String const& task_name + void StopTimers( + String const& timer_name ); // 移除任务 - void RemoveTasks( - String const& task_name + void RemoveTimers( + String const& timer_name ); // 启动所有任务 - void StartAllTasks(); + void StartAllTimers(); // 停止所有任务 - void StopAllTasks(); + void StopAllTimers(); // 移除所有任务 - void RemoveAllTasks(); + void RemoveAllTimers(); // 获取所有任务 - const Tasks& GetAllTasks() const; + const Timers& GetAllTimers() const; protected: - void UpdateTasks(Duration dt); + void UpdateTimers(Duration dt); protected: - Tasks tasks_; + Timers timers_; }; } diff --git a/easy2d/common/Json.h b/easy2d/common/Json.h index df59d7f5..d47c82f1 100644 --- a/easy2d/common/Json.h +++ b/easy2d/common/Json.h @@ -130,25 +130,23 @@ namespace easy2d }; - // - // basic_json - // - - E2D_DECLARE_BASIC_JSON_TEMPLATE - class basic_json + namespace __json_detail { - public: - using size_type = std::size_t; - using string_type = typename _StringTy; - using integer_type = typename _IntegerTy; - using float_type = typename _FloatTy; - using boolean_type = typename _BooleanTy; - using array_type = typename _ArrayTy>; - using object_type = typename _ObjectTy, _Allocator>>; - using initializer_list = std::initializer_list; + // + // json_value + // - struct JsonValue + template + struct json_value { + using string_type = typename _BasicJsonTy::string_type; + using char_type = typename _BasicJsonTy::char_type; + using integer_type = typename _BasicJsonTy::integer_type; + using float_type = typename _BasicJsonTy::float_type; + using boolean_type = typename _BasicJsonTy::boolean_type; + using array_type = typename _BasicJsonTy::array_type; + using object_type = typename _BasicJsonTy::object_type; + JsonType type; union { @@ -160,62 +158,62 @@ namespace easy2d boolean_type boolean; } data; - JsonValue() + json_value() { type = JsonType::Null; data.object = nullptr; } - JsonValue(std::nullptr_t) + json_value(std::nullptr_t) { type = JsonType::Null; data.object = nullptr; } - JsonValue(const object_type& value) + json_value(const object_type& value) { type = JsonType::Object; data.object = create(value); } - JsonValue(const array_type& value) + json_value(const array_type& value) { type = JsonType::Array; data.vector = create(value); } - JsonValue(const string_type& value) + json_value(const string_type& value) { type = JsonType::String; data.string = create(value); } template - JsonValue(const _CharT* str) + json_value(const _CharT* str) { type = JsonType::String; data.string = create(str); } - JsonValue(const integer_type value) + json_value(const integer_type value) { type = JsonType::Integer; data.number_integer = value; } - JsonValue(const float_type value) + json_value(const float_type value) { type = JsonType::Float; data.number_float = value; } - JsonValue(const boolean_type value) + json_value(const boolean_type value) { type = JsonType::Boolean; data.boolean = value; } - JsonValue(const JsonType value_type) + json_value(const JsonType value_type) { type = value_type; switch (type) @@ -244,7 +242,7 @@ namespace easy2d } } - JsonValue(JsonValue const& other) + json_value(json_value const& other) { type = other.type; @@ -274,7 +272,7 @@ namespace easy2d } } - JsonValue(JsonValue&& other) + json_value(json_value&& other) { type = other.type; data = other.data; @@ -282,7 +280,18 @@ namespace easy2d other.data.object = nullptr; } - ~JsonValue() + ~json_value() + { + clear(); + } + + void swap(json_value& other) + { + std::swap(type, other.type); + std::swap(data, other.data); + } + + void clear() { switch (type) { @@ -300,489 +309,53 @@ namespace easy2d } } - void swap(JsonValue& other) - { - std::swap(type, other.type); - std::swap(data, other.data); - } - template inline _Ty* create(_Args&&... args) { - using Allocator = _Allocator<_Ty>; - using AllocatorTraits = std::allocator_traits; + using allocator_type = typename _BasicJsonTy::template allocator_type<_Ty>; + using allocator_traits = std::allocator_traits; - Allocator allocator; - _Ty* ptr = AllocatorTraits::allocate(allocator, 1); - AllocatorTraits::construct(allocator, ptr, std::forward<_Args>(args)...); + allocator_type allocator; + _Ty* ptr = allocator_traits::allocate(allocator, 1); + allocator_traits::construct(allocator, ptr, std::forward<_Args>(args)...); return ptr; } template inline void destroy(_Ty* ptr) { - using Allocator = _Allocator<_Ty>; - using AllocatorTraits = std::allocator_traits; + using allocator_type = typename _BasicJsonTy::template allocator_type<_Ty>; + using allocator_traits = std::allocator_traits; - Allocator allocator; - AllocatorTraits::destroy(allocator, ptr); - AllocatorTraits::deallocate(allocator, ptr, 1); + allocator_type allocator; + allocator_traits::destroy(allocator, ptr); + allocator_traits::deallocate(allocator, ptr, 1); } - inline JsonValue& operator=(JsonValue const& other) + inline json_value& operator=(json_value const& other) { - JsonValue{ other }.swap(*this); + json_value{ other }.swap(*this); return (*this); } - inline JsonValue& operator=(JsonValue && other) + inline json_value& operator=(json_value && other) { - JsonValue{ std::forward(other) }.swap(*this); + clear(); + type = other.type; + data = std::move(other.data); + // invalidate payload + other.type = JsonType::Null; + other.data.object = nullptr; return (*this); } }; + } // end of namespace __json_detail - public: - basic_json() {} - - basic_json(std::nullptr_t) {} - - basic_json(const JsonType type) : value_(type) {} - - basic_json(basic_json const& other) : value_(other.value_) {} - - basic_json(string_type const& value) : value_(value) {} - - template < - typename _CompatibleTy, - enable_if_t::value, int> = 0> - basic_json(const _CompatibleTy& value) - { - value_.type = JsonType::String; - value_.data.string = value_.template create(value); - } - - basic_json(array_type const& arr) - : value_(arr) - { - } - - basic_json(object_type const& object) - : value_(object) - { - } - - template < - typename _FloatingTy, - enable_if_t::value, int> = 0> - basic_json(_FloatingTy value) - : value_(static_cast(value)) - { - } - - template < - typename _IntegerTy, - enable_if_t::value, int> = 0> - basic_json(_IntegerTy value) - : value_(static_cast(value)) - { - } - - basic_json(boolean_type value) - : value_(value) - { - } - - basic_json(initializer_list init_list) - { - bool is_an_object = std::all_of(init_list.begin(), init_list.end(), [](const basic_json& json) - { - return (json.is_array() && json.size() == 2 && json[0].is_string()); - }); - - if (is_an_object) - { - value_ = JsonType::Object; - - std::for_each(init_list.begin(), init_list.end(), [this](const basic_json& json) - { - value_.data.object->emplace( - *((*json.value_.data.vector)[0].value_.data.string), - (*json.value_.data.vector)[1] - ); - }); - } - else - { - value_ = JsonType::Array; - value_.data.vector->reserve(init_list.size()); - value_.data.vector->assign(init_list.begin(), init_list.end()); - } - } - - inline bool is_object() const { return value_.type == JsonType::Object; } - - inline bool is_array() const { return value_.type == JsonType::Array; } - - inline bool is_string() const { return value_.type == JsonType::String; } - - inline bool is_boolean() const { return value_.type == JsonType::Boolean; } - - inline bool is_integer() const { return value_.type == JsonType::Integer; } - - inline bool is_float() const { return value_.type == JsonType::Float; } - - inline bool is_number() const { return is_integer() || is_float(); } - - inline bool is_null() const { return value_.type == JsonType::Null; } - - inline JsonType type() const { return value_.type; } - - inline string_type type_name() const - { - switch (type()) - { - case JsonType::Object: - return string_type(L"object"); - case JsonType::Array: - return string_type(L"array"); - case JsonType::String: - return string_type(L"string"); - case JsonType::Integer: - return string_type(L"integer"); - case JsonType::Float: - return string_type(L"float"); - case JsonType::Boolean: - return string_type(L"boolean"); - case JsonType::Null: - return string_type(L"null"); - } - return string_type(); - } - - inline void swap(basic_json& rhs) { value_.swap(rhs.value_); } - - public: - // GET value functions - - inline bool get_value(boolean_type& val) const - { - if (is_boolean()) - { - val = value_.data.boolean; - return true; - } - return false; - } - - inline bool get_value(integer_type& val) const - { - if (is_integer()) - { - val = value_.data.number_integer; - return true; - } - return false; - } - - inline bool get_value(float_type& val) const - { - if (is_float()) - { - val = value_.data.number_float; - return true; - } - return false; - } - - template < - typename _IntegerTy, - enable_if_t::value, int> = 0> - inline bool get_value(_IntegerTy& val) const - { - if (is_integer()) - { - val = static_cast<_IntegerTy>(value_.data.number_integer); - return true; - } - return false; - } - - template < - typename _FloatingTy, - enable_if_t::value, int> = 0> - inline bool get_value(_FloatingTy& val) const - { - if (is_float()) - { - val = static_cast<_FloatingTy>(value_.data.number_float); - return true; - } - return false; - } - - inline bool get_value(array_type& val) const - { - if (is_array()) - { - val.assign((*value_.data.vector).begin(), (*value_.data.vector).end()); - return true; - } - return false; - } - - inline bool get_value(string_type& val) const - { - if (is_string()) - { - val.assign(*value_.data.string); - return true; - } - return false; - } - - inline bool get_value(object_type& val) const - { - if (is_object()) - { - val.assign(*value_.data.object); - return true; - } - return false; - } - - boolean_type as_bool() const - { - if (!is_boolean()) throw json_type_error(); - return value_.data.boolean; - } - - integer_type as_int() const - { - if (!is_integer()) throw json_type_error(); - return value_.data.number_integer; - } - - float_type as_float() const - { - if (!is_float()) throw json_type_error(); - return value_.data.number_float; - } - - const array_type& as_array() const - { - if (!is_array()) throw json_type_error(); - return *value_.data.vector; - } - - const string_type& as_string() const - { - if (!is_string()) throw json_type_error(); - return *value_.data.string; - } - - const object_type& as_object() const - { - if (!is_object()) throw json_type_error(); - return *value_.data.object; - } - - public: - // json_value_getter - - template - _Ty get() const - { - _Ty value; - json_value_getter::assign(*this, value); - return value; - } - - struct json_value_getter - { - template - static inline void assign(const _BasicJsonTy& json, object_type& value) - { - if (!json.is_object()) throw json_type_error(); - value = *json.value_.data.object; - } - - template - static inline void assign(const _BasicJsonTy& json, array_type& value) - { - if (!json.is_array()) throw json_type_error(); - value = *json.value_.data.vector; - } - - template - static inline void assign(const _BasicJsonTy& json, string_type& value) - { - if (!json.is_string()) throw json_type_error(); - value = *json.value_.data.string; - } - - template - static inline void assign(const _BasicJsonTy& json, boolean_type& value) - { - if (!json.is_boolean()) throw json_type_error(); - value = json.value_.data.boolean; - } - - template - static inline void assign(const _BasicJsonTy& json, integer_type& value) - { - if (!json.is_integer()) throw json_type_error(); - value = json.value_.data.number_integer; - } - - template < - typename _BasicJsonTy, - typename _IntegerTy, - enable_if_t::value, int> = 0> - static inline void assign(const _BasicJsonTy& json, _IntegerTy& value) - { - if (!json.is_integer()) throw json_type_error(); - value = static_cast<_IntegerTy>(json.value_.data.number_integer); - } - - template < - typename _BasicJsonTy, - typename _FloatingTy, - enable_if_t::value, int> = 0> - static inline void assign(const _BasicJsonTy& json, _FloatingTy& value) - { - if (!json.is_float()) throw json_type_error(); - value = static_cast<_FloatingTy>(json.value_.data.number_float); - } - }; - - friend struct json_value_getter; - - public: - // operator= functions - - inline basic_json& operator=(basic_json const& other) - { - value_ = other.value_; - return (*this); - } - - inline basic_json& operator=(std::nullptr_t) - { - value_ = nullptr; - return (*this); - } - - public: - // operator[] functions - - inline basic_json& operator[](size_type index) - { - if (is_null()) - { - value_ = JsonType::Array; - } - - if (!is_array()) - { - throw json_invalid_key(); - } - - if (index >= value_.data.vector->size()) - { - value_.data.vector->insert(value_.data.vector->end(), - index - value_.data.vector->size() + 1, - basic_json() - ); - } - return (*value_.data.vector)[index]; - } - - inline basic_json& operator[](size_type index) const - { - if (!is_array()) - { - throw json_invalid_key(); - } - - if (index >= value_.data.vector->size()) - { - throw json_invalid_key(); - } - return (*value_.data.vector)[index]; - } - - inline basic_json& operator[](const typename object_type::key_type& key) - { - if (is_null()) - { - value_ = JsonType::Object; - } - - if (!is_object()) - { - throw json_invalid_key(); - } - return (*value_.data.object)[key]; - } - - inline basic_json& operator[](const typename object_type::key_type& key) const - { - if (!is_object()) - { - throw json_invalid_key(); - } - - auto iter = value_.data.object->find(key); - if (iter == value_.data.object->end()) - { - throw json_invalid_key(); - } - return iter->second; - } - - template - inline basic_json& operator[](_CharT* key) - { - if (is_null()) - { - value_ = JsonType::Object; - } - - if (!is_object()) - { - throw json_invalid_key(); - } - return (*value_.data.object)[key]; - } - - template - inline basic_json& operator[](_CharT* key) const - { - if (!is_object()) - { - throw json_invalid_key(); - } - - auto iter = value_.data.object->find(key); - if (iter == value_.data.object->end()) - { - throw json_invalid_key(); - } - return iter->second; - } - - public: - // implicitly convert functions - - template - inline operator _Ty() const - { - return get<_Ty>(); - } - - public: + namespace __json_detail + { + // // iterator for basic_json + // struct original_iterator { @@ -798,7 +371,7 @@ namespace easy2d inline original_iterator operator++(int) { original_iterator old(it_); ++(*this); return old; } inline original_iterator& operator--() { --it_; return (*this); } - inline original_iterator operator--(int) { iterator_impl old = (*this); --(*this); return old; } + inline original_iterator operator--(int) { original_iterator old = (*this); --(*this); return old; } inline bool operator==(original_iterator const& other) const { return it_ == other.it_ && it_ == other.it_; } inline bool operator!=(original_iterator const& other) const { return !(*this == other); } @@ -820,19 +393,28 @@ namespace easy2d int it_; }; + template struct internal_iterator { - typename array_type::iterator array_iter; - typename object_type::iterator object_iter; + typename _BasicJsonTy::array_type::iterator array_iter; + typename _BasicJsonTy::object_type::iterator object_iter; original_iterator original_iter = 0; // for other types }; - template + template struct iterator_impl { - friend _Ty; + friend _BasicJsonTy; - using value_type = _Ty; + using string_type = typename _BasicJsonTy::string_type; + using char_type = typename _BasicJsonTy::char_type; + using integer_type = typename _BasicJsonTy::integer_type; + using float_type = typename _BasicJsonTy::float_type; + using boolean_type = typename _BasicJsonTy::boolean_type; + using array_type = typename _BasicJsonTy::array_type; + using object_type = typename _BasicJsonTy::object_type; + + using value_type = _BasicJsonTy; using difference_type = std::ptrdiff_t; using iterator_category = std::bidirectional_iterator_tag; using pointer = value_type*; @@ -1038,9 +620,9 @@ namespace easy2d } } - inline bool operator>(iterator_impl const& other) const { return other.operator<(*this); } - inline bool operator>=(iterator_impl const& other) const { return !operator<(other); } - inline bool operator<=(iterator_impl const& other) const { return !other.operator<(*this); } + inline bool operator>(iterator_impl const& other) const { return other.operator<(*this); } + inline bool operator>=(iterator_impl const& other) const { return !operator<(other); } + inline bool operator<=(iterator_impl const& other) const { return !other.operator<(*this); } inline bool operator<(iterator_impl const& other) const { check_data(); @@ -1092,204 +674,20 @@ namespace easy2d private: pointer data_; - internal_iterator it_; + internal_iterator<_BasicJsonTy> it_; }; + } // end of namespace __json_detail - public: - friend struct iterator_impl; - friend struct iterator_impl; - - using iterator = iterator_impl; - using const_iterator = iterator_impl; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - inline iterator begin() { iterator iter(this); iter.set_begin(); return iter; } - inline const_iterator begin() const { return cbegin(); } - inline const_iterator cbegin() const { const_iterator iter(this); iter.set_begin(); return iter; } - inline iterator end() { iterator iter(this); iter.set_end(); return iter; } - inline const_iterator end() const { return cend(); } - inline const_iterator cend() const { const_iterator iter(this); iter.set_end(); return iter; } - inline reverse_iterator rbegin() { return reverse_iterator(end()); } - inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - inline const_reverse_iterator crbegin() const { return rbegin(); } - inline reverse_iterator rend() { return reverse_iterator(begin()); } - inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - inline const_reverse_iterator crend() const { return rend(); } - - public: - inline size_type size() const - { - switch (type()) - { - case JsonType::Null: - return 0; - case JsonType::Array: - return value_.data.vector->size(); - case JsonType::Object: - return value_.data.object->size(); - default: - return 1; - } - } - - inline bool empty() const - { - if (is_null()) - return true; - - if (is_object()) - return value_.data.object->empty(); - - if (is_array()) - return value_.data.vector->empty(); - - return false; - } - - template - inline const_iterator find(_Kty && key) const - { - if (is_object()) - { - const_iterator iter; - iter.it_.object_iter = value_.data.object->find(std::forward<_Kty>(key)); - return iter; - } - return cend(); - } - - template - inline size_type count(_Kty && key) const - { - return is_object() ? value_.data.object->count(std::forward<_Kty>(key)) : 0; - } - - inline void clear() { value_ = nullptr; } - - public: - // compare functions - - friend bool operator==(const basic_json& lhs, const basic_json& rhs) - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case JsonType::Array: - return (*lhs.value_.data.vector == *rhs.value_.data.vector); - - case JsonType::Object: - return (*lhs.value_.data.object == *rhs.value_.data.object); - - case JsonType::Null: - return true; - - case JsonType::String: - return (*lhs.value_.data.string == *rhs.value_.data.string); - - case JsonType::Boolean: - return (lhs.value_.data.boolean == rhs.value_.data.boolean); - - case JsonType::Integer: - return (lhs.value_.data.number_integer == rhs.value_.data.number_integer); - - case JsonType::Float: - return (lhs.value_.data.number_float == rhs.value_.data.number_float); - - default: - return false; - } - } - else if (lhs_type == JsonType::Integer && rhs_type == JsonType::Float) - { - return (static_cast(lhs.value_.data.number_integer) == rhs.value_.data.number_float); - } - else if (lhs_type == JsonType::Float && rhs_type == JsonType::Integer) - { - return (lhs.value_.data.number_float == static_cast(rhs.value_.data.number_integer)); - } - - return false; - } - - friend bool operator!=(const basic_json& lhs, const basic_json& rhs) - { - return !(lhs == rhs); - } - - friend bool operator<(const basic_json& lhs, const basic_json& rhs) - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case JsonType::Array: - return (*lhs.value_.data.vector) < (*rhs.value_.data.vector); - - case JsonType::Object: - return (*lhs.value_.data.object) < (*rhs.value_.data.object); - - case JsonType::Null: - return false; - - case JsonType::String: - return (*lhs.value_.data.string) < (*rhs.value_.data.string); - - case JsonType::Boolean: - return (lhs.value_.data.boolean < rhs.value_.data.boolean); - - case JsonType::Integer: - return (lhs.value_.data.number_integer < rhs.value_.data.number_integer); - - case JsonType::Float: - return (lhs.value_.data.number_float < rhs.value_.data.number_float); - - default: - return false; - } - } - else if (lhs_type == JsonType::Integer && rhs_type == JsonType::Float) - { - return (static_cast(lhs.value_.data.number_integer) < rhs.value_.data.number_float); - } - else if (lhs_type == JsonType::Float && rhs_type == JsonType::Integer) - { - return (lhs.value_.data.number_float < static_cast(rhs.value_.data.number_integer)); - } - - return false; - } - - friend bool operator<=(const basic_json& lhs, const basic_json& rhs) - { - return !(rhs < lhs); - } - - friend bool operator>(const basic_json& lhs, const basic_json& rhs) - { - return rhs < lhs; - } - - friend bool operator>=(const basic_json& lhs, const basic_json& rhs) - { - return !(lhs < rhs); - } - - public: + namespace __json_detail + { + // // output_adapter + // template struct output_adapter { - using char_type = typename _StringTy::value_type; - using size_type = typename _StringTy::size_type; + using char_type = _CharTy; using char_traits = std::char_traits; virtual void write(const _CharTy ch) = 0; @@ -1297,7 +695,7 @@ namespace easy2d virtual void write(const _CharTy* str) { const auto size = char_traits::length(str); - write(str, static_cast(size)); + write(str, static_cast(size)); } }; @@ -1348,52 +746,24 @@ namespace easy2d private: std::basic_ostream& stream_; }; + } // end of namespace __json_detail - public: - friend std::basic_ostream& operator<<(std::basic_ostream& out, const basic_json& json) - { - using char_type = typename std::basic_ostream::char_type; - - const bool pretty_print = (out.width() > 0); - const auto indentation = (pretty_print ? out.width() : 0); - out.width(0); - - stream_output_adapter adapter(out); - json_serializer(&adapter, out.fill()).dump(json, pretty_print, static_cast(indentation)); - return out; - } - - string_type dump( - const int indent = -1, - const typename string_type::value_type indent_char = ' ') const - { - string_type result; - string_output_adapter adapter(result); - dump(&adapter, indent, indent_char); - return result; - } - - void dump( - output_adapter* adapter, - const int indent = -1, - const typename string_type::value_type indent_char = ' ') const - { - if (indent >= 0) - { - json_serializer(adapter, indent_char).dump(*this, true, static_cast(indent)); - } - else - { - json_serializer(adapter, indent_char).dump(*this, false, 0); - } - } - - public: + namespace __json_detail + { + // // json_serializer + // + template struct json_serializer { - using char_type = typename string_type::value_type; + using string_type = typename _BasicJsonTy::string_type; + using char_type = typename _BasicJsonTy::char_type; + using integer_type = typename _BasicJsonTy::integer_type; + using float_type = typename _BasicJsonTy::float_type; + using boolean_type = typename _BasicJsonTy::boolean_type; + using array_type = typename _BasicJsonTy::array_type; + using object_type = typename _BasicJsonTy::object_type; json_serializer(output_adapter* out, const wchar_t indent_char) : out(out) @@ -1402,7 +772,7 @@ namespace easy2d {} void dump( - const basic_json& json, + const _BasicJsonTy& json, const bool pretty_print, const unsigned int indent_step, const unsigned int current_indent = 0) @@ -1460,7 +830,7 @@ namespace easy2d out->write(iter->first.c_str()); out->write(L"\":"); dump(iter->second, false, indent_step, current_indent); - + // not last element if (i != size - 1) out->write(','); @@ -1622,11 +992,13 @@ namespace easy2d string_type indent_string; std::array number_buffer; }; + } // end of namespace __json_detail - friend struct json_serializer; - - public: + namespace __json_detail + { + // // input_adapter + // template struct input_adapter @@ -1726,51 +1098,51 @@ namespace easy2d const char_type* str; std::size_t index; }; + } // end of namespace __json_detail - public: - // json_parser + namespace __json_detail + { + // + // json_lexer & json_parser + // - friend std::basic_istream& - operator>>(std::basic_istream& in, basic_json& json) + enum class token_type { - using char_type = typename string_type::value_type; + uninitialized, - stream_input_adapter adapter(in); - json_parser(&adapter).parse(json); - return in; - } + literal_true, + literal_false, + literal_null, - static inline basic_json parse(const string_type& str) - { - string_input_adapter adapter(str); - return parse(&adapter); - } + value_string, + value_integer, + value_float, - static inline basic_json parse(const typename string_type::value_type* str) - { - buffer_input_adapter adapter(str); - return parse(&adapter); - } + begin_array, + end_array, - static inline basic_json parse(std::FILE* file) - { - using char_type = typename string_type::value_type; + begin_object, + end_object, - file_input_adapter adapter(file); - return parse(&adapter); - } + name_separator, + value_separator, - static inline basic_json parse(input_adapter* adapter) - { - basic_json result; - json_parser(adapter).parse(result); - return result; - } + parse_error, + end_of_input + }; + + template struct json_lexer { - using char_type = typename string_type::value_type; - using char_traits = std::char_traits; + using string_type = typename _BasicJsonTy::string_type; + using char_type = typename _BasicJsonTy::char_type; + using integer_type = typename _BasicJsonTy::integer_type; + using float_type = typename _BasicJsonTy::float_type; + using boolean_type = typename _BasicJsonTy::boolean_type; + using array_type = typename _BasicJsonTy::array_type; + using object_type = typename _BasicJsonTy::object_type; + using char_traits = std::char_traits; json_lexer(input_adapter* adapter) : adapter(adapter) { @@ -1778,32 +1150,6 @@ namespace easy2d read_next(); } - enum class token_type - { - uninitialized, - - literal_true, - literal_false, - literal_null, - - value_string, - value_integer, - value_float, - - begin_array, - end_array, - - begin_object, - end_object, - - name_separator, - value_separator, - - parse_error, - - end_of_input - }; - typename char_traits::int_type read_next() { current = adapter->get_char(); @@ -2080,15 +1426,25 @@ namespace easy2d string_type string_buffer; }; + + template struct json_parser { - using char_type = typename string_type::value_type; - using char_traits = std::char_traits; - using token_type = typename json_lexer::token_type; + using string_type = typename _BasicJsonTy::string_type; + using char_type = typename _BasicJsonTy::char_type; + using integer_type = typename _BasicJsonTy::integer_type; + using float_type = typename _BasicJsonTy::float_type; + using boolean_type = typename _BasicJsonTy::boolean_type; + using array_type = typename _BasicJsonTy::array_type; + using object_type = typename _BasicJsonTy::object_type; + using char_traits = std::char_traits; - json_parser(input_adapter* adapter) : lexer(adapter), last_token(token_type::uninitialized) {} + json_parser(input_adapter* adapter) + : lexer(adapter) + , last_token(token_type::uninitialized) + {} - void parse(basic_json& json) + void parse(_BasicJsonTy& json) { parse_value(json); @@ -2103,7 +1459,7 @@ namespace easy2d return last_token; } - void parse_value(basic_json& json) + void parse_value(_BasicJsonTy& json) { switch (get_token()) { @@ -2137,7 +1493,7 @@ namespace easy2d json = JsonType::Array; while (true) { - json.value_.data.vector->push_back(basic_json()); + json.value_.data.vector->push_back(_BasicJsonTy()); parse_value(json.value_.data.vector->back()); // read ',' @@ -2159,7 +1515,7 @@ namespace easy2d if (get_token() != token_type::name_separator) break; - basic_json object; + _BasicJsonTy object; parse_value(object); json.value_.data.object->insert(std::make_pair(key, object)); @@ -2179,14 +1535,912 @@ namespace easy2d } private: - json_lexer lexer; + json_lexer<_BasicJsonTy> lexer; token_type last_token; }; + } // end of namespace __json_detail - friend struct json_parser; + namespace __json_detail + { + // + // json_value_getter + // + + template + struct json_value_getter + { + using string_type = typename _BasicJsonTy::string_type; + using char_type = typename _BasicJsonTy::char_type; + using integer_type = typename _BasicJsonTy::integer_type; + using float_type = typename _BasicJsonTy::float_type; + using boolean_type = typename _BasicJsonTy::boolean_type; + using array_type = typename _BasicJsonTy::array_type; + using object_type = typename _BasicJsonTy::object_type; + + static inline void assign(const _BasicJsonTy& json, object_type& value) + { + if (!json.is_object()) throw json_type_error(); + value = *json.value_.data.object; + } + + static inline void assign(const _BasicJsonTy& json, array_type& value) + { + if (!json.is_array()) throw json_type_error(); + value = *json.value_.data.vector; + } + + static inline void assign(const _BasicJsonTy& json, string_type& value) + { + if (!json.is_string()) throw json_type_error(); + value = *json.value_.data.string; + } + + static inline void assign(const _BasicJsonTy& json, boolean_type& value) + { + if (!json.is_boolean()) throw json_type_error(); + value = json.value_.data.boolean; + } + + static inline void assign(const _BasicJsonTy& json, integer_type& value) + { + if (!json.is_integer()) throw json_type_error(); + value = json.value_.data.number_integer; + } + + template < + typename _IntegerTy, + typename std::enable_if::value, int>::type = 0> + static inline void assign(const _BasicJsonTy& json, _IntegerTy& value) + { + if (!json.is_integer()) throw json_type_error(); + value = static_cast<_IntegerTy>(json.value_.data.number_integer); + } + + template < + typename _FloatingTy, + typename std::enable_if::value, int>::type = 0> + static inline void assign(const _BasicJsonTy& json, _FloatingTy& value) + { + if (!json.is_float()) throw json_type_error(); + value = static_cast<_FloatingTy>(json.value_.data.number_float); + } + }; + } // end of namespace __json_detail + + // + // basic_json + // + + E2D_DECLARE_BASIC_JSON_TEMPLATE + class basic_json + { + friend struct __json_detail::iterator_impl; + friend struct __json_detail::iterator_impl; + friend struct __json_detail::json_serializer; + friend struct __json_detail::json_parser; + friend struct __json_detail::json_value_getter; + + public: + template + using allocator_type = _Allocator<_Ty>; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using string_type = _StringTy; + using char_type = typename _StringTy::value_type; + using integer_type = _IntegerTy; + using float_type = _FloatTy; + using boolean_type = _BooleanTy; + using array_type = typename _ArrayTy>; + using object_type = typename _ObjectTy, allocator_type>>; + using initializer_list = std::initializer_list; + + using iterator = __json_detail::iterator_impl; + using const_iterator = __json_detail::iterator_impl; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + public: + basic_json() {} + + basic_json(std::nullptr_t) {} + + basic_json(const JsonType type) : value_(type) {} + + basic_json(basic_json const& other) : value_(other.value_) {} + + basic_json(basic_json&& other) : value_(std::move(other.value_)) + { + // invalidate payload + other.value_.type = JsonType::Null; + other.value_.data.object = nullptr; + } + + basic_json(string_type const& value) : value_(value) {} + + template < + typename _CompatibleTy, + typename std::enable_if::value, int>::type = 0> + basic_json(const _CompatibleTy& value) + { + value_.type = JsonType::String; + value_.data.string = value_.template create(value); + } + + basic_json(array_type const& arr) + : value_(arr) + { + } + + basic_json(object_type const& object) + : value_(object) + { + } + + basic_json(integer_type value) + : value_(value) + { + } + + template < + typename _IntegerTy, + typename std::enable_if::value, int>::type = 0> + basic_json(_IntegerTy value) + : value_(static_cast(value)) + { + } + + basic_json(float_type value) + : value_(value) + { + } + + template < + typename _FloatingTy, + typename std::enable_if::value, int>::type = 0> + basic_json(_FloatingTy value) + : value_(static_cast(value)) + { + } + + basic_json(boolean_type value) + : value_(value) + { + } + + basic_json(initializer_list init_list) + { + bool is_an_object = std::all_of(init_list.begin(), init_list.end(), [](const basic_json& json) + { + return (json.is_array() && json.size() == 2 && json[0].is_string()); + }); + + if (is_an_object) + { + value_ = JsonType::Object; + + std::for_each(init_list.begin(), init_list.end(), [this](const basic_json& json) + { + value_.data.object->emplace( + *((*json.value_.data.vector)[0].value_.data.string), + (*json.value_.data.vector)[1] + ); + }); + } + else + { + value_ = JsonType::Array; + value_.data.vector->reserve(init_list.size()); + value_.data.vector->assign(init_list.begin(), init_list.end()); + } + } + + inline bool is_object() const { return value_.type == JsonType::Object; } + + inline bool is_array() const { return value_.type == JsonType::Array; } + + inline bool is_string() const { return value_.type == JsonType::String; } + + inline bool is_boolean() const { return value_.type == JsonType::Boolean; } + + inline bool is_integer() const { return value_.type == JsonType::Integer; } + + inline bool is_float() const { return value_.type == JsonType::Float; } + + inline bool is_number() const { return is_integer() || is_float(); } + + inline bool is_null() const { return value_.type == JsonType::Null; } + + inline JsonType type() const { return value_.type; } + + inline string_type type_name() const + { + switch (type()) + { + case JsonType::Object: + return string_type(L"object"); + case JsonType::Array: + return string_type(L"array"); + case JsonType::String: + return string_type(L"string"); + case JsonType::Integer: + return string_type(L"integer"); + case JsonType::Float: + return string_type(L"float"); + case JsonType::Boolean: + return string_type(L"boolean"); + case JsonType::Null: + return string_type(L"null"); + } + return string_type(); + } + + inline void swap(basic_json& rhs) { value_.swap(rhs.value_); } + + public: + + inline iterator begin() { iterator iter(this); iter.set_begin(); return iter; } + inline const_iterator begin() const { return cbegin(); } + inline const_iterator cbegin() const { const_iterator iter(this); iter.set_begin(); return iter; } + inline iterator end() { iterator iter(this); iter.set_end(); return iter; } + inline const_iterator end() const { return cend(); } + inline const_iterator cend() const { const_iterator iter(this); iter.set_end(); return iter; } + inline reverse_iterator rbegin() { return reverse_iterator(end()); } + inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + inline const_reverse_iterator crbegin() const { return rbegin(); } + inline reverse_iterator rend() { return reverse_iterator(begin()); } + inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + inline const_reverse_iterator crend() const { return rend(); } + + public: + inline size_type size() const + { + switch (type()) + { + case JsonType::Null: + return 0; + case JsonType::Array: + return value_.data.vector->size(); + case JsonType::Object: + return value_.data.object->size(); + default: + return 1; + } + } + + inline bool empty() const + { + if (is_null()) + return true; + + if (is_object()) + return value_.data.object->empty(); + + if (is_array()) + return value_.data.vector->empty(); + + return false; + } + + template + inline const_iterator find(_Kty && key) const + { + if (is_object()) + { + const_iterator iter; + iter.it_.object_iter = value_.data.object->find(std::forward<_Kty>(key)); + return iter; + } + return cend(); + } + + template + inline size_type count(_Kty && key) const + { + return is_object() ? value_.data.object->count(std::forward<_Kty>(key)) : 0; + } + + inline size_type erase(const typename object_type::key_type& key) + { + if (!is_object()) + { + throw json_invalid_key(); + } + return value_.data.object->erase(key); + } + + inline void erase(const size_type index) + { + if (!is_array()) + { + throw json_invalid_key(); + } + value_.data.vector->erase(value_.data.vector->begin() + static_cast(index)); + } + + template< + class _IteratorTy, + typename std::enable_if< + std::is_same<_IteratorTy, iterator>::value || + std::is_same<_IteratorTy, const_iterator>::value, int + >::type = 0> + inline _IteratorTy erase(_IteratorTy pos) + { + _IteratorTy result = end(); + + switch (type()) + { + case JsonType::Object: + { + result.it_.object_iter = value_.data.object->erase(pos.it_.object_iter); + break; + } + + case JsonType::Array: + { + result.it_.array_iter = value_.data.vector->erase(pos.it_.array_iter); + break; + } + + default: + throw json_invalid_iterator(); + } + + return result; + } + + template< + class _IteratorTy, + typename std::enable_if< + std::is_same<_IteratorTy, iterator>::value || + std::is_same<_IteratorTy, const_iterator>::value, int + >::type = 0> + inline _IteratorTy erase(_IteratorTy first, _IteratorTy last) + { + _IteratorTy result = end(); + + switch (type()) + { + case JsonType::Object: + { + result.it_.object_iter = value_.data.object->erase(first.it_.object_iter, last.it_.object_iter); + break; + } + + case JsonType::Array: + { + result.it_.array_iter = value_.data.vector->erase(first.it_.array_iter, last.it_.array_iter); + break; + } + + default: + throw json_invalid_iterator(); + } + + return result; + } + + inline void push_back(basic_json&& json) + { + if (!is_null() && !is_array()) + { + throw json_type_error(); + } + + if (is_null()) + { + value_ = JsonType::Array; + } + + value_.data.vector->push_back(std::move(json)); + } + + inline basic_json& operator+=(basic_json&& json) + { + push_back(std::move(json)); + return (*this); + } + + inline void clear() + { + switch (type()) + { + case JsonType::Integer: + { + value_.data.number_integer = 0; + break; + } + + case JsonType::Float: + { + value_.data.number_float = static_cast(0.0); + break; + } + + case JsonType::Boolean: + { + value_.data.boolean = false; + break; + } + + case JsonType::String: + { + value_.data.string->clear(); + break; + } + + case JsonType::Array: + { + value_.data.vector->clear(); + break; + } + + case JsonType::Object: + { + value_.data.object->clear(); + break; + } + + default: + break; + } + } + + public: + // GET value functions + + inline bool get_value(boolean_type& val) const + { + if (is_boolean()) + { + val = value_.data.boolean; + return true; + } + return false; + } + + inline bool get_value(integer_type& val) const + { + if (is_integer()) + { + val = value_.data.number_integer; + return true; + } + return false; + } + + inline bool get_value(float_type& val) const + { + if (is_float()) + { + val = value_.data.number_float; + return true; + } + return false; + } + + template < + typename _IntegerTy, + typename std::enable_if::value, int>::type = 0> + inline bool get_value(_IntegerTy& val) const + { + if (is_integer()) + { + val = static_cast<_IntegerTy>(value_.data.number_integer); + return true; + } + return false; + } + + template < + typename _FloatingTy, + typename std::enable_if::value, int>::type = 0> + inline bool get_value(_FloatingTy& val) const + { + if (is_float()) + { + val = static_cast<_FloatingTy>(value_.data.number_float); + return true; + } + return false; + } + + inline bool get_value(array_type& val) const + { + if (is_array()) + { + val.assign((*value_.data.vector).begin(), (*value_.data.vector).end()); + return true; + } + return false; + } + + inline bool get_value(string_type& val) const + { + if (is_string()) + { + val.assign(*value_.data.string); + return true; + } + return false; + } + + inline bool get_value(object_type& val) const + { + if (is_object()) + { + val.assign(*value_.data.object); + return true; + } + return false; + } + + boolean_type as_bool() const + { + if (!is_boolean()) throw json_type_error(); + return value_.data.boolean; + } + + integer_type as_int() const + { + if (!is_integer()) throw json_type_error(); + return value_.data.number_integer; + } + + float_type as_float() const + { + if (!is_float()) throw json_type_error(); + return value_.data.number_float; + } + + const array_type& as_array() const + { + if (!is_array()) throw json_type_error(); + return *value_.data.vector; + } + + const string_type& as_string() const + { + if (!is_string()) throw json_type_error(); + return *value_.data.string; + } + + const object_type& as_object() const + { + if (!is_object()) throw json_type_error(); + return *value_.data.object; + } + + template + _Ty get() const + { + _Ty value; + __json_detail::json_value_getter::assign(*this, value); + return value; + } + + public: + // operator= functions + + inline basic_json& operator=(basic_json const& other) + { + value_ = other.value_; + return (*this); + } + + inline basic_json& operator=(basic_json&& other) + { + value_ = std::move(other.value_); + return (*this); + } + + inline basic_json& operator=(std::nullptr_t) + { + value_ = nullptr; + return (*this); + } + + public: + // operator[] functions + + inline basic_json& operator[](size_type index) + { + if (is_null()) + { + value_ = JsonType::Array; + } + + if (!is_array()) + { + throw json_invalid_key(); + } + + if (index >= value_.data.vector->size()) + { + value_.data.vector->insert(value_.data.vector->end(), + index - value_.data.vector->size() + 1, + basic_json() + ); + } + return (*value_.data.vector)[index]; + } + + inline basic_json& operator[](size_type index) const + { + if (!is_array()) + { + throw json_invalid_key(); + } + + if (index >= value_.data.vector->size()) + { + throw json_invalid_key(); + } + return (*value_.data.vector)[index]; + } + + inline basic_json& operator[](const typename object_type::key_type& key) + { + if (is_null()) + { + value_ = JsonType::Object; + } + + if (!is_object()) + { + throw json_invalid_key(); + } + return (*value_.data.object)[key]; + } + + inline basic_json& operator[](const typename object_type::key_type& key) const + { + if (!is_object()) + { + throw json_invalid_key(); + } + + auto iter = value_.data.object->find(key); + if (iter == value_.data.object->end()) + { + throw json_invalid_key(); + } + return iter->second; + } + + template + inline basic_json& operator[](_CharT* key) + { + if (is_null()) + { + value_ = JsonType::Object; + } + + if (!is_object()) + { + throw json_invalid_key(); + } + return (*value_.data.object)[key]; + } + + template + inline basic_json& operator[](_CharT* key) const + { + if (!is_object()) + { + throw json_invalid_key(); + } + + auto iter = value_.data.object->find(key); + if (iter == value_.data.object->end()) + { + throw json_invalid_key(); + } + return iter->second; + } + + public: + // implicitly convert functions + + template + inline operator _Ty() const + { + return get<_Ty>(); + } + + public: + // dumps functions + + friend std::basic_ostream& operator<<(std::basic_ostream& out, const basic_json& json) + { + using char_type = typename std::basic_ostream::char_type; + + const bool pretty_print = (out.width() > 0); + const auto indentation = (pretty_print ? out.width() : 0); + out.width(0); + + __json_detail::stream_output_adapter adapter(out); + __json_detail::json_serializer(&adapter, out.fill()).dump(json, pretty_print, static_cast(indentation)); + return out; + } + + string_type dump( + const int indent = -1, + const char_type indent_char = ' ') const + { + string_type result; + __json_detail::string_output_adapter adapter(result); + dump(&adapter, indent, indent_char); + return result; + } + + void dump( + __json_detail::output_adapter* adapter, + const int indent = -1, + const char_type indent_char = ' ') const + { + if (indent >= 0) + { + __json_detail::json_serializer(adapter, indent_char).dump(*this, true, static_cast(indent)); + } + else + { + __json_detail::json_serializer(adapter, indent_char).dump(*this, false, 0); + } + } + + public: + // parse functions + + friend std::basic_istream& + operator>>(std::basic_istream& in, basic_json& json) + { + __json_detail::stream_input_adapter adapter(in); + __json_detail::json_parser(&adapter).parse(json); + return in; + } + + static inline basic_json parse(const string_type& str) + { + __json_detail::string_input_adapter adapter(str); + return parse(&adapter); + } + + static inline basic_json parse(const char_type* str) + { + __json_detail::buffer_input_adapter adapter(str); + return parse(&adapter); + } + + static inline basic_json parse(std::FILE* file) + { + __json_detail::file_input_adapter adapter(file); + return parse(&adapter); + } + + static inline basic_json parse(__json_detail::input_adapter* adapter) + { + basic_json result; + __json_detail::json_parser(adapter).parse(result); + return result; + } + + public: + // compare functions + + friend bool operator==(const basic_json& lhs, const basic_json& rhs) + { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case JsonType::Array: + return (*lhs.value_.data.vector == *rhs.value_.data.vector); + + case JsonType::Object: + return (*lhs.value_.data.object == *rhs.value_.data.object); + + case JsonType::Null: + return true; + + case JsonType::String: + return (*lhs.value_.data.string == *rhs.value_.data.string); + + case JsonType::Boolean: + return (lhs.value_.data.boolean == rhs.value_.data.boolean); + + case JsonType::Integer: + return (lhs.value_.data.number_integer == rhs.value_.data.number_integer); + + case JsonType::Float: + return (lhs.value_.data.number_float == rhs.value_.data.number_float); + + default: + return false; + } + } + else if (lhs_type == JsonType::Integer && rhs_type == JsonType::Float) + { + return (static_cast(lhs.value_.data.number_integer) == rhs.value_.data.number_float); + } + else if (lhs_type == JsonType::Float && rhs_type == JsonType::Integer) + { + return (lhs.value_.data.number_float == static_cast(rhs.value_.data.number_integer)); + } + + return false; + } + + friend bool operator!=(const basic_json& lhs, const basic_json& rhs) + { + return !(lhs == rhs); + } + + friend bool operator<(const basic_json& lhs, const basic_json& rhs) + { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case JsonType::Array: + return (*lhs.value_.data.vector) < (*rhs.value_.data.vector); + + case JsonType::Object: + return (*lhs.value_.data.object) < (*rhs.value_.data.object); + + case JsonType::Null: + return false; + + case JsonType::String: + return (*lhs.value_.data.string) < (*rhs.value_.data.string); + + case JsonType::Boolean: + return (lhs.value_.data.boolean < rhs.value_.data.boolean); + + case JsonType::Integer: + return (lhs.value_.data.number_integer < rhs.value_.data.number_integer); + + case JsonType::Float: + return (lhs.value_.data.number_float < rhs.value_.data.number_float); + + default: + return false; + } + } + else if (lhs_type == JsonType::Integer && rhs_type == JsonType::Float) + { + return (static_cast(lhs.value_.data.number_integer) < rhs.value_.data.number_float); + } + else if (lhs_type == JsonType::Float && rhs_type == JsonType::Integer) + { + return (lhs.value_.data.number_float < static_cast(rhs.value_.data.number_integer)); + } + + return false; + } + + friend bool operator<=(const basic_json& lhs, const basic_json& rhs) + { + return !(rhs < lhs); + } + + friend bool operator>(const basic_json& lhs, const basic_json& rhs) + { + return rhs < lhs; + } + + friend bool operator>=(const basic_json& lhs, const basic_json& rhs) + { + return !(lhs < rhs); + } private: - JsonValue value_; + __json_detail::json_value value_; }; #undef E2D_DECLARE_BASIC_JSON_TEMPLATE diff --git a/easy2d/common/String.h b/easy2d/common/String.h index 273cbca0..3bce8361 100644 --- a/easy2d/common/String.h +++ b/easy2d/common/String.h @@ -1080,7 +1080,7 @@ namespace easy2d using size_type = String::size_type; using traits = String::char_traits; - const typename ostream::sentry ok(os); + const ostream::sentry ok(os); std::ios_base::iostate state = std::ios_base::goodbit; if (!ok) @@ -1142,7 +1142,7 @@ namespace easy2d using traits = String::char_traits; bool changed = false; - const typename istream::sentry ok(is); + const istream::sentry ok(is); std::ios_base::iostate state = std::ios_base::goodbit; if (ok) diff --git a/easy2d/common/helper.h b/easy2d/common/helper.h index 591c66f8..853f62b1 100644 --- a/easy2d/common/helper.h +++ b/easy2d/common/helper.h @@ -48,7 +48,4 @@ namespace easy2d template using UnorderedMap = std::unordered_map<_Kty, _Ty, _Args...>; - - template - using enable_if_t = typename std::enable_if<_Boolean, _Ty>::type; } diff --git a/easy2d/easy2d.h b/easy2d/easy2d.h index 439d001d..5049f52e 100644 --- a/easy2d/easy2d.h +++ b/easy2d/easy2d.h @@ -71,8 +71,8 @@ #include "base/Event.hpp" #include "base/EventListener.h" #include "base/EventDispatcher.h" -#include "base/Task.h" -#include "base/TaskManager.h" +#include "base/Timer.h" +#include "base/TimerManager.h" #include "2d/Font.hpp" #include "2d/Color.h" diff --git a/samples/Samples/main.cpp b/samples/Samples/main.cpp index 666aa65f..14e197e9 100644 --- a/samples/Samples/main.cpp +++ b/samples/Samples/main.cpp @@ -29,7 +29,6 @@ class DemoApp public: DemoApp() { - ShowConsole(); // 使用 Audio 组件 Use(&Audio::Instance());