From 03edd40ecdb4e5c909647b15765a1caec92f5887 Mon Sep 17 00:00:00 2001 From: Nomango Date: Wed, 11 Dec 2019 13:44:40 +0800 Subject: [PATCH 01/27] update intrusive_ptr --- src/kiwano-audio/SoundPlayer.cpp | 8 +-- src/kiwano-physics/Joint.cpp | 2 +- src/kiwano-physics/Joint.h | 2 +- src/kiwano/2d/Actor.cpp | 10 ++-- src/kiwano/2d/Canvas.h | 2 +- src/kiwano/common/intrusive_list.hpp | 14 ++--- src/kiwano/common/intrusive_ptr.hpp | 45 +++++++------- src/kiwano/common/vector.hpp | 2 +- src/kiwano/renderer/Geometry.cpp | 58 ++++++------------- src/kiwano/renderer/Geometry.h | 28 +++++---- src/kiwano/renderer/RenderTarget.cpp | 30 +++++----- src/kiwano/renderer/RenderTarget.h | 30 +++++----- src/kiwano/renderer/Renderer.h | 4 +- src/kiwano/renderer/TextLayout.h | 2 +- .../renderer/win32/D2DDeviceResources.cpp | 18 +++--- .../renderer/win32/D2DDeviceResources.h | 28 ++++----- .../renderer/win32/D3D10DeviceResources.h | 10 ++-- .../renderer/win32/D3D11DeviceResources.h | 12 ++-- src/kiwano/ui/Menu.cpp | 2 +- src/kiwano/utils/ResourceCache.h | 2 +- 20 files changed, 148 insertions(+), 161 deletions(-) diff --git a/src/kiwano-audio/SoundPlayer.cpp b/src/kiwano-audio/SoundPlayer.cpp index 1d81484f..5146b885 100644 --- a/src/kiwano-audio/SoundPlayer.cpp +++ b/src/kiwano-audio/SoundPlayer.cpp @@ -118,7 +118,7 @@ namespace kiwano void SoundPlayer::SetVolume(float volume) { volume_ = std::min(std::max(volume, -224.f), 224.f); - for (const auto& pair : sound_cache_) + for (auto& pair : sound_cache_) { pair.second->SetVolume(volume_); } @@ -126,7 +126,7 @@ namespace kiwano void SoundPlayer::PauseAll() { - for (const auto& pair : sound_cache_) + for (auto& pair : sound_cache_) { pair.second->Pause(); } @@ -134,7 +134,7 @@ namespace kiwano void SoundPlayer::ResumeAll() { - for (const auto& pair : sound_cache_) + for (auto& pair : sound_cache_) { pair.second->Resume(); } @@ -142,7 +142,7 @@ namespace kiwano void SoundPlayer::StopAll() { - for (const auto& pair : sound_cache_) + for (auto& pair : sound_cache_) { pair.second->Stop(); } diff --git a/src/kiwano-physics/Joint.cpp b/src/kiwano-physics/Joint.cpp index 08be38b7..05b209d7 100644 --- a/src/kiwano-physics/Joint.cpp +++ b/src/kiwano-physics/Joint.cpp @@ -207,7 +207,7 @@ namespace kiwano { } - GearJoint::GearJoint(World* world, GearJoint::Param const& param) + GearJoint::GearJoint(World* world, GearJoint::Param param) : Joint() , raw_joint_(nullptr) { diff --git a/src/kiwano-physics/Joint.h b/src/kiwano-physics/Joint.h index 46548a4f..1168d27f 100644 --- a/src/kiwano-physics/Joint.h +++ b/src/kiwano-physics/Joint.h @@ -237,7 +237,7 @@ namespace kiwano GearJoint(); GearJoint(World* world, b2GearJointDef* def); - GearJoint(World* world, Param const& param); + GearJoint(World* world, Param param); // É趨³ÝÂÖ´«¶¯±È void SetRatio(float ratio); diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index ec4f0eff..427c2c9f 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -272,7 +272,7 @@ namespace kiwano } // update children's transform - for (Actor* child = children_.first_item().get(); child; child = child->next_item().get()) + for (auto child = children_.first_item().get(); child; child = child->next_item().get()) child->dirty_transform_ = true; } @@ -527,11 +527,11 @@ namespace kiwano Vector children; size_t hash_code = std::hash{}(name); - for (Actor* child = children_.first_item().get(); child; child = child->next_item().get()) + for (auto child = children_.first_item().get(); child; child = child->next_item().get()) { if (child->hash_name_ == hash_code && child->IsName(name)) { - children.push_back(child); + children.push_back(const_cast(child)); } } return children; @@ -541,11 +541,11 @@ namespace kiwano { size_t hash_code = std::hash{}(name); - for (Actor* child = children_.first_item().get(); child; child = child->next_item().get()) + for (auto child = children_.first_item().get(); child; child = child->next_item().get()) { if (child->hash_name_ == hash_code && child->IsName(name)) { - return child; + return const_cast(child); } } return nullptr; diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h index eefaee8e..b05976e8 100644 --- a/src/kiwano/2d/Canvas.h +++ b/src/kiwano/2d/Canvas.h @@ -247,9 +247,9 @@ namespace kiwano TextStyle text_style_; StrokeStyle stroke_style_; GeometrySink geo_sink_; - TextureRenderTarget rt_; mutable bool cache_expired_; mutable Texture texture_cached_; + mutable TextureRenderTarget rt_; }; } diff --git a/src/kiwano/common/intrusive_list.hpp b/src/kiwano/common/intrusive_list.hpp index 0e49d091..c2c62b00 100644 --- a/src/kiwano/common/intrusive_list.hpp +++ b/src/kiwano/common/intrusive_list.hpp @@ -43,8 +43,8 @@ class intrusive_list_item { public: using value_type = _Ty; - using reference = value_type&; - using const_reference = const value_type&; + using reference = _Ty&; + using const_reference = const _Ty&; intrusive_list_item() : prev_(), next_() {} intrusive_list_item(_Ty const& rhs) : prev_(rhs->prev_), next_(rhs->next_) {} @@ -80,7 +80,7 @@ public: reference last_item() { return last_; } bool empty() const { return !first_; } - void push_back(const_reference child) + void push_back(value_type child) { if (child->prev_) child->prev_->next_ = child->next_; @@ -104,7 +104,7 @@ public: KGE_DEBUG_CHECK_LIST(this); } - void push_front(const_reference child) + void push_front(value_type child) { if (child->prev_) child->prev_->next_ = child->next_; @@ -128,7 +128,7 @@ public: KGE_DEBUG_CHECK_LIST(this); } - void insert_before(const_reference child, const_reference before) + void insert_before(value_type child, value_type before) { if (child->prev_) child->prev_->next_ = child->next_; @@ -147,7 +147,7 @@ public: KGE_DEBUG_CHECK_LIST(this); } - void insert_after(const_reference child, const_reference after) + void insert_after(value_type child, value_type after) { if (child->prev_) child->prev_->next_ = child->next_; @@ -166,7 +166,7 @@ public: KGE_DEBUG_CHECK_LIST(this); } - void remove(const_reference child) + void remove(value_type child) { #ifdef KGE_DEBUG_ENABLE_LIST_CHECK _Ty tmp = first_; diff --git a/src/kiwano/common/intrusive_ptr.hpp b/src/kiwano/common/intrusive_ptr.hpp index 70aadb9c..168aa5e3 100644 --- a/src/kiwano/common/intrusive_ptr.hpp +++ b/src/kiwano/common/intrusive_ptr.hpp @@ -36,35 +36,40 @@ public: using value_type = _Ty; using pointer_type = _Ty*; using const_pointer_type = const _Ty*; + using reference_type = _Ty&; + using const_reference_type = const _Ty&; using manager_type = _ManagerTy; - intrusive_ptr() noexcept {} - intrusive_ptr(std::nullptr_t) noexcept {} - intrusive_ptr(pointer_type p) : ptr_(p) { typename manager_type::AddRef(ptr_); } - intrusive_ptr(const intrusive_ptr& other) : ptr_(other.ptr_) { typename manager_type::AddRef(ptr_); } - intrusive_ptr(intrusive_ptr&& other) noexcept { ptr_ = other.ptr_; other.ptr_ = nullptr; } - ~intrusive_ptr() { typename manager_type::Release(ptr_); } + intrusive_ptr() noexcept : ptr_(nullptr) {} + intrusive_ptr(std::nullptr_t) noexcept : ptr_(nullptr) {} + intrusive_ptr(pointer_type p) : ptr_(p) { typename manager_type::AddRef(ptr_); } + intrusive_ptr(const intrusive_ptr& other) : ptr_(other.ptr_) { typename manager_type::AddRef(ptr_); } + intrusive_ptr(intrusive_ptr&& other) noexcept : ptr_(nullptr) { swap(other); } + ~intrusive_ptr() { reset(); } template - intrusive_ptr(const intrusive_ptr<_UTy, manager_type>& other) : ptr_(other.get()) { typename manager_type::AddRef(ptr_); } + intrusive_ptr(const intrusive_ptr<_UTy, manager_type>& other) { ptr_ = const_cast(dynamic_cast(other.get())); typename manager_type::AddRef(ptr_); } - inline pointer_type get() const noexcept { return ptr_; } - inline void reset(pointer_type ptr = nullptr) { intrusive_ptr{ ptr }.swap(*this); } - inline void swap(intrusive_ptr& other) noexcept { std::swap(ptr_, other.ptr_); } + inline pointer_type get() noexcept { return ptr_; } + inline const_pointer_type get() const noexcept { return ptr_; } + inline void reset(pointer_type ptr = nullptr) { typename manager_type::Release(ptr_); ptr_ = nullptr; } + inline void swap(intrusive_ptr& other) noexcept { std::swap(ptr_, other.ptr_); } - inline pointer_type operator ->() const { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } - inline value_type& operator *() const { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } - inline pointer_type* operator &() { KGE_ASSERT(ptr_ == nullptr && "Memory leak"); return &ptr_; } - inline operator bool() const noexcept { return ptr_ != nullptr; } - inline bool operator !() const noexcept { return ptr_ == 0; } + inline pointer_type operator ->() { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } + inline const_pointer_type operator ->() const { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } + inline reference_type operator *() { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } + inline const_reference_type operator *() const { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } + inline pointer_type* operator &() { KGE_ASSERT(ptr_ == nullptr && "Memory leak"); return &ptr_; } + inline operator bool() const noexcept { return ptr_ != nullptr; } + inline bool operator !() const noexcept { return ptr_ == 0; } - inline const intrusive_ptr& operator=(const intrusive_ptr& other) const { if (other.ptr_ != ptr_) intrusive_ptr(other).swap(*const_cast(this)); return *this; } - inline const intrusive_ptr& operator=(intrusive_ptr&& other) const noexcept { if (other.ptr_ != ptr_) other.swap(*const_cast(this)); return *this; } - inline const intrusive_ptr& operator=(pointer_type p) const { if (p != ptr_) intrusive_ptr(p).swap(*const_cast(this)); return *this; } - inline const intrusive_ptr& operator=(std::nullptr_t) const noexcept { if (nullptr != ptr_) intrusive_ptr{}.swap(*const_cast(this)); return *this; } + inline intrusive_ptr& operator=(const intrusive_ptr& other) { if (other.ptr_ != ptr_) intrusive_ptr(other).swap(*this); return (*this); } + inline intrusive_ptr& operator=(intrusive_ptr&& other) noexcept { if (other.ptr_ != ptr_) other.swap(*this); return (*this); } + inline intrusive_ptr& operator=(pointer_type p) { if (p != ptr_) intrusive_ptr(p).swap(*this); return (*this); } + inline intrusive_ptr& operator=(std::nullptr_t) { reset(); return *this; } private: - pointer_type ptr_{ nullptr }; + pointer_type ptr_; }; template diff --git a/src/kiwano/common/vector.hpp b/src/kiwano/common/vector.hpp index dc8f9e0d..497357d0 100644 --- a/src/kiwano/common/vector.hpp +++ b/src/kiwano/common/vector.hpp @@ -21,7 +21,7 @@ #pragma once #include #include -#include +#include namespace kiwano { diff --git a/src/kiwano/renderer/Geometry.cpp b/src/kiwano/renderer/Geometry.cpp index 6b008ffc..e8d204b6 100644 --- a/src/kiwano/renderer/Geometry.cpp +++ b/src/kiwano/renderer/Geometry.cpp @@ -92,14 +92,10 @@ namespace kiwano return false; } - Geometry Geometry::CombineWith(Geometry input, CombineMode mode, Matrix3x2 const& input_matrix) const + void Geometry::CombineWith(GeometrySink& sink, Geometry input, CombineMode mode, Matrix3x2 const& input_matrix) const { if (geo_ && input.geo_) { - GeometrySink sink; - sink.Init(); - sink.OpenSink(); - ThrowIfFailed( geo_->CombineWithGeometry( input.geo_.get(), @@ -108,41 +104,18 @@ namespace kiwano sink.GetGeometrySink().get() ) ); - - sink.CloseSink(); - return sink.GetGeometry(); } - return Geometry(); } - Geometry Geometry::Combine(Vector const& geos, Vector const& modes, Vector const& matrixs) + Geometry Geometry::CombineWith(Geometry input, CombineMode mode, Matrix3x2 const& input_matrix) const { - if ((geos.size() == (modes.size() + 1) || modes.size() == 1) - && (geos.size() == (matrixs.size() + 1) || matrixs.size() == 1)) - { - GeometrySink sink; - sink.Init(); - sink.OpenSink(); + GeometrySink sink; + sink.Open(); - for (size_t i = 0; i < geos.size() - 1; i++) - { - CombineMode mode = (modes.size() == 1) ? modes[0] : modes[i]; - const Matrix3x2& matrix = (matrixs.size() == 1) ? matrixs[0] : matrixs[i]; + CombineWith(sink, input, mode, input_matrix); - ThrowIfFailed( - geos[i].geo_->CombineWithGeometry( - geos[i + 1].geo_.get(), - D2D1_COMBINE_MODE(mode), - DX::ConvertToMatrix3x2F(matrix), - sink.GetGeometrySink().get() - ) - ); - } - - sink.CloseSink(); - return sink.GetGeometry(); - } - return Geometry(); + sink.Close(); + return sink.GetGeometry(); } float Geometry::ComputeArea() const @@ -214,13 +187,16 @@ namespace kiwano { } + GeometrySink::~GeometrySink() + { + Close(); + } + GeometrySink& GeometrySink::BeginPath(Point const& begin_pos) { - Init(); - if (!sink_) { - OpenSink(); + Open(); } sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED); @@ -233,7 +209,7 @@ namespace kiwano { sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN); - CloseSink(); + Close(); } return (*this); } @@ -312,15 +288,17 @@ namespace kiwano } } - void GeometrySink::OpenSink() + void GeometrySink::Open() { + Init(); + if (!sink_) { ThrowIfFailed(path_geo_->Open(&sink_)); } } - void GeometrySink::CloseSink() + void GeometrySink::Close() { if (sink_) { diff --git a/src/kiwano/renderer/Geometry.h b/src/kiwano/renderer/Geometry.h index 859e07cc..ea3daa6c 100644 --- a/src/kiwano/renderer/Geometry.h +++ b/src/kiwano/renderer/Geometry.h @@ -23,6 +23,7 @@ namespace kiwano { + class GeometrySink; // ¼¸ºÎÌå class KGE_API Geometry @@ -72,19 +73,19 @@ namespace kiwano ) const; // ×éºÏ¼¸ºÎÌå - Geometry CombineWith( + void CombineWith( + GeometrySink& sink, Geometry input, CombineMode mode, Matrix3x2 const& input_matrix = Matrix3x2() ) const; - // ×éºÏ¶à¸ö¼¸ºÎÌå - // ²ÎÊý modes ºÍ matrixs µÄÊýÁ¿Ó¦Îª 1 »ò geos µÄÊýÁ¿¼õÒ» - static Geometry Combine( - Vector const& geos, - Vector const& modes, - Vector const& matrixs = { Matrix3x2() } - ); + // ×éºÏ¼¸ºÎÌå + Geometry CombineWith( + Geometry input, + CombineMode mode, + Matrix3x2 const& input_matrix = Matrix3x2() + ) const; // ´´½¨Ö±Ïß static Geometry CreateLine( @@ -133,6 +134,7 @@ namespace kiwano { public: GeometrySink(); + ~GeometrySink(); // ¿ªÊ¼Ìí¼Ó·¾¶ GeometrySink& BeginPath( @@ -179,6 +181,12 @@ namespace kiwano // »ñÈ¡Éú³É·¾¶¼¸ºÎÌå Geometry GetGeometry(); + // ´ò¿ªÁ÷ + void Open(); + + // ¹Ø±ÕÁ÷ + void Close(); + public: inline ComPtr GetPathGeometry() const { return path_geo_; } @@ -190,10 +198,6 @@ namespace kiwano void Init(); - void OpenSink(); - - void CloseSink(); - protected: ComPtr path_geo_; ComPtr sink_; diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp index cbe5a428..f1fea6c9 100644 --- a/src/kiwano/renderer/RenderTarget.cpp +++ b/src/kiwano/renderer/RenderTarget.cpp @@ -113,7 +113,7 @@ namespace kiwano } } - void RenderTarget::DrawGeometry(Geometry const& geometry, float stroke_width, StrokeStyle stroke) const + void RenderTarget::DrawGeometry(Geometry const& geometry, float stroke_width, StrokeStyle stroke) { HRESULT hr = S_OK; if (!render_target_ || !current_brush_) @@ -136,7 +136,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::FillGeometry(Geometry const& geometry) const + void RenderTarget::FillGeometry(Geometry const& geometry) { HRESULT hr = S_OK; if (!render_target_ || !current_brush_) @@ -157,7 +157,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::DrawLine(Point const& point1, Point const& point2, float stroke_width, StrokeStyle stroke) const + void RenderTarget::DrawLine(Point const& point1, Point const& point2, float stroke_width, StrokeStyle stroke) { HRESULT hr = S_OK; if (!render_target_ || !current_brush_) @@ -181,7 +181,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::DrawRectangle(Rect const& rect, float stroke_width, StrokeStyle stroke) const + void RenderTarget::DrawRectangle(Rect const& rect, float stroke_width, StrokeStyle stroke) { HRESULT hr = S_OK; @@ -205,7 +205,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::FillRectangle(Rect const& rect) const + void RenderTarget::FillRectangle(Rect const& rect) { HRESULT hr = S_OK; if (!render_target_ || !current_brush_) @@ -226,7 +226,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, float stroke_width, StrokeStyle stroke) const + void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, float stroke_width, StrokeStyle stroke) { HRESULT hr = S_OK; if (!render_target_ || !current_brush_) @@ -253,7 +253,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius) const + void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius) { HRESULT hr = S_OK; if (!render_target_ || !current_brush_) @@ -278,7 +278,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, float stroke_width, StrokeStyle stroke) const + void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, float stroke_width, StrokeStyle stroke) { HRESULT hr = S_OK; if (!render_target_ || !current_brush_) @@ -305,7 +305,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius) const + void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius) { HRESULT hr = S_OK; if (!render_target_ || !current_brush_) @@ -330,12 +330,12 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect) const + void RenderTarget::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect) { DrawTexture(texture, &src_rect, &dest_rect); } - void RenderTarget::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect) const + void RenderTarget::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect) { HRESULT hr = S_OK; if (!render_target_) @@ -363,7 +363,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::DrawTextLayout(TextLayout const& layout, Point const& offset) const + void RenderTarget::DrawTextLayout(TextLayout const& layout, Point const& offset) { HRESULT hr = S_OK; if (!text_renderer_) @@ -393,7 +393,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::CreateLayer(LayerArea& layer) const + void RenderTarget::CreateLayer(LayerArea& layer) { HRESULT hr = S_OK; @@ -540,7 +540,7 @@ namespace kiwano return global_transform_; } - ComPtr RenderTarget::GetStrokeStyle(StrokeStyle style) const + ComPtr RenderTarget::GetStrokeStyle(StrokeStyle style) { switch (style) { @@ -710,7 +710,7 @@ namespace kiwano { } - Texture TextureRenderTarget::GetOutput() const + Texture TextureRenderTarget::GetOutput() { HRESULT hr = E_FAIL; diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h index c886da3e..41f78436 100644 --- a/src/kiwano/renderer/RenderTarget.h +++ b/src/kiwano/renderer/RenderTarget.h @@ -52,75 +52,75 @@ namespace kiwano void CreateLayer( LayerArea& layer - ) const; + ); void DrawGeometry( Geometry const& geometry, float stroke_width, StrokeStyle stroke = StrokeStyle::Miter - ) const; + ); void FillGeometry( Geometry const& geometry - ) const; + ); void DrawLine( Point const& point1, Point const& point2, float stroke_width, StrokeStyle stroke = StrokeStyle::Miter - ) const; + ); void DrawRectangle( Rect const& rect, float stroke_width, StrokeStyle stroke = StrokeStyle::Miter - ) const; + ); void FillRectangle( Rect const& rect - ) const; + ); void DrawRoundedRectangle( Rect const& rect, Vec2 const& radius, float stroke_width, StrokeStyle stroke = StrokeStyle::Miter - ) const; + ); void FillRoundedRectangle( Rect const& rect, Vec2 const& radius - ) const; + ); void DrawEllipse( Point const& center, Vec2 const& radius, float stroke_width, StrokeStyle stroke = StrokeStyle::Miter - ) const; + ); void FillEllipse( Point const& center, Vec2 const& radius - ) const; + ); void DrawTexture( Texture const& texture, Rect const& src_rect, Rect const& dest_rect - ) const; + ); void DrawTexture( Texture const& texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr - ) const; + ); void DrawTextLayout( TextLayout const& layout, Point const& offset = Point{} - ) const; + ); void PushClipRect( Rect const& clip_rect @@ -206,7 +206,7 @@ namespace kiwano inline ComPtr GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_; } - ComPtr GetStrokeStyle(StrokeStyle style) const; + ComPtr GetStrokeStyle(StrokeStyle style); public: RenderTarget(); @@ -241,6 +241,6 @@ namespace kiwano public: TextureRenderTarget(); - Texture GetOutput() const; + Texture GetOutput(); }; } diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index 53488183..14ee8ca6 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -192,9 +192,9 @@ namespace kiwano inline Color const& GetClearColor() const { return clear_color_; } - inline ID2DDeviceResources* GetD2DDeviceResources() const { KGE_ASSERT(d2d_res_); return d2d_res_.get(); } + inline ID2DDeviceResources* GetD2DDeviceResources() { KGE_ASSERT(d2d_res_); return d2d_res_.get(); } - inline ID3DDeviceResources* GetD3DDeviceResources() const { KGE_ASSERT(d3d_res_); return d3d_res_.get(); } + inline ID3DDeviceResources* GetD3DDeviceResources() { KGE_ASSERT(d3d_res_); return d3d_res_.get(); } private: Renderer(); diff --git a/src/kiwano/renderer/TextLayout.h b/src/kiwano/renderer/TextLayout.h index cb5ad358..cc2c6d3c 100644 --- a/src/kiwano/renderer/TextLayout.h +++ b/src/kiwano/renderer/TextLayout.h @@ -76,6 +76,6 @@ namespace kiwano protected: TextStyle style_; TextFormat text_format_; - ComPtr text_layout_; + mutable ComPtr text_layout_; }; } diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp index 4ccdb0cd..d6e4bffc 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp @@ -66,20 +66,20 @@ namespace kiwano HRESULT CreateTextFormat( _Out_ ComPtr& text_format, _In_ Font const& font - ) const override; + ) override; HRESULT CreateTextLayout( _Out_ ComPtr& text_layout, _In_ String const& text, - _In_ ComPtr const& text_format - ) const override; + _In_ ComPtr text_format + ) override; HRESULT SetD2DDevice( - _In_ ComPtr const& device + _In_ ComPtr device ) override; void SetTargetBitmap( - _In_ ComPtr const& target + _In_ ComPtr target ) override; void DiscardResources() override; @@ -298,7 +298,7 @@ namespace kiwano return hr; } - HRESULT D2DDeviceResources::SetD2DDevice(_In_ ComPtr const& device) + HRESULT D2DDeviceResources::SetD2DDevice(_In_ ComPtr device) { ComPtr device_ctx; @@ -317,7 +317,7 @@ namespace kiwano return hr; } - void D2DDeviceResources::SetTargetBitmap(_In_ ComPtr const& target) + void D2DDeviceResources::SetTargetBitmap(_In_ ComPtr target) { target_bitmap_ = target; if (device_context_) @@ -435,7 +435,7 @@ namespace kiwano return hr; } - HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, _In_ Font const & font) const + HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, _In_ Font const & font) { if (!dwrite_factory_) return E_UNEXPECTED; @@ -460,7 +460,7 @@ namespace kiwano } HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr& text_layout, _In_ String const& text, - _In_ ComPtr const& text_format) const + _In_ ComPtr text_format) { if (!dwrite_factory_) return E_UNEXPECTED; diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.h b/src/kiwano/renderer/win32/D2DDeviceResources.h index 31ca7a0d..be14483d 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.h +++ b/src/kiwano/renderer/win32/D2DDeviceResources.h @@ -217,34 +217,34 @@ namespace kiwano virtual HRESULT CreateTextFormat( _Out_ ComPtr& text_format, _In_ Font const& font - ) const = 0; + ) = 0; virtual HRESULT CreateTextLayout( _Out_ ComPtr& text_layout, _In_ String const& text, - _In_ ComPtr const& text_format - ) const = 0; + _In_ ComPtr text_format + ) = 0; virtual HRESULT SetD2DDevice( - _In_ ComPtr const& device + _In_ ComPtr device ) = 0; virtual void SetTargetBitmap( - _In_ ComPtr const& target + _In_ ComPtr target ) = 0; virtual void DiscardResources() = 0; - inline ID2D1Factory1* GetFactory() const { KGE_ASSERT(factory_); return factory_.get(); } - inline IWICImagingFactory* GetWICImagingFactory() const { KGE_ASSERT(imaging_factory_); return imaging_factory_.get(); } - inline IDWriteFactory* GetDWriteFactory() const { KGE_ASSERT(dwrite_factory_); return dwrite_factory_.get(); } - inline ID2D1Device* GetDevice() const { KGE_ASSERT(device_); return device_.get(); } - inline ID2D1DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.get(); } - inline ID2D1Bitmap1* GetTargetBitmap() const { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); } + inline ID2D1Factory1* GetFactory() { KGE_ASSERT(factory_); return factory_.get(); } + inline IWICImagingFactory* GetWICImagingFactory() { KGE_ASSERT(imaging_factory_); return imaging_factory_.get(); } + inline IDWriteFactory* GetDWriteFactory() { KGE_ASSERT(dwrite_factory_); return dwrite_factory_.get(); } + inline ID2D1Device* GetDevice() { KGE_ASSERT(device_); return device_.get(); } + inline ID2D1DeviceContext* GetDeviceContext() { KGE_ASSERT(device_context_); return device_context_.get(); } + inline ID2D1Bitmap1* GetTargetBitmap() { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); } - inline ID2D1StrokeStyle* GetMiterStrokeStyle() const { KGE_ASSERT(miter_stroke_style_); return miter_stroke_style_.get(); } - inline ID2D1StrokeStyle* GetBevelStrokeStyle() const { KGE_ASSERT(bevel_stroke_style_); return bevel_stroke_style_.get(); } - inline ID2D1StrokeStyle* GetRoundStrokeStyle() const { KGE_ASSERT(round_stroke_style_); return round_stroke_style_.get(); } + inline ID2D1StrokeStyle* GetMiterStrokeStyle() { KGE_ASSERT(miter_stroke_style_); return miter_stroke_style_.get(); } + inline ID2D1StrokeStyle* GetBevelStrokeStyle() { KGE_ASSERT(bevel_stroke_style_); return bevel_stroke_style_.get(); } + inline ID2D1StrokeStyle* GetRoundStrokeStyle() { KGE_ASSERT(round_stroke_style_); return round_stroke_style_.get(); } protected: ComPtr factory_; diff --git a/src/kiwano/renderer/win32/D3D10DeviceResources.h b/src/kiwano/renderer/win32/D3D10DeviceResources.h index 9a5962ae..1d72688c 100644 --- a/src/kiwano/renderer/win32/D3D10DeviceResources.h +++ b/src/kiwano/renderer/win32/D3D10DeviceResources.h @@ -35,11 +35,11 @@ namespace kiwano public: static HRESULT Create(ID3D10DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd); - inline ID3D10Device* GetDevice() const { KGE_ASSERT(device_); return device_.get(); } - inline ID3D10RenderTargetView* GetRenderTargetView() const { KGE_ASSERT(rt_view_); return rt_view_.get(); } - inline ID3D10DepthStencilView* GetDepthStencilView() const { KGE_ASSERT(ds_view_); return ds_view_.get(); } - inline IDXGIFactory* GetDXGIFactory() const { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.get(); } - inline IDXGISwapChain* GetDXGISwapChain() const { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.get(); } + inline ID3D10Device* GetDevice() { KGE_ASSERT(device_); return device_.get(); } + inline ID3D10RenderTargetView* GetRenderTargetView() { KGE_ASSERT(rt_view_); return rt_view_.get(); } + inline ID3D10DepthStencilView* GetDepthStencilView() { KGE_ASSERT(ds_view_); return ds_view_.get(); } + inline IDXGIFactory* GetDXGIFactory() { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.get(); } + inline IDXGISwapChain* GetDXGISwapChain() { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.get(); } protected: ComPtr device_; diff --git a/src/kiwano/renderer/win32/D3D11DeviceResources.h b/src/kiwano/renderer/win32/D3D11DeviceResources.h index 2e50c2be..a7b9d65a 100644 --- a/src/kiwano/renderer/win32/D3D11DeviceResources.h +++ b/src/kiwano/renderer/win32/D3D11DeviceResources.h @@ -35,12 +35,12 @@ namespace kiwano public: static HRESULT Create(ID3D11DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd); - inline ID3D11Device* GetDevice() const { KGE_ASSERT(device_); return device_.get(); } - inline ID3D11DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.get(); } - inline ID3D11RenderTargetView* GetRenderTargetView() const { KGE_ASSERT(rt_view_); return rt_view_.get(); } - inline ID3D11DepthStencilView* GetDepthStencilView() const { KGE_ASSERT(ds_view_); return ds_view_.get(); } - inline IDXGIFactory* GetDXGIFactory() const { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.get(); } - inline IDXGISwapChain* GetDXGISwapChain() const { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.get(); } + inline ID3D11Device* GetDevice() { KGE_ASSERT(device_); return device_.get(); } + inline ID3D11DeviceContext* GetDeviceContext() { KGE_ASSERT(device_context_); return device_context_.get(); } + inline ID3D11RenderTargetView* GetRenderTargetView() { KGE_ASSERT(rt_view_); return rt_view_.get(); } + inline ID3D11DepthStencilView* GetDepthStencilView() { KGE_ASSERT(ds_view_); return ds_view_.get(); } + inline IDXGIFactory* GetDXGIFactory() { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.get(); } + inline IDXGISwapChain* GetDXGISwapChain() { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.get(); } protected: ComPtr device_; diff --git a/src/kiwano/ui/Menu.cpp b/src/kiwano/ui/Menu.cpp index d18531d6..611ccf8b 100644 --- a/src/kiwano/ui/Menu.cpp +++ b/src/kiwano/ui/Menu.cpp @@ -52,7 +52,7 @@ namespace kiwano { enabled_ = enabled; - for (const auto& button : buttons_) + for (auto& button : buttons_) { button->SetEnabled(enabled); } diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h index 15a831e1..ca113b8d 100644 --- a/src/kiwano/utils/ResourceCache.h +++ b/src/kiwano/utils/ResourceCache.h @@ -97,7 +97,7 @@ namespace kiwano auto iter = object_cache_.find(id); if (iter == object_cache_.end()) return nullptr; - return dynamic_cast<_Ty*>((*iter).second.get()); + return const_cast<_Ty*>(dynamic_cast((*iter).second.get())); } protected: From b53f77af059f4e0678115490e3f15b555b9692a0 Mon Sep 17 00:00:00 2001 From: Nomango Date: Tue, 17 Dec 2019 20:47:55 +0800 Subject: [PATCH 02/27] remove common & use OuterC instead --- projects/kiwano/kiwano.vcxproj | 9 - projects/kiwano/kiwano.vcxproj.filters | 27 - src/3rd-party/OuterC/LICENSE | 21 + .../any.hpp => 3rd-party/OuterC/oc/any.h} | 41 +- src/3rd-party/OuterC/oc/function.h | 169 + src/3rd-party/OuterC/oc/function/details.h | 168 + src/3rd-party/OuterC/oc/intrusive_list.h | 254 ++ src/3rd-party/OuterC/oc/intrusive_ptr.h | 201 ++ src/3rd-party/OuterC/oc/json.h | 50 + src/3rd-party/OuterC/oc/json/basic_json.h | 929 ++++++ src/3rd-party/OuterC/oc/json/json_exception.h | 47 + .../OuterC/oc/json/json_intput_adapter.h | 112 + src/3rd-party/OuterC/oc/json/json_iterator.h | 377 +++ .../OuterC/oc/json/json_output_adapter.h | 76 + src/3rd-party/OuterC/oc/json/json_parser.h | 567 ++++ .../OuterC/oc/json/json_serializer.h | 421 +++ src/3rd-party/OuterC/oc/json/json_value.h | 240 ++ .../OuterC/oc/json/json_value_getter.h | 79 + src/3rd-party/OuterC/oc/macros.h | 8 + src/3rd-party/OuterC/oc/noncopyable.h | 19 + src/3rd-party/OuterC/oc/oc.h | 13 + src/3rd-party/OuterC/oc/singleton.h | 50 + .../OuterC/oc/string.h} | 1933 ++++++------ .../OuterC/oc/vector.h} | 154 +- src/3rd-party/OuterC/oc/vector/details.h | 79 + src/kiwano-audio/AudioEngine.h | 4 +- src/kiwano-audio/Sound.cpp | 22 +- src/kiwano-audio/Sound.h | 1 - src/kiwano-audio/SoundPlayer.h | 1 - src/kiwano-audio/Transcoder.cpp | 6 +- src/kiwano-audio/audio-modules.cpp | 2 +- src/kiwano-imgui/ImGuiModule.cpp | 20 +- src/kiwano-imgui/ImGuiModule.h | 4 +- src/kiwano-network/HttpClient.cpp | 66 +- src/kiwano-network/HttpClient.h | 3 +- src/kiwano-network/HttpRequest.h | 3 +- src/kiwano/2d/Actor.cpp | 2 +- src/kiwano/2d/Canvas.cpp | 2 +- src/kiwano/2d/DebugActor.cpp | 4 +- src/kiwano/2d/Frame.cpp | 4 +- src/kiwano/2d/GifSprite.cpp | 8 +- src/kiwano/2d/Stage.cpp | 2 +- src/kiwano/2d/Transition.cpp | 2 +- src/kiwano/2d/action/ActionTween.h | 12 +- src/kiwano/common/basic_json.hpp | 2736 ----------------- src/kiwano/common/common.h | 56 +- src/kiwano/common/function.hpp | 355 --- src/kiwano/common/intrusive_list.hpp | 315 -- src/kiwano/common/intrusive_ptr.hpp | 151 - src/kiwano/common/noncopyable.hpp | 40 - src/kiwano/common/singleton.hpp | 85 - src/kiwano/config.h | 4 +- src/kiwano/core/Library.cpp | 2 +- src/kiwano/core/Logger.cpp | 53 +- src/kiwano/core/Logger.h | 32 +- src/kiwano/core/ObjectBase.cpp | 2 +- src/kiwano/core/RefCounter.hpp | 4 +- src/kiwano/core/Resource.cpp | 8 +- src/kiwano/core/SmartPtr.hpp | 10 +- src/kiwano/core/time.cpp | 2 +- src/kiwano/core/win32/ComPtr.hpp | 10 +- src/kiwano/core/win32/helper.h | 2 +- src/kiwano/kiwano.h | 9 - src/kiwano/platform/Application.cpp | 47 +- src/kiwano/platform/Application.h | 2 +- src/kiwano/platform/Director.h | 2 +- src/kiwano/platform/FileSystem.h | 2 +- src/kiwano/platform/Input.cpp | 4 + src/kiwano/platform/Input.h | 4 +- src/kiwano/platform/Window.cpp | 34 +- src/kiwano/platform/Window.h | 4 +- src/kiwano/platform/modules.cpp | 2 +- src/kiwano/renderer/Brush.cpp | 6 +- src/kiwano/renderer/FontCollection.cpp | 8 +- src/kiwano/renderer/Geometry.cpp | 12 +- src/kiwano/renderer/Geometry.h | 2 +- src/kiwano/renderer/GifImage.cpp | 4 +- src/kiwano/renderer/RenderTarget.h | 2 +- src/kiwano/renderer/Renderer.cpp | 48 +- src/kiwano/renderer/Renderer.h | 4 +- src/kiwano/renderer/TextLayout.cpp | 4 +- src/kiwano/renderer/Texture.cpp | 4 +- src/kiwano/renderer/TextureCache.h | 2 +- src/kiwano/ui/Button.cpp | 4 +- src/kiwano/utils/ResourceCache.cpp | 28 +- src/kiwano/utils/ResourceCache.h | 2 +- src/kiwano/utils/UserData.h | 2 +- 87 files changed, 5167 insertions(+), 5154 deletions(-) create mode 100644 src/3rd-party/OuterC/LICENSE rename src/{kiwano/common/any.hpp => 3rd-party/OuterC/oc/any.h} (86%) create mode 100644 src/3rd-party/OuterC/oc/function.h create mode 100644 src/3rd-party/OuterC/oc/function/details.h create mode 100644 src/3rd-party/OuterC/oc/intrusive_list.h create mode 100644 src/3rd-party/OuterC/oc/intrusive_ptr.h create mode 100644 src/3rd-party/OuterC/oc/json.h create mode 100644 src/3rd-party/OuterC/oc/json/basic_json.h create mode 100644 src/3rd-party/OuterC/oc/json/json_exception.h create mode 100644 src/3rd-party/OuterC/oc/json/json_intput_adapter.h create mode 100644 src/3rd-party/OuterC/oc/json/json_iterator.h create mode 100644 src/3rd-party/OuterC/oc/json/json_output_adapter.h create mode 100644 src/3rd-party/OuterC/oc/json/json_parser.h create mode 100644 src/3rd-party/OuterC/oc/json/json_serializer.h create mode 100644 src/3rd-party/OuterC/oc/json/json_value.h create mode 100644 src/3rd-party/OuterC/oc/json/json_value_getter.h create mode 100644 src/3rd-party/OuterC/oc/macros.h create mode 100644 src/3rd-party/OuterC/oc/noncopyable.h create mode 100644 src/3rd-party/OuterC/oc/oc.h create mode 100644 src/3rd-party/OuterC/oc/singleton.h rename src/{kiwano/common/string.hpp => 3rd-party/OuterC/oc/string.h} (50%) rename src/{kiwano/common/vector.hpp => 3rd-party/OuterC/oc/vector.h} (53%) create mode 100644 src/3rd-party/OuterC/oc/vector/details.h delete mode 100644 src/kiwano/common/basic_json.hpp delete mode 100644 src/kiwano/common/function.hpp delete mode 100644 src/kiwano/common/intrusive_list.hpp delete mode 100644 src/kiwano/common/intrusive_ptr.hpp delete mode 100644 src/kiwano/common/noncopyable.hpp delete mode 100644 src/kiwano/common/singleton.hpp diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index ffe0546b..9b035779 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -15,16 +15,7 @@ - - - - - - - - - diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index 87053e5a..e78486cc 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -150,30 +150,6 @@ 2d - - common - - - common - - - common - - - common - - - common - - - common - - - common - - - common - common @@ -276,9 +252,6 @@ utils - - common - utils diff --git a/src/3rd-party/OuterC/LICENSE b/src/3rd-party/OuterC/LICENSE new file mode 100644 index 00000000..9e74ea5c --- /dev/null +++ b/src/3rd-party/OuterC/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 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. diff --git a/src/kiwano/common/any.hpp b/src/3rd-party/OuterC/oc/any.h similarity index 86% rename from src/kiwano/common/any.hpp rename to src/3rd-party/OuterC/oc/any.h index 0b3dfd6d..fa4594b5 100644 --- a/src/kiwano/common/any.hpp +++ b/src/3rd-party/OuterC/oc/any.h @@ -1,32 +1,11 @@ -// Copyright (c) 2018-2019 Kiwano - 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. +// Copyright (c) 2019-2020 OuterC - Nomango #pragma once #include #include #include -namespace kiwano -{ - -namespace common +namespace oc { class bad_any_cast : public std::exception @@ -133,7 +112,7 @@ public: template const _Ty* cast_pointer() const noexcept { - static_assert(!std::is_void<_Ty>::value, "kiwano::any cannot contain void"); + static_assert(!std::is_void<_Ty>::value, "oc::any cannot contain void"); const type_info* const info = typeinfo(); if (info && (*info == typeid(std::decay<_Ty>::type))) @@ -519,14 +498,14 @@ _Ty any_cast(any&& a) return static_cast<_Ty>(std::move(*ptr)); } -} // namespace common - -} // namespace kiwano +} // namespace oc namespace std { - inline void swap(kiwano::common::any& lhs, kiwano::common::any& rhs) noexcept - { - lhs.swap(rhs); - } + +inline void swap(oc::any& lhs, oc::any& rhs) noexcept +{ + lhs.swap(rhs); +} + } diff --git a/src/3rd-party/OuterC/oc/function.h b/src/3rd-party/OuterC/oc/function.h new file mode 100644 index 00000000..af9cce32 --- /dev/null +++ b/src/3rd-party/OuterC/oc/function.h @@ -0,0 +1,169 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include "function/details.h" +#include + +namespace oc +{ + +class bad_function_call : public ::std::exception +{ +public: + bad_function_call() {} + + virtual const char* what() const override + { + return "bad function call"; + } +}; + + +template +class function; + +template +class function<_Ret(_Args...)> +{ +public: + function() + : callable_(nullptr) + { + } + + function(std::nullptr_t) + : callable_(nullptr) + { + } + + function(const function& rhs) + : callable_(rhs.callable_) + { + if (callable_) callable_->retain(); + } + + function(function&& rhs) noexcept + : callable_(rhs.callable_) + { + rhs.callable_ = nullptr; + } + + function(_Ret(*func)(_Args...)) + { + callable_ = __function_detail::proxy_callable<_Ret(*)(_Args...), _Ret, _Args...>::make(::std::move(func)); + if (callable_) callable_->retain(); + } + + template< + typename _Ty, + typename = typename ::std::enable_if<__function_detail::is_callable<_Ty, _Ret, _Args...>::value, int>::type> + function(_Ty val) + { + callable_ = __function_detail::proxy_callable<_Ty, _Ret, _Args...>::make(::std::move(val)); + if (callable_) callable_->retain(); + } + + template::value || ::std::is_base_of<_Ty, _Uty>::value, int>::type> + function(_Uty* ptr, _Ret(_Ty::* func)(_Args...)) + { + callable_ = __function_detail::proxy_mem_callable<_Ty, _Ret, _Args...>::make(ptr, func); + if (callable_) callable_->retain(); + } + + template::value || ::std::is_base_of<_Ty, _Uty>::value, int>::type> + function(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const) + { + callable_ = __function_detail::proxy_const_mem_callable<_Ty, _Ret, _Args...>::make(ptr, func); + if (callable_) callable_->retain(); + } + + ~function() + { + tidy(); + } + + inline void swap(const function& rhs) + { + std::swap(callable_, rhs.callable_); + } + + inline _Ret operator()(_Args... args) const + { + if (!callable_) + throw bad_function_call(); + return callable_->invoke(::std::forward<_Args>(args)...); + } + + inline operator bool() const + { + return !!callable_; + } + + inline function& operator=(const function& rhs) + { + tidy(); + callable_ = rhs.callable_; + if (callable_) callable_->retain(); + return (*this); + } + + inline function& operator=(function&& rhs) + { + tidy(); + callable_ = rhs.callable_; + rhs.callable_ = nullptr; + return (*this); + } + +private: + inline void tidy() + { + if (callable_) + { + callable_->release(); + callable_ = nullptr; + } + } + +private: + __function_detail::callable<_Ret, _Args...>* callable_; +}; + +template::value || std::is_base_of<_Ty, _Uty>::value, int + >::type, + typename _Ret, + typename... _Args +> +inline function<_Ret(_Args...)> closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...)) +{ + return function<_Ret(_Args...)>(ptr, func); +} + +template::value || std::is_base_of<_Ty, _Uty>::value, int + >::type, + typename _Ret, + typename... _Args +> +inline function<_Ret(_Args...)> closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const) +{ + return function<_Ret(_Args...)>(ptr, func); +} + + +template +inline void swap(oc::function<_Ret(_Args...)>& lhs, oc::function<_Ret(_Args...)>& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/function/details.h b/src/3rd-party/OuterC/oc/function/details.h new file mode 100644 index 00000000..9abefaa1 --- /dev/null +++ b/src/3rd-party/OuterC/oc/function/details.h @@ -0,0 +1,168 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include + +namespace oc +{ +namespace __function_detail +{ + +template +struct is_callable_helper +{ + template + struct class_mem; + + template + struct class_const_mem; + + template + static int test(...); + + template + static char test(class_mem<_Uty, &_Uty::operator()>*); + + template + static char test(class_const_mem<_Uty, &_Uty::operator()>*); + + template< + typename _Uty, + typename _Uret = typename std::decay().operator()(std::declval<_Args>()...))>::type, + typename = typename std::enable_if::value>::type + > + static char test(int); + + static constexpr bool value = sizeof(test<_Ty>(0)) == sizeof(char); +}; + +template +struct is_callable + : public ::std::bool_constant::value> +{ +}; + +// +// callable +// + +template +class callable +{ +public: + virtual ~callable() {} + + virtual void retain() = 0; + virtual void release() = 0; + virtual _Ret invoke(_Args... args) const = 0; +}; + +template +class ref_count_callable + : public callable<_Ret, _Args...> +{ +public: + ref_count_callable() : ref_count_(0) {} + + virtual void retain() override + { + ++ref_count_; + } + + virtual void release() override + { + --ref_count_; + if (ref_count_ <= 0) + { + delete this; + } + } + +private: + int ref_count_; +}; + +template +class proxy_callable + : public ref_count_callable<_Ret, _Args...> +{ +public: + proxy_callable(_Ty&& val) + : callee_(::std::move(val)) + { + } + + virtual _Ret invoke(_Args... args) const override + { + return callee_(::std::forward<_Args&&>(args)...); + } + + static inline callable<_Ret, _Args...>* make(_Ty&& val) + { + return new (::std::nothrow) proxy_callable<_Ty, _Ret, _Args...>(::std::move(val)); + } + +private: + _Ty callee_; +}; + +template +class proxy_mem_callable + : public ref_count_callable<_Ret, _Args...> +{ +public: + typedef _Ret(_Ty::* _FuncType)(_Args...); + + virtual _Ret invoke(_Args... args) const override + { + return (static_cast<_Ty*>(ptr_)->*func_)(::std::forward<_Args>(args)...); + } + + static inline callable<_Ret, _Args...>* make(void* ptr, _FuncType func) + { + return new (::std::nothrow) proxy_mem_callable<_Ty, _Ret, _Args...>(ptr, func); + } + +protected: + proxy_mem_callable(void* ptr, _FuncType func) + : ptr_(ptr) + , func_(func) + { + } + +protected: + void* ptr_; + _FuncType func_; +}; + +template +class proxy_const_mem_callable + : public ref_count_callable<_Ret, _Args...> +{ +public: + typedef _Ret(_Ty::* _FuncType)(_Args...) const; + + virtual _Ret invoke(_Args... args) const override + { + return (static_cast<_Ty*>(ptr_)->*func_)(::std::forward<_Args>(args)...); + } + + static inline callable<_Ret, _Args...>* make(void* ptr, _FuncType func) + { + return new (::std::nothrow) proxy_const_mem_callable<_Ty, _Ret, _Args...>(ptr, func); + } + +protected: + proxy_const_mem_callable(void* ptr, _FuncType func) + : ptr_(ptr) + , func_(func) + { + } + +protected: + void* ptr_; + _FuncType func_; +}; + +} // namespace __function_detail +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/intrusive_list.h b/src/3rd-party/OuterC/oc/intrusive_list.h new file mode 100644 index 00000000..4fc79ed3 --- /dev/null +++ b/src/3rd-party/OuterC/oc/intrusive_list.h @@ -0,0 +1,254 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include +#include +#include +#include "macros.h" + +namespace oc +{ + +template ::pointer> +class intrusive_list; + +template ::pointer> +class intrusive_list_item +{ +public: + using pointer_type = _PTy; + using const_pointer_type = const _PTy; + + intrusive_list_item() : prev_(nullptr), next_(nullptr) {} + intrusive_list_item(pointer_type rhs) : prev_(nullptr), next_(nullptr) { if (rhs) { prev_ = rhs->prev_; next_ = rhs->next_; } } + + const_pointer_type prev_item() const { return prev_; } + pointer_type prev_item() { return prev_; } + const_pointer_type next_item() const { return next_; } + pointer_type next_item() { return next_; } + +private: + pointer_type prev_; + pointer_type next_; + + friend class intrusive_list<_Ty>; +}; + + +template +class intrusive_list +{ +public: + using pointer_type = _PTy; + using const_pointer_type = const _PTy; + + intrusive_list() : first_(), last_() {} + ~intrusive_list() { clear(); } + + const_pointer_type first_item() const { return first_; } + pointer_type first_item() { return first_; } + const_pointer_type last_item() const { return last_; } + pointer_type last_item() { return last_; } + + inline bool empty() const + { + return first_ == nullptr; + } + + void push_back(pointer_type child) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + child->prev_ = last_; + child->next_ = nullptr; + + if (first_) + { + last_->next_ = child; + } + else + { + first_ = child; + } + + last_ = child; + } + + void push_front(pointer_type child) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + child->prev_ = nullptr; + child->next_ = first_; + + if (first_) + { + first_->prev_ = child; + } + else + { + last_ = child; + } + + first_ = child; + } + + void insert_before(pointer_type child, pointer_type before) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + if (before->prev_) + before->prev_->next_ = child; + else + first_ = child; + + child->prev_ = before->prev_; + child->next_ = before; + before->prev_ = child; + } + + void insert_after(pointer_type child, pointer_type after) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + if (after->next_) + after->next_->prev_ = child; + else + last_ = child; + + child->next_ = after->next_; + child->prev_ = after; + after->next_ = child; + } + + void remove(pointer_type child) + { + if (child->next_) + { + child->next_->prev_ = child->prev_; + } + else + { + last_ = child->prev_; + } + + if (child->prev_) + { + child->prev_->next_ = child->next_; + } + else + { + first_ = child->next_; + } + + child->prev_ = nullptr; + child->next_ = nullptr; + } + + void clear() + { + pointer_type p = first_; + while (p) + { + pointer_type tmp = p; + p = p->next_; + if (tmp) + { + tmp->next_ = nullptr; + tmp->prev_ = nullptr; + } + } + first_ = nullptr; + last_ = nullptr; + } + + void check_list() + { + if (!first_) + return; + + int pos = 0; + pointer_type p = first_; + pointer_type tmp = p; + do + { + tmp = p; + p = p->next_; + ++pos; + + if (p) + { + OC_ASSERT(p->prev_ == tmp && "Check list failed"); + } + else + { + OC_ASSERT(tmp == last_ && "Check list failed"); + } + } while (p); + } + +public: + // Iterator + template + struct iterator_impl + { + using iterator_category = std::bidirectional_iterator_tag; + using pointer_type = _PTy; + using const_pointer_type = const _PTy; + + inline iterator_impl(pointer_type ptr = nullptr, bool is_end = false) : base_(ptr), is_end_(is_end) {} + + inline pointer_type operator*() const { OC_ASSERT(base_ && !is_end_); return base_; } + inline iterator_impl& operator++() { OC_ASSERT(base_ && !is_end_); pointer_type next = base_->next_item(); if (next) base_ = next; else is_end_ = true; return (*this); } + inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; } + inline iterator_impl& operator--() { OC_ASSERT(base_); if (is_end_) is_end_ = false; else base_ = pointer_type(base_->prev_item()); return (*this); } + inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; } + inline bool operator==(iterator_impl const& other) const { return base_ == other.base_ && is_end_ == other.is_end_; } + inline bool operator!=(iterator_impl const& other) const { return !(*this == other); } + inline operator bool() const { return base_ != nullptr && !is_end_; } + + private: + bool is_end_; + pointer_type base_; + }; + + 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() { return iterator(first_item(), first_item() == nullptr); } + inline const_iterator begin() const { return const_iterator(first_item(), first_item() == nullptr); } + inline const_iterator cbegin() const { return begin(); } + inline iterator end() { return iterator(last_item(), true); } + inline const_iterator end() const { return const_iterator(last_item(), true); } + inline const_iterator cend() const { return end(); } + 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(); } + inline pointer_type front() { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); } + inline const_pointer_type front() const { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); } + inline pointer_type back() { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); } + inline const_pointer_type back() const { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); } + +private: + pointer_type first_; + pointer_type last_; +}; + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/intrusive_ptr.h b/src/3rd-party/OuterC/oc/intrusive_ptr.h new file mode 100644 index 00000000..e13aef0c --- /dev/null +++ b/src/3rd-party/OuterC/oc/intrusive_ptr.h @@ -0,0 +1,201 @@ +// Copyright (c) 2019-2020 OuterC - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining lhs 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. + +#pragma once +#include +#include +#include +#include "macros.h" + +namespace oc +{ + +template +class intrusive_ptr +{ +public: + using value_type = _Ty; + using pointer_type = _Ty*; + using const_pointer_type = const _Ty*; + using reference_type = _Ty&; + using const_reference_type = const _Ty&; + using ref_proxy_type = _ProxyTy; + + intrusive_ptr() noexcept : ptr_(nullptr) {} + intrusive_ptr(std::nullptr_t) noexcept : ptr_(nullptr) {} + intrusive_ptr(pointer_type p) : ptr_(p) { typename ref_proxy_type::add_ref(ptr_); } + intrusive_ptr(const intrusive_ptr& other) : ptr_(other.ptr_) { typename ref_proxy_type::add_ref(ptr_); } + intrusive_ptr(intrusive_ptr&& other) noexcept : ptr_(nullptr) { swap(other); } + ~intrusive_ptr() { tidy(); } + + template + intrusive_ptr(const intrusive_ptr<_UTy, ref_proxy_type>& other) { ptr_ = const_cast(dynamic_cast(other.get())); typename ref_proxy_type::add_ref(ptr_); } + + inline pointer_type get() noexcept { return ptr_; } + inline const_pointer_type get() const noexcept { return ptr_; } + inline void reset(pointer_type ptr = nullptr) { if (ptr) intrusive_ptr(ptr).swap(*this); else tidy(); } + inline void swap(intrusive_ptr& other) noexcept { std::swap(ptr_, other.ptr_); } + + inline pointer_type operator ->() { OC_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } + inline const_pointer_type operator ->() const { OC_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } + inline reference_type operator *() { OC_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } + inline const_reference_type operator *() const { OC_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } + inline pointer_type* operator &() { OC_ASSERT(ptr_ == nullptr && "Memory leak"); return &ptr_; } + inline operator bool() const noexcept { return ptr_ != nullptr; } + inline bool operator !() const noexcept { return ptr_ == 0; } + + inline intrusive_ptr& operator=(const intrusive_ptr& other) { if (other.ptr_ != ptr_) intrusive_ptr(other).swap(*this); return (*this); } + inline intrusive_ptr& operator=(intrusive_ptr&& other) noexcept { if (other.ptr_ != ptr_) other.swap(*this); return (*this); } + inline intrusive_ptr& operator=(pointer_type p) { if (p != ptr_) intrusive_ptr(p).swap(*this); return (*this); } + inline intrusive_ptr& operator=(std::nullptr_t) { tidy(); return *this; } + +private: + void tidy() + { + typename ref_proxy_type::release(ptr_); + ptr_ = nullptr; + } + +private: + pointer_type ptr_; +}; + +template +inline bool operator==(intrusive_ptr<_Ty, _ProxyTy> const& lhs, intrusive_ptr<_UTy, _ProxyTy> const& rhs) noexcept +{ + return lhs.get() == rhs.get(); +} + +template +inline bool operator==(intrusive_ptr<_Ty, _ProxyTy> const& lhs, _Ty* rhs) noexcept +{ + return lhs.get() == rhs; +} + +template +inline bool operator==(_Ty* lhs, intrusive_ptr<_Ty, _ProxyTy> const& rhs) noexcept +{ + return lhs == rhs.get(); +} + +template +inline bool operator==(intrusive_ptr<_Ty, _ProxyTy> const& lhs, std::nullptr_t) noexcept +{ + return !static_cast(lhs); +} + +template +inline bool operator==(std::nullptr_t, intrusive_ptr<_Ty, _ProxyTy> const& rhs) noexcept +{ + return !static_cast(rhs); +} + +template +inline bool operator!=(intrusive_ptr<_Ty, _ProxyTy> const& lhs, intrusive_ptr<_UTy, _ProxyTy> const& rhs) noexcept +{ + return !(lhs == rhs); +} + +template +inline bool operator!=(intrusive_ptr<_Ty, _ProxyTy> const& lhs, _Ty* rhs) noexcept +{ + return lhs.get() != rhs; +} + +template +inline bool operator!=(_Ty* lhs, intrusive_ptr<_Ty, _ProxyTy> const& rhs) noexcept +{ + return lhs != rhs.get(); +} + +template +inline bool operator!=(intrusive_ptr<_Ty, _ProxyTy> const& lhs, std::nullptr_t) noexcept +{ + return static_cast(lhs); +} + +template +inline bool operator!=(std::nullptr_t, intrusive_ptr<_Ty, _ProxyTy> const& rhs) noexcept +{ + return static_cast(rhs); +} + +template +inline bool operator<(intrusive_ptr<_Ty, _ProxyTy> const& lhs, intrusive_ptr<_UTy, _ProxyTy> const& rhs) noexcept +{ + return lhs.get() < rhs.get(); +} + +// template class cannot specialize std::swap, +// so implement a swap Function in oc namespace +template +inline void swap(intrusive_ptr<_Ty, _ProxyTy>& lhs, intrusive_ptr<_Ty, _ProxyTy>& rhs) noexcept +{ + lhs.swap(rhs); +} + + +class intrusive_ref +{ +public: + void add_ref() + { + ++ref_count_; + } + + void release() + { + --ref_count_; + if (ref_count_ == 0) + { + delete this; + } + } + + int16_t get_ref() const + { + return ref_count_; + } + +protected: + intrusive_ref() + : ref_count_(0) + { + } + +private: + std::atomic ref_count_; +}; + + +class intrusive_ref_proxy +{ +public: + static inline void add_ref(intrusive_ref* ptr) { if (ptr) ptr->add_ref(); } + + static inline void release(intrusive_ref* ptr) { if (ptr) ptr->release(); } +}; + +template< + typename _Ty, + typename = typename std::enable_if::value, int>::type> +using intrusive_ref_ptr = intrusive_ptr<_Ty, intrusive_ref_proxy>; + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json.h b/src/3rd-party/OuterC/oc/json.h new file mode 100644 index 00000000..e61c0d95 --- /dev/null +++ b/src/3rd-party/OuterC/oc/json.h @@ -0,0 +1,50 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include +#include "vector.h" +#include "string.h" +#include "json/basic_json.h" + +namespace oc +{ + +using json = oc::basic_json; +using wjson = oc::basic_json; + +} // namespace oc + +namespace std +{ + +template<> +struct hash<::oc::json> +{ + size_t operator()(const ::oc::json& json) const + { + return hash<::oc::json::string_type>{}(json.dump()); + } +}; + +template<> +struct hash<::oc::wjson> +{ + size_t operator()(const ::oc::wjson& json) const + { + return hash<::oc::wjson::string_type>{}(json.dump()); + } +}; + +template<> +inline void swap<::oc::json>(::oc::json& lhs, ::oc::json& rhs) noexcept +{ + lhs.swap(rhs); +} + +template<> +inline void swap<::oc::wjson>(::oc::wjson& lhs, ::oc::wjson& rhs) noexcept +{ + lhs.swap(rhs); +} + +} diff --git a/src/3rd-party/OuterC/oc/json/basic_json.h b/src/3rd-party/OuterC/oc/json/basic_json.h new file mode 100644 index 00000000..f5a3c5cb --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/basic_json.h @@ -0,0 +1,929 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include "json_exception.h" +#include "json_value.h" +#include "json_iterator.h" +#include "json_serializer.h" +#include "json_parser.h" +#include "json_value_getter.h" + +namespace oc +{ + +#define OC_DECLARE_BASIC_JSON_TEMPLATE\ + template <\ + template typename _ObjectTy, \ + template typename _ArrayTy, \ + typename _StringTy, \ + typename _IntegerTy, \ + typename _FloatTy, \ + typename _BooleanTy, \ + template typename _Allocator> + +#define OC_DECLARE_BASIC_JSON_TPL_ARGS \ + _ObjectTy, _ArrayTy, _StringTy, _IntegerTy, _FloatTy, _BooleanTy, _Allocator + + +OC_DECLARE_BASIC_JSON_TEMPLATE +class basic_json; + + +// +// is_basic_json +// + +template +struct is_basic_json + : std::false_type +{ +}; + +OC_DECLARE_BASIC_JSON_TEMPLATE +struct is_basic_json< basic_json > + : std::true_type +{ +}; + + +OC_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 = size_t; + using difference_type = 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 json_type type) : value_(type) {} + + basic_json(basic_json const& other) : value_(other.value_) {} + + basic_json(basic_json&& other) noexcept : value_(std::move(other.value_)) + { + // invalidate payload + other.value_.type = json_type::NIL; + 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 = json_type::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 const& 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_ = json_type::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_ = json_type::VECTOR; + value_.data.vector->reserve(init_list.size()); + value_.data.vector->assign(init_list.begin(), init_list.end()); + } + } + + static inline basic_json object(initializer_list const& init_list) + { + if (init_list.size() != 2 || !(*init_list.begin()).is_string()) + { + throw json_type_error("cannot create object from initializer_list"); + } + + basic_json json; + json.value_ = json_type::OBJECT; + json.value_.data.object->emplace(*((*init_list.begin()).value_.data.string), *(init_list.begin() + 1)); + return json; + } + + static inline basic_json array(initializer_list const& init_list) + { + basic_json json; + json.value_ = json_type::VECTOR; + + if (init_list.size()) + { + json.value_.data.vector->reserve(init_list.size()); + json.value_.data.vector->assign(init_list.begin(), init_list.end()); + } + return json; + } + + inline bool is_object() const { return value_.type == json_type::OBJECT; } + + inline bool is_array() const { return value_.type == json_type::VECTOR; } + + inline bool is_string() const { return value_.type == json_type::STRING; } + + inline bool is_boolean() const { return value_.type == json_type::BOOL; } + + inline bool is_integer() const { return value_.type == json_type::INTEGER; } + + inline bool is_float() const { return value_.type == json_type::FLOAT; } + + inline bool is_number() const { return is_integer() || is_float(); } + + inline bool is_null() const { return value_.type == json_type::NIL; } + + inline json_type type() const { return value_.type; } + + inline string_type type_name() const + { + switch (type()) + { + case json_type::OBJECT: + return string_type(L"object"); + case json_type::VECTOR: + return string_type(L"array"); + case json_type::STRING: + return string_type(L"string"); + case json_type::INTEGER: + return string_type(L"integer"); + case json_type::FLOAT: + return string_type(L"float"); + case json_type::BOOL: + return string_type(L"boolean"); + case json_type::NIL: + 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 json_type::NIL: + return 0; + case json_type::VECTOR: + return value_.data.vector->size(); + case json_type::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.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("cannot use erase() with non-object value"); + } + return value_.data.object->erase(key); + } + + inline void erase(const size_type index) + { + if (!is_array()) + { + throw json_invalid_key("cannot use erase() with non-array value"); + } + 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 json_type::OBJECT: + { + result.object_iter = value_.data.object->erase(pos.object_iter); + break; + } + + case json_type::VECTOR: + { + result.array_iter = value_.data.vector->erase(pos.array_iter); + break; + } + + default: + throw json_invalid_iterator("cannot use erase() with non-object & non-array value"); + } + + 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 json_type::OBJECT: + { + result.object_iter = value_.data.object->erase(first.object_iter, last.object_iter); + break; + } + + case json_type::VECTOR: + { + result.array_iter = value_.data.vector->erase(first.array_iter, last.array_iter); + break; + } + + default: + throw json_invalid_iterator("cannot use erase() with non-object & non-array value"); + } + + return result; + } + + inline void push_back(basic_json&& json) + { + if (!is_null() && !is_array()) + { + throw json_type_error("cannot use push_back() with non-array value"); + } + + if (is_null()) + { + value_ = json_type::VECTOR; + } + + 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 json_type::INTEGER: + { + value_.data.number_integer = 0; + break; + } + + case json_type::FLOAT: + { + value_.data.number_float = static_cast(0.0); + break; + } + + case json_type::BOOL: + { + value_.data.boolean = false; + break; + } + + case json_type::STRING: + { + value_.data.string->clear(); + break; + } + + case json_type::VECTOR: + { + value_.data.vector->clear(); + break; + } + + case json_type::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("json value must be boolean"); + return value_.data.boolean; + } + + integer_type as_int() const + { + if (!is_integer()) throw json_type_error("json value must be integer"); + return value_.data.number_integer; + } + + float_type as_float() const + { + if (!is_float()) throw json_type_error("json value must be float"); + return value_.data.number_float; + } + + const array_type& as_array() const + { + if (!is_array()) throw json_type_error("json value must be array"); + return *value_.data.vector; + } + + const string_type& as_string() const + { + if (!is_string()) throw json_type_error("json value must be string"); + return *value_.data.string; + } + + const object_type& as_object() const + { + if (!is_object()) throw json_type_error("json value must be object"); + 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) noexcept + { + 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_ = json_type::VECTOR; + } + + if (!is_array()) + { + throw json_invalid_key("operator[] called on a non-array object"); + } + + 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("operator[] called on a non-array type"); + } + + if (index >= value_.data.vector->size()) + { + throw std::out_of_range("operator[] index out of range"); + } + return (*value_.data.vector)[index]; + } + + inline basic_json& operator[](const typename object_type::key_type& key) + { + if (is_null()) + { + value_ = json_type::OBJECT; + } + + if (!is_object()) + { + throw json_invalid_key("operator[] called on a non-object type"); + } + return (*value_.data.object)[key]; + } + + inline basic_json& operator[](const typename object_type::key_type& key) const + { + if (!is_object()) + { + throw json_invalid_key("operator[] called on a non-object object"); + } + + auto iter = value_.data.object->find(key); + if (iter == value_.data.object->end()) + { + throw std::out_of_range("operator[] key out of range"); + } + return iter->second; + } + + template + inline basic_json& operator[](_CharT* key) + { + if (is_null()) + { + value_ = json_type::OBJECT; + } + + if (!is_object()) + { + throw json_invalid_key("operator[] called on a non-object object"); + } + return (*value_.data.object)[key]; + } + + template + inline basic_json& operator[](_CharT* key) const + { + if (!is_object()) + { + throw json_invalid_key("operator[] called on a non-object object"); + } + + auto iter = value_.data.object->find(key); + if (iter == value_.data.object->end()) + { + throw std::out_of_range("operator[] key out of range"); + } + return iter->second; + } + +public: + // implicitly convert functions + + inline operator boolean_type () const + { + return as_bool(); + } + + inline operator integer_type () const + { + return as_int(); + } + + inline operator float_type () const + { + return as_float(); + } + + inline operator const array_type& () const + { + return as_array(); + } + + inline operator const string_type& () const + { + return as_string(); + } + + inline operator const object_type& () const + { + return as_object(); + } + +public: + // dumps functions + + string_type dump( + const int indent = -1, + const char_type indent_char = ' ', + const bool char_escape = true) const + { + string_type result; + __json_detail::string_output_adapter adapter(result); + dump(&adapter, indent, indent_char, char_escape); + return result; + } + + void dump( + __json_detail::output_adapter* adapter, + const int indent = -1, + const char_type indent_char = ' ', + const bool char_escape = true) const + { + __json_detail::json_serializer(adapter, indent_char).dump(*this, (indent >= 0), char_escape, static_cast(indent)); + } + + 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, true, static_cast(indentation)); + return out; + } + +public: + // parse functions + + 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; + } + + 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; + } + +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 json_type::VECTOR: + return (*lhs.value_.data.vector == *rhs.value_.data.vector); + + case json_type::OBJECT: + return (*lhs.value_.data.object == *rhs.value_.data.object); + + case json_type::NIL: + return true; + + case json_type::STRING: + return (*lhs.value_.data.string == *rhs.value_.data.string); + + case json_type::BOOL: + return (lhs.value_.data.boolean == rhs.value_.data.boolean); + + case json_type::INTEGER: + return (lhs.value_.data.number_integer == rhs.value_.data.number_integer); + + case json_type::FLOAT: + return (lhs.value_.data.number_float == rhs.value_.data.number_float); + + default: + return false; + } + } + else if (lhs_type == json_type::INTEGER && rhs_type == json_type::FLOAT) + { + return (static_cast(lhs.value_.data.number_integer) == rhs.value_.data.number_float); + } + else if (lhs_type == json_type::FLOAT && rhs_type == json_type::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 json_type::VECTOR: + return (*lhs.value_.data.vector) < (*rhs.value_.data.vector); + + case json_type::OBJECT: + return (*lhs.value_.data.object) < (*rhs.value_.data.object); + + case json_type::NIL: + return false; + + case json_type::STRING: + return (*lhs.value_.data.string) < (*rhs.value_.data.string); + + case json_type::BOOL: + return (lhs.value_.data.boolean < rhs.value_.data.boolean); + + case json_type::INTEGER: + return (lhs.value_.data.number_integer < rhs.value_.data.number_integer); + + case json_type::FLOAT: + return (lhs.value_.data.number_float < rhs.value_.data.number_float); + + default: + return false; + } + } + else if (lhs_type == json_type::INTEGER && rhs_type == json_type::FLOAT) + { + return (static_cast(lhs.value_.data.number_integer) < rhs.value_.data.number_float); + } + else if (lhs_type == json_type::FLOAT && rhs_type == json_type::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: + __json_detail::json_value value_; +}; + +} // namespace oc + +#undef OC_DECLARE_BASIC_JSON_TEMPLATE +#undef OC_DECLARE_BASIC_JSON_TPL_ARGS diff --git a/src/3rd-party/OuterC/oc/json/json_exception.h b/src/3rd-party/OuterC/oc/json/json_exception.h new file mode 100644 index 00000000..0bf579e9 --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/json_exception.h @@ -0,0 +1,47 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include +#include "json_value.h" + +namespace oc +{ + +class json_exception + : public std::runtime_error +{ +public: + json_exception(const char* message) + : std::runtime_error(message) + {} +}; + +class json_type_error + : public json_exception +{ +public: + json_type_error(const char* message) : json_exception(message) {} +}; + +class json_invalid_key + : public json_exception +{ +public: + json_invalid_key(const char* message) : json_exception(message) {} +}; + +class json_invalid_iterator + : public json_exception +{ +public: + json_invalid_iterator(const char* message) : json_exception(message) {} +}; + +class json_parse_error + : public json_exception +{ +public: + json_parse_error(const char* message) : json_exception(message) {} +}; + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_intput_adapter.h b/src/3rd-party/OuterC/oc/json/json_intput_adapter.h new file mode 100644 index 00000000..5fdba4af --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/json_intput_adapter.h @@ -0,0 +1,112 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include + +namespace oc +{ +namespace __json_detail +{ + +template +struct input_adapter +{ + using char_type = _CharTy; + using char_traits = std::char_traits; + + virtual typename char_traits::int_type get_char() = 0; + virtual ~input_adapter() = default; +}; + +template +struct file_input_adapter + : public input_adapter<_CharTy> +{ + using char_type = typename input_adapter<_CharTy>::char_type; + using char_traits = typename input_adapter<_CharTy>::char_traits; + + file_input_adapter(std::FILE* file) : file(file) {} + + virtual typename char_traits::int_type get_char() override + { + return std::fgetc(file); + } + +private: + std::FILE* file; +}; + +template +struct stream_input_adapter + : public input_adapter<_CharTy> +{ + using char_type = typename input_adapter<_CharTy>::char_type; + using char_traits = typename input_adapter<_CharTy>::char_traits; + + stream_input_adapter(std::basic_istream& stream) : stream(stream), streambuf(*stream.rdbuf()) {} + + virtual typename char_traits::int_type get_char() override + { + auto ch = streambuf.sbumpc(); + if (ch == EOF) + { + stream.clear(stream.rdstate() | std::ios::eofbit); + } + return ch; + } + + virtual ~stream_input_adapter() + { + stream.clear(stream.rdstate() & std::ios::eofbit); + } + +private: + std::basic_istream& stream; + std::basic_streambuf& streambuf; +}; + +template +struct string_input_adapter + : public input_adapter +{ + using char_type = typename input_adapter::char_type; + using char_traits = typename input_adapter::char_traits; + + string_input_adapter(const _StringTy& str) : str(str), index(0) {} + + virtual typename char_traits::int_type get_char() override + { + if (index == str.size()) + return char_traits::eof(); + return str[index++]; + } + +private: + const _StringTy& str; + typename _StringTy::size_type index; +}; + +template +struct buffer_input_adapter + : public input_adapter<_CharTy> +{ + using char_type = typename input_adapter<_CharTy>::char_type; + using char_traits = typename input_adapter<_CharTy>::char_traits; + + buffer_input_adapter(const _CharTy* str) : str(str), index(0) {} + + virtual typename char_traits::int_type get_char() override + { + if (str[index] == '\0') + return char_traits::eof(); + return str[index++]; + } + +private: + const char_type* str; + uint32_t index; +}; + +} // namespace __json_detail + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_iterator.h b/src/3rd-party/OuterC/oc/json/json_iterator.h new file mode 100644 index 00000000..2520860b --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/json_iterator.h @@ -0,0 +1,377 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include + +namespace oc +{ +namespace __json_detail +{ + +struct primitive_iterator +{ + using difference_type = ptrdiff_t; + + inline primitive_iterator(difference_type it = 0) : it_(it) {} + + inline void set_begin() { it_ = 0; } + inline void set_end() { it_ = 1; } + + inline primitive_iterator& operator++() { ++it_; return *this; } + + inline primitive_iterator operator++(int) { primitive_iterator old(it_); ++(*this); return old; } + + inline primitive_iterator& operator--() { --it_; return (*this); } + inline primitive_iterator operator--(int) { primitive_iterator old = (*this); --(*this); return old; } + + inline bool operator==(primitive_iterator const& other) const { return it_ == other.it_; } + inline bool operator!=(primitive_iterator const& other) const { return !(*this == other); } + + inline const primitive_iterator operator+(difference_type off) const { return primitive_iterator(it_ + off); } + inline const primitive_iterator operator-(difference_type off) const { return primitive_iterator(it_ - off); } + + inline primitive_iterator& operator+=(difference_type off) { it_ += off; return (*this); } + inline primitive_iterator& operator-=(difference_type off) { it_ -= off; return (*this); } + + inline difference_type operator-(primitive_iterator const& other) const { return it_ - other.it_; } + + inline bool operator<(primitive_iterator const& other) const { return it_ < other.it_; } + inline bool operator<=(primitive_iterator const& other) const { return it_ <= other.it_; } + inline bool operator>(primitive_iterator const& other) const { return it_ > other.it_; } + inline bool operator>=(primitive_iterator const& other) const { return it_ >= other.it_; } + +private: + difference_type it_; +}; + +template +struct iterator_impl +{ + friend _BasicJsonTy; + + 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 = ptrdiff_t; + using iterator_category = std::bidirectional_iterator_tag; + using pointer = value_type*; + using reference = value_type&; + + using array_iterator = typename _BasicJsonTy::array_type::iterator; + using object_iterator = typename _BasicJsonTy::object_type::iterator; + + inline iterator_impl(pointer json = nullptr) : data_(json), primitive_iter(0), array_iter(), object_iter() {} + + inline iterator_impl(const iterator_impl& rhs) : iterator_impl() + { + operator=(rhs); + } + + ~iterator_impl() {} + + inline iterator_impl& operator=(const iterator_impl& rhs) + { + data_ = rhs.data_; + if (data_) + { + switch (data_->type()) + { + case json_type::OBJECT: + object_iter = rhs.object_iter; + break; + case json_type::VECTOR: + array_iter = rhs.array_iter; + break; + default: + primitive_iter = rhs.primitive_iter; + break; + } + } + return (*this); + } + + inline reference operator*() const + { + check_data(); + check_iterator(); + switch (data_->type()) + { + case json_type::OBJECT: + return (object_iter->second); + case json_type::VECTOR: + return (*array_iter); + default: + return *data_; + } + } + + inline pointer operator->() const + { + check_data(); + check_iterator(); + switch (data_->type()) + { + case json_type::OBJECT: + return &(object_iter->second); + case json_type::VECTOR: + return &(*array_iter); + default: + return data_; + } + } + + inline const typename object_type::key_type& key() const + { + check_data(); + check_iterator(); + if (!data_->is_object()) + throw json_invalid_iterator("cannot use key() with non-object type"); + return object_iter->first; + } + + inline reference value() const + { + return operator*(); + } + + inline void set_begin() + { + check_data(); + + switch (data_->type()) + { + case json_type::OBJECT: + { + object_iter = data_->value_.data.object->begin(); + break; + } + case json_type::VECTOR: + { + array_iter = data_->value_.data.vector->begin(); + break; + } + default: + { + primitive_iter.set_begin(); + break; + } + } + } + + inline void set_end() + { + check_data(); + + switch (data_->type()) + { + case json_type::OBJECT: + { + object_iter = data_->value_.data.object->end(); + break; + } + case json_type::VECTOR: + { + array_iter = data_->value_.data.vector->end(); + break; + } + default: + { + primitive_iter.set_end(); + break; + } + } + } + + inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; } + inline iterator_impl& operator++() + { + check_data(); + + switch (data_->type()) + { + case json_type::OBJECT: + { + std::advance(object_iter, 1); + break; + } + case json_type::VECTOR: + { + std::advance(array_iter, 1); + break; + } + default: + { + ++primitive_iter; + break; + } + } + return *this; + } + + inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; } + inline iterator_impl& operator--() + { + check_data(); + + switch (data_->type()) + { + case json_type::OBJECT: + { + std::advance(object_iter, -1); + break; + } + case json_type::VECTOR: + { + std::advance(array_iter, -1); + break; + } + default: + { + --primitive_iter; + break; + } + } + } + + inline const iterator_impl operator-(difference_type off) const { return operator+(-off); } + inline const iterator_impl operator+(difference_type off) const { iterator_impl ret(*this); ret += off; return ret; } + + inline iterator_impl& operator-=(difference_type off) { return operator+=(-off); } + inline iterator_impl& operator+=(difference_type off) + { + check_data(); + + switch (data_->type()) + { + case json_type::OBJECT: + { + throw json_invalid_iterator("cannot use offsets with object type"); + break; + } + case json_type::VECTOR: + { + std::advance(array_iter, off); + break; + } + default: + { + primitive_iter += off; + break; + } + } + return *this; + } + + inline bool operator!=(iterator_impl const& other) const { return !(*this == other); } + inline bool operator==(iterator_impl const& other) const + { + check_data(); + other.check_data(); + + if (data_ != other.data_) + throw json_invalid_iterator("cannot compare iterators of different objects"); + + switch (data_->type()) + { + case json_type::OBJECT: + { + return object_iter == other.object_iter; + } + case json_type::VECTOR: + { + return array_iter == other.array_iter; + } + default: + { + return primitive_iter == other.primitive_iter; + } + } + } + + 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(); + other.check_data(); + + if (data_ != other.data_) + throw json_invalid_iterator("cannot compare iterators of different objects"); + + switch (data_->type()) + { + case json_type::OBJECT: + throw json_invalid_iterator("cannot compare iterators with object type"); + case json_type::VECTOR: + return array_iter < other.array_iter; + default: + return primitive_iter < other.primitive_iter; + } + } + +private: + inline void check_data() const + { + if (data_ == nullptr) + { + throw json_invalid_iterator("iterator contains an empty object"); + } + } + + inline void check_iterator() const + { + switch (data_->type()) + { + case json_type::OBJECT: + if (object_iter == data_->value_.data.object->end()) + { + throw std::out_of_range("iterator out of range"); + } + break; + case json_type::VECTOR: + if (array_iter == data_->value_.data.vector->end()) + { + throw std::out_of_range("iterator out of range"); + } + break; + default: + if (primitive_iter == 1) + { + throw std::out_of_range("iterator out of range"); + } + break; + } + } + +private: + pointer data_; + + union + { + struct + { + array_iterator array_iter; + }; + + struct + { + object_iterator object_iter; + }; + + struct + { + primitive_iterator primitive_iter; // for other types + }; + }; +}; + +} // namespace __json_detail + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_output_adapter.h b/src/3rd-party/OuterC/oc/json/json_output_adapter.h new file mode 100644 index 00000000..8c0d2adb --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/json_output_adapter.h @@ -0,0 +1,76 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include + +namespace oc +{ +namespace __json_detail +{ + +template +struct output_adapter +{ + using char_type = _CharTy; + using char_traits = std::char_traits; + + virtual void write(const _CharTy ch) = 0; + virtual void write(const _CharTy* str, uint32_t size) = 0; + virtual void write(const _CharTy* str) + { + const auto size = char_traits::length(str); + write(str, static_cast(size)); + } +}; + +template +struct string_output_adapter + : public output_adapter +{ + using char_type = typename _StringTy::value_type; + using size_type = typename _StringTy::size_type; + using char_traits = std::char_traits; + + string_output_adapter(_StringTy& str) : str_(str) {} + + virtual void write(const char_type ch) override + { + str_.push_back(ch); + } + + virtual void write(const char_type* str, uint32_t size) override + { + str_.append(str, static_cast(size)); + } + +private: + _StringTy& str_; +}; + +template +struct stream_output_adapter + : public output_adapter<_CharTy> +{ + using char_type = _CharTy; + using size_type = typename std::streamsize; + using char_traits = std::char_traits; + + stream_output_adapter(std::basic_ostream& stream) : stream_(stream) {} + + virtual void write(const char_type ch) override + { + stream_.put(ch); + } + + virtual void write(const char_type* str, uint32_t size) override + { + stream_.write(str, static_cast(size)); + } + +private: + std::basic_ostream& stream_; +}; + +} // namespace __json_detail + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_parser.h b/src/3rd-party/OuterC/oc/json/json_parser.h new file mode 100644 index 00000000..706233e9 --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/json_parser.h @@ -0,0 +1,567 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include "json_intput_adapter.h" + +namespace oc +{ +namespace __json_detail +{ + +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 +}; + +template +struct json_lexer +{ + 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) + { + // read first char + read_next(); + } + + typename char_traits::int_type read_next() + { + current = adapter->get_char(); + return current; + } + + void skip_spaces() + { + while (current == ' ' || current == '\t' || current == '\n' || current == '\r') + { + read_next(); + } + } + + token_type scan() + { + skip_spaces(); + + token_type result = token_type::UNINITIALIZED; + switch (current) + { + case '[': + result = token_type::BEGIN_ARRAY; + break; + case ']': + result = token_type::END_ARRAY; + break; + case '{': + result = token_type::BEGIN_OBJECT; + break; + case '}': + result = token_type::END_OBJECT; + break; + case ':': + result = token_type::NAME_SEPARATOR; + break; + case ',': + result = token_type::VALUE_SEPARATOR; + break; + + case 't': + return scan_literal(L"true", token_type::LITERAL_TRUE); + case 'f': + return scan_literal(L"false", token_type::LITERAL_FALSE); + case 'n': + return scan_literal(L"null", token_type::LITERAL_NULL); + + case '\"': + return scan_string(); + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + case '\0': + case char_traits::eof(): + return token_type::END_OF_INPUT; + + // unexpected char + default: + return token_type::PARSE_ERROR; + } + + // skip current char + read_next(); + + return result; + } + + token_type scan_literal(const char_type* text, token_type result) + { + for (uint32_t i = 0; text[i] != '\0'; ++i) + { + if (text[i] != char_traits::to_char_type(current)) + { + return token_type::PARSE_ERROR; + } + read_next(); + } + return result; + } + + token_type scan_string() + { + if (current != '\"') + return token_type::PARSE_ERROR; + + string_buffer.clear(); + + while (true) + { + const auto ch = read_next(); + switch (ch) + { + case char_traits::eof(): + { + // unexpected end + return token_type::PARSE_ERROR; + } + + case '\"': + { + // skip last `\"` + read_next(); + return token_type::VALUE_STRING; + } + + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + { + // invalid control character + return token_type::PARSE_ERROR; + } + + case '\\': + { + switch (read_next()) + { + case '\"': + string_buffer.push_back('\"'); + break; + case '\\': + string_buffer.push_back('\\'); + break; + case '/': + string_buffer.push_back('/'); + break; + case 'b': + string_buffer.push_back('\b'); + break; + case 'f': + string_buffer.push_back('\f'); + break; + case 'n': + string_buffer.push_back('\n'); + break; + case 'r': + string_buffer.push_back('\r'); + break; + case 't': + string_buffer.push_back('\t'); + break; + + case 'u': + { + // unicode escapes + uint16_t byte = 0; + + for (const auto factor : { 12, 8, 4, 0 }) + { + const auto n = read_next(); + if (n >= L'0' && n <= L'9') + { + byte += ((n - L'0') << factor); + } + else if (n >= L'A' && n <= L'F') + { + byte += ((n - L'A' + 10) << factor); + } + else if (n >= L'a' && n <= L'f') + { + byte += ((n - L'a' + 10) << factor); + } + else + { + // '\u' must be followed by 4 hex digits + return token_type::PARSE_ERROR; + } + } + + string_buffer.push_back(char_traits::to_char_type(byte)); + break; + } + + default: + { + return token_type::PARSE_ERROR; + } + } + break; + } + + default: + { + if (ch > 0x1F && ch < 0x7F) + { + string_buffer.push_back(char_traits::to_char_type(ch)); + break; + } + else + { + return token_type::PARSE_ERROR; + } + } + + } + } + } + + token_type scan_number() + { + is_negative = false; + number_value = static_cast(0.0); + + if (current == '-') + { + return scan_negative(); + } + + if (current == '0') + { + return scan_zero(); + } + + return scan_integer(); + } + + token_type scan_negative() + { + if (current == '-') + { + is_negative = true; + read_next(); + + return scan_integer(); + } + return token_type::PARSE_ERROR; + } + + token_type scan_zero() + { + if (current == '0') + { + if (read_next() == '.') + return scan_float(); + else + return token_type::VALUE_INTEGER; + } + return token_type::PARSE_ERROR; + } + + token_type scan_integer() + { + if (std::isdigit(current)) + { + number_value = static_cast(current - '0'); + + while (true) + { + const auto ch = read_next(); + if (ch == '.') + return scan_float(); + + if (ch == 'e' || ch == 'E') + return scan_exponent(); + + if (std::isdigit(ch)) + number_value = number_value * 10 + (ch - '0'); + else + break; + } + return token_type::VALUE_INTEGER; + } + return token_type::PARSE_ERROR; + } + + token_type scan_float() + { + if (current != '.') + return token_type::PARSE_ERROR; + + if (std::isdigit(read_next())) + { + float_type fraction = static_cast(0.1); + number_value += static_cast(current - '0') * fraction; + + while (true) + { + const auto ch = read_next(); + if (ch == 'e' || ch == 'E') + return scan_exponent(); + + if (std::isdigit(ch)) + { + fraction *= static_cast(0.1); + number_value += static_cast(ch - '0') * fraction; + } + else + break; + } + return token_type::VALUE_FLOAT; + } + return token_type::PARSE_ERROR; + } + + token_type scan_exponent() + { + if (current != 'e' && current != 'E') + return token_type::PARSE_ERROR; + + // skip current char + read_next(); + + if ((std::isdigit(current) && current != '0') || (current == '-') || (current == '+')) + { + float_type core = 10; + if (current == '+') + { + read_next(); + } + else if (current == '-') + { + core = static_cast(0.1); + read_next(); + } + + uint32_t exponent = static_cast(current - '0'); + while (std::isdigit(read_next())) + { + exponent = (exponent * 10) + static_cast(current - '0'); + } + + float_type power = 1; + for (; exponent; exponent >>= 1, core *= core) + if (exponent & 1) + power *= core; + + number_value *= power; + return token_type::VALUE_FLOAT; + } + return token_type::PARSE_ERROR; + } + + integer_type token_to_integer() const + { + integer_type integer = static_cast(number_value); + return is_negative ? -integer : integer; + } + + float_type token_to_float() const + { + return is_negative ? -number_value : number_value; + } + + string_type token_to_string() const + { + return string_buffer; + } + +private: + input_adapter* adapter; + typename char_traits::int_type current; + + bool is_negative; + float_type number_value; + string_type string_buffer; +}; + + +template +struct json_parser +{ + 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) + {} + + void parse(_BasicJsonTy& json) + { + parse_value(json); + + if (get_token() != token_type::END_OF_INPUT) + throw json_parse_error("unexpected token, expect end"); + } + +private: + token_type get_token() + { + last_token = lexer.scan(); + return last_token; + } + + void parse_value(_BasicJsonTy& json) + { + switch (get_token()) + { + case token_type::LITERAL_TRUE: + json = json_type::BOOL; + json.value_.data.boolean = true; + break; + + case token_type::LITERAL_FALSE: + json = json_type::BOOL; + json.value_.data.boolean = false; + break; + + case token_type::LITERAL_NULL: + json = json_type::NIL; + break; + + case token_type::VALUE_STRING: + json = lexer.token_to_string(); + break; + + case token_type::VALUE_INTEGER: + json = lexer.token_to_integer(); + break; + + case token_type::VALUE_FLOAT: + json = lexer.token_to_float(); + break; + + case token_type::BEGIN_ARRAY: + json = json_type::VECTOR; + while (true) + { + json.value_.data.vector->push_back(_BasicJsonTy()); + parse_value(json.value_.data.vector->back()); + + // read ',' + if (get_token() != token_type::VALUE_SEPARATOR) + break; + } + if (last_token != token_type::END_ARRAY) + throw json_parse_error("unexpected token in array"); + break; + + case token_type::BEGIN_OBJECT: + json = json_type::OBJECT; + while (true) + { + if (get_token() != token_type::VALUE_STRING) + break; + string_type key = lexer.token_to_string(); + + if (get_token() != token_type::NAME_SEPARATOR) + break; + + _BasicJsonTy object; + parse_value(object); + json.value_.data.object->insert(std::make_pair(key, object)); + + // read ',' + if (get_token() != token_type::VALUE_SEPARATOR) + break; + } + if (last_token != token_type::END_OBJECT) + throw json_parse_error("unexpected token in object"); + break; + + default: + // unexpected token + throw json_parse_error("unexpected token"); + break; + } + } + +private: + json_lexer<_BasicJsonTy> lexer; + token_type last_token; +}; + +} // namespace __json_detail + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_serializer.h b/src/3rd-party/OuterC/oc/json/json_serializer.h new file mode 100644 index 00000000..68e120d1 --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/json_serializer.h @@ -0,0 +1,421 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include "json_output_adapter.h" +#include +#include + +namespace oc +{ + +namespace __json_detail +{ + +template +struct json_literaler +{ + using char_type = _CharTy; + using string_type = const char_type*; + + static inline string_type value_separator() { return ",\n"; } + + static inline string_type empty_object() { return "{}"; } + static inline string_type object_begin() { return "{\n"; } + static inline string_type object_key_begin() { return "\": "; } + + static inline string_type empty_array() { return "[]"; } + static inline string_type array_begin() { return "[\n"; } + + static inline string_type literal_true() { return "true"; } + static inline string_type literal_false() { return "false"; } + static inline string_type literal_null() { return "null"; } + + static inline string_type escape_t() { return "\\t"; } + static inline string_type escape_r() { return "\\r"; } + static inline string_type escape_n() { return "\\n"; } + static inline string_type escape_b() { return "\\b"; } + static inline string_type escape_f() { return "\\f"; } + static inline string_type escape_quote() { return "\\\""; } + static inline string_type escape_slash() { return "\\\\"; } + + template + static inline void sprint_float(char_type* buff, const _FloatTy value) + { + const auto digits = std::numeric_limits<_FloatTy>::max_digits10; + const auto len = ::_scprintf("%.*g", digits, value); + if (len) + { + buff[0] = '\0'; + ::sprintf_s(buff, size_t(len) + 1, "%.*g", digits, value); + } + else + { + buff[0] = '0'; + buff[1] = '.'; + buff[2] = '0'; + buff[3] = '\0'; + } + } +}; + +template <> +struct json_literaler +{ + using char_type = wchar_t; + using string_type = const char_type*; + + static inline string_type value_separator() { return L",\n"; } + + static inline string_type empty_object() { return L"{}"; } + static inline string_type object_begin() { return L"{\n"; } + static inline string_type object_key_begin() { return L"\":"; } + + static inline string_type empty_array() { return L"[]"; } + static inline string_type array_begin() { return L"[\n"; } + + static inline string_type literal_true() { return L"true"; } + static inline string_type literal_false() { return L"false"; } + static inline string_type literal_null() { return L"null"; } + + static inline string_type escape_t() { return L"\\t"; } + static inline string_type escape_r() { return L"\\r"; } + static inline string_type escape_n() { return L"\\n"; } + static inline string_type escape_b() { return L"\\b"; } + static inline string_type escape_f() { return L"\\f"; } + static inline string_type escape_quote() { return L"\\\""; } + static inline string_type escape_slash() { return L"\\\\"; } + + template + static inline void sprint_float(char_type* buff, const _FloatTy value) + { + const auto digits = std::numeric_limits<_FloatTy>::max_digits10; + const auto len = ::_scwprintf(L"%.*g", digits, value); + if (len) + { + buff[0] = '\0'; + ::swprintf_s(buff, size_t(len) + 1, L"%.*g", digits, value); + } + else + { + buff[0] = '0'; + buff[1] = '.'; + buff[2] = '0'; + buff[3] = '\0'; + } + } +}; + +template +struct json_serializer +{ + 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 literaler = json_literaler; + + json_serializer(output_adapter* out, const char_type indent_char) + : out(out) + , indent_char(indent_char) + , indent_string(32, indent_char) + {} + + void dump( + const _BasicJsonTy& json, + const bool pretty_print, + const bool char_escape, + const uint32_t indent_step, + const uint32_t current_indent = 0) + { + switch (json.type()) + { + case json_type::OBJECT: + { + auto& object = *json.value_.data.object; + + if (object.empty()) + { + out->write(literaler::empty_object()); + return; + } + + if (pretty_print) + { + out->write(literaler::object_begin()); + + const auto new_indent = current_indent + indent_step; + if (indent_string.size() < new_indent) + { + indent_string.resize(indent_string.size() * 2, indent_char); + } + + auto iter = object.cbegin(); + const auto size = object.size(); + for (uint32_t i = 0; i < size; ++i, ++iter) + { + out->write(indent_string.c_str(), new_indent); + out->write('\"'); + out->write(iter->first.c_str()); + out->write(literaler::object_key_begin()); + out->write(' '); + dump(iter->second, pretty_print, char_escape, indent_step, new_indent); + + // not last element + if (i != size - 1) + out->write(literaler::value_separator()); + } + + out->write('\n'); + out->write(indent_string.c_str(), current_indent); + out->write('}'); + } + else + { + out->write('{'); + + auto iter = object.cbegin(); + const auto size = object.size(); + for (uint32_t i = 0; i < size; ++i, ++iter) + { + out->write('\"'); + out->write(iter->first.c_str()); + out->write(literaler::object_key_begin()); + dump(iter->second, pretty_print, char_escape, indent_step, current_indent); + + // not last element + if (i != size - 1) + out->write(','); + } + + out->write('}'); + } + + return; + } + + case json_type::VECTOR: + { + auto& vector = *json.value_.data.vector; + + if (vector.empty()) + { + out->write(literaler::empty_array()); + return; + } + + if (pretty_print) + { + out->write(literaler::array_begin()); + + const auto new_indent = current_indent + indent_step; + if (indent_string.size() < new_indent) + { + indent_string.resize(indent_string.size() * 2, indent_char); + } + + auto iter = vector.cbegin(); + const auto size = vector.size(); + for (uint32_t i = 0; i < size; ++i, ++iter) + { + out->write(indent_string.c_str(), new_indent); + dump(*iter, pretty_print, char_escape, indent_step, new_indent); + + // not last element + if (i != size - 1) + out->write(literaler::value_separator()); + } + + out->write('\n'); + out->write(indent_string.c_str(), current_indent); + out->write(']'); + } + else + { + out->write('['); + + auto iter = vector.cbegin(); + const auto size = vector.size(); + for (uint32_t i = 0; i < size; ++i, ++iter) + { + dump(*iter, pretty_print, char_escape, indent_step, current_indent); + // not last element + if (i != size - 1) + out->write(','); + } + + out->write(']'); + } + + return; + } + + case json_type::STRING: + { + out->write('\"'); + dump_string(*json.value_.data.string, char_escape); + out->write('\"'); + return; + } + + case json_type::BOOL: + { + if (json.value_.data.boolean) + { + out->write(literaler::literal_true()); + } + else + { + out->write(literaler::literal_false()); + } + return; + } + + case json_type::INTEGER: + { + dump_integer(json.value_.data.number_integer); + return; + } + + case json_type::FLOAT: + { + dump_float(json.value_.data.number_float); + return; + } + + case json_type::NIL: + { + out->write(literaler::literal_null()); + return; + } + } + } + + void dump_integer(integer_type val) + { + if (val == 0) + { + out->write('0'); + return; + } + + auto uval = static_cast>(val); + + if (val < 0) + uval = 0 - uval; + + if (number_buffer == nullptr) + number_buffer.reset(new number_buffer_type); + + auto next = (*number_buffer).rbegin(); + *next = '\0'; + + do + { + *(++next) = static_cast('0' + uval % 10); + uval /= 10; + } while (uval != 0); + + if (val < 0) + *(++next) = '-'; + + out->write(&(*next)); + } + + void dump_float(float_type val) + { + if (number_buffer == nullptr) + number_buffer.reset(new number_buffer_type); + + literaler::sprint_float((*number_buffer).data(), val); + out->write((*number_buffer).data()); + } + + void dump_string(const string_type & val, const bool char_escape) + { + for (const auto& ch : val) + { + switch (ch) + { + case '\t': + { + out->write(literaler::escape_t()); + break; + } + + case '\r': + { + out->write(literaler::escape_r()); + break; + } + + case '\n': + { + out->write(literaler::escape_n()); + break; + } + + case '\b': + { + out->write(literaler::escape_b()); + break; + } + + case '\f': + { + out->write(literaler::escape_f()); + break; + } + + case '\"': + { + out->write(literaler::escape_quote()); + break; + } + + case '\\': + { + out->write(literaler::escape_slash()); + break; + } + + default: + { + uint32_t char_byte = static_cast(ch); + if (char_byte > 0x1F && (!char_escape || char_byte < 0x7F)) + { + out->write(ch); + } + else + { + char_type escaped[7] = { '\\', 'u', 0 }; + + uint8_t index = 2; + for (const auto factor : { 12, 8, 4, 0 }) + { + char_type code = ((char_byte >> factor) & 0x0F); + code += (code < 0x0A) ? '0' : 'a' - 0x0A; + escaped[index++] = code; + } + out->write(escaped); + } + break; + } + } + } + } + +private: + output_adapter* out; + char_type indent_char; + string_type indent_string; + + using number_buffer_type = std::array; + std::unique_ptr number_buffer; +}; + +} // namespace __json_detail + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_value.h b/src/3rd-party/OuterC/oc/json/json_value.h new file mode 100644 index 00000000..94f5ba0f --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/json_value.h @@ -0,0 +1,240 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include +#include + +namespace oc +{ + +enum class json_type +{ + INTEGER, + FLOAT, + STRING, + VECTOR, + OBJECT, + BOOL, + NIL, +}; + +namespace __json_detail +{ + +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; + + json_type type; + union + { + object_type* object; + array_type* vector; + string_type* string; + integer_type number_integer; + float_type number_float; + boolean_type boolean; + } data; + + json_value() + { + type = json_type::NIL; + data.object = nullptr; + } + + json_value(std::nullptr_t) + { + type = json_type::NIL; + data.object = nullptr; + } + + json_value(const object_type& value) + { + type = json_type::OBJECT; + data.object = create(value); + } + + json_value(const array_type& value) + { + type = json_type::VECTOR; + data.vector = create(value); + } + + json_value(const string_type& value) + { + type = json_type::STRING; + data.string = create(value); + } + + template + json_value(const _CharT* str) + { + type = json_type::STRING; + data.string = create(str); + } + + json_value(const integer_type value) + { + type = json_type::INTEGER; + data.number_integer = value; + } + + json_value(const float_type value) + { + type = json_type::FLOAT; + data.number_float = value; + } + + json_value(const boolean_type value) + { + type = json_type::BOOL; + data.boolean = value; + } + + json_value(const json_type value_type) + { + type = value_type; + switch (type) + { + case json_type::OBJECT: + data.object = create(); + break; + case json_type::VECTOR: + data.vector = create(); + break; + case json_type::STRING: + data.string = create(); + break; + case json_type::INTEGER: + data.number_integer = integer_type(0); + break; + case json_type::FLOAT: + data.number_float = float_type(0.0); + break; + case json_type::BOOL: + data.boolean = boolean_type(false); + break; + default: + data.object = nullptr; + break; + } + } + + json_value(json_value const& other) + { + type = other.type; + + switch (other.type) + { + case json_type::OBJECT: + data.object = create(*other.data.object); + break; + case json_type::VECTOR: + data.vector = create(*other.data.vector); + break; + case json_type::STRING: + data.string = create(*other.data.string); + break; + case json_type::INTEGER: + data.number_integer = other.data.number_integer; + break; + case json_type::FLOAT: + data.number_float = other.data.number_float; + break; + case json_type::BOOL: + data.boolean = other.data.boolean; + break; + default: + data.object = nullptr; + break; + } + } + + json_value(json_value&& other) noexcept + { + type = other.type; + data = other.data; + other.type = json_type::NIL; + other.data.object = nullptr; + } + + ~json_value() + { + clear(); + } + + void swap(json_value& other) + { + std::swap(type, other.type); + std::swap(data, other.data); + } + + void clear() + { + switch (type) + { + case json_type::OBJECT: + destroy(data.object); + break; + case json_type::VECTOR: + destroy(data.vector); + break; + case json_type::STRING: + destroy(data.string); + break; + default: + break; + } + } + + template + inline _Ty* create(_Args&&... args) + { + using allocator_type = typename _BasicJsonTy::template allocator_type<_Ty>; + using allocator_traits = std::allocator_traits; + + 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_type = typename _BasicJsonTy::template allocator_type<_Ty>; + using allocator_traits = std::allocator_traits; + + allocator_type allocator; + allocator_traits::destroy(allocator, ptr); + allocator_traits::deallocate(allocator, ptr, 1); + } + + inline json_value& operator=(json_value const& other) + { + json_value{ other }.swap(*this); + return (*this); + } + + inline json_value& operator=(json_value&& other) noexcept + { + clear(); + type = other.type; + data = std::move(other.data); + // invalidate payload + other.type = json_type::NIL; + other.data.object = nullptr; + return (*this); + } +}; + +} // namespace __json_detail + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_value_getter.h b/src/3rd-party/OuterC/oc/json/json_value_getter.h new file mode 100644 index 00000000..220deb27 --- /dev/null +++ b/src/3rd-party/OuterC/oc/json/json_value_getter.h @@ -0,0 +1,79 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include "json_value.h" + +namespace oc +{ +namespace __json_detail +{ + +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("json value type must be object"); + value = *json.value_.data.object; + } + + static inline void assign(const _BasicJsonTy& json, array_type& value) + { + if (!json.is_array()) throw json_type_error("json value type must be array"); + value = *json.value_.data.vector; + } + + static inline void assign(const _BasicJsonTy& json, string_type& value) + { + if (!json.is_string()) throw json_type_error("json value type must be string"); + value = *json.value_.data.string; + } + + static inline void assign(const _BasicJsonTy& json, boolean_type& value) + { + if (!json.is_boolean()) throw json_type_error("json value type must be boolean"); + value = json.value_.data.boolean; + } + + static inline void assign(const _BasicJsonTy& json, integer_type& value) + { + if (!json.is_integer()) throw json_type_error("json value type must be integer"); + 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("json value type must be integer"); + value = static_cast<_IntegerTy>(json.value_.data.number_integer); + } + + static inline void assign(const _BasicJsonTy& json, float_type& value) + { + if (!json.is_float()) throw json_type_error("json value type must be float"); + value = json.value_.data.number_float; + } + + 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("json value type must be float"); + value = static_cast<_FloatingTy>(json.value_.data.number_float); + } +}; + +} // namespace __json_detail + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/macros.h b/src/3rd-party/OuterC/oc/macros.h new file mode 100644 index 00000000..c85a8d7b --- /dev/null +++ b/src/3rd-party/OuterC/oc/macros.h @@ -0,0 +1,8 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include +#include +#include + +#define OC_ASSERT(EXPR) assert(EXPR) diff --git a/src/3rd-party/OuterC/oc/noncopyable.h b/src/3rd-party/OuterC/oc/noncopyable.h new file mode 100644 index 00000000..76725522 --- /dev/null +++ b/src/3rd-party/OuterC/oc/noncopyable.h @@ -0,0 +1,19 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once + +namespace oc +{ + +class noncopyable +{ +protected: + noncopyable() = default; + +private: + noncopyable(const noncopyable&) = delete; + + noncopyable& operator=(const noncopyable&) = delete; +}; + +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/oc.h b/src/3rd-party/OuterC/oc/oc.h new file mode 100644 index 00000000..5171e999 --- /dev/null +++ b/src/3rd-party/OuterC/oc/oc.h @@ -0,0 +1,13 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include "macros.h" +#include "vector.h" +#include "string.h" +#include "any.h" +#include "function.h" +#include "noncopyable.h" +#include "singleton.h" +#include "intrusive_ptr.h" +#include "intrusive_list.h" +#include "json.h" diff --git a/src/3rd-party/OuterC/oc/singleton.h b/src/3rd-party/OuterC/oc/singleton.h new file mode 100644 index 00000000..44726bb6 --- /dev/null +++ b/src/3rd-party/OuterC/oc/singleton.h @@ -0,0 +1,50 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once + +// Class that will implement the singleton mode must use the macro in its delare file + +#ifndef OC_DECLARE_SINGLETON +#define OC_DECLARE_SINGLETON( CLASS ) \ + friend ::oc::singleton< CLASS >; +#endif + +namespace oc +{ + +template +struct singleton +{ +protected: + singleton() = default; + singleton(const singleton&) = delete; + singleton& operator=(const singleton&) = delete; + +private: + struct object_creator + { + object_creator() + { + (void)singleton<_Ty>::instance(); + } + + inline void dummy() const {} + }; + static object_creator creator_; + +public: + using object_type = _Ty; + + static inline object_type& instance() + { + static object_type instance; + creator_.dummy(); + return instance; + } +}; + +template +typename singleton<_Ty>::object_creator singleton<_Ty>::creator_; + + +} // namespace oc diff --git a/src/kiwano/common/string.hpp b/src/3rd-party/OuterC/oc/string.h similarity index 50% rename from src/kiwano/common/string.hpp rename to src/3rd-party/OuterC/oc/string.h index a34789e8..0fc944d4 100644 --- a/src/kiwano/common/string.hpp +++ b/src/3rd-party/OuterC/oc/string.h @@ -1,22 +1,4 @@ -// Copyright (c) 2016-2018 Kiwano - 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. +// Copyright (c) 2019-2020 OuterC - Nomango #pragma once #include @@ -27,9 +9,7 @@ #include #include -namespace kiwano -{ -namespace common +namespace oc { // @@ -425,8 +405,8 @@ basic_string format_string(const wchar_t* const fmt, _Args&& ... args); // // string && wstring // -using string = ::kiwano::common::basic_string; -using wstring = ::kiwano::common::basic_string; +using string = ::oc::basic_string; +using wstring = ::oc::basic_string; inline string to_string(int val) { return to_basic_string(val); } @@ -450,10 +430,9 @@ inline wstring to_wstring(double val) { return to_basic_string(val); inline wstring to_wstring(long double val) { return to_basic_string(val); } -} // namespace common -} // namespace kiwano +} // namespace oc -namespace kiwano +namespace oc { // @@ -515,153 +494,95 @@ namespace __string_details } } -namespace common + +template +inline basic_string<_CharTy>::basic_string() + : str_(nullptr) + , size_(0) + , capacity_(0) + , operable_(true) { +} - template - inline basic_string<_CharTy>::basic_string() - : str_(nullptr) - , size_(0) - , capacity_(0) - , operable_(true) +template +inline basic_string<_CharTy>::basic_string(const char_type* cstr, bool const_str) + : operable_(!const_str) + , size_(0) + , capacity_(0) + , str_(nullptr) +{ + if (cstr == nullptr) + return; + + if (operable_) { + assign(cstr, traits_type::length(cstr)); } - - template - inline basic_string<_CharTy>::basic_string(const char_type* cstr, bool const_str) - : operable_(!const_str) - , size_(0) - , capacity_(0) - , str_(nullptr) + else { - if (cstr == nullptr) - return; - - if (operable_) - { - assign(cstr, traits_type::length(cstr)); - } - else - { - const_str_ = cstr; - size_ = traits_type::length(cstr); - capacity_ = size_; - } + const_str_ = cstr; + size_ = traits_type::length(cstr); + capacity_ = size_; } +} - template - inline basic_string<_CharTy>::basic_string(const char_type* cstr, size_type count) - : basic_string() +template +inline basic_string<_CharTy>::basic_string(const char_type* cstr, size_type count) + : basic_string() +{ + assign(cstr, count); +} + +template +inline basic_string<_CharTy>::basic_string(size_type count, char_type ch) + : basic_string() +{ + assign(count, ch); +} + +template +inline basic_string<_CharTy>::basic_string(basic_string const& rhs) + : basic_string(rhs.const_str_, !rhs.operable_) +{ +} + +template +inline basic_string<_CharTy>::basic_string(basic_string const& rhs, size_type pos, size_type count) + : basic_string() +{ + assign(rhs, pos, count); +} + +template +inline basic_string<_CharTy>::basic_string(std::basic_string const& str) + : basic_string(str.c_str(), false) +{ +} + +template +inline basic_string<_CharTy>::basic_string(basic_string&& rhs) noexcept + : str_(rhs.str_) + , size_(rhs.size_) + , capacity_(rhs.capacity_) + , operable_(rhs.operable_) +{ + rhs.str_ = nullptr; + rhs.size_ = rhs.capacity_ = 0; +} + +template +inline basic_string<_CharTy>::~basic_string() +{ + destroy(); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::assign(size_type count, const char_type ch) +{ + discard_const_data(); + + if (count != 0) { - assign(cstr, count); - } - - template - inline basic_string<_CharTy>::basic_string(size_type count, char_type ch) - : basic_string() - { - assign(count, ch); - } - - template - inline basic_string<_CharTy>::basic_string(basic_string const& rhs) - : basic_string(rhs.const_str_, !rhs.operable_) - { - } - - template - inline basic_string<_CharTy>::basic_string(basic_string const& rhs, size_type pos, size_type count) - : basic_string() - { - assign(rhs, pos, count); - } - - template - inline basic_string<_CharTy>::basic_string(std::basic_string const& str) - : basic_string(str.c_str(), false) - { - } - - template - inline basic_string<_CharTy>::basic_string(basic_string&& rhs) noexcept - : str_(rhs.str_) - , size_(rhs.size_) - , capacity_(rhs.capacity_) - , operable_(rhs.operable_) - { - rhs.str_ = nullptr; - rhs.size_ = rhs.capacity_ = 0; - } - - template - inline basic_string<_CharTy>::~basic_string() - { - destroy(); - } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::assign(size_type count, const char_type ch) - { - discard_const_data(); - - if (count != 0) - { - if (count > capacity_) - { - destroy(); - str_ = allocate(count + 1); - capacity_ = count; - } - size_ = count; - - traits_type::assign(str_, size_, ch); - traits_type::assign(*(str_ + size_), value_type()); - } - else - { - clear(); - } - return (*this); - } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::assign(const char_type* cstr, size_type count) - { - discard_const_data(); - - if (cstr && count) - { - if (count > capacity_) - { - destroy(); - str_ = allocate(count + 1); - capacity_ = count; - } - size_ = count; - - traits_type::move(str_, cstr, size_); - traits_type::assign(str_[size_], value_type()); - } - else - { - clear(); - } - return (*this); - } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::assign(basic_string const& rhs, size_type pos, size_type count) - { - if (count == 0 || pos > rhs.size()) - { - clear(); - return (*this); - } - - discard_const_data(); - - count = rhs.clamp_suffix_size(pos, count); - if (count > capacity_) { destroy(); @@ -670,855 +591,911 @@ namespace common } size_ = count; - traits_type::move(str_, rhs.begin().core() + pos, size_); + traits_type::assign(str_, size_, ch); + traits_type::assign(*(str_ + size_), value_type()); + } + else + { + clear(); + } + return (*this); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::assign(const char_type* cstr, size_type count) +{ + discard_const_data(); + + if (cstr && count) + { + if (count > capacity_) + { + destroy(); + str_ = allocate(count + 1); + capacity_ = count; + } + size_ = count; + + traits_type::move(str_, cstr, size_); traits_type::assign(str_[size_], value_type()); + } + else + { + clear(); + } + return (*this); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::assign(basic_string const& rhs, size_type pos, size_type count) +{ + if (count == 0 || pos > rhs.size()) + { + clear(); return (*this); } - template - inline basic_string<_CharTy>& basic_string<_CharTy>::erase(size_type offset, size_type count) + discard_const_data(); + + count = rhs.clamp_suffix_size(pos, count); + + if (count > capacity_) { - if (count == 0) - return (*this); - - check_offset(offset); - check_operability(); - - count = clamp_suffix_size(offset, count); - - if (count == 0) - { - clear(); - return (*this); - } - - size_type new_size = size_ - count; - iterator erase_at = begin().core() + offset; - traits_type::move(erase_at.core(), erase_at.core() + count, new_size - offset + 1); - return (*this); - } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, size_type count, char_type ch) - { - if (count == 0) - return (*this); - - if (index >= size()) - return append(count, ch); - - check_operability(); - - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - index + 1; - - size_ = old_size + count; - - if (size_ > old_capacity) - { - capacity_ = size_; - char_type* new_ptr = allocate(capacity_ + 1); - - char_type* const insert_at = new_ptr + index; - traits_type::move(new_ptr, old_ptr, index); // (0) - (index) - traits_type::assign(insert_at, count, ch); // (index) - (index + count) - traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) - - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - else - { - char_type* const insert_at = old_ptr + index; - traits_type::move(insert_at + count, old_ptr + index, suffix_size); - traits_type::assign(insert_at, count, ch); - } - - return (*this); - } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, const char_type* cstr, size_type count) - { - if (count == 0) - return (*this); - - if (index >= size()) - return append(cstr, count); - - check_operability(); - - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - index + 1; - - size_ = old_size + count; - - if (size_ > old_capacity) - { - capacity_ = size_; - char_type* new_ptr = allocate(capacity_ + 1); - - char_type* const insert_at = new_ptr + index; - traits_type::move(new_ptr, old_ptr, index); // (0) - (index) - traits_type::move(insert_at, cstr, count); // (index) - (index + count) - traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) - - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - else - { - char_type* const insert_at = old_ptr + index; - traits_type::move(insert_at + count, old_ptr + index, suffix_size); - traits_type::move(insert_at, cstr, count); - } - - return (*this); - } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, const basic_string& str, size_type off, size_type count) - { - if (count == 0 || off > str.size()) - return (*this); - - if (index >= size()) - return append(str, off, count); - - check_operability(); - - count = clamp_suffix_size(off, count); - - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - index + 1; - - size_ = old_size + count; - - if (size_ > old_capacity) - { - capacity_ = size_; - char_type* new_ptr = allocate(capacity_ + 1); - - char_type* const insert_at = new_ptr + index; - traits_type::move(new_ptr, old_ptr, index); // (0) - (index) - traits_type::move(insert_at, str.begin().core() + off, count); // (index) - (index + count) - traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) - - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - else - { - char_type* const insert_at = old_ptr + index; - traits_type::move(insert_at + count, old_ptr + index, suffix_size); - traits_type::move(insert_at, str.begin().core() + off, count); - } - - return (*this); - } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::append(size_type count, char_type ch) - { - check_operability(); - - size_type new_size = size_ + count; - size_type new_cap = new_size + 1; - char_type* new_str = allocate(new_cap); - - traits_type::move(new_str, str_, size_); - traits_type::assign(new_str + size_, count, ch); - traits_type::assign(new_str[new_size], value_type()); - destroy(); + str_ = allocate(count + 1); + capacity_ = count; + } + size_ = count; - str_ = new_str; - size_ = new_size; - capacity_ = new_cap; + traits_type::move(str_, rhs.begin().core() + pos, size_); + traits_type::assign(str_[size_], value_type()); + return (*this); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::erase(size_type offset, size_type count) +{ + if (count == 0) + return (*this); + + check_offset(offset); + check_operability(); + + count = clamp_suffix_size(offset, count); + + if (count == 0) + { + clear(); return (*this); } - template - inline basic_string<_CharTy>& basic_string<_CharTy>::append(const char_type* cstr, size_type count) + size_type new_size = size_ - count; + iterator erase_at = begin().core() + offset; + traits_type::move(erase_at.core(), erase_at.core() + count, new_size - offset + 1); + return (*this); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, size_type count, char_type ch) +{ + if (count == 0) + return (*this); + + if (index >= size()) + return append(count, ch); + + check_operability(); + + char_type* const old_ptr = str_; + const size_type old_size = size_; + const size_type old_capacity = capacity_; + const size_type suffix_size = old_size - index + 1; + + size_ = old_size + count; + + if (size_ > old_capacity) { - check_operability(); + capacity_ = size_; + char_type* new_ptr = allocate(capacity_ + 1); - size_type new_size = size_ + count; - size_type new_cap = new_size + 1; - char_type* new_str = allocate(new_cap); + char_type* const insert_at = new_ptr + index; + traits_type::move(new_ptr, old_ptr, index); // (0) - (index) + traits_type::assign(insert_at, count, ch); // (index) - (index + count) + traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) - traits_type::move(new_str, str_, size_); - traits_type::move(new_str + size_, cstr, count); - traits_type::assign(new_str[new_size], value_type()); + deallocate(str_, old_capacity + 1); + str_ = new_ptr; + } + else + { + char_type* const insert_at = old_ptr + index; + traits_type::move(insert_at + count, old_ptr + index, suffix_size); + traits_type::assign(insert_at, count, ch); + } - destroy(); + return (*this); +} - str_ = new_str; - size_ = new_size; - capacity_ = new_cap; +template +inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, const char_type* cstr, size_type count) +{ + if (count == 0) + return (*this); + + if (index >= size()) + return append(cstr, count); + + check_operability(); + + char_type* const old_ptr = str_; + const size_type old_size = size_; + const size_type old_capacity = capacity_; + const size_type suffix_size = old_size - index + 1; + + size_ = old_size + count; + + if (size_ > old_capacity) + { + capacity_ = size_; + char_type* new_ptr = allocate(capacity_ + 1); + + char_type* const insert_at = new_ptr + index; + traits_type::move(new_ptr, old_ptr, index); // (0) - (index) + traits_type::move(insert_at, cstr, count); // (index) - (index + count) + traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) + + deallocate(str_, old_capacity + 1); + str_ = new_ptr; + } + else + { + char_type* const insert_at = old_ptr + index; + traits_type::move(insert_at + count, old_ptr + index, suffix_size); + traits_type::move(insert_at, cstr, count); + } + + return (*this); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, const basic_string& str, size_type off, size_type count) +{ + if (count == 0 || off > str.size()) + return (*this); + + if (index >= size()) + return append(str, off, count); + + check_operability(); + + count = clamp_suffix_size(off, count); + + char_type* const old_ptr = str_; + const size_type old_size = size_; + const size_type old_capacity = capacity_; + const size_type suffix_size = old_size - index + 1; + + size_ = old_size + count; + + if (size_ > old_capacity) + { + capacity_ = size_; + char_type* new_ptr = allocate(capacity_ + 1); + + char_type* const insert_at = new_ptr + index; + traits_type::move(new_ptr, old_ptr, index); // (0) - (index) + traits_type::move(insert_at, str.begin().core() + off, count); // (index) - (index + count) + traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) + + deallocate(str_, old_capacity + 1); + str_ = new_ptr; + } + else + { + char_type* const insert_at = old_ptr + index; + traits_type::move(insert_at + count, old_ptr + index, suffix_size); + traits_type::move(insert_at, str.begin().core() + off, count); + } + + return (*this); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::append(size_type count, char_type ch) +{ + check_operability(); + + size_type new_size = size_ + count; + size_type new_cap = new_size + 1; + char_type* new_str = allocate(new_cap); + + traits_type::move(new_str, str_, size_); + traits_type::assign(new_str + size_, count, ch); + traits_type::assign(new_str[new_size], value_type()); + + destroy(); + + str_ = new_str; + size_ = new_size; + capacity_ = new_cap; + return (*this); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::append(const char_type* cstr, size_type count) +{ + check_operability(); + + size_type new_size = size_ + count; + size_type new_cap = new_size + 1; + char_type* new_str = allocate(new_cap); + + traits_type::move(new_str, str_, size_); + traits_type::move(new_str + size_, cstr, count); + traits_type::assign(new_str[new_size], value_type()); + + destroy(); + + str_ = new_str; + size_ = new_size; + capacity_ = new_cap; + return (*this); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::append(basic_string const& other, size_type pos, size_type count) +{ + check_operability(); + + if (pos >= other.size()) + return (*this); + + count = other.clamp_suffix_size(pos, count); + + size_type new_size = size_ + count; + size_type new_cap = new_size + 1; + char_type* new_str = allocate(new_cap); + + traits_type::move(new_str, str_, size_); + traits_type::move(new_str + size_, other.begin().core() + pos, count); + traits_type::assign(new_str[new_size], value_type()); + + destroy(); + + str_ = new_str; + size_ = new_size; + capacity_ = new_cap; + return (*this); +} + +template +inline void basic_string<_CharTy>::reserve(const size_type new_cap) +{ + if (new_cap <= capacity_) + return; + + check_operability(); + + char_type* new_str = allocate(new_cap); + traits_type::move(new_str, str_, capacity_); + + destroy(); + + str_ = new_str; + capacity_ = new_cap; +} + +template +inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::hash() const +{ + static size_type fnv_prime = 16777619U; + size_type fnv_offset_basis = 2166136261U; + + for (size_type index = 0; index < size_; ++index) + { + fnv_offset_basis ^= static_cast(const_str_[index]); + fnv_offset_basis *= fnv_prime; + } + return fnv_offset_basis; +} + +template +inline int basic_string<_CharTy>::compare(const char_type* const str) const +{ + size_type count1 = size(); + size_type count2 = traits_type::length(str); + size_type rlen = std::min(count1, count2); + + int ret = traits_type::compare(const_str_, str, rlen); + if (ret != 0) + return ret; + + if (count1 < count2) + return -1; + + if (count1 > count2) + return 1; + + return 0; +} + +template +inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find(const char_type ch, size_type offset) const +{ + if (offset >= size_) + return basic_string<_CharTy>::npos; + + const_iterator citer = traits_type::find(cbegin().core() + offset, size_, ch); + return citer ? (citer - cbegin()) : basic_string<_CharTy>::npos; +} + +template +inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find(const char_type* const str, size_type offset, size_type count) const +{ + if (offset >= size_) + return basic_string<_CharTy>::npos; + return __string_details::TraitsFind(const_str_, size_, offset, str, count); +} + +template +inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_first_of(const char_type* const str, size_type offset, size_type count) const +{ + if (offset >= size_) + return basic_string<_CharTy>::npos; + + const_iterator citer = std::find_first_of(cbegin().core() + offset, cend().core(), str, str + count); + return (citer != cend()) ? (citer - cbegin()) : basic_string<_CharTy>::npos; +} + +template +inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_last_of(const char_type ch, size_type pos) const +{ + if (pos == 0 || pos > size_ || pos == npos) + return npos; + + const_reverse_iterator criter = std::find(crbegin(), crend(), ch); + return (criter != crend()) ? (criter.core() - cbegin()) : basic_string<_CharTy>::npos; +} + +template +inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_last_of(const char_type* const str, size_type pos, size_type count) const +{ + if (pos == 0 || pos > size_ || pos == npos) + return npos; + + return __string_details::TraitsFindLastOf(const_str_, size_, pos, str, count); +} + +template +inline basic_string<_CharTy>& basic_string<_CharTy>::replace(size_type pos, size_type count, const char_type* cstr, size_type count2) +{ + check_offset(pos); + check_operability(); + + count = clamp_suffix_size(pos, count); + if (count == count2) + { + traits_type::move(str_ + pos, cstr, count2); return (*this); } - template - inline basic_string<_CharTy>& basic_string<_CharTy>::append(basic_string const& other, size_type pos, size_type count) + char_type* new_ptr = nullptr; + char_type* const old_ptr = str_; + const size_type old_size = size_; + const size_type old_capacity = capacity_; + const size_type suffix_size = old_size - count - pos + 1; + + if (count < count2 && (old_size + count2 - count) > capacity_) { - check_operability(); + const size_type growth = count2 - count; + size_ = old_size + growth; + capacity_ = size_; + new_ptr = allocate(capacity_ + 1); - if (pos >= other.size()) - return (*this); + traits_type::move(new_ptr, old_ptr, pos); + } + else + { + size_ = old_size - (count - count2); + } - count = other.clamp_suffix_size(pos, count); + char_type* const insert_at = (new_ptr ? new_ptr : old_ptr) + pos; + traits_type::move(insert_at, cstr, count2); + traits_type::move(insert_at + count2, old_ptr + count, suffix_size); - size_type new_size = size_ + count; - size_type new_cap = new_size + 1; - char_type* new_str = allocate(new_cap); + if (new_ptr) + { + deallocate(str_, old_capacity + 1); + str_ = new_ptr; + } - traits_type::move(new_str, str_, size_); - traits_type::move(new_str + size_, other.begin().core() + pos, count); - traits_type::assign(new_str[new_size], value_type()); + return (*this); +} - destroy(); +template +inline basic_string<_CharTy>& basic_string<_CharTy>::replace(size_type pos, size_type count, size_type count2, const char_type ch) +{ + check_offset(pos); + check_operability(); - str_ = new_str; - size_ = new_size; - capacity_ = new_cap; + count = clamp_suffix_size(pos, count); + if (count == count2) + { + traits_type::assign(str_ + pos, count2, ch); return (*this); } - template - inline void basic_string<_CharTy>::reserve(const size_type new_cap) + char_type* new_ptr = nullptr; + char_type* const old_ptr = str_; + const size_type old_size = size_; + const size_type old_capacity = capacity_; + const size_type suffix_size = old_size - count - pos + 1; + + if (count < count2 && (old_size + count2 - count) > capacity_) { - if (new_cap <= capacity_) - return; + const size_type growth = count2 - count; + size_ = old_size + growth; + capacity_ = size_; + new_ptr = allocate(capacity_ + 1); - check_operability(); - - char_type* new_str = allocate(new_cap); - traits_type::move(new_str, str_, capacity_); - - destroy(); - - str_ = new_str; - capacity_ = new_cap; + traits_type::move(new_ptr, old_ptr, pos); + } + else + { + size_ = old_size - (count - count2); } - template - inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::hash() const - { - static size_type fnv_prime = 16777619U; - size_type fnv_offset_basis = 2166136261U; + char_type* const insert_at = (new_ptr ? new_ptr : old_ptr) + pos; + traits_type::assign(insert_at, count2, ch); + traits_type::move(insert_at + count2, old_ptr + count, suffix_size); - for (size_type index = 0; index < size_; ++index) - { - fnv_offset_basis ^= static_cast(const_str_[index]); - fnv_offset_basis *= fnv_prime; - } - return fnv_offset_basis; + if (new_ptr) + { + deallocate(str_, old_capacity + 1); + str_ = new_ptr; } - template - inline int basic_string<_CharTy>::compare(const char_type* const str) const - { - size_type count1 = size(); - size_type count2 = traits_type::length(str); - size_type rlen = std::min(count1, count2); - - int ret = traits_type::compare(const_str_, str, rlen); - if (ret != 0) - return ret; - - if (count1 < count2) - return -1; - - if (count1 > count2) - return 1; + return (*this); +} +template +inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::copy(char_type* cstr, size_type count, size_type pos) const +{ + if (count == 0 || cstr == const_str_) return 0; - } - template - inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find(const char_type ch, size_type offset) const + check_offset(pos); + + count = clamp_suffix_size(pos, count); + traits_type::move(cstr, cbegin().core() + pos, count); + return count; +} + +template +inline typename basic_string<_CharTy>::char_type* basic_string<_CharTy>::allocate(size_type count) +{ + return get_allocator().allocate(count); +} + +template +inline void basic_string<_CharTy>::deallocate(char_type*& ptr, size_type count) +{ + get_allocator().deallocate(ptr, count); + ptr = nullptr; +} + +template +inline void basic_string<_CharTy>::destroy() +{ + if (operable_ && str_) { - if (offset >= size_) - return basic_string<_CharTy>::npos; - - const_iterator citer = traits_type::find(cbegin().core() + offset, size_, ch); - return citer ? (citer - cbegin()) : basic_string<_CharTy>::npos; + deallocate(str_, capacity_ + 1); } - - template - inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find(const char_type* const str, size_type offset, size_type count) const + else { - if (offset >= size_) - return basic_string<_CharTy>::npos; - return __string_details::TraitsFind(const_str_, size_, offset, str, count); + const_str_ = nullptr; } + size_ = capacity_ = 0; +} - template - inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_first_of(const char_type* const str, size_type offset, size_type count) const +template +inline void basic_string<_CharTy>::swap(basic_string& rhs) noexcept +{ + std::swap(const_str_, rhs.const_str_); + std::swap(size_, rhs.size_); + std::swap(capacity_, rhs.capacity_); + + // swap const datas + std::swap(*const_cast(&operable_), *const_cast(&rhs.operable_)); +} + +template +inline void basic_string<_CharTy>::discard_const_data() +{ + if (!operable_) { - if (offset >= size_) - return basic_string<_CharTy>::npos; - - const_iterator citer = std::find_first_of(cbegin().core() + offset, cend().core(), str, str + count); - return (citer != cend()) ? (citer - cbegin()) : basic_string<_CharTy>::npos; + // force to enable operability + *const_cast(&operable_) = true; + const_str_ = nullptr; + capacity_ = size_ = 0; } +} - template - inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_last_of(const char_type ch, size_type pos) const +template +inline void basic_string<_CharTy>::check_operability() +{ + if (!operable_) { - if (pos == 0 || pos > size_ || pos == npos) - return npos; - - const_reverse_iterator criter = std::find(crbegin(), crend(), ch); - return (criter != crend()) ? (criter.core() - cbegin()) : basic_string<_CharTy>::npos; + // create a new string, then swap it with self + basic_string(const_str_, false).swap(*this); } +} - template - inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_last_of(const char_type* const str, size_type pos, size_type count) const +// +// details of basic_string<>::parese +// + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(int val) { return ::oc::to_basic_string(val); } + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned int val) { return ::oc::to_basic_string(val); } + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(long val) { return ::oc::to_basic_string(val); } + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned long val) { return ::oc::to_basic_string(val); } + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(long long val) { return ::oc::to_basic_string(val); } + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned long long val) { return ::oc::to_basic_string(val); } + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(float val) { return ::oc::to_basic_string(val); } + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(double val) { return ::oc::to_basic_string(val); } + +template +inline basic_string<_CharTy> basic_string<_CharTy>::parse(long double val) { return ::oc::to_basic_string(val); } + +// +// details of basic_string::format +// + +template +template +inline basic_string<_CharTy> basic_string<_CharTy>::format(const char_type* fmt, _Args&& ... args) +{ + return ::oc::format_string(fmt, std::forward<_Args>(args)...); +} + +// +// details of operator<<>> +// + +template +inline std::basic_ostream::char_type>& operator<<(std::basic_ostream::char_type>& os, const basic_string<_CharTy>& str) +{ + using ostream = std::basic_ostream::char_type, typename basic_string<_CharTy>::traits_type>; + using size_type = typename basic_string<_CharTy>::size_type; + using traits = typename basic_string<_CharTy>::traits_type; + + const ostream::sentry ok(os); + std::ios_base::iostate state = std::ios_base::goodbit; + + if (!ok) { - if (pos == 0 || pos > size_ || pos == npos) - return npos; - - return __string_details::TraitsFindLastOf(const_str_, size_, pos, str, count); + state |= std::ios_base::badbit; } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::replace(size_type pos, size_type count, const char_type* cstr, size_type count2) + else { - check_offset(pos); - check_operability(); + const auto str_size = str.size(); + size_type pad = (os.width() <= 0 || static_cast(os.width()) <= str_size) ? 0 : static_cast(os.width()) - str_size; - count = clamp_suffix_size(pos, count); - if (count == count2) + try { - traits_type::move(str_ + pos, cstr, count2); - return (*this); - } - - char_type* new_ptr = nullptr; - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - count - pos + 1; - - if (count < count2 && (old_size + count2 - count) > capacity_) - { - const size_type growth = count2 - count; - size_ = old_size + growth; - capacity_ = size_; - new_ptr = allocate(capacity_ + 1); - - traits_type::move(new_ptr, old_ptr, pos); - } - else - { - size_ = old_size - (count - count2); - } - - char_type* const insert_at = (new_ptr ? new_ptr : old_ptr) + pos; - traits_type::move(insert_at, cstr, count2); - traits_type::move(insert_at + count2, old_ptr + count, suffix_size); - - if (new_ptr) - { - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - - return (*this); - } - - template - inline basic_string<_CharTy>& basic_string<_CharTy>::replace(size_type pos, size_type count, size_type count2, const char_type ch) - { - check_offset(pos); - check_operability(); - - count = clamp_suffix_size(pos, count); - if (count == count2) - { - traits_type::assign(str_ + pos, count2, ch); - return (*this); - } - - char_type* new_ptr = nullptr; - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - count - pos + 1; - - if (count < count2 && (old_size + count2 - count) > capacity_) - { - const size_type growth = count2 - count; - size_ = old_size + growth; - capacity_ = size_; - new_ptr = allocate(capacity_ + 1); - - traits_type::move(new_ptr, old_ptr, pos); - } - else - { - size_ = old_size - (count - count2); - } - - char_type* const insert_at = (new_ptr ? new_ptr : old_ptr) + pos; - traits_type::assign(insert_at, count2, ch); - traits_type::move(insert_at + count2, old_ptr + count, suffix_size); - - if (new_ptr) - { - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - - return (*this); - } - - template - inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::copy(char_type* cstr, size_type count, size_type pos) const - { - if (count == 0 || cstr == const_str_) - return 0; - - check_offset(pos); - - count = clamp_suffix_size(pos, count); - traits_type::move(cstr, cbegin().core() + pos, count); - return count; - } - - template - inline typename basic_string<_CharTy>::char_type* basic_string<_CharTy>::allocate(size_type count) - { - return get_allocator().allocate(count); - } - - template - inline void basic_string<_CharTy>::deallocate(char_type*& ptr, size_type count) - { - get_allocator().deallocate(ptr, count); - ptr = nullptr; - } - - template - inline void basic_string<_CharTy>::destroy() - { - if (operable_ && str_) - { - deallocate(str_, capacity_ + 1); - } - else - { - const_str_ = nullptr; - } - size_ = capacity_ = 0; - } - - template - inline void basic_string<_CharTy>::swap(basic_string& rhs) noexcept - { - std::swap(const_str_, rhs.const_str_); - std::swap(size_, rhs.size_); - std::swap(capacity_, rhs.capacity_); - - // swap const datas - std::swap(*const_cast(&operable_), *const_cast(&rhs.operable_)); - } - - template - inline void basic_string<_CharTy>::discard_const_data() - { - if (!operable_) - { - // force to enable operability - *const_cast(&operable_) = true; - const_str_ = nullptr; - capacity_ = size_ = 0; - } - } - - template - inline void basic_string<_CharTy>::check_operability() - { - if (!operable_) - { - // create a new string, then swap it with self - basic_string(const_str_, false).swap(*this); - } - } - - // - // details of basic_string<>::parese - // - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(int val) { return ::kiwano::common::to_basic_string(val); } - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned int val) { return ::kiwano::common::to_basic_string(val); } - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(long val) { return ::kiwano::common::to_basic_string(val); } - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned long val) { return ::kiwano::common::to_basic_string(val); } - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(long long val) { return ::kiwano::common::to_basic_string(val); } - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned long long val) { return ::kiwano::common::to_basic_string(val); } - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(float val) { return ::kiwano::common::to_basic_string(val); } - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(double val) { return ::kiwano::common::to_basic_string(val); } - - template - inline basic_string<_CharTy> basic_string<_CharTy>::parse(long double val) { return ::kiwano::common::to_basic_string(val); } - - // - // details of basic_string::format - // - - template - template - inline basic_string<_CharTy> basic_string<_CharTy>::format(const char_type* fmt, _Args&& ... args) - { - return ::kiwano::common::format_string(fmt, std::forward<_Args>(args)...); - } - - // - // details of operator<<>> - // - - template - inline std::basic_ostream::char_type>& operator<<(std::basic_ostream::char_type>& os, const basic_string<_CharTy>& str) - { - using ostream = std::basic_ostream::char_type, typename basic_string<_CharTy>::traits_type>; - using size_type = typename basic_string<_CharTy>::size_type; - using traits = typename basic_string<_CharTy>::traits_type; - - const ostream::sentry ok(os); - std::ios_base::iostate state = std::ios_base::goodbit; - - if (!ok) - { - state |= std::ios_base::badbit; - } - else - { - const auto str_size = str.size(); - size_type pad = (os.width() <= 0 || static_cast(os.width()) <= str_size) ? 0 : static_cast(os.width()) - str_size; - - try + if ((os.flags() & std::ios_base::adjustfield) != std::ios_base::left) { - if ((os.flags() & std::ios_base::adjustfield) != std::ios_base::left) + for (; 0 < pad; --pad) { - for (; 0 < pad; --pad) + if (traits::eq_int_type(traits::eof(), os.rdbuf()->sputc(os.fill()))) { - if (traits::eq_int_type(traits::eof(), os.rdbuf()->sputc(os.fill()))) - { - state |= std::ios_base::badbit; - break; - } + state |= std::ios_base::badbit; + break; } } + } - if (state == std::ios_base::goodbit - && os.rdbuf()->sputn(str.data(), (std::streamsize)str_size) != (std::streamsize)str_size) + if (state == std::ios_base::goodbit + && os.rdbuf()->sputn(str.data(), (std::streamsize)str_size) != (std::streamsize)str_size) + { + state |= std::ios_base::badbit; + } + else + { + for (; 0 < pad; --pad) { - state |= std::ios_base::badbit; + if (traits::eq_int_type(traits::eof(), os.rdbuf()->sputc(os.fill()))) + { + state |= std::ios_base::badbit; + break; + } + } + } + os.width(0); + } + catch (...) + { + os.setstate(std::ios_base::badbit, true); + } + } + + os.setstate(state); + return (os); +} + +template +inline std::basic_istream::char_type>& operator>>(std::basic_istream::char_type>& is, basic_string<_CharTy>& str) +{ + using ctype = std::ctype::char_type>; + using istream = std::basic_istream::char_type, typename basic_string<_CharTy>::traits_type>; + using size_type = typename basic_string<_CharTy>::size_type; + using traits = typename basic_string<_CharTy>::traits_type; + + bool changed = false; + const istream::sentry ok(is); + std::ios_base::iostate state = std::ios_base::goodbit; + + if (ok) + { + const ctype& ctype_fac = std::use_facet(is.getloc()); + str.erase(); + try + { + size_type size = (0 < is.width() && static_cast(is.width()) < str.max_size()) ? static_cast(is.width()) : str.max_size(); + typename traits::int_type meta = is.rdbuf()->sgetc(); + + for (; 0 < size; --size, meta = is.rdbuf()->snextc()) + { + if (traits::eq_int_type(traits::eof(), meta)) + { + state |= std::ios_base::eofbit; + break; + } + else if (ctype_fac.is(ctype::space, traits::to_char_type(meta))) + { + break; } else { - for (; 0 < pad; --pad) - { - if (traits::eq_int_type(traits::eof(), os.rdbuf()->sputc(os.fill()))) - { - state |= std::ios_base::badbit; - break; - } - } - } - os.width(0); - } - catch (...) - { - os.setstate(std::ios_base::badbit, true); - } - } - - os.setstate(state); - return (os); - } - - template - inline std::basic_istream::char_type>& operator>>(std::basic_istream::char_type>& is, basic_string<_CharTy>& str) - { - using ctype = std::ctype::char_type>; - using istream = std::basic_istream::char_type, typename basic_string<_CharTy>::traits_type>; - using size_type = typename basic_string<_CharTy>::size_type; - using traits = typename basic_string<_CharTy>::traits_type; - - bool changed = false; - const istream::sentry ok(is); - std::ios_base::iostate state = std::ios_base::goodbit; - - if (ok) - { - const ctype& ctype_fac = std::use_facet(is.getloc()); - str.erase(); - try - { - size_type size = (0 < is.width() && static_cast(is.width()) < str.max_size()) ? static_cast(is.width()) : str.max_size(); - typename traits::int_type meta = is.rdbuf()->sgetc(); - - for (; 0 < size; --size, meta = is.rdbuf()->snextc()) - { - if (traits::eq_int_type(traits::eof(), meta)) - { - state |= std::ios_base::eofbit; - break; - } - else if (ctype_fac.is(ctype::space, traits::to_char_type(meta))) - { - break; - } - else - { - str.push_back(traits::to_char_type(meta)); - changed = true; - } + str.push_back(traits::to_char_type(meta)); + changed = true; } } - catch (...) - { - is.setstate(std::ios_base::badbit, true); - } } - - is.width(0); - if (!changed) - state |= std::ios_base::failbit; - is.setstate(state); - return is; - } - - // - // details of to_string functions - // - - namespace __to_string_detail - { - template - struct FloatingToString + catch (...) { - // template - // static basic_string<_CharTy> convert(const _Ty val); - }; - - template - struct IntegralToString - { - // template - // static basic_string<_CharTy> convert(const _Ty val); - }; - } - - template - inline basic_string<_CharTy> to_basic_string(int val) - { - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); - } - - template - inline basic_string<_CharTy> to_basic_string(unsigned int val) - { - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); - } - - template - inline basic_string<_CharTy> to_basic_string(long val) - { - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); - } - - template - inline basic_string<_CharTy> to_basic_string(unsigned long val) - { - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); - } - - template - inline basic_string<_CharTy> to_basic_string(long long val) - { - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); - } - - template - inline basic_string<_CharTy> to_basic_string(unsigned long long val) - { - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); - } - - template - inline basic_string<_CharTy> to_basic_string(float val) - { - return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); - } - - template - inline basic_string<_CharTy> to_basic_string(double val) - { - return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); - } - - template - inline basic_string<_CharTy> to_basic_string(long double val) - { - return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); - } - - template - inline basic_string format_string(const char* const fmt, _Args&& ... args) - { - using string_type = basic_string; - const auto len = static_cast(::_scprintf(fmt, std::forward<_Args>(args)...)); - if (len) - { - string_type str(len, '\0'); - ::sprintf_s(&str[0], len + 1, fmt, std::forward<_Args>(args)...); - return str; + is.setstate(std::ios_base::badbit, true); } - return string_type{}; } - template - inline basic_string format_string(const wchar_t* const fmt, _Args&& ... args) - { - using string_type = basic_string; - const auto len = static_cast(::_scwprintf(fmt, std::forward<_Args>(args)...)); - if (len) - { - string_type str(len, L'\0'); - ::swprintf_s(&str[0], len + 1, fmt, std::forward<_Args>(args)...); - return str; - } - return string_type{}; - } - - namespace __to_string_detail - { - template - _Elem* __IntegerToStringBufferEnd(const _Ty val, _Elem* const buffer_end) - { - using _UTy = std::make_unsigned_t<_Ty>; - - _Elem* next = buffer_end; - auto uval = static_cast<_UTy>(val); - - if (val < 0) - uval = 0 - uval; - - do - { - *--next = static_cast<_Elem>('0' + uval % 10); - uval /= 10; - } while (uval != 0); - - if (val < 0) - * --next = static_cast<_Elem>('-'); - - return next; - } - - template <> - struct IntegralToString - { - template - static basic_string convert(const _Ty val) - { - static_assert(std::is_integral<_Ty>::value, "_Ty must be integral"); - - using _Elem = typename basic_string::traits_type::char_type; - - _Elem buffer[21]; - _Elem* const buffer_end = std::end(buffer); - _Elem* buffer_begin = __IntegerToStringBufferEnd(val, buffer_end); - - return basic_string(buffer_begin, buffer_end); - } - }; - - template <> - struct IntegralToString - { - template - static basic_string convert(const _Ty val) - { - static_assert(std::is_integral<_Ty>::value, "_Ty must be integral"); - - using _Elem = typename basic_string::traits_type::char_type; - - _Elem buffer[21]; - _Elem* const buffer_end = std::end(buffer); - _Elem* buffer_begin = __IntegerToStringBufferEnd(val, buffer_end); - - return basic_string(buffer_begin, buffer_end); - } - }; - - template<> - struct FloatingToString - { - static inline basic_string convert(const float val) - { - return format_string(L"%g", val); - } - - static inline basic_string convert(const double val) - { - return format_string(L"%g", val); - } - - static inline basic_string convert(const long double val) - { - return format_string(L"%Lg", val); - } - }; - - template<> - struct FloatingToString - { - static inline basic_string convert(const float val) - { - return format_string("%g", val); - } - - static inline basic_string convert(const double val) - { - return format_string("%g", val); - } - - static inline basic_string convert(const long double val) - { - return format_string("%Lg", val); - } - }; - } -} + is.width(0); + if (!changed) + state |= std::ios_base::failbit; + is.setstate(state); + return is; } -namespace kiwano +// +// details of to_string functions +// + +namespace __to_string_detail +{ + template + struct FloatingToString + { + // template + // static basic_string<_CharTy> convert(const _Ty val); + }; + + template + struct IntegralToString + { + // template + // static basic_string<_CharTy> convert(const _Ty val); + }; +} + +template +inline basic_string<_CharTy> to_basic_string(int val) +{ + return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); +} + +template +inline basic_string<_CharTy> to_basic_string(unsigned int val) +{ + return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); +} + +template +inline basic_string<_CharTy> to_basic_string(long val) +{ + return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); +} + +template +inline basic_string<_CharTy> to_basic_string(unsigned long val) +{ + return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); +} + +template +inline basic_string<_CharTy> to_basic_string(long long val) +{ + return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); +} + +template +inline basic_string<_CharTy> to_basic_string(unsigned long long val) +{ + return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); +} + +template +inline basic_string<_CharTy> to_basic_string(float val) +{ + return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); +} + +template +inline basic_string<_CharTy> to_basic_string(double val) +{ + return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); +} + +template +inline basic_string<_CharTy> to_basic_string(long double val) +{ + return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); +} + +template +inline basic_string format_string(const char* const fmt, _Args&& ... args) +{ + using string_type = basic_string; + const auto len = static_cast(::_scprintf(fmt, std::forward<_Args>(args)...)); + if (len) + { + string_type str(len, '\0'); + ::sprintf_s(&str[0], len + 1, fmt, std::forward<_Args>(args)...); + return str; + } + return string_type{}; +} + +template +inline basic_string format_string(const wchar_t* const fmt, _Args&& ... args) +{ + using string_type = basic_string; + const auto len = static_cast(::_scwprintf(fmt, std::forward<_Args>(args)...)); + if (len) + { + string_type str(len, L'\0'); + ::swprintf_s(&str[0], len + 1, fmt, std::forward<_Args>(args)...); + return str; + } + return string_type{}; +} + +namespace __to_string_detail +{ + template + _Elem* __IntegerToStringBufferEnd(const _Ty val, _Elem* const buffer_end) + { + using _UTy = std::make_unsigned_t<_Ty>; + + _Elem* next = buffer_end; + auto uval = static_cast<_UTy>(val); + + if (val < 0) + uval = 0 - uval; + + do + { + *--next = static_cast<_Elem>('0' + uval % 10); + uval /= 10; + } while (uval != 0); + + if (val < 0) + * --next = static_cast<_Elem>('-'); + + return next; + } + + template <> + struct IntegralToString + { + template + static basic_string convert(const _Ty val) + { + static_assert(std::is_integral<_Ty>::value, "_Ty must be integral"); + + using _Elem = typename basic_string::traits_type::char_type; + + _Elem buffer[21]; + _Elem* const buffer_end = std::end(buffer); + _Elem* buffer_begin = __IntegerToStringBufferEnd(val, buffer_end); + + return basic_string(buffer_begin, buffer_end); + } + }; + + template <> + struct IntegralToString + { + template + static basic_string convert(const _Ty val) + { + static_assert(std::is_integral<_Ty>::value, "_Ty must be integral"); + + using _Elem = typename basic_string::traits_type::char_type; + + _Elem buffer[21]; + _Elem* const buffer_end = std::end(buffer); + _Elem* buffer_begin = __IntegerToStringBufferEnd(val, buffer_end); + + return basic_string(buffer_begin, buffer_end); + } + }; + + template<> + struct FloatingToString + { + static inline basic_string convert(const float val) + { + return format_string(L"%g", val); + } + + static inline basic_string convert(const double val) + { + return format_string(L"%g", val); + } + + static inline basic_string convert(const long double val) + { + return format_string(L"%Lg", val); + } + }; + + template<> + struct FloatingToString + { + static inline basic_string convert(const float val) + { + return format_string("%g", val); + } + + static inline basic_string convert(const double val) + { + return format_string("%g", val); + } + + static inline basic_string convert(const long double val) + { + return format_string("%Lg", val); + } + }; +} + +} + +namespace oc { template @@ -1527,8 +1504,8 @@ class string_convert enum : size_t { BUFFER_INCREASE = 8, BUFFER_MAX = 16 }; public: - using byte_string = ::kiwano::common::basic_string; - using wide_string = ::kiwano::common::basic_string<_Elem>; + using byte_string = ::oc::basic_string; + using wide_string = ::oc::basic_string<_Elem>; using codecvt_type = _Codecvt; using state_type = typename codecvt_type::state_type; using int_type = typename wide_string::traits_type::int_type; @@ -1605,7 +1582,8 @@ public: case codecvt_type::noconv: { // no conversion, just copy code values - for (; first != last; ++first) { + for (; first != last; ++first) + { wstr.push_back(static_cast<_Elem>(*first)); } break; @@ -1693,7 +1671,7 @@ private: const codecvt_type* cvt_; std::locale loc_; state_type state_; - size_t conv_num_; + size_t conv_num_; }; class chs_codecvt @@ -1702,63 +1680,62 @@ class chs_codecvt public: chs_codecvt() : codecvt_byname("chs") {} - static inline ::kiwano::common::wstring string_to_wide(::kiwano::common::string const& str) + static inline ::oc::wstring string_to_wide(::oc::string const& str) { string_convert conv; return conv.from_bytes(str); } - static inline ::kiwano::common::string wide_to_string(::kiwano::common::wstring const& str) + static inline ::oc::string wide_to_string(::oc::wstring const& str) { string_convert conv; return conv.to_bytes(str); } }; -inline ::kiwano::common::wstring string_to_wide(::kiwano::common::string const& str) +inline ::oc::wstring string_to_wide(::oc::string const& str) { - return kiwano::chs_codecvt::string_to_wide(str); + return oc::chs_codecvt::string_to_wide(str); } -inline ::kiwano::common::string wide_to_string(::kiwano::common::wstring const& str) +inline ::oc::string wide_to_string(::oc::wstring const& str) { - return kiwano::chs_codecvt::wide_to_string(str); + return oc::chs_codecvt::wide_to_string(str); } -} +} // namespace oc namespace std { - template<> - struct hash<::kiwano::common::string> - { - inline size_t operator()(const ::kiwano::common::string& key) const - { - return key.hash(); - } - }; - template<> - struct hash<::kiwano::common::wstring> - { - inline size_t operator()(const ::kiwano::common::wstring& key) const - { - return key.hash(); - } - }; -} - -namespace std +template<> +struct hash<::oc::string> { - template<> - inline void swap<::kiwano::common::string>(::kiwano::common::string& lhs, ::kiwano::common::string& rhs) noexcept + inline size_t operator()(const ::oc::string& key) const { - lhs.swap(rhs); + return key.hash(); } +}; - template<> - inline void swap<::kiwano::common::wstring>(::kiwano::common::wstring& lhs, ::kiwano::common::wstring& rhs) noexcept +template<> +struct hash<::oc::wstring> +{ + inline size_t operator()(const ::oc::wstring& key) const { - lhs.swap(rhs); + return key.hash(); } +}; + +template<> +inline void swap<::oc::string>(::oc::string& lhs, ::oc::string& rhs) noexcept +{ + lhs.swap(rhs); +} + +template<> +inline void swap<::oc::wstring>(::oc::wstring& lhs, ::oc::wstring& rhs) noexcept +{ + lhs.swap(rhs); +} + } diff --git a/src/kiwano/common/vector.hpp b/src/3rd-party/OuterC/oc/vector.h similarity index 53% rename from src/kiwano/common/vector.hpp rename to src/3rd-party/OuterC/oc/vector.h index 497357d0..813afec0 100644 --- a/src/kiwano/common/vector.hpp +++ b/src/3rd-party/OuterC/oc/vector.h @@ -1,52 +1,18 @@ -// Copyright (c) 2016-2018 Kiwano - 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. +// Copyright (c) 2019-2020 OuterC - Nomango #pragma once #include -#include #include +#include "vector/details.h" -namespace kiwano +namespace oc { -namespace common -{ - - -// -// vector_memory_manager<> with memory operations -// -namespace __vector_details -{ - template::value> - struct vector_memory_manager; -} - // // vector<> // Lightweight std::vector<>-like class // -template< - typename _Ty, - typename _Alloc = std::allocator<_Ty>, - typename _Manager = __vector_details::vector_memory_manager<_Ty, _Alloc>> +template > class vector { public: @@ -59,7 +25,7 @@ public: using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using allocator_type = typename _Alloc; - using manager = typename _Manager; + using manager = typename __vector_details::vector_memory_manager<_Ty, _Alloc>; using initializer_list = std::initializer_list; public: @@ -74,11 +40,11 @@ public: template inline vector(_Iter first, _Iter last) : vector() { assign(first, last); } - inline vector& operator=(const vector& src) { if (&src != this) { resize(src.size_); manager::copy_data(begin(), src.cbegin(), size_); } return (*this); } + inline vector& operator=(const vector& src) { if (&src != this) { resize(src.size_); manager::copy_n(begin(), src.cbegin(), size_); } return (*this); } inline vector& operator=(vector&& src) noexcept { swap(src); return *this; } inline vector& operator=(initializer_list list) { if (list.size()) { assign(list.begin(), list.end()); } else clear(); return (*this); } - inline vector& assign(size_type count, const _Ty& val) { if (count > 0) { resize(count); manager::copy_data(begin(), count, val); } else clear(); return (*this); } + inline vector& assign(size_type count, const _Ty& val) { if (count > 0) { resize(count); manager::copy(begin(), count, val); } else clear(); return (*this); } inline vector& assign(const vector& src) { return operator=(src); } inline vector& assign(initializer_list list) { return operator=(list); } @@ -140,8 +106,8 @@ protected: _Ty* data_; }; -template -void vector<_Ty, _Alloc, _Manager>::resize(size_type new_size, const _Ty& val) +template +void vector<_Ty, _Alloc>::resize(size_type new_size, const _Ty& val) { if (new_size > size_) { @@ -158,8 +124,8 @@ void vector<_Ty, _Alloc, _Manager>::resize(size_type new_size, const _Ty& val) size_ = new_size; } -template -void vector<_Ty, _Alloc, _Manager>::reserve(size_type new_capacity) +template +void vector<_Ty, _Alloc>::reserve(size_type new_capacity) { if (new_capacity <= capacity_) return; @@ -167,8 +133,7 @@ void vector<_Ty, _Alloc, _Manager>::reserve(size_type new_capacity) auto new_data = manager::allocate(new_capacity); if (data_) { - manager::construct(new_data, size_/* only construct needed size */); - manager::copy_data(new_data, data_, size_); + manager::construct_n(new_data, data_, size_/* only construct needed size */); /* destroy old memory, but not resize */ destroy(); } @@ -176,9 +141,9 @@ void vector<_Ty, _Alloc, _Manager>::reserve(size_type new_capacity) capacity_ = new_capacity; } -template -typename vector<_Ty, _Alloc, _Manager>::iterator - vector<_Ty, _Alloc, _Manager>::erase(const_iterator first, const_iterator last) +template +typename vector<_Ty, _Alloc>::iterator + vector<_Ty, _Alloc>::erase(const_iterator first, const_iterator last) { const auto off = first - begin(); const auto count = last - first; @@ -187,15 +152,15 @@ typename vector<_Ty, _Alloc, _Manager>::iterator { check_offset(off); - manager::move_data(begin() + off, begin() + off + count, size_ - off - count); + manager::move(begin() + off, begin() + off + count, size_ - off - count); resize(size_ - count); // do destruction } return begin() + off; } -template -typename vector<_Ty, _Alloc, _Manager>::iterator - vector<_Ty, _Alloc, _Manager>::insert(const_iterator where, const _Ty& v) +template +typename vector<_Ty, _Alloc>::iterator + vector<_Ty, _Alloc>::insert(const_iterator where, const _Ty& v) { const auto off = where - begin(); const auto insert_at = begin() + off; @@ -203,86 +168,9 @@ typename vector<_Ty, _Alloc, _Manager>::iterator check_offset(off); resize(size_ + 1); - manager::move_data(insert_at + 1, insert_at, size_ - off - 1); + manager::move(insert_at + 1, insert_at, size_ - off - 1); data_[off] = v; return begin() + off; } -namespace __vector_details -{ - // - // vector_memory_manager for common type - // - template - struct vector_memory_manager<_Ty, _Alloc, false> - { - using value_type = _Ty; - using size_type = size_t; - using allocator_type = typename _Alloc; - - static void copy_data(value_type* dest, const value_type* src, size_type count) { if (src == dest) return; ::memcpy(dest, src, size_type(count) * sizeof(value_type)); } - static void copy_data(value_type* dest, size_type count, const value_type& val) { ::memset(dest, int(val), size_type(count) * sizeof(value_type)); } - static void move_data(value_type* dest, const value_type* src, size_type count) { if (src == dest) return; ::memmove(dest, src, size_type(count) * sizeof(value_type)); } - - static value_type* allocate(size_type count) { return get_allocator().allocate(count); } - static void deallocate(value_type*& ptr, size_type count) { if (ptr) { get_allocator().deallocate(ptr, count); ptr = nullptr; } } - - static void construct(value_type* ptr, size_type count) { } - static void construct(value_type* ptr, size_type count, const value_type& val) { while (count) { --count; *(ptr + count) = val; } } - static void destroy(value_type* ptr, size_type count) { } - - private: - static allocator_type& get_allocator() - { - static allocator_type allocator_; - return allocator_; - } - }; - - // - // vector_memory_manager for classes - // - template - struct vector_memory_manager<_Ty, _Alloc, true> - { - using value_type = _Ty; - using size_type = size_t; - using allocator_type = typename _Alloc; - - static void copy_data(value_type* dest, const value_type* src, size_type count) { if (src == dest) return; while (count--) (*dest++) = (*src++); } - static void copy_data(value_type* dest, size_type count, const value_type& val) { while (count--) (*dest++) = val; } - static void move_data(value_type* dest, const value_type* src, size_type count) - { - if (src == dest) return; - if (dest > src && dest < src + count) - { - src = src + count - 1; - dest = dest + count - 1; - while (count--) - (*dest--) = (*src--); - } - else - { - while (count--) - (*dest++) = (*src++); - } - } - - static value_type* allocate(size_type count) { return get_allocator().allocate(count); } - static void deallocate(value_type*& ptr, size_type count) { if (ptr) { get_allocator().deallocate(ptr, count); ptr = nullptr; } } - - static void construct(value_type* ptr, size_type count) { construct(ptr, count, value_type()); } - static void construct(value_type* ptr, size_type count, const value_type& val) { while (count) get_allocator().construct(ptr + (--count), val); } - static void destroy(value_type* ptr, size_type count) { while (count) get_allocator().destroy(ptr + (--count)); } - - private: - static allocator_type& get_allocator() - { - static allocator_type allocator_; - return allocator_; - } - }; -} - -} // namespace common -} // namespace kiwano +} // namespace oc diff --git a/src/3rd-party/OuterC/oc/vector/details.h b/src/3rd-party/OuterC/oc/vector/details.h new file mode 100644 index 00000000..b860a6bc --- /dev/null +++ b/src/3rd-party/OuterC/oc/vector/details.h @@ -0,0 +1,79 @@ +// Copyright (c) 2019-2020 OuterC - Nomango + +#pragma once +#include +#include +#include +#include + +namespace oc +{ + +namespace __vector_details +{ + +// vector_memory_manager<> with memory operations +template::value> +struct vector_memory_manager; + + +// +// vector_memory_manager for common type +// +template +struct vector_memory_manager<_Ty, _Alloc, true> +{ + using value_type = _Ty; + using size_type = size_t; + using allocator_type = typename _Alloc; + + static void copy(value_type* const dest, const size_type count, const value_type& val) { for (size_type i = 0; i < count; ++i) std::memcpy(&dest[i], &val, sizeof(value_type)); } + static void copy_n(value_type* const dest, const value_type* src, const size_type count) { if (src == dest) return; std::memcpy(dest, src, count * sizeof(value_type)); } + static void move(value_type* const dest, const value_type* src, const size_type count) { if (src == dest) return; std::memmove(dest, src, count * sizeof(value_type)); } + + static void construct(value_type* const ptr, const size_type count, const value_type& val) { copy(ptr, count, val); } + static void construct_n(value_type* const ptr, const value_type* src, const size_type count) { copy_n(ptr, src, count); } + static void destroy(value_type* const ptr, const size_type count) { } + + static value_type* allocate(const size_type count) { return get_allocator().allocate(count); } + static void deallocate(value_type*& ptr, const size_type count) { if (ptr) { get_allocator().deallocate(ptr, count); ptr = nullptr; } } + +private: + static allocator_type& get_allocator() + { + static allocator_type allocator_; + return allocator_; + } +}; + +// +// vector_memory_manager for classes +// +template +struct vector_memory_manager<_Ty, _Alloc, false> +{ + using value_type = _Ty; + using size_type = size_t; + using allocator_type = typename _Alloc; + + static void copy(value_type* const dest, const size_type count, const value_type& val) { std::fill_n(dest, count, val); } + static void copy_n(value_type* const dest, const value_type* src, const size_type count) { if (src == dest) return; std::copy_n(src, count, dest); } + static void move(value_type* const dest, const value_type* src, const size_type count) { if (src == dest) return; if (dest > src && dest < src + count) std::copy_backward(src, src + count, dest); else copy_n(dest, src, count); } + + static void construct(value_type* const ptr, const size_type count, const value_type& val) { for (size_type i = 0; i < count; ++i) get_allocator().construct(std::addressof(ptr[i]), val); } + static void construct_n(value_type* const ptr, const value_type* src, const size_type count) { for (size_type i = 0; i < count; ++i) get_allocator().construct(std::addressof(ptr[i]), src[i]); } + static void destroy(value_type* const ptr, const size_type count) { for (size_type i = 0; i < count; ++i) get_allocator().destroy(std::addressof(ptr[i])); } + + static value_type* allocate(const size_type count) { return get_allocator().allocate(count); } + static void deallocate(value_type*& ptr, const size_type count) { if (ptr) { get_allocator().deallocate(ptr, count); ptr = nullptr; } } + +private: + static allocator_type& get_allocator() + { + static allocator_type allocator_; + return allocator_; + } +}; + +} // namespace __vector_details +} // namespace oc diff --git a/src/kiwano-audio/AudioEngine.h b/src/kiwano-audio/AudioEngine.h index 11187a2a..9bb8e177 100644 --- a/src/kiwano-audio/AudioEngine.h +++ b/src/kiwano-audio/AudioEngine.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #include #include #include @@ -33,7 +33,7 @@ namespace kiwano : public Singleton , public ComponentBase { - KGE_DECLARE_SINGLETON(AudioEngine); + OC_DECLARE_SINGLETON(AudioEngine); public: // ¿ªÆôÉ豸 diff --git a/src/kiwano-audio/Sound.cpp b/src/kiwano-audio/Sound.cpp index 622391fb..8e503f31 100644 --- a/src/kiwano-audio/Sound.cpp +++ b/src/kiwano-audio/Sound.cpp @@ -54,9 +54,9 @@ namespace kiwano bool Sound::Load(String const& file_path) { - if (!FileSystem::GetInstance()->IsFileExists(file_path)) + if (!FileSystem::instance().IsFileExists(file_path)) { - KGE_WARNING_LOG(L"Media file '%s' not found", file_path.c_str()); + KGE_WARN(L"Media file '%s' not found", file_path.c_str()); return false; } @@ -65,22 +65,22 @@ namespace kiwano Close(); } - String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path); + String full_path = FileSystem::instance().GetFullPathForFile(file_path); HRESULT hr = transcoder_.LoadMediaFile(full_path); if (FAILED(hr)) { - KGE_ERROR_LOG(L"Load media file failed with HRESULT of %08X", hr); + KGE_ERROR(L"Load media file failed with HRESULT of %08X", hr); return false; } - hr = AudioEngine::GetInstance()->CreateVoice(&voice_, transcoder_.GetBuffer()); + hr = AudioEngine::instance().CreateVoice(&voice_, transcoder_.GetBuffer()); if (FAILED(hr)) { Close(); - KGE_ERROR_LOG(L"Create source voice failed with HRESULT of %08X", hr); + KGE_ERROR(L"Create source voice failed with HRESULT of %08X", hr); return false; } @@ -99,16 +99,16 @@ namespace kiwano if (FAILED(hr)) { - KGE_ERROR_LOG(L"Load media resource failed with HRESULT of %08X", hr); + KGE_ERROR(L"Load media resource failed with HRESULT of %08X", hr); return false; } - hr = AudioEngine::GetInstance()->CreateVoice(&voice_, transcoder_.GetBuffer()); + hr = AudioEngine::instance().CreateVoice(&voice_, transcoder_.GetBuffer()); if (FAILED(hr)) { Close(); - KGE_ERROR_LOG(L"Create source voice failed with HRESULT of %08X", hr); + KGE_ERROR(L"Create source voice failed with HRESULT of %08X", hr); return false; } @@ -120,7 +120,7 @@ namespace kiwano { if (!opened_) { - KGE_ERROR_LOG(L"Sound must be opened first!"); + KGE_ERROR(L"Sound must be opened first!"); return; } @@ -151,7 +151,7 @@ namespace kiwano if (FAILED(hr)) { - KGE_ERROR_LOG(L"Submitting source buffer failed with HRESULT of %08X", hr); + KGE_ERROR(L"Submitting source buffer failed with HRESULT of %08X", hr); } playing_ = SUCCEEDED(hr); diff --git a/src/kiwano-audio/Sound.h b/src/kiwano-audio/Sound.h index e94171a4..85e4add4 100644 --- a/src/kiwano-audio/Sound.h +++ b/src/kiwano-audio/Sound.h @@ -19,7 +19,6 @@ // THE SOFTWARE. #pragma once -#include #include #include #include diff --git a/src/kiwano-audio/SoundPlayer.h b/src/kiwano-audio/SoundPlayer.h index 913fe04f..c7d3d91e 100644 --- a/src/kiwano-audio/SoundPlayer.h +++ b/src/kiwano-audio/SoundPlayer.h @@ -19,7 +19,6 @@ // THE SOFTWARE. #pragma once -#include #include #include diff --git a/src/kiwano-audio/Transcoder.cpp b/src/kiwano-audio/Transcoder.cpp index 256ebe83..4ddd43e4 100644 --- a/src/kiwano-audio/Transcoder.cpp +++ b/src/kiwano-audio/Transcoder.cpp @@ -23,7 +23,7 @@ #endif #include -#include +#include #include #include #include @@ -108,7 +108,7 @@ namespace kiwano if (stream == nullptr) { - KGE_ERROR_LOG(L"SHCreateMemStream failed"); + KGE_ERROR(L"SHCreateMemStream failed"); return E_OUTOFMEMORY; } @@ -225,7 +225,7 @@ namespace kiwano if (data == nullptr) { - KGE_ERROR_LOG(L"Low memory"); + KGE_ERROR(L"Low memory"); hr = E_OUTOFMEMORY; } else diff --git a/src/kiwano-audio/audio-modules.cpp b/src/kiwano-audio/audio-modules.cpp index f140f00d..55c1206f 100644 --- a/src/kiwano-audio/audio-modules.cpp +++ b/src/kiwano-audio/audio-modules.cpp @@ -52,7 +52,7 @@ namespace kiwano } else { - KGE_ERROR_LOG(L"Load xaudio2.dll failed"); + KGE_ERROR(L"Load xaudio2.dll failed"); throw std::runtime_error("Load xaudio2.dll failed"); } } diff --git a/src/kiwano-imgui/ImGuiModule.cpp b/src/kiwano-imgui/ImGuiModule.cpp index f164f2bd..1d79f6a7 100644 --- a/src/kiwano-imgui/ImGuiModule.cpp +++ b/src/kiwano-imgui/ImGuiModule.cpp @@ -1,8 +1,6 @@ // Copyright (C) 2019 Nomango #include -#include -#include #include #include #include @@ -45,9 +43,9 @@ namespace kiwano //ImGui::StyleColorsClassic(); // Setup Platform/Renderer bindings - Init(Window::GetInstance()->GetHandle()); + Init(Window::instance().GetHandle()); - target_window_ = Renderer::GetInstance()->GetTargetWindow(); + target_window_ = Renderer::instance().GetTargetWindow(); } void ImGuiModule::DestroyComponent() @@ -64,9 +62,9 @@ namespace kiwano io.DeltaTime = dt.Seconds(); // Read keyboard modifiers inputs - io.KeyCtrl = Input::GetInstance()->IsDown(KeyCode::Ctrl); - io.KeyShift = Input::GetInstance()->IsDown(KeyCode::Shift); - io.KeyAlt = Input::GetInstance()->IsDown(KeyCode::Alt); + io.KeyCtrl = Input::instance().IsDown(KeyCode::Ctrl); + io.KeyShift = Input::instance().IsDown(KeyCode::Shift); + io.KeyAlt = Input::instance().IsDown(KeyCode::Alt); io.KeySuper = false; // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. @@ -106,7 +104,7 @@ namespace kiwano io.KeyMap[ImGuiKey_Y] = KeyCode::Y; io.KeyMap[ImGuiKey_Z] = KeyCode::Z; - ImGui_Impl_Init(Renderer::GetInstance()); + ImGui_Impl_Init(&Renderer::instance()); } void ImGuiModule::BeforeRender() @@ -213,7 +211,7 @@ namespace kiwano KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!"); // Setup display size (every frame to accommodate for window resizing) - Size display_size = Renderer::GetInstance()->GetOutputSize(); + Size display_size = Renderer::instance().GetOutputSize(); io.DisplaySize = ImVec2(display_size.x, display_size.y); ImGui::NewFrame(); @@ -238,7 +236,7 @@ namespace kiwano ::SetCursorPos(pos.x, pos.y); } - Point pos = Input::GetInstance()->GetMousePos(); + Point pos = Input::instance().GetMousePos(); io.MousePos = ImVec2(pos.x, pos.y); } @@ -260,7 +258,7 @@ namespace kiwano case ImGuiMouseCursor_Hand: cursor = CursorType::Hand; break; } - Window::GetInstance()->SetCursor(cursor); + Window::instance().SetCursor(cursor); } void ImGuiModule::UpdateGamepads() { diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h index c9069a40..f5e3fffa 100644 --- a/src/kiwano-imgui/ImGuiModule.h +++ b/src/kiwano-imgui/ImGuiModule.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include namespace kiwano { @@ -32,7 +32,7 @@ namespace kiwano , public UpdateComponent , public EventComponent { - KGE_DECLARE_SINGLETON(ImGuiModule); + OC_DECLARE_SINGLETON(ImGuiModule); private: void Init(HWND hwnd); diff --git a/src/kiwano-network/HttpClient.cpp b/src/kiwano-network/HttpClient.cpp index 7e7d97cc..d0c3db54 100644 --- a/src/kiwano-network/HttpClient.cpp +++ b/src/kiwano-network/HttpClient.cpp @@ -36,7 +36,7 @@ namespace uint32_t write_data(void* buffer, uint32_t size, uint32_t nmemb, void* userp) { - common::string* recv_buffer = (common::string*)userp; + oc::string* recv_buffer = (oc::string*)userp; uint32_t total = size * nmemb; // add data to the end of recv_buffer @@ -46,10 +46,10 @@ namespace return total; } - common::string convert_to_utf8(common::wstring const& str) + oc::string convert_to_utf8(oc::wstring const& str) { std::wstring_convert> utf8_conv; - common::string result; + oc::string result; try { @@ -63,10 +63,10 @@ namespace return result; } - common::wstring convert_from_utf8(common::string const& str) + oc::wstring convert_from_utf8(oc::string const& str) { - kiwano::string_convert> utf8_conv; - common::wstring result; + oc::string_convert> utf8_conv; + oc::wstring result; try { @@ -104,7 +104,7 @@ namespace } } - bool Init(HttpClient* client, Vector const& headers, common::string const& url, common::string* response_data, common::string* response_header, char* error_buffer) + bool Init(HttpClient* client, Vector const& headers, oc::string const& url, oc::string* response_data, oc::string* response_header, char* error_buffer) { if (!SetOption(CURLOPT_ERRORBUFFER, error_buffer)) return false; @@ -170,11 +170,11 @@ namespace public: static inline bool GetRequest( HttpClient* client, - Vector const& headers, - common::string const& url, + Vector const& headers, + oc::string const& url, long* response_code, - common::string* response_data, - common::string* response_header, + oc::string* response_data, + oc::string* response_header, char* error_buffer) { Curl curl; @@ -185,12 +185,12 @@ namespace static inline bool PostRequest( HttpClient* client, - Vector const& headers, - common::string const& url, - common::string const& request_data, + Vector const& headers, + oc::string const& url, + oc::string const& request_data, long* response_code, - common::string* response_data, - common::string* response_header, + oc::string* response_data, + oc::string* response_header, char* error_buffer) { Curl curl; @@ -203,12 +203,12 @@ namespace static inline bool PutRequest( HttpClient* client, - Vector const& headers, - common::string const& url, - common::string const& request_data, + Vector const& headers, + oc::string const& url, + oc::string const& request_data, long* response_code, - common::string* response_data, - common::string* response_header, + oc::string* response_data, + oc::string* response_header, char* error_buffer) { Curl curl; @@ -221,11 +221,11 @@ namespace static inline bool DeleteRequest( HttpClient* client, - Vector const& headers, - common::string const& url, + Vector const& headers, + oc::string const& url, long* response_code, - common::string* response_data, - common::string* response_header, + oc::string* response_data, + oc::string* response_header, char* error_buffer) { Curl curl; @@ -307,13 +307,13 @@ namespace kiwano bool ok = false; long response_code = 0; char error_message[256] = { 0 }; - common::string response_header; - common::string response_data; + oc::string response_header; + oc::string response_data; - common::string url = convert_to_utf8(request->GetUrl()); - common::string data = convert_to_utf8(request->GetData()); + oc::string url = convert_to_utf8(request->GetUrl()); + oc::string data = convert_to_utf8(request->GetData()); - Vector headers; + Vector headers; headers.reserve(request->GetHeaders().size()); for (const auto& pair : request->GetHeaders()) { @@ -335,17 +335,17 @@ namespace kiwano ok = Curl::DeleteRequest(this, headers, url, &response_code, &response_data, &response_header, error_message); break; default: - KGE_ERROR_LOG(L"HttpClient: unknown request type, only GET, POST, PUT or DELETE is supported"); + KGE_ERROR(L"HttpClient: unknown request type, only GET, POST, PUT or DELETE is supported"); return; } response->SetResponseCode(response_code); - response->SetHeader(string_to_wide(response_header)); + response->SetHeader(oc::string_to_wide(response_header)); response->SetData(convert_from_utf8(response_data)); if (!ok) { response->SetSucceed(false); - response->SetError(string_to_wide(error_message)); + response->SetError(oc::string_to_wide(error_message)); } else { diff --git a/src/kiwano-network/HttpClient.h b/src/kiwano-network/HttpClient.h index 31e7bf1f..7008b212 100644 --- a/src/kiwano-network/HttpClient.h +++ b/src/kiwano-network/HttpClient.h @@ -20,7 +20,6 @@ #pragma once #include -#include #include #include #include @@ -33,7 +32,7 @@ namespace kiwano : public Singleton , public ComponentBase { - KGE_DECLARE_SINGLETON(HttpClient); + OC_DECLARE_SINGLETON(HttpClient); public: void Send(HttpRequestPtr request); diff --git a/src/kiwano-network/HttpRequest.h b/src/kiwano-network/HttpRequest.h index 716f8240..a2617058 100644 --- a/src/kiwano-network/HttpRequest.h +++ b/src/kiwano-network/HttpRequest.h @@ -19,8 +19,7 @@ // THE SOFTWARE. #pragma once -#include -#include +#include #include #include diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index 427c2c9f..54b1a627 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -481,7 +481,7 @@ namespace kiwano { if (parent == child) { - KGE_ERROR_LOG(L"A actor cannot be its own parent"); + KGE_ERROR(L"A actor cannot be its own parent"); return; } } diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp index cbb6b60e..6799fbd0 100644 --- a/src/kiwano/2d/Canvas.cpp +++ b/src/kiwano/2d/Canvas.cpp @@ -31,7 +31,7 @@ namespace kiwano , stroke_color_(Color::White) , stroke_style_(StrokeStyle::Miter) { - Renderer::GetInstance()->CreateTextureRenderTarget(rt_); + Renderer::instance().CreateTextureRenderTarget(rt_); } Canvas::~Canvas() diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index f220de25..94d71106 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -109,9 +109,9 @@ namespace kiwano } #endif - ss << "Render: " << Renderer::GetInstance()->GetStatus().duration.Milliseconds() << "ms" << std::endl; + ss << "Render: " << Renderer::instance().GetStatus().duration.Milliseconds() << "ms" << std::endl; - ss << "Primitives / sec: " << std::fixed << Renderer::GetInstance()->GetStatus().primitives * frame_time_.size() << std::endl; + ss << "Primitives / sec: " << std::fixed << Renderer::instance().GetStatus().primitives * frame_time_.size() << std::endl; ss << "Memory: "; { diff --git a/src/kiwano/2d/Frame.cpp b/src/kiwano/2d/Frame.cpp index c3e7364a..5b1cae14 100644 --- a/src/kiwano/2d/Frame.cpp +++ b/src/kiwano/2d/Frame.cpp @@ -44,7 +44,7 @@ namespace kiwano bool Frame::Load(String const& file_path) { - Texture texture = TextureCache::GetInstance()->AddOrGetTexture(file_path); + Texture texture = TextureCache::instance().AddOrGetTexture(file_path); if (texture.IsValid()) { SetTexture(texture); @@ -55,7 +55,7 @@ namespace kiwano bool Frame::Load(Resource const& res) { - Texture texture = TextureCache::GetInstance()->AddOrGetTexture(res); + Texture texture = TextureCache::instance().AddOrGetTexture(res); if (texture.IsValid()) { SetTexture(texture); diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp index b8dc4e64..bb66209c 100644 --- a/src/kiwano/2d/GifSprite.cpp +++ b/src/kiwano/2d/GifSprite.cpp @@ -51,13 +51,13 @@ namespace kiwano bool GifSprite::Load(String const& file_path) { - GifImage texture = TextureCache::GetInstance()->AddOrGetGifImage(file_path); + GifImage texture = TextureCache::instance().AddOrGetGifImage(file_path); return Load(texture); } bool GifSprite::Load(Resource const& res) { - GifImage texture = TextureCache::GetInstance()->AddOrGetGifImage(res); + GifImage texture = TextureCache::instance().AddOrGetGifImage(res); return Load(texture); } @@ -75,7 +75,7 @@ namespace kiwano if (!frame_rt_.IsValid()) { - Renderer::GetInstance()->CreateTextureRenderTarget(frame_rt_); + Renderer::instance().CreateTextureRenderTarget(frame_rt_); } if (gif_.GetFramesCount() > 0) @@ -168,7 +168,7 @@ namespace kiwano void GifSprite::OverlayNextFrame() { - Renderer::GetInstance()->CreateGifImageFrame(frame_, gif_, next_index_); + Renderer::instance().CreateGifImageFrame(frame_, gif_, next_index_); if (frame_.disposal_type == GifImage::DisposalType::Previous) { diff --git a/src/kiwano/2d/Stage.cpp b/src/kiwano/2d/Stage.cpp index 6dcaac31..b1e9e9fc 100644 --- a/src/kiwano/2d/Stage.cpp +++ b/src/kiwano/2d/Stage.cpp @@ -29,7 +29,7 @@ namespace kiwano SetStage(this); SetAnchor(Vec2{ 0, 0 }); - SetSize(Renderer::GetInstance()->GetOutputSize()); + SetSize(Renderer::instance().GetOutputSize()); } Stage::~Stage() diff --git a/src/kiwano/2d/Transition.cpp b/src/kiwano/2d/Transition.cpp index 5000a306..33c47f1c 100644 --- a/src/kiwano/2d/Transition.cpp +++ b/src/kiwano/2d/Transition.cpp @@ -60,7 +60,7 @@ namespace kiwano out_stage_ = prev; in_stage_ = next; - window_size_ = Renderer::GetInstance()->GetOutputSize(); + window_size_ = Renderer::instance().GetOutputSize(); if (in_stage_) { diff --git a/src/kiwano/2d/action/ActionTween.h b/src/kiwano/2d/action/ActionTween.h index 27a50115..09405dc4 100644 --- a/src/kiwano/2d/action/ActionTween.h +++ b/src/kiwano/2d/action/ActionTween.h @@ -145,7 +145,7 @@ namespace kiwano // »ñÈ¡¸Ã¶¯×÷µÄµ¹×ª virtual ActionPtr Reverse() const override { - KGE_ERROR_LOG(L"Reverse() not supported in ActionMoveTo"); + KGE_ERROR(L"Reverse() not supported in ActionMoveTo"); return nullptr; } @@ -209,7 +209,7 @@ namespace kiwano // »ñÈ¡¸Ã¶¯×÷µÄµ¹×ª virtual ActionPtr Reverse() const override { - KGE_ERROR_LOG(L"Reverse() not supported in ActionJumpTo"); + KGE_ERROR(L"Reverse() not supported in ActionJumpTo"); return nullptr; } @@ -282,7 +282,7 @@ namespace kiwano // »ñÈ¡¸Ã¶¯×÷µÄµ¹×ª virtual ActionPtr Reverse() const override { - KGE_ERROR_LOG(L"Reverse() not supported in ActionScaleTo"); + KGE_ERROR(L"Reverse() not supported in ActionScaleTo"); return nullptr; } @@ -312,7 +312,7 @@ namespace kiwano // »ñÈ¡¸Ã¶¯×÷µÄµ¹×ª virtual ActionPtr Reverse() const override { - KGE_ERROR_LOG(L"Reverse() not supported in ActionFadeTo"); + KGE_ERROR(L"Reverse() not supported in ActionFadeTo"); return nullptr; } @@ -399,7 +399,7 @@ namespace kiwano // »ñÈ¡¸Ã¶¯×÷µÄµ¹×ª virtual ActionPtr Reverse() const override { - KGE_ERROR_LOG(L"Reverse() not supported in ActionRotateTo"); + KGE_ERROR(L"Reverse() not supported in ActionRotateTo"); return nullptr; } @@ -430,7 +430,7 @@ namespace kiwano // »ñÈ¡¸Ã¶¯×÷µÄµ¹×ª ActionPtr Reverse() const override { - KGE_ERROR_LOG(L"Reverse() not supported in ActionCustom"); + KGE_ERROR(L"Reverse() not supported in ActionCustom"); return nullptr; } diff --git a/src/kiwano/common/basic_json.hpp b/src/kiwano/common/basic_json.hpp deleted file mode 100644 index b72653ce..00000000 --- a/src/kiwano/common/basic_json.hpp +++ /dev/null @@ -1,2736 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - 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. - -#pragma once -#include -#include -#include -#include -#include - -namespace kiwano -{ - -namespace common -{ - -// -// details of basic_json -// - -#define KGE_DECLARE_BASIC_JSON_TEMPLATE\ - template <\ - template typename _ObjectTy, \ - template typename _ArrayTy, \ - typename _StringTy, \ - typename _IntegerTy, \ - typename _FloatTy, \ - typename _BooleanTy, \ - template typename _Allocator> - -#define KGE_DECLARE_BASIC_JSON_TPL_ARGS \ - _ObjectTy, _ArrayTy, _StringTy, _IntegerTy, _FloatTy, _BooleanTy, _Allocator - - -KGE_DECLARE_BASIC_JSON_TEMPLATE -class basic_json; - -// -// json value type -// - -enum class JsonType -{ - Integer, - Float, - String, - Vector, - Object, - Boolean, - Null, -}; - - -// -// is_basic_json -// - -template -struct is_basic_json - : std::false_type -{ -}; - -KGE_DECLARE_BASIC_JSON_TEMPLATE -struct is_basic_json< basic_json > - : std::true_type -{ -}; - -// -// exceptions -// - -class json_exception - : public std::runtime_error -{ -public: - json_exception(const char* message) - : std::runtime_error(message) - {} -}; - -class json_type_error - : public json_exception -{ -public: - json_type_error(const char* message) : json_exception(message) {} -}; - -class json_invalid_key - : public json_exception -{ -public: - json_invalid_key(const char* message) : json_exception(message) {} -}; - -class json_invalid_iterator - : public json_exception -{ -public: - json_invalid_iterator(const char* message) : json_exception(message) {} -}; - -class json_parse_error - : public json_exception -{ -public: - json_parse_error(const char* message) : json_exception(message) {} -}; - - -namespace __json_detail -{ - // - // json_value - // - - 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 - { - object_type* object; - array_type* vector; - string_type* string; - integer_type number_integer; - float_type number_float; - boolean_type boolean; - } data; - - json_value() - { - type = JsonType::Null; - data.object = nullptr; - } - - json_value(std::nullptr_t) - { - type = JsonType::Null; - data.object = nullptr; - } - - json_value(const object_type& value) - { - type = JsonType::Object; - data.object = create(value); - } - - json_value(const array_type& value) - { - type = JsonType::Vector; - data.vector = create(value); - } - - json_value(const string_type& value) - { - type = JsonType::String; - data.string = create(value); - } - - template - json_value(const _CharT* str) - { - type = JsonType::String; - data.string = create(str); - } - - json_value(const integer_type value) - { - type = JsonType::Integer; - data.number_integer = value; - } - - json_value(const float_type value) - { - type = JsonType::Float; - data.number_float = value; - } - - json_value(const boolean_type value) - { - type = JsonType::Boolean; - data.boolean = value; - } - - json_value(const JsonType value_type) - { - type = value_type; - switch (type) - { - case JsonType::Object: - data.object = create(); - break; - case JsonType::Vector: - data.vector = create(); - break; - case JsonType::String: - data.string = create(); - break; - case JsonType::Integer: - data.number_integer = integer_type(0); - break; - case JsonType::Float: - data.number_float = float_type(0.0); - break; - case JsonType::Boolean: - data.boolean = boolean_type(false); - break; - default: - data.object = nullptr; - break; - } - } - - json_value(json_value const& other) - { - type = other.type; - - switch (other.type) - { - case JsonType::Object: - data.object = create(*other.data.object); - break; - case JsonType::Vector: - data.vector = create(*other.data.vector); - break; - case JsonType::String: - data.string = create(*other.data.string); - break; - case JsonType::Integer: - data.number_integer = other.data.number_integer; - break; - case JsonType::Float: - data.number_float = other.data.number_float; - break; - case JsonType::Boolean: - data.boolean = other.data.boolean; - break; - default: - data.object = nullptr; - break; - } - } - - json_value(json_value&& other) noexcept - { - type = other.type; - data = other.data; - other.type = JsonType::Null; - other.data.object = nullptr; - } - - ~json_value() - { - clear(); - } - - void swap(json_value& other) - { - std::swap(type, other.type); - std::swap(data, other.data); - } - - void clear() - { - switch (type) - { - case JsonType::Object: - destroy(data.object); - break; - case JsonType::Vector: - destroy(data.vector); - break; - case JsonType::String: - destroy(data.string); - break; - default: - break; - } - } - - template - inline _Ty* create(_Args&&... args) - { - using allocator_type = typename _BasicJsonTy::template allocator_type<_Ty>; - using allocator_traits = std::allocator_traits; - - 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_type = typename _BasicJsonTy::template allocator_type<_Ty>; - using allocator_traits = std::allocator_traits; - - allocator_type allocator; - allocator_traits::destroy(allocator, ptr); - allocator_traits::deallocate(allocator, ptr, 1); - } - - inline json_value& operator=(json_value const& other) - { - json_value{ other }.swap(*this); - return (*this); - } - - inline json_value& operator=(json_value && other) noexcept - { - 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 - -namespace __json_detail -{ - // - // iterator for basic_json - // - - struct primitive_iterator - { - using difference_type = ptrdiff_t; - - inline primitive_iterator(difference_type it = 0) : it_(it) {} - - inline void set_begin() { it_ = 0; } - inline void set_end() { it_ = 1; } - - inline primitive_iterator& operator++() { ++it_; return *this; } - - inline primitive_iterator operator++(int) { primitive_iterator old(it_); ++(*this); return old; } - - inline primitive_iterator& operator--() { --it_; return (*this); } - inline primitive_iterator operator--(int) { primitive_iterator old = (*this); --(*this); return old; } - - inline bool operator==(primitive_iterator const& other) const { return it_ == other.it_; } - inline bool operator!=(primitive_iterator const& other) const { return !(*this == other); } - - inline const primitive_iterator operator+(difference_type off) const { return primitive_iterator(it_ + off); } - inline const primitive_iterator operator-(difference_type off) const { return primitive_iterator(it_ - off); } - - inline primitive_iterator& operator+=(difference_type off) { it_ += off; return (*this); } - inline primitive_iterator& operator-=(difference_type off) { it_ -= off; return (*this); } - - inline difference_type operator-(primitive_iterator const& other) const { return it_ - other.it_; } - - inline bool operator<(primitive_iterator const& other) const { return it_ < other.it_; } - inline bool operator<=(primitive_iterator const& other) const { return it_ <= other.it_; } - inline bool operator>(primitive_iterator const& other) const { return it_ > other.it_; } - inline bool operator>=(primitive_iterator const& other) const { return it_ >= other.it_; } - - private: - difference_type it_; - }; - - template - struct iterator_impl - { - friend _BasicJsonTy; - - 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 = ptrdiff_t; - using iterator_category = std::bidirectional_iterator_tag; - using pointer = value_type*; - using reference = value_type&; - - using array_iterator = typename _BasicJsonTy::array_type::iterator; - using object_iterator = typename _BasicJsonTy::object_type::iterator; - - inline iterator_impl(pointer json = nullptr) : data_(json), primitive_iter(0), array_iter(), object_iter() {} - - inline iterator_impl(const iterator_impl& rhs) : iterator_impl() - { - operator=(rhs); - } - - ~iterator_impl() {} - - inline iterator_impl& operator=(const iterator_impl& rhs) - { - data_ = rhs.data_; - if (data_) - { - switch (data_->type()) - { - case JsonType::Object: - object_iter = rhs.object_iter; - break; - case JsonType::Vector: - array_iter = rhs.array_iter; - break; - default: - primitive_iter = rhs.primitive_iter; - break; - } - } - return (*this); - } - - inline reference operator*() const - { - check_data(); - check_iterator(); - switch (data_->type()) - { - case JsonType::Object: - return (object_iter->second); - case JsonType::Vector: - return (*array_iter); - default: - return *data_; - } - } - - inline pointer operator->() const - { - check_data(); - check_iterator(); - switch (data_->type()) - { - case JsonType::Object: - return &(object_iter->second); - case JsonType::Vector: - return &(*array_iter); - default: - return data_; - } - } - - inline const typename object_type::key_type& key() const - { - check_data(); - check_iterator(); - if (!data_->is_object()) - throw json_invalid_iterator("cannot use key() with non-object type"); - return object_iter->first; - } - - inline reference value() const - { - return operator*(); - } - - inline void set_begin() - { - check_data(); - - switch (data_->type()) - { - case JsonType::Object: - { - object_iter = data_->value_.data.object->begin(); - break; - } - case JsonType::Vector: - { - array_iter = data_->value_.data.vector->begin(); - break; - } - default: - { - primitive_iter.set_begin(); - break; - } - } - } - - inline void set_end() - { - check_data(); - - switch (data_->type()) - { - case JsonType::Object: - { - object_iter = data_->value_.data.object->end(); - break; - } - case JsonType::Vector: - { - array_iter = data_->value_.data.vector->end(); - break; - } - default: - { - primitive_iter.set_end(); - break; - } - } - } - - inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; } - inline iterator_impl& operator++() - { - check_data(); - - switch (data_->type()) - { - case JsonType::Object: - { - std::advance(object_iter, 1); - break; - } - case JsonType::Vector: - { - std::advance(array_iter, 1); - break; - } - default: - { - ++primitive_iter; - break; - } - } - return *this; - } - - inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; } - inline iterator_impl& operator--() - { - check_data(); - - switch (data_->type()) - { - case JsonType::Object: - { - std::advance(object_iter, -1); - break; - } - case JsonType::Vector: - { - std::advance(array_iter, -1); - break; - } - default: - { - --primitive_iter; - break; - } - } - } - - inline const iterator_impl operator-(difference_type off) const { return operator+(-off); } - inline const iterator_impl operator+(difference_type off) const { iterator_impl ret(*this); ret += off; return ret; } - - inline iterator_impl& operator-=(difference_type off) { return operator+=(-off); } - inline iterator_impl& operator+=(difference_type off) - { - check_data(); - - switch (data_->type()) - { - case JsonType::Object: - { - throw json_invalid_iterator("cannot use offsets with object type"); - break; - } - case JsonType::Vector: - { - std::advance(array_iter, off); - break; - } - default: - { - primitive_iter += off; - break; - } - } - return *this; - } - - inline bool operator!=(iterator_impl const& other) const { return !(*this == other); } - inline bool operator==(iterator_impl const& other) const - { - check_data(); - other.check_data(); - - if (data_ != other.data_) - throw json_invalid_iterator("cannot compare iterators of different objects"); - - switch (data_->type()) - { - case JsonType::Object: - { - return object_iter == other.object_iter; - } - case JsonType::Vector: - { - return array_iter == other.array_iter; - } - default: - { - return primitive_iter == other.primitive_iter; - } - } - } - - 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(); - other.check_data(); - - if (data_ != other.data_) - throw json_invalid_iterator("cannot compare iterators of different objects"); - - switch (data_->type()) - { - case JsonType::Object: - throw json_invalid_iterator("cannot compare iterators with object type"); - case JsonType::Vector: - return array_iter < other.array_iter; - default: - return primitive_iter < other.primitive_iter; - } - } - - private: - inline void check_data() const - { - if (data_ == nullptr) - { - throw json_invalid_iterator("iterator contains an empty object"); - } - } - - inline void check_iterator() const - { - switch (data_->type()) - { - case JsonType::Object: - if (object_iter == data_->value_.data.object->end()) - { - throw std::out_of_range("iterator out of range"); - } - break; - case JsonType::Vector: - if (array_iter == data_->value_.data.vector->end()) - { - throw std::out_of_range("iterator out of range"); - } - break; - default: - if (primitive_iter == 1) - { - throw std::out_of_range("iterator out of range"); - } - break; - } - } - - private: - pointer data_; - - union - { - struct - { - array_iterator array_iter; - }; - - struct - { - object_iterator object_iter; - }; - - struct - { - primitive_iterator primitive_iter; // for other types - }; - }; - }; -} // end of namespace __json_detail - -namespace __json_detail -{ - // - // output_adapter - // - - template - struct output_adapter - { - using char_type = _CharTy; - using char_traits = std::char_traits; - - virtual void write(const _CharTy ch) = 0; - virtual void write(const _CharTy* str, uint32_t size) = 0; - virtual void write(const _CharTy* str) - { - const auto size = char_traits::length(str); - write(str, static_cast(size)); - } - }; - - template - struct string_output_adapter - : public output_adapter - { - using char_type = typename _StringTy::value_type; - using size_type = typename _StringTy::size_type; - using char_traits = std::char_traits; - - string_output_adapter(_StringTy& str) : str_(str) {} - - virtual void write(const char_type ch) override - { - str_.push_back(ch); - } - - virtual void write(const char_type* str, uint32_t size) override - { - str_.append(str, static_cast(size)); - } - - private: - _StringTy& str_; - }; - - template - struct stream_output_adapter - : public output_adapter<_CharTy> - { - using char_type = _CharTy; - using size_type = typename std::streamsize; - using char_traits = std::char_traits; - - stream_output_adapter(std::basic_ostream& stream) : stream_(stream) {} - - virtual void write(const char_type ch) override - { - stream_.put(ch); - } - - virtual void write(const char_type* str, uint32_t size) override - { - stream_.write(str, static_cast(size)); - } - - private: - std::basic_ostream& stream_; - }; -} // end of namespace __json_detail - -namespace __json_detail -{ - // - // json_serializer - // - - template - struct json_serializer - { - 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 char_type indent_char) - : out(out) - , indent_char(indent_char) - , indent_string(32, indent_char) - , number_buffer() - {} - - void dump( - const _BasicJsonTy& json, - const bool pretty_print, - const uint32_t indent_step, - const uint32_t current_indent = 0) - { - switch (json.type()) - { - case JsonType::Object: - { - auto& object = *json.value_.data.object; - - if (object.empty()) - { - out->write(L"{}"); - return; - } - - if (pretty_print) - { - out->write(L"{\n"); - - const auto new_indent = current_indent + indent_step; - if (indent_string.size() < new_indent) - { - indent_string.resize(indent_string.size() * 2, indent_char); - } - - auto iter = object.cbegin(); - const auto size = object.size(); - for (uint32_t i = 0; i < size; ++i, ++iter) - { - out->write(indent_string.c_str(), new_indent); - out->write('\"'); - out->write(iter->first.c_str()); - out->write(L"\": "); - dump(iter->second, true, indent_step, new_indent); - - // not last element - if (i != size - 1) - out->write(L",\n"); - } - - out->write('\n'); - out->write(indent_string.c_str(), current_indent); - out->write('}'); - } - else - { - out->write('{'); - - auto iter = object.cbegin(); - const auto size = object.size(); - for (uint32_t i = 0; i < size; ++i, ++iter) - { - out->write('\"'); - 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(','); - } - - out->write('}'); - } - - return; - } - - case JsonType::Vector: - { - auto& vector = *json.value_.data.vector; - - if (vector.empty()) - { - out->write(L"[]"); - return; - } - - if (pretty_print) - { - out->write(L"[\n"); - - const auto new_indent = current_indent + indent_step; - if (indent_string.size() < new_indent) - { - indent_string.resize(indent_string.size() * 2, indent_char); - } - - auto iter = vector.cbegin(); - const auto size = vector.size(); - for (uint32_t i = 0; i < size; ++i, ++iter) - { - out->write(indent_string.c_str(), new_indent); - dump(*iter, true, indent_step, new_indent); - - // not last element - if (i != size - 1) - out->write(L",\n"); - } - - out->write('\n'); - out->write(indent_string.c_str(), current_indent); - out->write(']'); - } - else - { - out->write('['); - - auto iter = vector.cbegin(); - const auto size = vector.size(); - for (uint32_t i = 0; i < size; ++i, ++iter) - { - dump(*iter, false, indent_step, current_indent); - // not last element - if (i != size - 1) - out->write(','); - } - - out->write(']'); - } - - return; - } - - case JsonType::String: - { - out->write('\"'); - dump_string(*json.value_.data.string); - out->write('\"'); - return; - } - - case JsonType::Boolean: - { - if (json.value_.data.boolean) - { - out->write(L"true"); - } - else - { - out->write(L"false"); - } - return; - } - - case JsonType::Integer: - { - dump_integer(json.value_.data.number_integer); - return; - } - - case JsonType::Float: - { - dump_float(json.value_.data.number_float); - return; - } - - case JsonType::Null: - { - out->write(L"null"); - return; - } - } - } - - void dump_integer(integer_type val) - { - if (val == 0) - { - out->write('0'); - return; - } - - auto uval = static_cast>(val); - - if (val < 0) - uval = 0 - uval; - - auto next = number_buffer.rbegin(); - *next = '\0'; - - do - { - *(++next) = static_cast('0' + uval % 10); - uval /= 10; - } while (uval != 0); - - if (val < 0) - *(++next) = '-'; - - out->write(&(*next)); - } - - void dump_float(float_type val) - { - const auto digits = std::numeric_limits::max_digits10; - const auto len = ::_scwprintf(L"%.*g", digits, val); - if (len) - { - number_buffer[0] = '\0'; - ::swprintf_s(&number_buffer[0], size_t(len) + 1, L"%.*g", digits, val); - } - else - { - number_buffer[0] = '0'; - number_buffer[1] = '.'; - number_buffer[2] = '0'; - number_buffer[3] = '\0'; - } - out->write(number_buffer.data()); - } - - void dump_string(const string_type & val) - { - for (const auto& ch : val) - { - switch (ch) - { - case '\t': - { - out->write(L"\\t"); - break; - } - - case '\r': - { - out->write(L"\\r"); - break; - } - - case '\n': - { - out->write(L"\\n"); - break; - } - - case '\b': - { - out->write(L"\\b"); - break; - } - - case '\f': - { - out->write(L"\\f"); - break; - } - - case '\"': - { - out->write(L"\\\""); - break; - } - - case '\\': - { - out->write(L"\\\\"); - break; - } - - default: - { - const auto char_byte = static_cast(ch); - if ((char_byte > 0x1F) && (char_byte < 0x7F)) - { - out->write(ch); - } - else - { - char_type escaped[7] = { 0 }; - ::swprintf_s(escaped, 7, L"\\u%04x", char_byte); - out->write(escaped); - } - break; - } - } - } - } - - private: - output_adapter* out; - char_type indent_char; - string_type indent_string; - std::array number_buffer; - }; -} // end of namespace __json_detail - -namespace __json_detail -{ - // - // input_adapter - // - - template - struct input_adapter - { - using char_type = _CharTy; - using char_traits = std::char_traits; - - virtual typename char_traits::int_type get_char() = 0; - virtual ~input_adapter() = default; - }; - - template - struct file_input_adapter - : public input_adapter<_CharTy> - { - using char_type = typename input_adapter<_CharTy>::char_type; - using char_traits = typename input_adapter<_CharTy>::char_traits; - - file_input_adapter(std::FILE* file) : file(file) {} - - virtual typename char_traits::int_type get_char() override - { - return std::fgetc(file); - } - - private: - std::FILE* file; - }; - - template - struct stream_input_adapter - : public input_adapter<_CharTy> - { - using char_type = typename input_adapter<_CharTy>::char_type; - using char_traits = typename input_adapter<_CharTy>::char_traits; - - stream_input_adapter(std::basic_istream& stream) : stream(stream), streambuf(*stream.rdbuf()) {} - - virtual typename char_traits::int_type get_char() override - { - auto ch = streambuf.sbumpc(); - if (ch == EOF) - { - stream.clear(stream.rdstate() | std::ios::eofbit); - } - return ch; - } - - virtual ~stream_input_adapter() - { - stream.clear(stream.rdstate() & std::ios::eofbit); - } - - private: - std::basic_istream& stream; - std::basic_streambuf& streambuf; - }; - - template - struct string_input_adapter - : public input_adapter - { - using char_type = typename input_adapter::char_type; - using char_traits = typename input_adapter::char_traits; - - string_input_adapter(const _StringTy& str) : str(str), index(0) {} - - virtual typename char_traits::int_type get_char() override - { - if (index == str.size()) - return char_traits::eof(); - return str[index++]; - } - - private: - const _StringTy& str; - typename _StringTy::size_type index; - }; - - template - struct buffer_input_adapter - : public input_adapter<_CharTy> - { - using char_type = typename input_adapter<_CharTy>::char_type; - using char_traits = typename input_adapter<_CharTy>::char_traits; - - buffer_input_adapter(const _CharTy* str) : str(str), index(0) {} - - virtual typename char_traits::int_type get_char() override - { - if (str[index] == '\0') - return char_traits::eof(); - return str[index++]; - } - - private: - const char_type* str; - uint32_t index; - }; -} // end of namespace __json_detail - -namespace __json_detail -{ - // - // json_lexer & json_parser - // - - 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 - }; - - template - struct json_lexer - { - 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) - { - // read first char - read_next(); - } - - typename char_traits::int_type read_next() - { - current = adapter->get_char(); - return current; - } - - void skip_spaces() - { - while (current == ' ' || current == '\t' || current == '\n' || current == '\r') - { - read_next(); - } - } - - token_type scan() - { - skip_spaces(); - - token_type result = token_type::uninitialized; - switch (current) - { - case '[': - result = token_type::begin_array; - break; - case ']': - result = token_type::end_array; - break; - case '{': - result = token_type::begin_object; - break; - case '}': - result = token_type::end_object; - break; - case ':': - result = token_type::name_separator; - break; - case ',': - result = token_type::value_separator; - break; - - case 't': - return scan_literal(L"true", token_type::literal_true); - case 'f': - return scan_literal(L"false", token_type::literal_false); - case 'n': - return scan_literal(L"null", token_type::literal_null); - - case '\"': - return scan_string(); - - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return scan_number(); - - case '\0': - case char_traits::eof(): - return token_type::end_of_input; - - // unexpected char - default: - return token_type::parse_error; - } - - // skip current char - read_next(); - - return result; - } - - token_type scan_literal(const char_type* text, token_type result) - { - for (uint32_t i = 0; text[i] != '\0'; ++i) - { - if (text[i] != char_traits::to_char_type(current)) - { - return token_type::parse_error; - } - read_next(); - } - return result; - } - - token_type scan_string() - { - if (current != '\"') - return token_type::parse_error; - - string_buffer.clear(); - - while (true) - { - const auto ch = read_next(); - switch (ch) - { - case char_traits::eof(): - { - // unexpected end - return token_type::parse_error; - } - - case '\"': - { - // skip last `\"` - read_next(); - return token_type::value_string; - } - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - { - // invalid control character - return token_type::parse_error; - } - - case '\\': - { - switch (read_next()) - { - case '\"': - string_buffer.push_back('\"'); - break; - case '\\': - string_buffer.push_back('\\'); - break; - case '/': - string_buffer.push_back('/'); - break; - case 'b': - string_buffer.push_back('\b'); - break; - case 'f': - string_buffer.push_back('\f'); - break; - case 'n': - string_buffer.push_back('\n'); - break; - case 'r': - string_buffer.push_back('\r'); - break; - case 't': - string_buffer.push_back('\t'); - break; - - case 'u': - { - // unicode escapes - uint16_t byte = 0; - - for (const auto factor : { 12, 8, 4, 0 }) - { - const auto n = read_next(); - if (n >= L'0' && n <= L'9') - { - byte += ((n - L'0') << factor); - } - else if (n >= L'A' && n <= L'F') - { - byte += ((n - L'A' + 10) << factor); - } - else if (n >= L'a' && n <= L'f') - { - byte += ((n - L'a' + 10) << factor); - } - else - { - // '\u' must be followed by 4 hex digits - return token_type::parse_error; - } - } - - string_buffer.push_back(char_traits::to_char_type(byte)); - break; - } - - default: - { - return token_type::parse_error; - } - } - break; - } - - default: - { - if (ch > 0x1F && ch < 0x7F) - { - string_buffer.push_back(char_traits::to_char_type(ch)); - break; - } - else - { - return token_type::parse_error; - } - } - - } - } - } - - token_type scan_number() - { - is_negative = false; - number_value = static_cast(0.0); - - if (current == '-') - { - return scan_negative(); - } - - if (current == '0') - { - return scan_zero(); - } - - return scan_integer(); - } - - token_type scan_negative() - { - if (current == '-') - { - is_negative = true; - read_next(); - - return scan_integer(); - } - return token_type::parse_error; - } - - token_type scan_zero() - { - if (current == '0') - { - if (read_next() == '.') - return scan_float(); - else - return token_type::value_integer; - } - return token_type::parse_error; - } - - token_type scan_integer() - { - if (std::isdigit(current)) - { - number_value = static_cast(current - '0'); - - while (true) - { - const auto ch = read_next(); - if (ch == '.') - return scan_float(); - - if (ch == 'e' || ch == 'E') - return scan_exponent(); - - if (std::isdigit(ch)) - number_value = number_value * 10 + (ch - '0'); - else - break; - } - return token_type::value_integer; - } - return token_type::parse_error; - } - - token_type scan_float() - { - if (current != '.') - return token_type::parse_error; - - if (std::isdigit(read_next())) - { - float_type fraction = static_cast(0.1); - number_value += static_cast(current - '0') * fraction; - - while (true) - { - const auto ch = read_next(); - if (ch == 'e' || ch == 'E') - return scan_exponent(); - - if (std::isdigit(ch)) - { - fraction *= static_cast(0.1); - number_value += static_cast(ch - '0') * fraction; - } - else - break; - } - return token_type::value_float; - } - return token_type::parse_error; - } - - token_type scan_exponent() - { - if (current != 'e' && current != 'E') - return token_type::parse_error; - - // skip current char - read_next(); - - if ((std::isdigit(current) && current != '0') || (current == '-') || (current == '+')) - { - float_type core = 10; - if (current == '+') - { - read_next(); - } - else if (current == '-') - { - core = static_cast(0.1); - read_next(); - } - - uint32_t exponent = static_cast(current - '0'); - while (std::isdigit(read_next())) - { - exponent = (exponent * 10) + static_cast(current - '0'); - } - - float_type power = 1; - for (; exponent; exponent >>= 1, core *= core) - if (exponent & 1) - power *= core; - - number_value *= power; - return token_type::value_float; - } - return token_type::parse_error; - } - - integer_type token_to_integer() const - { - integer_type integer = static_cast(number_value); - return is_negative ? -integer : integer; - } - - float_type token_to_float() const - { - return is_negative ? -number_value : number_value; - } - - string_type token_to_string() const - { - return string_buffer; - } - - private: - input_adapter* adapter; - typename char_traits::int_type current; - - bool is_negative; - float_type number_value; - string_type string_buffer; - }; - - - template - struct json_parser - { - 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) - {} - - void parse(_BasicJsonTy& json) - { - parse_value(json); - - if (get_token() != token_type::end_of_input) - throw json_parse_error("unexpected token, expect end"); - } - - private: - token_type get_token() - { - last_token = lexer.scan(); - return last_token; - } - - void parse_value(_BasicJsonTy& json) - { - switch (get_token()) - { - case token_type::literal_true: - json = JsonType::Boolean; - json.value_.data.boolean = true; - break; - - case token_type::literal_false: - json = JsonType::Boolean; - json.value_.data.boolean = false; - break; - - case token_type::literal_null: - json = JsonType::Null; - break; - - case token_type::value_string: - json = lexer.token_to_string(); - break; - - case token_type::value_integer: - json = lexer.token_to_integer(); - break; - - case token_type::value_float: - json = lexer.token_to_float(); - break; - - case token_type::begin_array: - json = JsonType::Vector; - while (true) - { - json.value_.data.vector->push_back(_BasicJsonTy()); - parse_value(json.value_.data.vector->back()); - - // read ',' - if (get_token() != token_type::value_separator) - break; - } - if (last_token != token_type::end_array) - throw json_parse_error("unexpected token in array"); - break; - - case token_type::begin_object: - json = JsonType::Object; - while (true) - { - if (get_token() != token_type::value_string) - break; - string_type key = lexer.token_to_string(); - - if (get_token() != token_type::name_separator) - break; - - _BasicJsonTy object; - parse_value(object); - json.value_.data.object->insert(std::make_pair(key, object)); - - // read ',' - if (get_token() != token_type::value_separator) - break; - } - if (last_token != token_type::end_object) - throw json_parse_error("unexpected token in object"); - break; - - default: - // unexpected token - throw json_parse_error("unexpected token"); - break; - } - } - - private: - json_lexer<_BasicJsonTy> lexer; - token_type last_token; - }; -} // end of namespace __json_detail - -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("json value type must be object"); - value = *json.value_.data.object; - } - - static inline void assign(const _BasicJsonTy& json, array_type& value) - { - if (!json.is_array()) throw json_type_error("json value type must be array"); - value = *json.value_.data.vector; - } - - static inline void assign(const _BasicJsonTy& json, string_type& value) - { - if (!json.is_string()) throw json_type_error("json value type must be string"); - value = *json.value_.data.string; - } - - static inline void assign(const _BasicJsonTy& json, boolean_type& value) - { - if (!json.is_boolean()) throw json_type_error("json value type must be boolean"); - value = json.value_.data.boolean; - } - - static inline void assign(const _BasicJsonTy& json, integer_type& value) - { - if (!json.is_integer()) throw json_type_error("json value type must be integer"); - 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("json value type must be integer"); - value = static_cast<_IntegerTy>(json.value_.data.number_integer); - } - - static inline void assign(const _BasicJsonTy& json, float_type& value) - { - if (!json.is_float()) throw json_type_error("json value type must be float"); - value = json.value_.data.number_float; - } - - 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("json value type must be float"); - value = static_cast<_FloatingTy>(json.value_.data.number_float); - } - }; -} // end of namespace __json_detail - -// -// basic_json -// - -KGE_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 = size_t; - using difference_type = 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) noexcept : 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 const& 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::Vector; - value_.data.vector->reserve(init_list.size()); - value_.data.vector->assign(init_list.begin(), init_list.end()); - } - } - - static inline basic_json object(initializer_list const& init_list) - { - if (init_list.size() != 2 || !(*init_list.begin()).is_string()) - { - throw json_type_error("cannot create object from initializer_list"); - } - - basic_json json; - json.value_ = JsonType::Object; - json.value_.data.object->emplace(*((*init_list.begin()).value_.data.string), *(init_list.begin() + 1)); - return json; - } - - static inline basic_json array(initializer_list const& init_list) - { - basic_json json; - json.value_ = JsonType::Vector; - - if (init_list.size()) - { - json.value_.data.vector->reserve(init_list.size()); - json.value_.data.vector->assign(init_list.begin(), init_list.end()); - } - return json; - } - - inline bool is_object() const { return value_.type == JsonType::Object; } - - inline bool is_array() const { return value_.type == JsonType::Vector; } - - 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::Vector: - 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::Vector: - 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.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("cannot use erase() with non-object value"); - } - return value_.data.object->erase(key); - } - - inline void erase(const size_type index) - { - if (!is_array()) - { - throw json_invalid_key("cannot use erase() with non-array value"); - } - 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.object_iter = value_.data.object->erase(pos.object_iter); - break; - } - - case JsonType::Vector: - { - result.array_iter = value_.data.vector->erase(pos.array_iter); - break; - } - - default: - throw json_invalid_iterator("cannot use erase() with non-object & non-array value"); - } - - 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.object_iter = value_.data.object->erase(first.object_iter, last.object_iter); - break; - } - - case JsonType::Vector: - { - result.array_iter = value_.data.vector->erase(first.array_iter, last.array_iter); - break; - } - - default: - throw json_invalid_iterator("cannot use erase() with non-object & non-array value"); - } - - return result; - } - - inline void push_back(basic_json&& json) - { - if (!is_null() && !is_array()) - { - throw json_type_error("cannot use push_back() with non-array value"); - } - - if (is_null()) - { - value_ = JsonType::Vector; - } - - 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::Vector: - { - 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("json value must be boolean"); - return value_.data.boolean; - } - - integer_type as_int() const - { - if (!is_integer()) throw json_type_error("json value must be integer"); - return value_.data.number_integer; - } - - float_type as_float() const - { - if (!is_float()) throw json_type_error("json value must be float"); - return value_.data.number_float; - } - - const array_type& as_array() const - { - if (!is_array()) throw json_type_error("json value must be array"); - return *value_.data.vector; - } - - const string_type& as_string() const - { - if (!is_string()) throw json_type_error("json value must be string"); - return *value_.data.string; - } - - const object_type& as_object() const - { - if (!is_object()) throw json_type_error("json value must be object"); - 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) noexcept - { - 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::Vector; - } - - if (!is_array()) - { - throw json_invalid_key("operator[] called on a non-array object"); - } - - 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("operator[] called on a non-array type"); - } - - if (index >= value_.data.vector->size()) - { - throw std::out_of_range("operator[] index out of range"); - } - 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("operator[] called on a non-object type"); - } - return (*value_.data.object)[key]; - } - - inline basic_json& operator[](const typename object_type::key_type& key) const - { - if (!is_object()) - { - throw json_invalid_key("operator[] called on a non-object object"); - } - - auto iter = value_.data.object->find(key); - if (iter == value_.data.object->end()) - { - throw std::out_of_range("operator[] key out of range"); - } - return iter->second; - } - - template - inline basic_json& operator[](_CharT* key) - { - if (is_null()) - { - value_ = JsonType::Object; - } - - if (!is_object()) - { - throw json_invalid_key("operator[] called on a non-object object"); - } - return (*value_.data.object)[key]; - } - - template - inline basic_json& operator[](_CharT* key) const - { - if (!is_object()) - { - throw json_invalid_key("operator[] called on a non-object object"); - } - - auto iter = value_.data.object->find(key); - if (iter == value_.data.object->end()) - { - throw std::out_of_range("operator[] key out of range"); - } - return iter->second; - } - -public: - // implicitly convert functions - - inline operator boolean_type () const - { - return as_bool(); - } - - inline operator integer_type () const - { - return as_int(); - } - - inline operator float_type () const - { - return as_float(); - } - - inline operator const array_type& () const - { - return as_array(); - } - - inline operator const string_type& () const - { - return as_string(); - } - - inline operator const object_type& () const - { - return as_object(); - } - -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::Vector: - 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::Vector: - 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: - __json_detail::json_value value_; -}; - -} // namespace common - -} // namespace kiwano - -#undef KGE_DECLARE_BASIC_JSON_TEMPLATE -#undef KGE_DECLARE_BASIC_JSON_TPL_ARGS diff --git a/src/kiwano/common/common.h b/src/kiwano/common/common.h index c09b8cd4..ebdfff2f 100644 --- a/src/kiwano/common/common.h +++ b/src/kiwano/common/common.h @@ -28,24 +28,17 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include <3rd-party/OuterC/oc/oc.h> +#include namespace kiwano { - using String = kiwano::common::wstring; + using String = oc::wstring; using StringStream = std::wstringstream; template - using Vector = kiwano::common::vector<_Ty, _Args...>; + using Vector = oc::vector<_Ty, _Args...>; template using List = std::list<_Ty, _Args...>; @@ -72,37 +65,38 @@ namespace kiwano using UnorderedMap = std::unordered_map<_Kty, _Ty, _Args...>; template - using Function = kiwano::common::function<_FuncTy>; + using Function = oc::function<_FuncTy>; - using Any = kiwano::common::any; + using Any = oc::any; - using Json = kiwano::common::basic_json; + using Json = oc::basic_json; template - using Singleton = common::singleton<_Ty>; + using Singleton = oc::singleton<_Ty>; template - using IntrusiveList = common::intrusive_list<_Ty>; + using IntrusiveList = oc::intrusive_list<_Ty>; template - using IntrusiveListItem = common::intrusive_list_item<_Ty>; -} + using IntrusiveListItem = oc::intrusive_list_item<_Ty>; -namespace std -{ - template<> - struct hash<::kiwano::Json> + template + using IntrusivePtr = oc::intrusive_ptr<_Ty, _RefProxyTy>; + + using Noncopyable = oc::noncopyable; + + + // Closure + + template + inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...)) { - size_t operator()(const ::kiwano::Json& json) const - { - return hash<::kiwano::Json::string_type>{}(json.dump()); - } - }; + return oc::closure(ptr, func); + } - template<> - inline void swap<::kiwano::Json>(::kiwano::Json& lhs, ::kiwano::Json& rhs) noexcept + template + inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const) { - lhs.swap(rhs); + return oc::closure(ptr, func); } } diff --git a/src/kiwano/common/function.hpp b/src/kiwano/common/function.hpp deleted file mode 100644 index c561db6f..00000000 --- a/src/kiwano/common/function.hpp +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - 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. - -#pragma once -#include -#include - -namespace kiwano -{ - -namespace common -{ -// -// function is a light weight ::std::function<>-like class -// - -namespace __function_detail -{ - // - // is_callable - // - - namespace __callable_detail - { - template - struct helper - { - template static int test(...); - - template struct class_mem; - template static char test(class_mem<_Uty, &_Uty::operator()>*); - - template struct class_const_mem; - template static char test(class_const_mem<_Uty, &_Uty::operator()>*); - - template< - typename _Uty, - typename _Uret = typename ::std::decay().operator()(::std::declval<_Args>()...))>::type, - typename = typename ::std::enable_if<::std::is_convertible<_Ret, _Uret>::value>::type> - static char test(int); - - static constexpr bool value = sizeof(test<_Ty>(0)) == sizeof(char); - }; - } - - template - struct is_callable - : public ::std::bool_constant<__callable_detail::helper<_Ty, _Ret, _Args...>::value> - { - }; - - // - // callable - // - - template - class callable - { - public: - virtual ~callable() {} - - virtual void retain() = 0; - virtual void release() = 0; - virtual _Ret invoke(_Args... args) const = 0; - }; - - template - class ref_count_callable - : public callable<_Ret, _Args...> - { - public: - ref_count_callable() : ref_count_(0) {} - - virtual void retain() override - { - ++ref_count_; - } - - virtual void release() override - { - --ref_count_; - if (ref_count_ <= 0) - { - delete this; - } - } - - private: - int ref_count_; - }; - - template - class proxy_callable - : public ref_count_callable<_Ret, _Args...> - { - public: - proxy_callable(_Ty&& val) - : callee_(::std::move(val)) - { - } - - virtual _Ret invoke(_Args... args) const override - { - return callee_(::std::forward<_Args&&>(args)...); - } - - static inline callable<_Ret, _Args...>* make(_Ty&& val) - { - return new (::std::nothrow) proxy_callable<_Ty, _Ret, _Args...>(::std::move(val)); - } - - private: - _Ty callee_; - }; - - template - class proxy_mem_callable - : public ref_count_callable<_Ret, _Args...> - { - public: - typedef _Ret(_Ty::* _FuncType)(_Args...); - - virtual _Ret invoke(_Args... args) const override - { - return (static_cast<_Ty*>(ptr_)->*func_)(::std::forward<_Args>(args)...); - } - - static inline callable<_Ret, _Args...>* make(void* ptr, _FuncType func) - { - return new (::std::nothrow) proxy_mem_callable<_Ty, _Ret, _Args...>(ptr, func); - } - - protected: - proxy_mem_callable(void* ptr, _FuncType func) - : ptr_(ptr) - , func_(func) - { - } - - protected: - void* ptr_; - _FuncType func_; - }; - - template - class proxy_const_mem_callable - : public ref_count_callable<_Ret, _Args...> - { - public: - typedef _Ret(_Ty::* _FuncType)(_Args...) const; - - virtual _Ret invoke(_Args... args) const override - { - return (static_cast<_Ty*>(ptr_)->*func_)(::std::forward<_Args>(args)...); - } - - static inline callable<_Ret, _Args...>* make(void* ptr, _FuncType func) - { - return new (::std::nothrow) proxy_const_mem_callable<_Ty, _Ret, _Args...>(ptr, func); - } - - protected: - proxy_const_mem_callable(void* ptr, _FuncType func) - : ptr_(ptr) - , func_(func) - { - } - - protected: - void* ptr_; - _FuncType func_; - }; -} - -// -// exceptions -// -class bad_function_call : public ::std::exception -{ -public: - bad_function_call() {} - - virtual const char* what() const override - { - return "bad function call"; - } -}; - - -// -// function details -// -template -class function; - -template -class function<_Ret(_Args...)> -{ -public: - function() - : callable_(nullptr) - { - } - - function(std::nullptr_t) - : callable_(nullptr) - { - } - - function(const function& rhs) - : callable_(rhs.callable_) - { - if (callable_) callable_->retain(); - } - - function(function&& rhs) noexcept - : callable_(rhs.callable_) - { - rhs.callable_ = nullptr; - } - - function(_Ret(*func)(_Args...)) - { - callable_ = __function_detail::proxy_callable<_Ret(*)(_Args...), _Ret, _Args...>::make(::std::move(func)); - if (callable_) callable_->retain(); - } - - template< - typename _Ty, - typename = typename ::std::enable_if<__function_detail::is_callable<_Ty, _Ret, _Args...>::value, int>::type> - function(_Ty val) - { - callable_ = __function_detail::proxy_callable<_Ty, _Ret, _Args...>::make(::std::move(val)); - if (callable_) callable_->retain(); - } - - template::value || ::std::is_base_of<_Ty, _Uty>::value, int>::type> - function(_Uty* ptr, _Ret(_Ty::* func)(_Args...)) - { - callable_ = __function_detail::proxy_mem_callable<_Ty, _Ret, _Args...>::make(ptr, func); - if (callable_) callable_->retain(); - } - - template::value || ::std::is_base_of<_Ty, _Uty>::value, int>::type> - function(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const) - { - callable_ = __function_detail::proxy_const_mem_callable<_Ty, _Ret, _Args...>::make(ptr, func); - if (callable_) callable_->retain(); - } - - ~function() - { - tidy(); - } - - inline void swap(const function& rhs) - { - ::std::swap(callable_, rhs.callable_); - } - - inline _Ret operator()(_Args... args) const - { - if (!callable_) - throw bad_function_call(); - return callable_->invoke(::std::forward<_Args>(args)...); - } - - inline operator bool() const - { - return !!callable_; - } - - inline function& operator=(const function& rhs) - { - tidy(); - callable_ = rhs.callable_; - if (callable_) callable_->retain(); - return (*this); - } - - inline function& operator=(function&& rhs) - { - tidy(); - callable_ = rhs.callable_; - rhs.callable_ = nullptr; - return (*this); - } - -private: - inline void tidy() - { - if (callable_) - { - callable_->release(); - callable_ = nullptr; - } - } - -private: - __function_detail::callable<_Ret, _Args...>* callable_; -}; - -} // namespace common - -} // namespace kiwano - -namespace kiwano -{ - template::value || std::is_base_of<_Ty, _Uty>::value, int - >::type, - typename _Ret, - typename... _Args - > - inline common::function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...)) - { - return common::function<_Ret(_Args...)>(ptr, func); - } - - template::value || std::is_base_of<_Ty, _Uty>::value, int - >::type, - typename _Ret, - typename... _Args - > - inline common::function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const) - { - return common::function<_Ret(_Args...)>(ptr, func); - } -} diff --git a/src/kiwano/common/intrusive_list.hpp b/src/kiwano/common/intrusive_list.hpp deleted file mode 100644 index c2c62b00..00000000 --- a/src/kiwano/common/intrusive_list.hpp +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - 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. - -#pragma once -#include - -// #define KGE_DEBUG_ENABLE_LIST_CHECK - -#ifdef KGE_DEBUG_ENABLE_LIST_CHECK -# define KGE_DEBUG_CHECK_LIST(list_ptr) list_ptr->check_list() -#else -# define KGE_DEBUG_CHECK_LIST __noop -#endif - -namespace kiwano -{ - -namespace common -{ - -template -class intrusive_list; - -template -class intrusive_list_item -{ -public: - using value_type = _Ty; - using reference = _Ty&; - using const_reference = const _Ty&; - - intrusive_list_item() : prev_(), next_() {} - intrusive_list_item(_Ty const& rhs) : prev_(rhs->prev_), next_(rhs->next_) {} - - const_reference prev_item() const { return prev_; } - reference prev_item() { return prev_; } - const_reference next_item() const { return next_; } - reference next_item() { return next_; } - -private: - _Ty prev_; - _Ty next_; - - template - friend class intrusive_list; -}; - - -template -class intrusive_list -{ -public: - using value_type = _Ty; - using reference = value_type&; - using const_reference = const value_type&; - - intrusive_list() : first_(), last_() {} - ~intrusive_list() { clear(); } - - const_reference first_item() const { return first_; } - reference first_item() { return first_; } - const_reference last_item() const { return last_; } - reference last_item() { return last_; } - bool empty() const { return !first_; } - - void push_back(value_type child) - { - if (child->prev_) - child->prev_->next_ = child->next_; - if (child->next_) - child->next_->prev_ = child->prev_; - - child->prev_ = last_; - child->next_ = nullptr; - - if (first_) - { - last_->next_ = child; - } - else - { - first_ = child; - } - - last_ = child; - - KGE_DEBUG_CHECK_LIST(this); - } - - void push_front(value_type child) - { - if (child->prev_) - child->prev_->next_ = child->next_; - if (child->next_) - child->next_->prev_ = child->prev_; - - child->prev_ = nullptr; - child->next_ = first_; - - if (first_) - { - first_->prev_ = child; - } - else - { - last_ = child; - } - - first_ = child; - - KGE_DEBUG_CHECK_LIST(this); - } - - void insert_before(value_type child, value_type before) - { - if (child->prev_) - child->prev_->next_ = child->next_; - if (child->next_) - child->next_->prev_ = child->prev_; - - if (before->prev_) - before->prev_->next_ = child; - else - first_ = child; - - child->prev_ = before->prev_; - child->next_ = before; - before->prev_ = child; - - KGE_DEBUG_CHECK_LIST(this); - } - - void insert_after(value_type child, value_type after) - { - if (child->prev_) - child->prev_->next_ = child->next_; - if (child->next_) - child->next_->prev_ = child->prev_; - - if (after->next_) - after->next_->prev_ = child; - else - last_ = child; - - child->next_ = after->next_; - child->prev_ = after; - after->next_ = child; - - KGE_DEBUG_CHECK_LIST(this); - } - - void remove(value_type child) - { -#ifdef KGE_DEBUG_ENABLE_LIST_CHECK - _Ty tmp = first_; - while (tmp != child) - { - KGE_ASSERT((tmp != last_) && "The actor to be removed is not in this list"); - tmp = tmp->next_; - } -#endif - - if (child->next_) - { - child->next_->prev_ = child->prev_; - } - else - { - last_ = child->prev_; - } - - if (child->prev_) - { - child->prev_->next_ = child->next_; - } - else - { - first_ = child->next_; - } - - child->prev_ = nullptr; - child->next_ = nullptr; - - KGE_DEBUG_CHECK_LIST(this); - } - - void clear() - { - _Ty p = first_; - while (p) - { - _Ty tmp = p; - p = p->next_; - if (tmp) - { - tmp->next_ = nullptr; - tmp->prev_ = nullptr; - } - } - first_ = nullptr; - last_ = nullptr; - } - -#ifdef KGE_DEBUG_ENABLE_LIST_CHECK - -private: - void check_list() - { - if (!first_) - return; - - int pos = 0; - _Ty p = first_; - _Ty tmp = p; - do - { - tmp = p; - p = p->next_; - ++pos; - - if (p) - { - KGE_ASSERT(p->prev_ == tmp && "Check list failed"); - } - else - { - KGE_ASSERT(tmp == last_ && "Check list failed"); - } - } while (p); - } - -#endif - -private: - // Iterator - template - struct iterator_impl - { - using iterator_category = std::bidirectional_iterator_tag; - using value_type = _Ty; - using reference = _Ty&; - using difference_type = ptrdiff_t; - - // disable warning 4996 - using _Unchecked_type = _Ty; - - inline iterator_impl(value_type core = nullptr, bool is_end = false) : base_(core), is_end_(is_end) {} - - inline _Ty operator*() const { KGE_ASSERT(base_); return static_cast<_Ty>(const_cast(base_)); } - inline iterator_impl& operator++() { KGE_ASSERT(base_ && !is_end_); value_type next = base_->next_item(); if (next) base_ = next; else is_end_ = true; return (*this);} - inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; } - inline iterator_impl& operator--() { KGE_ASSERT(base_); if (is_end_) is_end_ = false; else base_ = value_type(base_->prev_item()); return (*this); } - inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; } - inline bool operator==(iterator_impl const& other) const { return base_ == other.base_ && is_end_ == other.is_end_; } - inline bool operator!=(iterator_impl const& other) const { return !(*this == other); } - inline operator bool() const { return base_ != nullptr && !is_end_; } - - private: - bool is_end_; - value_type base_; - }; - -public: - using reference = value_type&; - using const_reference = const value_type&; - 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() { return iterator(first_item(), first_item() == nullptr); } - inline const_iterator begin() const { return const_iterator(first_item(), first_item() == nullptr); } - inline const_iterator cbegin() const { return begin(); } - inline iterator end() { return iterator(last_item(), true); } - inline const_iterator end() const { return const_iterator(last_item(), true); } - inline const_iterator cend() const { return end(); } - 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(); } - inline reference front() { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); } - inline const_reference front() const { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); } - inline reference back() { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); } - inline const_reference back() const { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); } - -private: - value_type first_; - value_type last_; -}; - -} // namespace common - -} // namespace kiwano - -#undef KGE_DEBUG_CHECK_LIST -#undef KGE_DEBUG_ENABLE_LIST_CHECK diff --git a/src/kiwano/common/intrusive_ptr.hpp b/src/kiwano/common/intrusive_ptr.hpp deleted file mode 100644 index 168aa5e3..00000000 --- a/src/kiwano/common/intrusive_ptr.hpp +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - Nomango -// -// Permission is hereby granted, free of charge, to any person obtaining lhs 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. - -#pragma once -#include -#include -#include - -namespace kiwano -{ - -namespace common -{ - -template -class intrusive_ptr -{ -public: - using value_type = _Ty; - using pointer_type = _Ty*; - using const_pointer_type = const _Ty*; - using reference_type = _Ty&; - using const_reference_type = const _Ty&; - using manager_type = _ManagerTy; - - intrusive_ptr() noexcept : ptr_(nullptr) {} - intrusive_ptr(std::nullptr_t) noexcept : ptr_(nullptr) {} - intrusive_ptr(pointer_type p) : ptr_(p) { typename manager_type::AddRef(ptr_); } - intrusive_ptr(const intrusive_ptr& other) : ptr_(other.ptr_) { typename manager_type::AddRef(ptr_); } - intrusive_ptr(intrusive_ptr&& other) noexcept : ptr_(nullptr) { swap(other); } - ~intrusive_ptr() { reset(); } - - template - intrusive_ptr(const intrusive_ptr<_UTy, manager_type>& other) { ptr_ = const_cast(dynamic_cast(other.get())); typename manager_type::AddRef(ptr_); } - - inline pointer_type get() noexcept { return ptr_; } - inline const_pointer_type get() const noexcept { return ptr_; } - inline void reset(pointer_type ptr = nullptr) { typename manager_type::Release(ptr_); ptr_ = nullptr; } - inline void swap(intrusive_ptr& other) noexcept { std::swap(ptr_, other.ptr_); } - - inline pointer_type operator ->() { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } - inline const_pointer_type operator ->() const { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } - inline reference_type operator *() { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } - inline const_reference_type operator *() const { KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } - inline pointer_type* operator &() { KGE_ASSERT(ptr_ == nullptr && "Memory leak"); return &ptr_; } - inline operator bool() const noexcept { return ptr_ != nullptr; } - inline bool operator !() const noexcept { return ptr_ == 0; } - - inline intrusive_ptr& operator=(const intrusive_ptr& other) { if (other.ptr_ != ptr_) intrusive_ptr(other).swap(*this); return (*this); } - inline intrusive_ptr& operator=(intrusive_ptr&& other) noexcept { if (other.ptr_ != ptr_) other.swap(*this); return (*this); } - inline intrusive_ptr& operator=(pointer_type p) { if (p != ptr_) intrusive_ptr(p).swap(*this); return (*this); } - inline intrusive_ptr& operator=(std::nullptr_t) { reset(); return *this; } - -private: - pointer_type ptr_; -}; - -template -inline bool operator==(intrusive_ptr<_Ty, manager_type> const& lhs, intrusive_ptr<_UTy, manager_type> const& rhs) noexcept -{ - return lhs.get() == rhs.get(); -} - -template -inline bool operator==(intrusive_ptr<_Ty, manager_type> const& lhs, _Ty* rhs) noexcept -{ - return lhs.get() == rhs; -} - -template -inline bool operator==(_Ty* lhs, intrusive_ptr<_Ty, manager_type> const& rhs) noexcept -{ - return lhs == rhs.get(); -} - -template -inline bool operator==(intrusive_ptr<_Ty, manager_type> const& lhs, std::nullptr_t) noexcept -{ - return !static_cast(lhs); -} - -template -inline bool operator==(std::nullptr_t, intrusive_ptr<_Ty, manager_type> const& rhs) noexcept -{ - return !static_cast(rhs); -} - -template -inline bool operator!=(intrusive_ptr<_Ty, manager_type> const& lhs, intrusive_ptr<_UTy, manager_type> const& rhs) noexcept -{ - return !(lhs == rhs); -} - -template -inline bool operator!=(intrusive_ptr<_Ty, manager_type> const& lhs, _Ty* rhs) noexcept -{ - return lhs.get() != rhs; -} - -template -inline bool operator!=(_Ty* lhs, intrusive_ptr<_Ty, manager_type> const& rhs) noexcept -{ - return lhs != rhs.get(); -} - -template -inline bool operator!=(intrusive_ptr<_Ty, manager_type> const& lhs, std::nullptr_t) noexcept -{ - return static_cast(lhs); -} - -template -inline bool operator!=(std::nullptr_t, intrusive_ptr<_Ty, manager_type> const& rhs) noexcept -{ - return static_cast(rhs); -} - -template -inline bool operator<(intrusive_ptr<_Ty, manager_type> const& lhs, intrusive_ptr<_UTy, manager_type> const& rhs) noexcept -{ - return lhs.get() < rhs.get(); -} - -// template class cannot specialize std::swap, -// so implement a swap Function in kiwano namespace -template -inline void swap(intrusive_ptr<_Ty, manager_type>& lhs, intrusive_ptr<_Ty, manager_type>& rhs) noexcept -{ - lhs.swap(rhs); -} - -} // namespace common - -} // namespace kiwano diff --git a/src/kiwano/common/noncopyable.hpp b/src/kiwano/common/noncopyable.hpp deleted file mode 100644 index 9328c7e7..00000000 --- a/src/kiwano/common/noncopyable.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - 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. - -#pragma once - -namespace kiwano -{ -namespace common -{ - -class noncopyable -{ -protected: - noncopyable() = default; - -private: - noncopyable(const noncopyable&) = delete; - - noncopyable& operator=(const noncopyable&) = delete; -}; - -} // namespace common -} // namespace kiwano diff --git a/src/kiwano/common/singleton.hpp b/src/kiwano/common/singleton.hpp deleted file mode 100644 index afc3fff4..00000000 --- a/src/kiwano/common/singleton.hpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - 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. - -#pragma once -#include -#include - -// Class that will implement the singleton mode, -// must use the macro in its delare file - -#ifndef KGE_DECLARE_SINGLETON -#define KGE_DECLARE_SINGLETON( CLASS ) \ - friend ::kiwano::common::singleton< CLASS >; \ - friend typename std::unique_ptr< CLASS >::deleter_type -#endif - -namespace kiwano -{ -namespace common -{ - -template -struct singleton -{ -public: - static inline _Ty* GetInstance() - { - if (!instance_) - { - std::call_once(once_, InitInstance); - } - return instance_.get(); - } - - static inline void DestroyInstance() - { - instance_.reset(); - } - -protected: - singleton() = default; - -private: - singleton(const singleton&) = delete; - - singleton& operator=(const singleton&) = delete; - - static inline void InitInstance() - { - if (!instance_) - { - instance_.reset(new (std::nothrow) _Ty); - } - } - -private: - static std::once_flag once_; - static std::unique_ptr<_Ty> instance_; -}; - -template -std::once_flag singleton<_Ty>::once_; - -template -std::unique_ptr<_Ty> singleton<_Ty>::instance_; - -} // namespace common -} // namespace kiwano diff --git a/src/kiwano/config.h b/src/kiwano/config.h index a3999050..29d79ab2 100644 --- a/src/kiwano/config.h +++ b/src/kiwano/config.h @@ -10,8 +10,8 @@ //---- Define debug-output handler. Defaults to calling kiwano::logs::Messageln()/Warningln()/Errorln() //#define KGE_LOG(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__) -//#define KGE_WARNING_LOG(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__) -//#define KGE_ERROR_LOG(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__) +//#define KGE_WARN(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__) +//#define KGE_ERROR(FORMAT, ...) wprintf(FORMAT L"\n", __VA_ARGS__) //---- Define attributes of all API symbols declarations for DLL //#define KGE_USE_DLL diff --git a/src/kiwano/core/Library.cpp b/src/kiwano/core/Library.cpp index 1f4c0c94..fda1c0c0 100644 --- a/src/kiwano/core/Library.cpp +++ b/src/kiwano/core/Library.cpp @@ -62,7 +62,7 @@ namespace kiwano FARPROC Library::GetProcess(String const& proc_name) { KGE_ASSERT(instance_ != nullptr); - return GetProcAddress(instance_, wide_to_string(proc_name).c_str()); + return GetProcAddress(instance_, oc::wide_to_string(proc_name).c_str()); } } diff --git a/src/kiwano/core/Logger.cpp b/src/kiwano/core/Logger.cpp index cadc07de..e0aaf751 100644 --- a/src/kiwano/core/Logger.cpp +++ b/src/kiwano/core/Logger.cpp @@ -25,66 +25,52 @@ namespace { - std::streambuf* cin_buffer, * cout_buffer, * cerr_buffer; - std::fstream console_input, console_output, console_error; + std::streambuf* cout_buffer, * cerr_buffer; + std::fstream console_output, console_error; - std::wstreambuf* wcin_buffer, * wcout_buffer, * wcerr_buffer; - std::wfstream wconsole_input, wconsole_output, wconsole_error; + std::wstreambuf* wcout_buffer, * wcerr_buffer; + std::wfstream wconsole_output, wconsole_error; void RedirectStdIO() { - cin_buffer = std::cin.rdbuf(); cout_buffer = std::cout.rdbuf(); cerr_buffer = std::cerr.rdbuf(); - wcin_buffer = std::wcin.rdbuf(); wcout_buffer = std::wcout.rdbuf(); wcerr_buffer = std::wcerr.rdbuf(); - console_input.open("CONIN$", std::ios::in); console_output.open("CONOUT$", std::ios::out); console_error.open("CONOUT$", std::ios::out); - wconsole_input.open("CONIN$", std::ios::in); wconsole_output.open("CONOUT$", std::ios::out); wconsole_error.open("CONOUT$", std::ios::out); FILE* dummy; freopen_s(&dummy, "CONOUT$", "w+t", stdout); - freopen_s(&dummy, "CONIN$", "r+t", stdin); freopen_s(&dummy, "CONOUT$", "w+t", stderr); (void)dummy; - std::cin.rdbuf(console_input.rdbuf()); std::cout.rdbuf(console_output.rdbuf()); std::cerr.rdbuf(console_error.rdbuf()); - std::wcin.rdbuf(wconsole_input.rdbuf()); std::wcout.rdbuf(wconsole_output.rdbuf()); std::wcerr.rdbuf(wconsole_error.rdbuf()); } void ResetStdIO() { - console_input.close(); console_output.close(); console_error.close(); - wconsole_input.close(); wconsole_output.close(); wconsole_error.close(); - std::cin.rdbuf(cin_buffer); std::cout.rdbuf(cout_buffer); std::cerr.rdbuf(cerr_buffer); - std::wcin.rdbuf(wcin_buffer); std::wcout.rdbuf(wcout_buffer); std::wcerr.rdbuf(wcerr_buffer); fclose(stdout); - fclose(stdin); fclose(stderr); - cin_buffer = nullptr; cout_buffer = nullptr; cerr_buffer = nullptr; - wcin_buffer = nullptr; wcout_buffer = nullptr; wcerr_buffer = nullptr; } @@ -125,17 +111,17 @@ namespace kiwano { namespace __console_colors { - const WORD _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY; - const WORD _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY; - const WORD _red = FOREGROUND_RED | FOREGROUND_INTENSITY; - const WORD _yellow = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; - const WORD _white = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; + const WORD _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY; + const WORD _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY; + const WORD _red = FOREGROUND_RED | FOREGROUND_INTENSITY; + const WORD _yellow = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; + const WORD _white = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; - const WORD _blue_bg = _white | BACKGROUND_BLUE | BACKGROUND_INTENSITY; - const WORD _green_bg = _white | BACKGROUND_GREEN | BACKGROUND_INTENSITY; - const WORD _red_bg = _white | BACKGROUND_RED | BACKGROUND_INTENSITY; - const WORD _yellow_bg = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; - const WORD _white_bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; + const WORD _blue_bg = _white | BACKGROUND_BLUE | BACKGROUND_INTENSITY; + const WORD _green_bg = _white | BACKGROUND_GREEN | BACKGROUND_INTENSITY; + const WORD _red_bg = _white | BACKGROUND_RED | BACKGROUND_INTENSITY; + const WORD _yellow_bg = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; + const WORD _white_bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; const WORD _reset = _white; @@ -202,6 +188,11 @@ namespace kiwano default_stderr_color_ = stderr_info.wAttributes; } + // replace the C++ global locale with the user-preferred locale + (void)std::locale::global(std::locale("")); + (void)std::wcout.imbue(std::locale()); + (void)std::wcerr.imbue(std::locale()); + RedirectOutputStreamBuffer(std::wcout.rdbuf()); RedirectErrorStreamBuffer(std::wcerr.rdbuf()); } @@ -298,10 +289,12 @@ namespace kiwano std::wostream& Logger::OutPrefix(std::wostream& out) { + out << L"[KIWANO] "; + time_t unix = std::time(nullptr); std::tm tmbuf; localtime_s(&tmbuf, &unix); - out << std::put_time(&tmbuf, L"[kiwano] %H:%M:%S"); + out << std::put_time(&tmbuf, L"%H:%M:%S"); return out; } @@ -319,7 +312,7 @@ namespace kiwano HWND console = ::AllocateConsole(); if (!console) { - KGE_WARNING_LOG(L"AllocConsole failed"); + KGE_WARN(L"AllocConsole failed"); } else { diff --git a/src/kiwano/core/Logger.h b/src/kiwano/core/Logger.h index 9f4732e9..60e224eb 100644 --- a/src/kiwano/core/Logger.h +++ b/src/kiwano/core/Logger.h @@ -28,26 +28,26 @@ #ifndef KGE_LOG # ifdef KGE_DEBUG -# define KGE_LOG(FORMAT, ...) ::kiwano::Logger::GetInstance()->Messagef((FORMAT ## "\n"), __VA_ARGS__) +# define KGE_LOG(FORMAT, ...) ::kiwano::Logger::instance().Messagef((FORMAT ## "\n"), __VA_ARGS__) # else # define KGE_LOG __noop # endif #endif -#ifndef KGE_WARNING_LOG -# define KGE_WARNING_LOG(FORMAT, ...) ::kiwano::Logger::GetInstance()->Warningf((FORMAT ## "\n"), __VA_ARGS__) +#ifndef KGE_WARN +# define KGE_WARN(FORMAT, ...) ::kiwano::Logger::instance().Warningf((FORMAT ## "\n"), __VA_ARGS__) #endif -#ifndef KGE_ERROR_LOG -# define KGE_ERROR_LOG(FORMAT, ...) ::kiwano::Logger::GetInstance()->Errorf((FORMAT ## "\n"), __VA_ARGS__) +#ifndef KGE_ERROR +# define KGE_ERROR(FORMAT, ...) ::kiwano::Logger::instance().Errorf((FORMAT ## "\n"), __VA_ARGS__) #endif #ifndef KGE_PRINT -# define KGE_PRINT(...) ::kiwano::Logger::GetInstance()->Println(__VA_ARGS__) +# define KGE_PRINT(...) ::kiwano::Logger::instance().Println(__VA_ARGS__) #endif #ifndef KGE_PRINTF -# define KGE_PRINTF(FORMAT, ...) ::kiwano::Logger::GetInstance()->Printf((FORMAT), __VA_ARGS__) +# define KGE_PRINTF(FORMAT, ...) ::kiwano::Logger::instance().Printf((FORMAT), __VA_ARGS__) #endif namespace kiwano @@ -55,7 +55,7 @@ namespace kiwano class KGE_API Logger : public Singleton { - KGE_DECLARE_SINGLETON(Logger); + OC_DECLARE_SINGLETON(Logger); public: // ÏÔʾ»ò¹Ø±Õ¿ØÖÆÌ¨ @@ -99,6 +99,10 @@ namespace kiwano template void Errorln(_Args&& ... args); + std::wostream& GetOutputStream(); + + std::wostream& GetErrorStream(); + std::wstreambuf* RedirectOutputStreamBuffer(std::wstreambuf* buf); std::wstreambuf* RedirectErrorStreamBuffer(std::wstreambuf* buf); @@ -292,7 +296,17 @@ namespace kiwano inline std::wostream& Logger::DefaultOutputColor(std::wostream& out) { - ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), Logger::GetInstance()->default_stdout_color_); + ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), Logger::instance().default_stdout_color_); return out; } + + inline std::wostream& Logger::GetOutputStream() + { + return output_stream_; + } + + inline std::wostream& Logger::GetErrorStream() + { + return error_stream_; + } } diff --git a/src/kiwano/core/ObjectBase.cpp b/src/kiwano/core/ObjectBase.cpp index ce4b7ff3..c6c033e8 100644 --- a/src/kiwano/core/ObjectBase.cpp +++ b/src/kiwano/core/ObjectBase.cpp @@ -90,7 +90,7 @@ namespace kiwano String ObjectBase::DumpObject() { - String name = kiwano::string_to_wide(typeid(*this).name()); + String name = oc::string_to_wide(typeid(*this).name()); return String::format(L"{ class=\"%s\" id=%d refcount=%d name=\"%s\" }", name.c_str(), GetObjectID(), GetRefCount(), GetName().c_str()); } diff --git a/src/kiwano/core/RefCounter.hpp b/src/kiwano/core/RefCounter.hpp index 14bfa5d2..235ae5bb 100644 --- a/src/kiwano/core/RefCounter.hpp +++ b/src/kiwano/core/RefCounter.hpp @@ -20,12 +20,12 @@ #pragma once #include -#include +#include namespace kiwano { class KGE_API RefCounter - : protected common::noncopyable + : protected Noncopyable { public: // Ôö¼ÓÒýÓüÆÊý diff --git a/src/kiwano/core/Resource.cpp b/src/kiwano/core/Resource.cpp index f2c7c8af..ae57a3a5 100644 --- a/src/kiwano/core/Resource.cpp +++ b/src/kiwano/core/Resource.cpp @@ -50,28 +50,28 @@ namespace kiwano HRSRC res_info = FindResourceW(nullptr, MAKEINTRESOURCE(id_), type_); if (res_info == nullptr) { - KGE_ERROR_LOG(L"FindResource failed"); + KGE_ERROR(L"FindResource failed"); break; } HGLOBAL res_data = LoadResource(nullptr, res_info); if (res_data == nullptr) { - KGE_ERROR_LOG(L"LoadResource failed"); + KGE_ERROR(L"LoadResource failed"); break; } DWORD size = SizeofResource(nullptr, res_info); if (size == 0) { - KGE_ERROR_LOG(L"SizeofResource failed"); + KGE_ERROR(L"SizeofResource failed"); break; } LPVOID buffer = LockResource(res_data); if (buffer == nullptr) { - KGE_ERROR_LOG(L"LockResource failed"); + KGE_ERROR(L"LockResource failed"); break; } diff --git a/src/kiwano/core/SmartPtr.hpp b/src/kiwano/core/SmartPtr.hpp index 15edf87d..c1cdad5a 100644 --- a/src/kiwano/core/SmartPtr.hpp +++ b/src/kiwano/core/SmartPtr.hpp @@ -20,25 +20,25 @@ #pragma once #include -#include +#include namespace kiwano { - struct DefaultIntrusivePtrManager + struct DefaultIntrusivePtrProxy { - static inline void AddRef(RefCounter* ptr) + static inline void add_ref(RefCounter* ptr) { if (ptr) ptr->Retain(); } - static inline void Release(RefCounter* ptr) + static inline void release(RefCounter* ptr) { if (ptr) ptr->Release(); } }; template - using SmartPtr = common::intrusive_ptr<_Ty, DefaultIntrusivePtrManager>; + using SmartPtr = IntrusivePtr<_Ty, DefaultIntrusivePtrProxy>; } diff --git a/src/kiwano/core/time.cpp b/src/kiwano/core/time.cpp index 568aff2b..ccdeb49f 100644 --- a/src/kiwano/core/time.cpp +++ b/src/kiwano/core/time.cpp @@ -363,7 +363,7 @@ namespace kiwano if (!std::regex_match(str.c_str(), duration_regex)) { - KGE_ERROR_LOG(L"Duration::Parse failed, invalid duration"); + KGE_ERROR(L"Duration::Parse failed, invalid duration"); return ret; } diff --git a/src/kiwano/core/win32/ComPtr.hpp b/src/kiwano/core/win32/ComPtr.hpp index 0cc76527..4a0484cd 100644 --- a/src/kiwano/core/win32/ComPtr.hpp +++ b/src/kiwano/core/win32/ComPtr.hpp @@ -20,19 +20,19 @@ #pragma once #include -#include +#include #include namespace kiwano { - struct ComPtrManager + struct ComPtrProxy { - static inline void AddRef(IUnknown* ptr) + static inline void add_ref(IUnknown* ptr) { if (ptr) ptr->AddRef(); } - static inline void Release(IUnknown* ptr) + static inline void release(IUnknown* ptr) { if (ptr) ptr->Release(); } @@ -42,6 +42,6 @@ namespace kiwano template< typename _Ty, typename = typename std::enable_if::value, int>::type> - using ComPtr = common::intrusive_ptr<_Ty, ComPtrManager>; + using ComPtr = IntrusivePtr<_Ty, ComPtrProxy>; } diff --git a/src/kiwano/core/win32/helper.h b/src/kiwano/core/win32/helper.h index a731dc96..940013ae 100644 --- a/src/kiwano/core/win32/helper.h +++ b/src/kiwano/core/win32/helper.h @@ -28,7 +28,7 @@ namespace kiwano { if (FAILED(hr)) { - KGE_ERROR_LOG(L"Fatal error with HRESULT of %08X", hr); + KGE_ERROR(L"Fatal error with HRESULT of %08X", hr); StackWalker{}.ShowCallstack(); diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h index 6c8af7a6..bb842ecf 100644 --- a/src/kiwano/kiwano.h +++ b/src/kiwano/kiwano.h @@ -32,15 +32,6 @@ // common // -#include -#include -#include -#include -#include -#include -#include -#include -#include #include diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index e55436e4..62733d9f 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -69,9 +69,9 @@ namespace kiwano { ThrowIfFailed(::CoInitialize(nullptr)); - Use(Renderer::GetInstance()); - Use(Input::GetInstance()); - Use(Director::GetInstance()); + Use(&Renderer::instance()); + Use(&Input::instance()); + Use(&Director::instance()); } Application::~Application() @@ -83,8 +83,8 @@ namespace kiwano void Application::Init(const Config& config) { - Window::GetInstance()->Init(config.window, Application::WndProc); - Renderer::GetInstance()->Init(config.render); + Window::instance().Init(config.window, Application::WndProc); + Renderer::instance().Init(config.render); // Setup all components for (auto c : comps_) @@ -94,14 +94,14 @@ namespace kiwano if (config.debug) { - Director::GetInstance()->ShowDebugInfo(true); - Renderer::GetInstance()->SetCollectingStatus(true); + Director::instance().ShowDebugInfo(true); + Renderer::instance().SetCollectingStatus(true); } // Everything is ready OnReady(); - HWND hwnd = Window::GetInstance()->GetHandle(); + HWND hwnd = Window::instance().GetHandle(); // disable imm ::ImmAssociateContext(hwnd, nullptr); @@ -118,10 +118,10 @@ namespace kiwano end_ = false; - Window::GetInstance()->Prepare(); + Window::instance().Prepare(); while (!end_) { - Window::GetInstance()->PollEvents(); + Window::instance().PollEvents(); } } @@ -133,9 +133,9 @@ namespace kiwano void Application::Destroy() { // Clear all resources - Director::GetInstance()->ClearStages(); - ResourceCache::GetInstance()->Clear(); - TextureCache::GetInstance()->Clear(); + Director::instance().ClearStages(); + ResourceCache::instance().Clear(); + TextureCache::instance().Clear(); if (inited_) { @@ -148,16 +148,9 @@ namespace kiwano comps_.clear(); } - // Destroy all instances - Director::DestroyInstance(); - ResourceCache::DestroyInstance(); - TextureCache::DestroyInstance(); - Input::DestroyInstance(); - Renderer::DestroyInstance(); - Window::DestroyInstance(); - - // DO NOT destroy Logger instance manually - // Logger::DestroyInstance(); + Input::instance().Destroy(); + Renderer::instance().Destroy(); + Window::instance().Destroy(); } void Application::Use(ComponentBase* component) @@ -248,7 +241,7 @@ namespace kiwano } // Rendering - Renderer* renderer = Renderer::GetInstance(); + Renderer* renderer = &Renderer::instance(); for (auto c : render_comps_) { c->OnRender(renderer); @@ -396,7 +389,7 @@ namespace kiwano { // KGE_LOG(L"Window resized"); - Window::GetInstance()->UpdateWindowRect(); + Window::instance().UpdateWindowRect(); WindowResizedEvent evt; evt.width = LOWORD(lparam); @@ -422,7 +415,7 @@ namespace kiwano { bool active = (LOWORD(wparam) != WA_INACTIVE); - Window::GetInstance()->SetActive(active); + Window::instance().SetActive(active); WindowFocusChangedEvent evt; evt.focus = active; @@ -456,7 +449,7 @@ namespace kiwano case WM_SETCURSOR: { - Window::GetInstance()->UpdateCursor(); + Window::instance().UpdateCursor(); } break; diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h index 1d443de9..7f6053ae 100644 --- a/src/kiwano/platform/Application.h +++ b/src/kiwano/platform/Application.h @@ -50,7 +50,7 @@ namespace kiwano // Ó¦Óà class KGE_API Application - : protected common::noncopyable + : protected Noncopyable { public: Application(); diff --git a/src/kiwano/platform/Director.h b/src/kiwano/platform/Director.h index 613bc981..4cd606b5 100644 --- a/src/kiwano/platform/Director.h +++ b/src/kiwano/platform/Director.h @@ -31,7 +31,7 @@ namespace kiwano , public RenderComponent , public EventComponent { - KGE_DECLARE_SINGLETON(Director); + OC_DECLARE_SINGLETON(Director); public: // Çл»Îę̀ diff --git a/src/kiwano/platform/FileSystem.h b/src/kiwano/platform/FileSystem.h index 7e9d47a3..9af781ad 100644 --- a/src/kiwano/platform/FileSystem.h +++ b/src/kiwano/platform/FileSystem.h @@ -27,7 +27,7 @@ namespace kiwano class KGE_API FileSystem : public Singleton { - KGE_DECLARE_SINGLETON(FileSystem); + OC_DECLARE_SINGLETON(FileSystem); public: // Ìí¼ÓÎļþËÑË÷·¾¶ diff --git a/src/kiwano/platform/Input.cpp b/src/kiwano/platform/Input.cpp index 9803760c..98416b96 100644 --- a/src/kiwano/platform/Input.cpp +++ b/src/kiwano/platform/Input.cpp @@ -140,4 +140,8 @@ namespace kiwano { return Point{ mouse_pos_x_, mouse_pos_y_ }; } + + void Input::Destroy() + { + } } diff --git a/src/kiwano/platform/Input.h b/src/kiwano/platform/Input.h index 5b17d98e..01e4197f 100644 --- a/src/kiwano/platform/Input.h +++ b/src/kiwano/platform/Input.h @@ -32,7 +32,7 @@ namespace kiwano , public UpdateComponent , public EventComponent { - KGE_DECLARE_SINGLETON(Input); + OC_DECLARE_SINGLETON(Input); public: // ¼ì²â¼üÅÌ»òÊó±ê°´¼üÊÇ·ñÕý±»°´Ï @@ -72,6 +72,8 @@ namespace kiwano void UpdateMousePos(float, float); + void Destroy(); + protected: Input(); diff --git a/src/kiwano/platform/Window.cpp b/src/kiwano/platform/Window.cpp index dff73d1e..f70f6a19 100644 --- a/src/kiwano/platform/Window.cpp +++ b/src/kiwano/platform/Window.cpp @@ -63,20 +63,6 @@ namespace kiwano Window::~Window() { - if (is_fullscreen_) - RestoreResolution(device_name_); - - if (device_name_) - { - delete[] device_name_; - device_name_ = nullptr; - } - - if (handle_) - { - ::DestroyWindow(handle_); - handle_ = nullptr; - } } void Window::Init(WindowConfig const& config, WNDPROC proc) @@ -388,6 +374,24 @@ namespace kiwano } } + void Window::Destroy() + { + if (is_fullscreen_) + RestoreResolution(device_name_); + + if (device_name_) + { + delete[] device_name_; + device_name_ = nullptr; + } + + if (handle_) + { + ::DestroyWindow(handle_); + handle_ = nullptr; + } + } + namespace { MONITORINFOEX GetMoniterInfoEx(HWND hwnd) @@ -434,7 +438,7 @@ namespace kiwano mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (::ChangeDisplaySettingsExW(device_name, &mode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL) - KGE_ERROR_LOG(L"ChangeDisplaySettings failed"); + KGE_ERROR(L"ChangeDisplaySettings failed"); } void RestoreResolution(WCHAR* device_name) diff --git a/src/kiwano/platform/Window.h b/src/kiwano/platform/Window.h index d2279335..14798536 100644 --- a/src/kiwano/platform/Window.h +++ b/src/kiwano/platform/Window.h @@ -63,7 +63,7 @@ namespace kiwano class KGE_API Window : public Singleton { - KGE_DECLARE_SINGLETON(Window); + OC_DECLARE_SINGLETON(Window); public: // »ñÈ¡±êÌâ @@ -110,6 +110,8 @@ namespace kiwano void SetActive(bool actived); + void Destroy(); + protected: Window(); diff --git a/src/kiwano/platform/modules.cpp b/src/kiwano/platform/modules.cpp index dd5d57dd..305beb6e 100644 --- a/src/kiwano/platform/modules.cpp +++ b/src/kiwano/platform/modules.cpp @@ -37,7 +37,7 @@ namespace kiwano } else { - KGE_ERROR_LOG(L"Load shlapi.dll failed"); + KGE_ERROR(L"Load shlapi.dll failed"); throw std::runtime_error("Load shlapi.dll failed"); } } diff --git a/src/kiwano/renderer/Brush.cpp b/src/kiwano/renderer/Brush.cpp index 9ada29e3..6b9f1a08 100644 --- a/src/kiwano/renderer/Brush.cpp +++ b/src/kiwano/renderer/Brush.cpp @@ -111,20 +111,20 @@ namespace kiwano } else { - Renderer::GetInstance()->CreateSolidBrush(*this, style.color); + Renderer::instance().CreateSolidBrush(*this, style.color); type_ = Type::SolidColor; } } void Brush::SetStyle(LinearGradientStyle const& style) { - Renderer::GetInstance()->CreateLinearGradientBrush(*this, style.begin, style.end, style.stops, style.extend_mode); + Renderer::instance().CreateLinearGradientBrush(*this, style.begin, style.end, style.stops, style.extend_mode); type_ = Type::LinearGradient; } void Brush::SetStyle(RadialGradientStyle const& style) { - Renderer::GetInstance()->CreateRadialGradientBrush(*this, style.center, style.offset, style.radius, style.stops, style.extend_mode); + Renderer::instance().CreateRadialGradientBrush(*this, style.center, style.offset, style.radius, style.stops, style.extend_mode); type_ = Type::RadialGradient; } diff --git a/src/kiwano/renderer/FontCollection.cpp b/src/kiwano/renderer/FontCollection.cpp index e9a18553..df0118cc 100644 --- a/src/kiwano/renderer/FontCollection.cpp +++ b/src/kiwano/renderer/FontCollection.cpp @@ -49,25 +49,25 @@ namespace kiwano bool FontCollection::Load(String const& file) { - Renderer::GetInstance()->CreateFontCollection(*this, { file }); + Renderer::instance().CreateFontCollection(*this, { file }); return IsValid(); } bool FontCollection::Load(Vector const& files) { - Renderer::GetInstance()->CreateFontCollection(*this, files); + Renderer::instance().CreateFontCollection(*this, files); return IsValid(); } bool FontCollection::Load(Resource const& res) { - Renderer::GetInstance()->CreateFontCollection(*this, { res }); + Renderer::instance().CreateFontCollection(*this, { res }); return IsValid(); } bool FontCollection::Load(Vector const& res_arr) { - Renderer::GetInstance()->CreateFontCollection(*this, res_arr); + Renderer::instance().CreateFontCollection(*this, res_arr); return IsValid(); } diff --git a/src/kiwano/renderer/Geometry.cpp b/src/kiwano/renderer/Geometry.cpp index e8d204b6..9a6a46c5 100644 --- a/src/kiwano/renderer/Geometry.cpp +++ b/src/kiwano/renderer/Geometry.cpp @@ -147,35 +147,35 @@ namespace kiwano Geometry Geometry::CreateLine(Point const& begin, Point const& end) { Geometry output; - Renderer::GetInstance()->CreateLineGeometry(output, begin, end); + Renderer::instance().CreateLineGeometry(output, begin, end); return output; } Geometry Geometry::CreateRect(Rect const& rect) { Geometry output; - Renderer::GetInstance()->CreateRectGeometry(output, rect); + Renderer::instance().CreateRectGeometry(output, rect); return output; } Geometry Geometry::CreateRoundedRect(Rect const& rect, Vec2 const& radius) { Geometry output; - Renderer::GetInstance()->CreateRoundedRectGeometry(output, rect, radius); + Renderer::instance().CreateRoundedRectGeometry(output, rect, radius); return output; } Geometry Geometry::CreateCircle(Point const& center, float radius) { Geometry output; - Renderer::GetInstance()->CreateEllipseGeometry(output, center, Vec2{ radius, radius }); + Renderer::instance().CreateEllipseGeometry(output, center, Vec2{ radius, radius }); return output; } Geometry Geometry::CreateEllipse(Point const& center, Vec2 const& radius) { Geometry output; - Renderer::GetInstance()->CreateEllipseGeometry(output, center, radius); + Renderer::instance().CreateEllipseGeometry(output, center, radius); return output; } @@ -284,7 +284,7 @@ namespace kiwano { if (!path_geo_) { - Renderer::GetInstance()->CreatePathGeometrySink(*this); + Renderer::instance().CreatePathGeometrySink(*this); } } diff --git a/src/kiwano/renderer/Geometry.h b/src/kiwano/renderer/Geometry.h index ea3daa6c..73aab3f6 100644 --- a/src/kiwano/renderer/Geometry.h +++ b/src/kiwano/renderer/Geometry.h @@ -130,7 +130,7 @@ namespace kiwano // ¼¸ºÎÌåÉú³ÉÆ÷ class KGE_API GeometrySink - : protected common::noncopyable + : protected Noncopyable { public: GeometrySink(); diff --git a/src/kiwano/renderer/GifImage.cpp b/src/kiwano/renderer/GifImage.cpp index 25282aef..d8c633df 100644 --- a/src/kiwano/renderer/GifImage.cpp +++ b/src/kiwano/renderer/GifImage.cpp @@ -44,7 +44,7 @@ namespace kiwano bool GifImage::Load(String const& file_path) { - Renderer::GetInstance()->CreateGifImage(*this, file_path); + Renderer::instance().CreateGifImage(*this, file_path); if (IsValid()) { @@ -60,7 +60,7 @@ namespace kiwano bool GifImage::Load(Resource const& res) { - Renderer::GetInstance()->CreateGifImage(*this, res); + Renderer::instance().CreateGifImage(*this, res); if (IsValid()) { diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h index 41f78436..af0b5475 100644 --- a/src/kiwano/renderer/RenderTarget.h +++ b/src/kiwano/renderer/RenderTarget.h @@ -41,7 +41,7 @@ namespace kiwano // äÖȾĿ±ê class KGE_API RenderTarget - : public common::noncopyable + : public Noncopyable { public: bool IsValid() const; diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index e1573261..38d3dea1 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -52,8 +52,8 @@ namespace kiwano { KGE_LOG(L"Creating device resources"); - hwnd_ = Window::GetInstance()->GetHandle(); - output_size_ = Window::GetInstance()->GetSize(); + hwnd_ = Window::instance().GetHandle(); + output_size_ = Window::instance().GetSize(); d2d_res_ = nullptr; d3d_res_ = nullptr; @@ -247,15 +247,15 @@ namespace kiwano hr = E_UNEXPECTED; } - if (!FileSystem::GetInstance()->IsFileExists(file_path)) + if (!FileSystem::instance().IsFileExists(file_path)) { - KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str()); + KGE_WARN(L"Texture file '%s' not found!", file_path.c_str()); hr = E_FAIL; } if (SUCCEEDED(hr)) { - String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path); + String full_path = FileSystem::instance().GetFullPathForFile(file_path); ComPtr decoder; hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path); @@ -298,7 +298,7 @@ namespace kiwano if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load texture failed with HRESULT of %08X!", hr); + KGE_WARN(L"Load texture failed with HRESULT of %08X!", hr); } } @@ -353,7 +353,7 @@ namespace kiwano if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load texture failed with HRESULT of %08X!", hr); + KGE_WARN(L"Load texture failed with HRESULT of %08X!", hr); } } @@ -365,15 +365,15 @@ namespace kiwano hr = E_UNEXPECTED; } - if (!FileSystem::GetInstance()->IsFileExists(file_path)) + if (!FileSystem::instance().IsFileExists(file_path)) { - KGE_WARNING_LOG(L"Gif texture file '%s' not found!", file_path.c_str()); + KGE_WARN(L"Gif texture file '%s' not found!", file_path.c_str()); hr = E_FAIL; } if (SUCCEEDED(hr)) { - String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path); + String full_path = FileSystem::instance().GetFullPathForFile(file_path); ComPtr decoder; hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path); @@ -386,7 +386,7 @@ namespace kiwano if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load GIF texture failed with HRESULT of %08X!", hr); + KGE_WARN(L"Load GIF texture failed with HRESULT of %08X!", hr); } } @@ -411,7 +411,7 @@ namespace kiwano if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load GIF texture failed with HRESULT of %08X!", hr); + KGE_WARN(L"Load GIF texture failed with HRESULT of %08X!", hr); } } @@ -578,7 +578,7 @@ namespace kiwano if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load GIF frame failed with HRESULT of %08X!", hr); + KGE_WARN(L"Load GIF frame failed with HRESULT of %08X!", hr); } } @@ -596,13 +596,13 @@ namespace kiwano { for (auto& file_path : full_paths) { - if (!FileSystem::GetInstance()->IsFileExists(file_path)) + if (!FileSystem::instance().IsFileExists(file_path)) { - KGE_WARNING_LOG(L"Font file '%s' not found!", file_path.c_str()); + KGE_WARN(L"Font file '%s' not found!", file_path.c_str()); hr = E_FAIL; } - file_path = FileSystem::GetInstance()->GetFullPathForFile(file_path); + file_path = FileSystem::instance().GetFullPathForFile(file_path); } } @@ -632,7 +632,7 @@ namespace kiwano if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load font failed with HRESULT of %08X!", hr); + KGE_WARN(L"Load font failed with HRESULT of %08X!", hr); } } @@ -670,7 +670,7 @@ namespace kiwano if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load font failed with HRESULT of %08X!", hr); + KGE_WARN(L"Load font failed with HRESULT of %08X!", hr); } } @@ -1015,4 +1015,16 @@ namespace kiwano ThrowIfFailed(hr); } + void Renderer::Destroy() + { + DiscardDeviceResources(); + + d2d_res_.reset(); + d3d_res_.reset(); + drawing_state_block_.reset(); + font_collection_loader_.reset(); + res_font_file_loader_.reset(); + res_font_collection_loader_.reset(); + } + } diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index 14ee8ca6..f3a2be25 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -59,7 +59,7 @@ namespace kiwano , public EventComponent , public RenderTarget { - KGE_DECLARE_SINGLETON(Renderer); + OC_DECLARE_SINGLETON(Renderer); public: // ÉèÖÃÇåÆÁÑÕÉ« @@ -185,6 +185,8 @@ namespace kiwano void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override; + void Destroy(); + public: inline HWND GetTargetWindow() const { return hwnd_; } diff --git a/src/kiwano/renderer/TextLayout.cpp b/src/kiwano/renderer/TextLayout.cpp index 9eb57318..69d9b8cf 100644 --- a/src/kiwano/renderer/TextLayout.cpp +++ b/src/kiwano/renderer/TextLayout.cpp @@ -39,7 +39,7 @@ namespace kiwano void TextFormat::Update(Font const& font) { - Renderer::GetInstance()->CreateTextFormat(*this, font); + Renderer::instance().CreateTextFormat(*this, font); } @@ -72,7 +72,7 @@ namespace kiwano return; } - Renderer::GetInstance()->CreateTextLayout( + Renderer::instance().CreateTextLayout( *this, text, text_format_ diff --git a/src/kiwano/renderer/Texture.cpp b/src/kiwano/renderer/Texture.cpp index 01f0f921..486c6e39 100644 --- a/src/kiwano/renderer/Texture.cpp +++ b/src/kiwano/renderer/Texture.cpp @@ -55,13 +55,13 @@ namespace kiwano bool Texture::Load(String const& file_path) { - Renderer::GetInstance()->CreateTexture(*this, file_path); + Renderer::instance().CreateTexture(*this, file_path); return IsValid(); } bool Texture::Load(Resource const& res) { - Renderer::GetInstance()->CreateTexture(*this, res); + Renderer::instance().CreateTexture(*this, res); return IsValid(); } diff --git a/src/kiwano/renderer/TextureCache.h b/src/kiwano/renderer/TextureCache.h index d5fc996c..e8c19dd7 100644 --- a/src/kiwano/renderer/TextureCache.h +++ b/src/kiwano/renderer/TextureCache.h @@ -27,7 +27,7 @@ namespace kiwano class KGE_API TextureCache : public Singleton { - KGE_DECLARE_SINGLETON(TextureCache); + OC_DECLARE_SINGLETON(TextureCache); public: Texture AddOrGetTexture(String const& file_path); diff --git a/src/kiwano/ui/Button.cpp b/src/kiwano/ui/Button.cpp index f8390b5a..9552d605 100644 --- a/src/kiwano/ui/Button.cpp +++ b/src/kiwano/ui/Button.cpp @@ -113,7 +113,7 @@ namespace kiwano if (evt.type == event::MouseHover) { SetStatus(Status::Hover); - Window::GetInstance()->SetCursor(CursorType::Hand); + Window::instance().SetCursor(CursorType::Hand); if (mouse_over_callback_) mouse_over_callback_(); @@ -121,7 +121,7 @@ namespace kiwano else if (evt.type == event::MouseOut) { SetStatus(Status::Normal); - Window::GetInstance()->SetCursor(CursorType::Arrow); + Window::instance().SetCursor(CursorType::Arrow); if (mouse_out_callback_) mouse_out_callback_(); diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index 7f36b8ac..2f13f0cd 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -61,9 +61,9 @@ namespace kiwano bool ResourceCache::LoadFromJsonFile(String const& file_path) { - if (!FileSystem::GetInstance()->IsFileExists(file_path)) + if (!FileSystem::instance().IsFileExists(file_path)) { - KGE_WARNING_LOG(L"ResourceCache::LoadFromJsonFile failed: File not found."); + KGE_WARN(L"ResourceCache::LoadFromJsonFile failed: File not found."); return false; } @@ -73,19 +73,19 @@ namespace kiwano try { - String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path); + String full_path = FileSystem::instance().GetFullPathForFile(file_path); ifs.open(full_path.c_str()); ifs >> json_data; ifs.close(); } catch (std::wifstream::failure& e) { - KGE_WARNING_LOG(L"ResourceCache::LoadFromJsonFile failed: Cannot open file. (%s)", string_to_wide(e.what()).c_str()); + KGE_WARN(L"ResourceCache::LoadFromJsonFile failed: Cannot open file. (%s)", oc::string_to_wide(e.what()).c_str()); return false; } - catch (common::json_exception& e) + catch (oc::json_exception& e) { - KGE_WARNING_LOG(L"ResourceCache::LoadFromJsonFile failed: Cannot parse to JSON. (%s)", string_to_wide(e.what()).c_str()); + KGE_WARN(L"ResourceCache::LoadFromJsonFile failed: Cannot parse to JSON. (%s)", oc::string_to_wide(e.what()).c_str()); return false; } return LoadFromJson(json_data); @@ -113,7 +113,7 @@ namespace kiwano } catch (std::exception& e) { - KGE_WARNING_LOG(L"ResourceCache::LoadFromJson failed: JSON data is invalid. (%s)", string_to_wide(e.what()).c_str()); + KGE_WARN(L"ResourceCache::LoadFromJson failed: JSON data is invalid. (%s)", oc::string_to_wide(e.what()).c_str()); return false; } return false; @@ -121,9 +121,9 @@ namespace kiwano bool ResourceCache::LoadFromXmlFile(String const& file_path) { - if (!FileSystem::GetInstance()->IsFileExists(file_path)) + if (!FileSystem::instance().IsFileExists(file_path)) { - KGE_WARNING_LOG(L"ResourceCache::LoadFromXmlFile failed: File not found."); + KGE_WARN(L"ResourceCache::LoadFromXmlFile failed: File not found."); return false; } @@ -133,7 +133,7 @@ namespace kiwano try { - String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path); + String full_path = FileSystem::instance().GetFullPathForFile(file_path); ifs.open(full_path.c_str()); StringStream ss; @@ -141,14 +141,14 @@ namespace kiwano if (tinyxml2::XML_SUCCESS != doc.Parse(ss.str().c_str())) { - KGE_WARNING_LOG(L"ResourceCache::LoadFromXmlFile failed: %s (%s)", + KGE_WARN(L"ResourceCache::LoadFromXmlFile failed: %s (%s)", tinyxml2::XMLDocument::ErrorIDToName(doc.ErrorID()), doc.ErrorStr()); return false; } } catch (std::wifstream::failure& e) { - KGE_WARNING_LOG(L"ResourceCache::LoadFromXmlFile failed: Cannot open file. (%s)", string_to_wide(e.what()).c_str()); + KGE_WARN(L"ResourceCache::LoadFromXmlFile failed: Cannot open file. (%s)", oc::string_to_wide(e.what()).c_str()); return false; } @@ -183,7 +183,7 @@ namespace kiwano } catch (std::exception& e) { - KGE_WARNING_LOG(L"ResourceCache::LoadFromXml failed: %s", string_to_wide(e.what()).c_str()); + KGE_WARN(L"ResourceCache::LoadFromXml failed: %s", oc::string_to_wide(e.what()).c_str()); return false; } } @@ -363,6 +363,8 @@ namespace kiwano void ResourceCache::Clear() { object_cache_.clear(); + gif_cache_.clear(); + font_collection_cache_.clear(); } } diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h index ca113b8d..b02febee 100644 --- a/src/kiwano/utils/ResourceCache.h +++ b/src/kiwano/utils/ResourceCache.h @@ -30,7 +30,7 @@ namespace kiwano class KGE_API ResourceCache : public Singleton { - KGE_DECLARE_SINGLETON(ResourceCache); + OC_DECLARE_SINGLETON(ResourceCache); public: // ´Ó JSON Îļþ¼ÓÔØ×ÊÔ´ÐÅÏ¢ diff --git a/src/kiwano/utils/UserData.h b/src/kiwano/utils/UserData.h index 250f3388..67ac9a64 100644 --- a/src/kiwano/utils/UserData.h +++ b/src/kiwano/utils/UserData.h @@ -27,7 +27,7 @@ namespace kiwano class KGE_API UserData : public Singleton { - KGE_DECLARE_SINGLETON(UserData); + OC_DECLARE_SINGLETON(UserData); public: using DataMap = UnorderedMap; From 1c923ca76df776668011399cc3a776c5efe6fd14 Mon Sep 17 00:00:00 2001 From: Nomango Date: Fri, 20 Dec 2019 17:49:16 +0800 Subject: [PATCH 03/27] Update doxygen --- .gitignore | 4 +- Doxyfile | 86 +++++++++++++ logo/logo_square_tiny.png | Bin 0 -> 2461 bytes src/3rd-party/OuterC/oc/intrusive_list.h | 2 +- src/kiwano-audio/AudioEngine.h | 2 +- src/kiwano-imgui/ImGuiModule.h | 2 +- src/kiwano-network/HttpClient.h | 2 +- src/kiwano/core/Component.h | 50 +++++++- src/kiwano/core/Logger.h | 2 +- src/kiwano/core/keys.h | 156 ++++++++++++----------- src/kiwano/core/time.cpp | 35 ++--- src/kiwano/core/time.h | 127 ++++++++++++------ src/kiwano/platform/Application.cpp | 4 +- src/kiwano/platform/Application.h | 106 ++++++++++++--- src/kiwano/platform/Director.h | 60 +++++++-- src/kiwano/platform/FileSystem.h | 72 +++++++++-- src/kiwano/platform/Input.h | 48 ++++++- src/kiwano/platform/Window.h | 112 ++++++++++++---- src/kiwano/renderer/Renderer.h | 2 +- src/kiwano/renderer/TextureCache.h | 2 +- src/kiwano/utils/ResourceCache.h | 2 +- src/kiwano/utils/UserData.h | 2 +- 22 files changed, 643 insertions(+), 235 deletions(-) create mode 100644 Doxyfile create mode 100644 logo/logo_square_tiny.png diff --git a/.gitignore b/.gitignore index 17c3d9fa..e430d78f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,6 @@ packages/ !*.lib # Resources bin -*.aps \ No newline at end of file +*.aps + +docs/ \ No newline at end of file diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 00000000..68464f37 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,86 @@ +# Doxyfile 1.8.16 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +PROJECT_NAME = "Kiwano Engine" +PROJECT_NUMBER = v1.0.0 +PROJECT_BRIEF = +PROJECT_LOGO = logo/logo_square_tiny.png + +DOXYFILE_ENCODING = UTF-8 +CREATE_SUBDIRS = YES + +OUTPUT_LANGUAGE = Chinese +OUTPUT_DIRECTORY = docs/ + +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = NO + +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = NO + +SHOW_INCLUDE_FILES = YES +SHOW_USED_FILES = NO +SHOW_FILES = NO +SHOW_NAMESPACES = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +INPUT = src/ +INPUT_ENCODING = gb2312 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + +RECURSIVE = YES +EXCLUDE = src/3rd-party + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +PREDEFINED = KGE_API= + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. + +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +GENERATE_HTML = YES +HTML_OUTPUT = html + +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = + +GENERATE_TREEVIEW = YES +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# Configuration options related to the LATEX output +#--------------------------------------------------------------------------- + +GENERATE_LATEX = NO diff --git a/logo/logo_square_tiny.png b/logo/logo_square_tiny.png new file mode 100644 index 0000000000000000000000000000000000000000..63829ef397e206ea37bd8fc1e3a7012503e707cb GIT binary patch literal 2461 zcmV;O31aq%P)adJlu!vKDw={yDT20aFSP9Jtz~yR7ay7#DbViB(*FHR{66jM%$)gs z&pE%}`JUhJ24FtIPP>_MxKW)V#As_;Uf7*&gLP7keEm%zaNABN>o0^=w5RHi9 z_4~*$3=G4V^F2Wj5Coy7ckRG2IrD=)pN~)|H1D&TrZF})hG7`9NSN2n&CN)XG;bTl zVv$@f2QX(x%mqi}G)=?j^AQe*Q51y(2M*BJ*GD#+y=D{&g#yWBl4qWI23eM=R4UfJ zB}4yPGp-&M-MSi7d<4^lB!PVa=K~Y~Q{em&-MaoXh1x(=Mt1GmMIw=4XlMvowr94jr!-BYv9S@i+s*UOKTl_8Ck+h^ zEL*k=Ns_MX8-Bl^SZqf8=(;}Zo_QUM#h93wps}&>n)d}kz%UFZCMJ0O_18Iax6{+p!<%ou zNnKr?t>99XoX6u~a&nUH?rs8s0B*N?(MGEpQmGXC_wT2_zyG>^dNrz&3xz`b_~VcC z_xH1G*)nupx1!&pB-NUgXa||K!r8OTgd$S6^RG zI-Ta5Z@$6f@lD~Zf>Tot`1$-ktB&{aIfYDc$1w~8kHCE=RVoz>!(ivmojmf$Bb3W!rl+S-6op%ExrJ@pwsGHm_gTJT7r9)HyY9M+ zM<0EZ$;nA3Cno_=6a`gP*|u#PsZ`4P->wXE37C;xE|<$m zvs5Y-LZJ{IkB3sJWEn4tB2!aS1cN~u8X9J)99#A}dDxt4raHLZ)T?D-udA!0zrUY! zI!!nnM$-8cC0?$7CEHA(OGR@7+gu`Lt@i={b zeXLuzj?X^(j6@>gNWs_D)iE+M!k#^Q07xd2L?RKA$t0yxi8tPOgL1iSEBs#xM+=jw zBaa_Hjwp)c^La~94-O7;`0!y?tXM%f944R7+iq9aby`|lIC$_NTefUr=gyr3gF(i} z$Jx7gFF*Y71F2NXu_|&z&YW&{+;Im}Q&Vi(v|dh{su_4Qo3bO})uX=!PxN$%AoDNKcO{``4hhV+spO9%u4HET}uy?8v%^z<~U zsuGDrkY(BOLC1F1YKSCB*X+a>LQETmfh^0Gl)Difd&4;tlTa;^>v}ME0Vd4lrWVvZ zEsMn>qobo%$^d4j)QxP1WLYMg&63aOkt7LC(+G#d`2GHx{Ma!$S(X_e9|vIf?%lMv zx1;MiUw!oz`}gm+QV~udiXxRtg@J(qwr}6g#*G_M6oo(_z}~%k>Fw>MwYAkz{sd|u zS1cBhB#C|d_OW5Z2J8RF9(#;rGD$~Ahm~Hi3r*9IWf@75xcA*Zg%%MYv0EkAT=(>(!7{p>RE?&II;lqb*S(B9R~-kMqYLf3Rc6 z4h9DYt#pK4M59rD{`qIx+uJ#I>=;c=O~hg`B9RFD_U&Wcx^;|=jXCZ#Tha2$C?!b} zkw}EDt}afTIKhJtK1jJ-=Fp)-q|<3@w_FQ?!61Eoef0G7kj-WZ1OkkVjLb^6Uv1BP zutmqMi7LmBUm+{D2l?}ci+v*l`9z?9bGVi z>=c3^pePE7M1u9}*IPN8`B2r;QmKUB@8_wfo}y4FP^naER_Qm2!NEZ`ZQ8_bx7}t- ztyCo^2m%um6KvkRnH@WJaPs6yDwWFrYy{1s=E;*MdHCUndF7Q?C=?2|BBrf?a{2OQ zrlzKN_uY5Vb)C-6PJ+Q8(P*?LL2CzB*5^h>Mp(aoJ)NDMcsw54^*LMQBuTQ0gzvrg z9{1dH4_#ed3=9m+TUj-WidT=ac|ANl%+Sz~m2ABdX7FllZRNS=p5w(AU&Q5dIjXD* z>2x}e&4X>4rs4H^X>4pnQ53%Y_S>3j;%>JaRaN=uqmOLY#Pj()xm?c4p041CocVEB zn9~fANMtcjGdL%AJ^Y`ZLn$oCA)8urCJS+pW; + friend class intrusive_list<_Ty, _PTy>; }; diff --git a/src/kiwano-audio/AudioEngine.h b/src/kiwano-audio/AudioEngine.h index 9bb8e177..9d0fb384 100644 --- a/src/kiwano-audio/AudioEngine.h +++ b/src/kiwano-audio/AudioEngine.h @@ -33,7 +33,7 @@ namespace kiwano : public Singleton , public ComponentBase { - OC_DECLARE_SINGLETON(AudioEngine); + friend Singleton; public: // ¿ªÆôÉ豸 diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h index f5e3fffa..5ec0e712 100644 --- a/src/kiwano-imgui/ImGuiModule.h +++ b/src/kiwano-imgui/ImGuiModule.h @@ -32,7 +32,7 @@ namespace kiwano , public UpdateComponent , public EventComponent { - OC_DECLARE_SINGLETON(ImGuiModule); + friend Singleton; private: void Init(HWND hwnd); diff --git a/src/kiwano-network/HttpClient.h b/src/kiwano-network/HttpClient.h index 7008b212..17ccaf6a 100644 --- a/src/kiwano-network/HttpClient.h +++ b/src/kiwano-network/HttpClient.h @@ -32,7 +32,7 @@ namespace kiwano : public Singleton , public ComponentBase { - OC_DECLARE_SINGLETON(HttpClient); + friend Singleton; public: void Send(HttpRequestPtr request); diff --git a/src/kiwano/core/Component.h b/src/kiwano/core/Component.h index 9dde2529..577e541d 100644 --- a/src/kiwano/core/Component.h +++ b/src/kiwano/core/Component.h @@ -27,11 +27,19 @@ namespace kiwano class RenderTarget; class Event; - // »ù´¡×é¼þ + /** + * \~chinese + * @brief »ù´¡¹¦ÄÜ×é¼þ + */ class KGE_API ComponentBase { public: + /// \~chinese + /// @brief Æô¶¯×é¼þ virtual void SetupComponent() = 0; + + /// \~chinese + /// @brief Ïú»Ù×é¼þ virtual void DestroyComponent() = 0; bool Check(const int flag); @@ -44,15 +52,25 @@ namespace kiwano }; - // äÖȾ֧³Ö×é¼þ + /** + * \~chinese + * @brief äÖȾ֧³Ö×é¼þ + */ class KGE_API RenderComponent : public virtual ComponentBase { public: + /// \~chinese + /// @brief äÖȾǰ virtual void BeforeRender() {} - virtual void OnRender(RenderTarget*) {} + /// \~chinese + /// @brief äÖȾʱ + /// @param rt äÖȾĿ±ê + virtual void OnRender(RenderTarget* rt) {} + /// \~chinese + /// @brief äÖȾºó virtual void AfterRender() {} public: @@ -62,15 +80,25 @@ namespace kiwano }; - // ¸üÐÂÖ§³Ö×é¼þ + /** + * \~chinese + * @brief ¸üÐÂÖ§³Ö×é¼þ + */ class KGE_API UpdateComponent : public virtual ComponentBase { public: + /// \~chinese + /// @brief ¸üÐÂǰ virtual void BeforeUpdate() {} - virtual void OnUpdate(Duration) {} + /// \~chinese + /// @brief ¸üÐÂʱ + /// @param dt ¼ä¸ôʱ¼ä + virtual void OnUpdate(Duration dt) {} + /// \~chinese + /// @brief ¸üкó virtual void AfterUpdate() {} public: @@ -80,13 +108,21 @@ namespace kiwano }; - // ʼþÖ§³Ö×é¼þ + /** + * \~chinese + * @brief ʼþÖ§³Ö×é¼þ + */ class KGE_API EventComponent : public virtual ComponentBase { public: - virtual void HandleEvent(Event&) {} + /// \~chinese + /// @brief ʼþ´¦Àí + /// @param evt ʼþ + virtual void HandleEvent(Event& evt) {} + /// \~chinese + /// @brief Windows ÏûÏ¢´¦Àí virtual void HandleMessage(HWND, UINT32, WPARAM, LPARAM) {} public: diff --git a/src/kiwano/core/Logger.h b/src/kiwano/core/Logger.h index 60e224eb..71f75403 100644 --- a/src/kiwano/core/Logger.h +++ b/src/kiwano/core/Logger.h @@ -55,7 +55,7 @@ namespace kiwano class KGE_API Logger : public Singleton { - OC_DECLARE_SINGLETON(Logger); + friend Singleton; public: // ÏÔʾ»ò¹Ø±Õ¿ØÖÆÌ¨ diff --git a/src/kiwano/core/keys.h b/src/kiwano/core/keys.h index 4f2839dc..f259a0da 100644 --- a/src/kiwano/core/keys.h +++ b/src/kiwano/core/keys.h @@ -23,103 +23,105 @@ namespace kiwano { - // Êó±ê°´¼ü + /// \~chinese + /// @brief Êó±ê°´¼ü struct MouseButton { typedef int Value; enum : Value { - Left = VK_LBUTTON, // Êó±ê×ó¼ü - Right = VK_RBUTTON, // Êó±êÓÒ¼ü - Middle = VK_MBUTTON // Êó±êÖмü + Left = VK_LBUTTON, ///< Êó±ê×ó¼ü + Right = VK_RBUTTON, ///< Êó±êÓÒ¼ü + Middle = VK_MBUTTON ///< Êó±êÖмü }; }; - // °´¼ü¼üÖµ + /// \~chinese + /// @brief °´¼ü¼üÖµ struct KeyCode { typedef int Value; enum : Value { - Unknown = 0, - Up = VK_UP, - Left = VK_LEFT, - Right = VK_RIGHT, - Down = VK_DOWN, - Enter = VK_RETURN, - Space = VK_SPACE, - Esc = VK_ESCAPE, - Ctrl = VK_CONTROL, - Shift = VK_SHIFT, - Alt = VK_MENU, - Tab = VK_TAB, - Delete = VK_DELETE, - Back = VK_BACK, + Unknown = 0, ///< δ֪ + Up = VK_UP, ///< Éϼü + Left = VK_LEFT, ///< ×ó¼ü + Right = VK_RIGHT, ///< ÓÒ¼ü + Down = VK_DOWN, ///< ϼü + Enter = VK_RETURN, ///< »Ø³µ¼ü + Space = VK_SPACE, ///< ¿Õ¸ñ¼ü + Esc = VK_ESCAPE, ///< Í˳ö¼ü + Ctrl = VK_CONTROL, ///< CTRL¼ü + Shift = VK_SHIFT, ///< SHIFT¼ü + Alt = VK_MENU, ///< ALT¼ü + Tab = VK_TAB, ///< TAB¼ü + Delete = VK_DELETE, ///< ɾ³ý¼ü + Back = VK_BACK, ///< Í˸ñ¼ü - A = 0x41, - B, - C, - D, - E, - F, - G, - H, - I, - J, - K, - L, - M, - N, - O, - P, - Q, - R, - S, - T, - U, - V, - W, - X, - Y, - Z, + A = 0x41, ///< A¼ü + B, ///< B¼ü + C, ///< C¼ü + D, ///< D¼ü + E, ///< E¼ü + F, ///< F¼ü + G, ///< G¼ü + H, ///< H¼ü + I, ///< I¼ü + J, ///< J¼ü + K, ///< K¼ü + L, ///< L¼ü + M, ///< M¼ü + N, ///< N¼ü + O, ///< O¼ü + P, ///< P¼ü + Q, ///< Q¼ü + R, ///< R¼ü + S, ///< S¼ü + T, ///< T¼ü + U, ///< U¼ü + V, ///< V¼ü + W, ///< W¼ü + X, ///< X¼ü + Y, ///< Y¼ü + Z, ///< Z¼ü - Num0 = 0x30, - Num1, - Num2, - Num3, - Num4, - Num5, - Num6, - Num7, - Num8, - Num9, + Num0 = 0x30, ///< Êý×Ö0¼ü + Num1, ///< Êý×Ö1¼ü + Num2, ///< Êý×Ö2¼ü + Num3, ///< Êý×Ö3¼ü + Num4, ///< Êý×Ö4¼ü + Num5, ///< Êý×Ö5¼ü + Num6, ///< Êý×Ö6¼ü + Num7, ///< Êý×Ö7¼ü + Num8, ///< Êý×Ö8¼ü + Num9, ///< Êý×Ö9¼ü - Numpad0 = VK_NUMPAD0, - Numpad1, - Numpad2, - Numpad3, - Numpad4, - Numpad5, - Numpad6, - Numpad7, - Numpad8, - Numpad9, + Numpad0 = VK_NUMPAD0, ///< Êý×ÖС¼üÅÌ0¼ü + Numpad1, ///< Êý×ÖС¼üÅÌ1¼ü + Numpad2, ///< Êý×ÖС¼üÅÌ2¼ü + Numpad3, ///< Êý×ÖС¼üÅÌ3¼ü + Numpad4, ///< Êý×ÖС¼üÅÌ4¼ü + Numpad5, ///< Êý×ÖС¼üÅÌ5¼ü + Numpad6, ///< Êý×ÖС¼üÅÌ6¼ü + Numpad7, ///< Êý×ÖС¼üÅÌ7¼ü + Numpad8, ///< Êý×ÖС¼üÅÌ8¼ü + Numpad9, ///< Êý×ÖС¼üÅÌ9¼ü - F1 = VK_F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, + F1 = VK_F1, ///< F1¼ü + F2, ///< F2¼ü + F3, ///< F3¼ü + F4, ///< F4¼ü + F5, ///< F5¼ü + F6, ///< F6¼ü + F7, ///< F7¼ü + F8, ///< F8¼ü + F9, ///< F9¼ü + F10, ///< F10¼ü + F11, ///< F11¼ü + F12, ///< F12¼ü }; }; } diff --git a/src/kiwano/core/time.cpp b/src/kiwano/core/time.cpp index ccdeb49f..b12bde7b 100644 --- a/src/kiwano/core/time.cpp +++ b/src/kiwano/core/time.cpp @@ -354,25 +354,24 @@ namespace kiwano return dur * val; } - Duration Duration::Parse(const String& str) + Duration Duration::Parse(const String& format) { - bool negative = false; - size_t len = str.length(); - size_t pos = 0; - Duration ret; + bool negative = false; + size_t len = format.length(); + size_t pos = 0; + Duration ret; - if (!std::regex_match(str.c_str(), duration_regex)) + if (!std::regex_match(format.c_str(), duration_regex)) { - KGE_ERROR(L"Duration::Parse failed, invalid duration"); - return ret; + throw std::runtime_error("Duration::Parse failed, invalid duration"); } - if (str.empty() || str == L"0") { return ret; } + if (format.empty() || format == L"0") { return ret; } // ·ûºÅλ - if (str[0] == L'-' || str[0] == L'+') + if (format[0] == L'-' || format[0] == L'+') { - negative = (str[0] == L'-'); + negative = (format[0] == L'-'); pos++; } @@ -382,32 +381,34 @@ namespace kiwano size_t i = pos; for (; i < len; ++i) { - wchar_t ch = str[i]; + wchar_t ch = format[i]; if (!(ch == L'.' || L'0' <= ch && ch <= L'9')) { break; } } - String num_str = str.substr(pos, i - pos); + String num_str = format.substr(pos, i - pos); pos = i; - KGE_ASSERT(!(num_str.empty() || num_str == L".") && "Duration::Parse failed, invalid duration"); + if (num_str.empty() || num_str == L".") + throw std::runtime_error("Duration::Parse failed, invalid duration"); // µ¥Î» for (; i < len; ++i) { - wchar_t ch = str[i]; + wchar_t ch = format[i]; if (ch == L'.' || L'0' <= ch && ch <= L'9') { break; } } - String unit_str = str.substr(pos, i - pos); + String unit_str = format.substr(pos, i - pos); pos = i; - KGE_ASSERT(unit_map.find(unit_str) != unit_map.end() && "Duration::Parse failed, invalid duration"); + if (unit_map.find(unit_str) == unit_map.end()) + throw std::runtime_error("Duration::Parse failed, invalid duration"); double num = std::wcstod(num_str.c_str(), nullptr); Duration unit = unit_map.at(unit_str); diff --git a/src/kiwano/core/time.h b/src/kiwano/core/time.h index f6c47257..2e06bd74 100644 --- a/src/kiwano/core/time.h +++ b/src/kiwano/core/time.h @@ -24,51 +24,98 @@ namespace kiwano { - // ʱ¼ä¶Î - // - // ʱ¼ä¶Î±íʾ·¨: - // 5 Ãë: time::Second * 5 - // 1.5 Сʱ: time::Hour * 1.5 - // 3 Сʱ 45 ·Ö 15 Ãë: time::Hour * 3 + time::Minute * 45 + time::Second * 15 - // ÔÚ VS2015 ¼°¸ü¸ß°æ±¾¿ÉÒÔʹÓà time literals: - // 5 Ãë: 5_s - // 1.5 Сʱ: 1.5_h - // 3 Сʱ 45 ·Ö 15 Ãë: 3_h + 45_m + 15_s - // + /** + * \~chinese + * @brief ʱ¼ä¶Î + * @details + * ʱ¼ä¶Î±íʾ·¨: + * 5 Ãë: time::Second * 5 + * 1.5 Сʱ: time::Hour * 1.5 + * 3 Сʱ 45 ·Ö 15 Ãë: time::Hour * 3 + time::Minute * 45 + time::Second * 15 + * ÔÚ VS2015 ¼°¸ü¸ß°æ±¾¿ÉÒÔʹÓà time literals: + * 5 Ãë: 5_s + * 1.5 Сʱ: 1.5_h + * 3 Сʱ 45 ·Ö 15 Ãë: 3_h + 45_m + 15_s + */ struct KGE_API Duration { + /// \~chinese + /// @brief ¹¹Ôìʱ¼ä¶Î Duration(); + /// \~chinese + /// @brief ¹¹Ôìʱ¼ä¶Î + /// @param milliseconds ºÁÃëÊý Duration( long milliseconds ); - // ת»¯ÎªºÁÃë + /// \~chinese + /// @brief »ñÈ¡ºÁÃëÊý + /// @return ºÁÃëÊý long Milliseconds() const; - // ת»¯ÎªÃë + /// \~chinese + /// @brief »ñÈ¡ÃëÊý + /// @return ÃëÊý float Seconds() const; - // ת»¯Îª·ÖÖÓ + /// \~chinese + /// @brief »ñÈ¡·ÖÖÓÊý + /// @return ·ÖÖÓÊý float Minutes() const; - // ת»¯ÎªÐ¡Ê± + /// \~chinese + /// @brief »ñȡСʱÊý + /// @return СʱÊý float Hours() const; - // ʱ³¤ÊÇ·ñÊÇÁã + /// \~chinese + /// @brief ʱ³¤ÊÇ·ñÊÇÁã + /// @return Èôʱ³¤ÊÇÁ㣬·µ»Øtrue bool IsZero() const; + /// \~chinese + /// @brief ÉèÖúÁÃëÊý + /// @param ms ºÁÃëÊý void SetMilliseconds(long ms); + /// \~chinese + /// @brief ÉèÖÃÃëÊý + /// @param seconds ÃëÊý void SetSeconds(float seconds); + /// \~chinese + /// @brief ÉèÖ÷ÖÖÓÊý + /// @param minutes ·ÖÖÓÊý void SetMinutes(float minutes); + /// \~chinese + /// @brief ÉèÖÃСʱÊý + /// @param hours СʱÊý void SetHours(float hours); - // תΪ×Ö·û´® + /// \~chinese + /// @brief תΪ×Ö·û´® + /// @return ¸ñʽ»¯ºóµÄ×Ö·û´® String ToString() const; + /// \~chinese + /// @brief ʱ¼ä¶Î¸ñʽ»¯ + /// @param format ¸ñʽ + /// @details + /// ʱ¼ä¶Î×Ö·û´®ÔÊÐíÊÇÓзûºÅµÄ¸¡µãÊý, ²¢ÇÒ´øÓÐʱ¼äµ¥Î»ºó׺ + /// ÀýÈç: "300ms", "-1.5h", "2h45m" + /// ÔÊÐíµÄʱ¼äµ¥Î»ÓÐ "ms", "s", "m", "h" + /// @return ½âÎö³öµÄʱ¼ä¶Î + /// @throw std::runtime_error ´«ÈëÁËÒ»¸ö²»ºÏ·¨µÄ¸ñʽ + static Duration Parse(const String& str); + + static const Duration Ms; ///< ºÁÃë + static const Duration Second; ///< Ãë + static const Duration Minute; ///< ·ÖÖÓ + static const Duration Hour; ///< Сʱ + bool operator== (const Duration &) const; bool operator!= (const Duration &) const; bool operator> (const Duration &) const; @@ -107,37 +154,38 @@ namespace kiwano friend const Duration operator/ (float, const Duration &); friend const Duration operator/ (double, const Duration &); - // ʱ¼ä¶Î¸ñʽ»¯ - // - // ʱ¼ä¶Î×Ö·û´®ÔÊÐíÊÇÓзûºÅµÄ¸¡µãÊý, ²¢ÇÒ´øÓÐʱ¼äµ¥Î»ºó׺ - // ÀýÈç: "300ms", "-1.5h", "2h45m" - // ÔÊÐíµÄʱ¼äµ¥Î»ÓÐ "ms", "s", "m", "h" - static Duration Parse(const String& parse_str); - - static const Duration Ms; // ºÁÃë - static const Duration Second; // Ãë - static const Duration Minute; // ·ÖÖÓ - static const Duration Hour; // Сʱ - private: long milliseconds_; }; - // ʱ¼ä - // - // »ñÈ¡µ±Ç°Ê±¼ä: Time now = Time::Now(); - // Á½Ê±¼äÏà¼õ, µÃµ½Ò»¸ö Duration ¶ÔÏó, ÀýÈç: - // Time t1, t2; - // int ms = (t2 - t1).Milliseconds(); // »ñÈ¡Á½Ê±¼äÏà²îµÄºÁÃëÊý - // + /** + * \~chinese + * @brief ʱ¼ä + * @par ʾÀý£º + * @code + * // Á½Ê±¼äÏà¼õ, ¿ÉµÃµ½Ò»¸ö Duration ¶ÔÏó + * Time t1 = Time::Now(); + * // µÈ´ýÒ»¶Îʱ¼äºó + * Time t2 = Time::Now(); + * int ms = (t2 - t1).Milliseconds(); // »ñÈ¡Á½Ê±¼äÏà²îµÄºÁÃëÊý + * @endcode + * @note ʱ¼äµãÓëϵͳʱÖÓÎ޹أ¬Òò´Ë²»Äܽ«Ê±¼äµãת»¯ÎªÊ±·ÖÃë + */ struct KGE_API Time { Time(); - // ÊÇ·ñÊÇÁãʱ + /// \~chinese + /// @brief ÊÇ·ñÊÇÁãʱ + /// @return ÈôÊÇÁãʱ£¬·µ»Øtrue bool IsZero() const; + /// \~chinese + /// @brief »ñÈ¡µ±Ç°Ê±¼ä + /// @return µ±Ç°Ê±¼ä + static Time Now() noexcept; + const Duration operator -(const Time&) const; const Time operator +(const Duration &) const; @@ -146,11 +194,6 @@ namespace kiwano Time& operator +=(const Duration &); Time& operator -=(const Duration &); - // »ñÈ¡µ±Ç°Ê±¼ä - // ÓÉÓÚ¸Ãʱ¼äµã»ùÓÚϵͳÆô¶¯Ê±¼ä¿ªÊ¼¼ÆËã, ËùÒÔÎÞ·¨¸ñʽ»¯¸Ãʱ¼ä, - // Ò²ÎÞ·¨»ñµÃ¸Ãʱ¼äµÄ Unix ʱ¼ä´Á - static Time Now() noexcept; - private: Time(long ms); diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 62733d9f..3cd8c03c 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -262,10 +262,10 @@ namespace kiwano } } - void Application::PreformInMainThread(Function Function) + void Application::PreformInMainThread(Function func) { std::lock_guard lock(perform_mutex_); - functions_to_perform_.push(Function); + functions_to_perform_.push(func); } LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h index 7f6053ae..7c8efbc8 100644 --- a/src/kiwano/platform/Application.h +++ b/src/kiwano/platform/Application.h @@ -28,19 +28,36 @@ namespace kiwano { + /** + * \~chinese + * @brief Ó¦ÓóÌÐòÅäÖà + * @details Æô¶¯ Kiwano Ó¦ÓóÌÐòǰµÄ³õʼ»¯Ñ¡Ïî + */ struct Config { - WindowConfig window; // ´°¿ÚÉèÖà - RenderConfig render; // äÖȾÉèÖà - bool debug; // µ÷ÊÔģʽ + WindowConfig window; ///< ´°¿ÚÅäÖà + RenderConfig render; ///< äÖȾÅäÖà + bool debug; ///< ÆôÓõ÷ÊÔģʽ + /** + * \~chinese + * @param title ´°¿Ú±êÌâ + * @param width ´°¿Ú¿í¶È + * @param height ´°¿Ú¸ß¶È + * @param icon ´°¿Úͼ±êµÄ×ÊÔ´ID + */ Config( - String const& title = L"Kiwano Game", + String const& title = L"Kiwano Game", uint32_t width = 640, - uint32_t height = 480, + uint32_t height = 480, uint32_t icon = 0 ); + /** + * \~chinese + * @param wnd_config ´°¿ÚÅäÖà + * @param render_config äÖȾÅäÖà + */ Config( WindowConfig const& wnd_config, RenderConfig const& render_config = RenderConfig() @@ -48,7 +65,10 @@ namespace kiwano }; - // Ó¦Óà + /** + * \~chinese + * @brief Ó¦ÓóÌÐò£¬¿ØÖÆÓÎÏ·µÄÕû¸öÉúÃüÖÜÆÚ£¬°üÀ¨³õʼ»¯¡¢Æô¶¯¡¢½áÊøÒÔ¼°Ê¼þ·Ö·¢µÈ + */ class KGE_API Application : protected Noncopyable { @@ -57,46 +77,94 @@ namespace kiwano virtual ~Application(); - // ³õʼ»¯ + /** + * \~chinese + * @brief ³õʼ»¯Ó¦ÓóÌÐò + * @details ³õʼ»¯ËùÓй¦ÄÜ×é¼þºóÖ´ÐÐ OnReady º¯Êý + * @param config ³õʼ»¯ÅäÖà + * @attention Ó¦ÔÚʹÓÃÆäËû¹¦ÄÜǰִÐгõʼ»¯£¬·ñÔò¿ÉÄÜÒý·¢Òì³£ + */ void Init( Config const& config = Config() ); - // ³õʼ»¯³É¹¦Ê± + /** + * \~chinese + * @brief ³õʼ»¯Íê³É´¦Àí + * @details ÖØÔØ¸Ãº¯ÊýÒÔÔÚÓ¦ÓóÌÐò³õʼ»¯Íê³Éºó×Ô¶¯Ö´ÐÐ + */ virtual void OnReady() {} - // ´°¿Ú¹Ø±Õʱ + /** + * \~chinese + * @brief ´°¿Ú¹Ø±Õ´¦Àí + * @details ÖØÔØ¸Ãº¯ÊýÒÔ´¦ÀíÓû§¹Ø±ÕÓ¦ÓóÌÐò´°¿ÚʱµÄÐÐΪ + * @return ·µ»Ø true ÔòÕý³£¹Ø±Õ´°¿Ú£¬·ñÔò×èÖ¹´°¿Ú¹Ø±Õ + */ virtual bool OnClosing() { return true; } - // Ïú»Ùʱ + /** + * \~chinese + * @brief Ó¦ÓóÌÐòÏú»Ù´¦Àí + * @details ÖØÔØ¸Ãº¯ÊýÒÔ´¦ÀíÓ¦ÓóÌÐòÏú»ÙʱµÄÐÐΪ£¬ÈçÍê³É×ÊÔ´»ØÊÕµÈ + */ virtual void OnDestroy() {} - // ÔËÐÐ + /** + * \~chinese + * @brief Æô¶¯Ó¦ÓóÌÐò + * @note ¸Ãº¯ÊýÊÇ×èÈûµÄ£¬Ó¦ÓóÌÐò½áÊøÊ±º¯Êý·µ»Ø + */ void Run(); - // ½áÊø + /** + * \~chinese + * @brief ÖÕÖ¹Ó¦ÓóÌÐò + */ void Quit(); - // Ïú»Ù + /** + * \~chinese + * @brief Ïú»ÙÓÎÏ·ÔËÐйý³ÌÖвúÉúµÄËùÓÐ×ÊÔ´ + */ void Destroy(); - // Ìí¼Ó×é¼þ + /** + * \~chinese + * @brief Ìí¼Ó¹¦ÄÜ×é¼þ + * @param[in] component ¹¦ÄÜ×é¼þ + */ void Use( ComponentBase* component ); - // ÉèÖÃʱ¼äËõ·ÅÒò×Ó + /** + * \~chinese + * @brief ÉèÖÃʱ¼äËõ·ÅÒò×Ó + * @details ÉèÖÃʱ¼äËõ·ÅÒò×ӿɵȱÈÀý·Å´ó»òËõСʱ¼ä½ø¶È + * @param scale_factor Ëõ·ÅÒò×Ó + * @warning ÉèÖÃΪ¸ºÊý¿ÉÄܵ¼Ö¶¯»­ÏµÍ³ÎÉÂÒ + */ void SetTimeScale( float scale_factor ); - // ·Ö·¢Ê¼þ + /** + * \~chinese + * @brief ·Ö·¢Ê¼þ + * @details ½«Ê¼þ·Ö·¢¸øËùÓÐʼþ¹¦ÄÜ×é¼þ + * @param evt ʼþ + */ void DispatchEvent(Event& evt); - // ÔÚ Kiwano Ö÷Ïß³ÌÖÐÖ´Ðк¯Êý - // µ±ÔÚÆäËûÏ̵߳÷Óà Kiwano º¯ÊýʱʹÓà + /** + * \~chinese + * @brief ÔÚÖ÷Ïß³ÌÖÐÖ´Ðк¯Êý + * @details ÌṩÔÚÆäËûÏ̵߳÷Óà Kiwano º¯ÊýµÄÄÜÁ¦ + * @param func ÐèÒªÖ´Ðеĺ¯Êý + */ static void PreformInMainThread( - Function Function + Function func ); protected: diff --git a/src/kiwano/platform/Director.h b/src/kiwano/platform/Director.h index 4cd606b5..7c63666b 100644 --- a/src/kiwano/platform/Director.h +++ b/src/kiwano/platform/Director.h @@ -24,43 +24,75 @@ namespace kiwano { - // µ¼ÑÝ + /** + * \~chinese + * @brief µ¼ÑÝÍê³É³¡¾°µÄäÖȾ¡¢¸üС¢Ê¼þ·Ö·¢ÒÔ¼°¿ØÖƳ¡¾°¼äÌø×ª + */ class KGE_API Director : public Singleton , public UpdateComponent , public RenderComponent , public EventComponent { - OC_DECLARE_SINGLETON(Director); + friend Singleton; public: - // Çл»Îę̀ + /** + * \~chinese + * @brief Çл»Îę̀ + * @param[in] stage Îę̀ + * @param[in] transition ¹ý¶É¶¯»­ + */ void EnterStage( - StagePtr stage, /* Îę̀ */ - TransitionPtr transition = nullptr /* ¹ý¶É¶¯»­ */ + StagePtr stage, + TransitionPtr transition = nullptr ); - // Îę̀ѹջ + /** + * \~chinese + * @brief Çл»Îę̀£¬²¢½«µ±Ç°Îę̀ѹջ + * @param[in] stage Îę̀ + * @param[in] transition ¹ý¶É¶¯»­ + */ void PushStage( - StagePtr stage, /* Îę̀ */ - TransitionPtr transition = nullptr /* ¹ý¶É¶¯»­ */ + StagePtr stage, + TransitionPtr transition = nullptr ); - // Îę̀³öÕ» + /** + * \~chinese + * @brief Í˳öµ±Ç°Îę̀£¬²¢Çл»µ½Õ»¶¥Îę̀ + * @param[in] transition ¹ý¶É¶¯»­ + */ void PopStage( - TransitionPtr transition = nullptr /* ¹ý¶É¶¯»­ */ + TransitionPtr transition = nullptr ); - // »ñÈ¡µ±Ç°Îę̀ + /** + * \~chinese + * @brief »ñÈ¡µ±Ç°Îę̀ + * @return ·µ»Øµ±Ç°Îę̀µÄÖ¸Õë + */ StagePtr GetCurrentStage(); - // ÆôÓûò½ûÓýÇÉ«±ß½çäÖȾ¹¦ÄÜ + /** + * \~chinese + * @brief ÆôÓûò½ûÓýÇÉ«±ß½çäÖȾ¹¦ÄÜ + * @param enabled ÊÇ·ñÆôÓà + */ void SetRenderBorderEnabled(bool enabled); - // ÏÔʾµ÷ÊÔÐÅÏ¢ + /** + * \~chinese + * @brief ÏÔʾ»òÒþ²Øµ÷ÊÔÐÅÏ¢ + * @param show ÊÇ·ñÏÔʾ + */ void ShowDebugInfo(bool show = true); - // Çå¿ÕÎę̀ + /** + * \~chinese + * @brief Í˳öµ±Ç°Îę̀²¢Çå¿ÕÎę̀ջ + */ void ClearStages(); public: diff --git a/src/kiwano/platform/FileSystem.h b/src/kiwano/platform/FileSystem.h index 9af781ad..7ac2089c 100644 --- a/src/kiwano/platform/FileSystem.h +++ b/src/kiwano/platform/FileSystem.h @@ -23,41 +23,87 @@ namespace kiwano { - // Îļþ + /** + * \~chinese + * @brief Îļþϵͳ£¬ÎªÆäËûÄ£¿éÌṩÎļþËÑË÷¹æÔòµÈ + */ class KGE_API FileSystem : public Singleton { - OC_DECLARE_SINGLETON(FileSystem); + friend Singleton; public: - // Ìí¼ÓÎļþËÑË÷·¾¶ + /** + * \~chinese + * @brief Ìí¼ÓÎļþËÑË÷·¾¶ + * @param path ÎļþËÑË÷·¾¶ + */ void AddSearchPath(String const& path); - // ÉèÖÃÎļþËÑË÷·¾¶ + /** + * \~chinese + * @brief ÉèÖÃÎļþËÑË÷·¾¶ + * @param paths ËÑË÷·¾¶Êý×é + */ void SetSearchPaths(Vector const& paths); - // »ñÈ¡ÎļþµÄÍêÕû·¾¶ + /** + * \~chinese + * @brief ÔÚËÑË÷ÁбíÖвéÕÒÎļþ²¢»ñÈ¡ÍêÕû·¾¶ + * @param file Îļþ·¾¶ + * @return ÍêÕûµÄÎļþ·¾¶ + */ String GetFullPathForFile(String const& file) const; - // Ìí¼ÓÎļþ·¾¶²éÕÒ×ֵ乿Ôò + /** + * \~chinese + * @brief Ìí¼ÓÎļþ·¾¶²éÕÒ×ֵ乿Ôò + * @param key Îļþ¹Ø¼ü´Ê + * @param file_path Îļþ·¾¶ + */ void AddFileLookupRule(String const& key, String const& file_path); - // ÉèÖÃÎļþ·¾¶²éÕÒ×Öµä + /** + * \~chinese + * @brief ÉèÖÃÎļþ·¾¶²éÕÒ×Öµä + * @param dict Îļþ·¾¶²éÕÒ×Öµä + */ void SetFileLookupDictionary(UnorderedMap const& dict); - // ÎļþÊÇ·ñ´æÔÚ + /** + * \~chinese + * @brief ÎļþÊÇ·ñ´æÔÚ + * @param file_path Îļþ·¾¶ + * @return ÈôÎļþ´æÔÚ£¬·µ»Ø true + */ bool IsFileExists(String const& file_path) const; - // ÅжÏ·¾¶ÊÇ·ñÊǾø¶Ô·¾¶ + /** + * \~chinese + * @brief ÅжÏ·¾¶ÊÇ·ñÊǾø¶Ô·¾¶ + * @param path Îļþ·¾¶ + * @return ÈôÊǾø¶Ô·¾¶£¬·µ»Ø true + */ bool IsAbsolutePath(String const& path) const; - // ɾ³ýÎļþ + /** + * \~chinese + * @brief ɾ³ýÎļþ + * @param path Îļþ·¾¶ + * @return ɾ³ýÊÇ·ñ³É¹¦ + */ bool RemoveFile(String const& file_path) const; - // ÊͷŶþ½øÖÆ×ÊÔ´µ½ÁÙʱÎļþĿ¼ + /** + * \~chinese + * @brief ÊͷŶþ½øÖÆ×ÊÔ´µ½ÁÙʱÎļþĿ¼ + * @param res ×ÊÔ´ + * @param dest_file_name Ä¿±êÎļþÃû + * @return ²Ù×÷ÊÇ·ñ³É¹¦ + */ bool ExtractResourceToFile( - Resource const& res, /* ×ÊÔ´ */ - String const& dest_file_name /* Ä¿±êÎļþÃû */ + Resource const& res, + String const& dest_file_name ) const; private: diff --git a/src/kiwano/platform/Input.h b/src/kiwano/platform/Input.h index 01e4197f..cc072cc1 100644 --- a/src/kiwano/platform/Input.h +++ b/src/kiwano/platform/Input.h @@ -27,36 +27,70 @@ namespace kiwano { + /** + * \~chinese + * @brief ÊäÈëÉ豸ʵÀý£¬¿É»ñÈ¡Êó±êºÍ¼üÅ̵İ´¼ü״̬ + */ class KGE_API Input : public Singleton , public UpdateComponent , public EventComponent { - OC_DECLARE_SINGLETON(Input); + friend Singleton; public: - // ¼ì²â¼üÅÌ»òÊó±ê°´¼üÊÇ·ñÕý±»°´Ï + /** + * \~chinese + * @brief ¼ì²â¼üÅÌ»òÊó±ê°´¼üÊÇ·ñÕý±»°´Ï + * @param key_or_btn ¼üÖµ + * @return ÊÇ·ñÕý±»°´Ï + * @see kiwano::KeyCode kiwano::MouseButton + */ bool IsDown( int key_or_btn ); - // ¼ì²â¼üÅÌ»òÊó±ê°´¼üÊÇ·ñ¸Õ±»µã»÷ + /** + * \~chinese + * @brief ¼ì²â¼üÅÌ»òÊó±ê°´¼üÊÇ·ñ¸Õ±»µã»÷ + * @param key_or_btn ¼üÖµ + * @return ÊÇ·ñ¸Õ±»µã»÷ + * @see kiwano::KeyCode kiwano::MouseButton + */ bool WasPressed( int key_or_btn ); - // ¼ì²â¼üÅÌ»òÊó±ê°´¼üÊÇ·ñ¸Õ̧Æð + /** + * \~chinese + * @brief ¼ì²â¼üÅÌ»òÊó±ê°´¼üÊÇ·ñ¸Õ̧Æð + * @param key_or_btn ¼üÖµ + * @return ÊÇ·ñ¸Õ̧Æð + * @see kiwano::KeyCode kiwano::MouseButton + */ bool WasReleased( int key_or_btn ); - // »ñµÃÊó±ê x ×ø±ê + /** + * \~chinese + * @brief »ñµÃÊó±ê x ×ø±ê + * @return Êó±ê x ×ø±ê + */ float GetMouseX(); - // »ñµÃÊó±ê y ×ø±ê + /** + * \~chinese + * @brief »ñµÃÊó±ê y ×ø±ê + * @return Êó±ê y ×ø±ê + */ float GetMouseY(); - // »ñµÃÊó±ê×ø±ê + /** + * \~chinese + * @brief »ñµÃÊó±ê×ø±ê + * @return Êó±ê×ø±ê + */ Point GetMousePos(); public: diff --git a/src/kiwano/platform/Window.h b/src/kiwano/platform/Window.h index 14798536..51dba59d 100644 --- a/src/kiwano/platform/Window.h +++ b/src/kiwano/platform/Window.h @@ -25,29 +25,45 @@ namespace kiwano { - // Êó±êÖ¸ÕëÀàÐÍ + /** + * \~chinese + * @brief Êó±êÖ¸ÕëÀàÐÍ + */ enum class CursorType { - Arrow, /* Ö¸Õë */ - TextInput, /* Îı¾ */ - Hand, /* ÊÖÖ¸ */ - SizeAll, - SizeNESW, - SizeNS, - SizeNWSE, - SizeWE, + Arrow, ///< Ö¸Õë + TextInput, ///< Îı¾ + Hand, ///< ÊÖ + SizeAll, ///< Ö¸ÏòËĸö·½ÏòµÄ¼ýÍ· + SizeWE, ///< Ö¸Ïò×óÓÒ·½ÏòµÄ¼ýÍ· + SizeNS, ///< Ö¸ÏòÉÏÏ·½ÏòµÄ¼ýÍ· + SizeNESW, ///< Ö¸Ïò×óϵ½ÓÒÉÏ·½ÏòµÄ¼ýÍ· + SizeNWSE, ///< Ö¸Ïò×óÉϵ½ÓÒÏ·½ÏòµÄ¼ýÍ· }; - // ´°¿ÚÉèÖà + /** + * \~chinese + * @brief ´°¿ÚÉèÖà + */ struct WindowConfig { - String title; // ±êÌâ - uint32_t width; // ¿í¶È - uint32_t height; // ¸ß¶È - uint32_t icon; // ͼ±ê×ÊÔ´ ID - bool resizable; // ´°¿Ú´óС¿ÉÀ­Éì - bool fullscreen; // È«ÆÁģʽ + String title; ///< ±êÌâ + uint32_t width; ///< ¿í¶È + uint32_t height; ///< ¸ß¶È + uint32_t icon; ///< ͼ±ê×ÊÔ´ ID + bool resizable; ///< ´°¿Ú´óС¿ÉÀ­Éì + bool fullscreen; ///< È«ÆÁģʽ + /** + * \~chinese + * @brief ¹¹½¨´°¿ÚÉèÖà + * @param title ±êÌâ + * @param width ¿í¶È + * @param height ¸ß¶È + * @param icon ͼ±ê×ÊÔ´ID + * @param resizable ´°¿Ú´óС¿ÉÀ­Éì + * @param fullscreen È«ÆÁģʽ + */ WindowConfig( String const& title = L"Kiwano Game", uint32_t width = 640, @@ -59,38 +75,80 @@ namespace kiwano }; - // ´°¿Ú + /** + * \~chinese + * @brief ´°¿ÚʵÀý£¬¿ØÖÆ´°¿Ú±êÌâ¡¢´óС¡¢Í¼±êµÈ + */ class KGE_API Window : public Singleton { - OC_DECLARE_SINGLETON(Window); + friend Singleton; public: - // »ñÈ¡±êÌâ + /** + * \~chinese + * @brief »ñÈ¡´°¿Ú±êÌâ + * @return ´°¿Ú±êÌâ + */ String GetTitle() const; - // »ñÈ¡´°¿Ú´óС + /** + * \~chinese + * @brief »ñÈ¡´°¿Ú´óС + * @return ´°¿Ú´óС + */ Size GetSize() const; - // »ñÈ¡´°¿Ú¿í¶È + /** + * \~chinese + * @brief »ñÈ¡´°¿Ú¿í¶È + * @return ´°¿Ú¿í¶È + */ float GetWidth() const; - // »ñÈ¡´°¿Ú¸ß¶È + /** + * \~chinese + * @brief »ñÈ¡´°¿Ú¸ß¶È + * @return ´°¿Ú¸ß¶È + */ float GetHeight() const; - // ÉèÖñêÌâ + /** + * \~chinese + * @brief ÉèÖñêÌâ + * @param title ±êÌâ + */ void SetTitle(String const& title); - // ÉèÖô°¿Úͼ±ê + /** + * \~chinese + * @brief ÉèÖô°¿Úͼ±ê + * @param icon_resource ͼ±ê×ÊÔ´ID + */ void SetIcon(uint32_t icon_resource); - // ÖØÉè´°¿Ú´óС + /** + * \~chinese + * @brief ÖØÉè´°¿Ú´óС + * @param width ´°¿Ú¿í¶È + * @param height ´°¿Ú¸ß¶È + */ void Resize(int width, int height); - // ÉèÖÃÈ«ÆÁģʽ + /** + * \~chinese + * @brief ÉèÖÃÈ«ÆÁģʽ + * @param fullscreen ÊÇ·ñÈ«ÆÁ + * @param width ´°¿Ú¿í¶È + * @param height ´°¿Ú¸ß¶È + */ void SetFullscreen(bool fullscreen, int width, int height); - // ÉèÖÃÊó±êÖ¸ÕëÀàÐÍ + /** + * \~chinese + * @brief ÉèÖÃÊó±êÖ¸ÕëÀàÐÍ + * @param cursor Êó±êÖ¸ÕëÀàÐÍ + */ void SetCursor(CursorType cursor); public: diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index f3a2be25..bab77019 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -59,7 +59,7 @@ namespace kiwano , public EventComponent , public RenderTarget { - OC_DECLARE_SINGLETON(Renderer); + friend Singleton; public: // ÉèÖÃÇåÆÁÑÕÉ« diff --git a/src/kiwano/renderer/TextureCache.h b/src/kiwano/renderer/TextureCache.h index e8c19dd7..990557b5 100644 --- a/src/kiwano/renderer/TextureCache.h +++ b/src/kiwano/renderer/TextureCache.h @@ -27,7 +27,7 @@ namespace kiwano class KGE_API TextureCache : public Singleton { - OC_DECLARE_SINGLETON(TextureCache); + friend Singleton; public: Texture AddOrGetTexture(String const& file_path); diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h index b02febee..7055116e 100644 --- a/src/kiwano/utils/ResourceCache.h +++ b/src/kiwano/utils/ResourceCache.h @@ -30,7 +30,7 @@ namespace kiwano class KGE_API ResourceCache : public Singleton { - OC_DECLARE_SINGLETON(ResourceCache); + friend Singleton; public: // ´Ó JSON Îļþ¼ÓÔØ×ÊÔ´ÐÅÏ¢ diff --git a/src/kiwano/utils/UserData.h b/src/kiwano/utils/UserData.h index 67ac9a64..e12f99c1 100644 --- a/src/kiwano/utils/UserData.h +++ b/src/kiwano/utils/UserData.h @@ -27,7 +27,7 @@ namespace kiwano class KGE_API UserData : public Singleton { - OC_DECLARE_SINGLETON(UserData); + friend Singleton; public: using DataMap = UnorderedMap; From fad362f1aada97e72acf63e57bfb94da42a2c789 Mon Sep 17 00:00:00 2001 From: Nomango Date: Sat, 21 Dec 2019 18:41:16 +0800 Subject: [PATCH 04/27] Update Events & docs --- Doxyfile | 2 +- src/kiwano-physics/ContactEvent.cpp | 14 +- src/kiwano-physics/ContactEvent.h | 37 +++-- src/kiwano/2d/Actor.cpp | 36 ++--- src/kiwano/2d/DebugActor.cpp | 4 +- src/kiwano/2d/Layer.cpp | 56 +++---- src/kiwano/core/AsyncTask.h | 20 +++ src/kiwano/core/Event.cpp | 66 ++++---- src/kiwano/core/Event.h | 239 ++++++++++++++++++---------- src/kiwano/core/EventDispatcher.cpp | 2 +- src/kiwano/core/time.h | 59 +++---- src/kiwano/ui/Button.cpp | 20 +-- 12 files changed, 334 insertions(+), 221 deletions(-) diff --git a/Doxyfile b/Doxyfile index 68464f37..c9a4f675 100644 --- a/Doxyfile +++ b/Doxyfile @@ -53,7 +53,7 @@ EXCLUDE = src/3rd-party ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES -PREDEFINED = KGE_API= +PREDEFINED = KGE_API= # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the diff --git a/src/kiwano-physics/ContactEvent.cpp b/src/kiwano-physics/ContactEvent.cpp index ae7f13ac..02fa63c9 100644 --- a/src/kiwano-physics/ContactEvent.cpp +++ b/src/kiwano-physics/ContactEvent.cpp @@ -22,17 +22,17 @@ namespace kiwano { - namespace event - { - EventType event::ContactBegin = EventType(L"ContactBegin"); - EventType event::ContactEnd = EventType(L"ContactEnd"); - } namespace physics { + namespace events + { + KGE_IMPLEMENT_EVENT_TYPE(ContactBegin, physics::ContactBeginEvent); + KGE_IMPLEMENT_EVENT_TYPE(ContactEnd, physics::ContactEndEvent); + } ContactBeginEvent::ContactBeginEvent() - : Event(event::ContactBegin) + : Event(events::ContactBegin) , body_a(nullptr) , body_b(nullptr) { @@ -47,7 +47,7 @@ namespace kiwano } ContactEndEvent::ContactEndEvent() - : Event(event::ContactEnd) + : Event(events::ContactEnd) , body_a(nullptr) , body_b(nullptr) { diff --git a/src/kiwano-physics/ContactEvent.h b/src/kiwano-physics/ContactEvent.h index ba2488f4..d154993d 100644 --- a/src/kiwano-physics/ContactEvent.h +++ b/src/kiwano-physics/ContactEvent.h @@ -26,37 +26,46 @@ namespace kiwano { namespace physics { - // ½Ó´¥¿ªÊ¼Ê¼þ + namespace events + { + /** + * \addtogroup EventTypes + * @{ + */ + + KGE_DECLARE_EVENT_TYPE(ContactBegin); ///< ½Ó´¥¿ªÊ¼ + KGE_DECLARE_EVENT_TYPE(ContactEnd); ///< ½Ó´¥½áÊø + + /** @} */ + } + + /// \~chinese + /// @brief ½Ó´¥¿ªÊ¼Ê¼þ class KGE_API ContactBeginEvent : public Event { public: - Contact contact; - Body* body_a; - Body* body_b; + Contact contact; ///< ²úÉúµÄ½Ó´¥ + Body* body_a; ///< ²úÉú½Ó´¥µÄÎïÌåA + Body* body_b; ///< ²úÉú½Ó´¥µÄÎïÌåB ContactBeginEvent(); ContactBeginEvent(Contact const& contact); }; - // ½Ó´¥½áÊøÊ¼þ + /// \~chinese + /// @brief ½Ó´¥½áÊøÊ¼þ class KGE_API ContactEndEvent : public Event { public: - Contact contact; - Body* body_a; - Body* body_b; + Contact contact; ///< ²úÉúµÄ½Ó´¥ + Body* body_a; ///< ²úÉú½Ó´¥µÄÎïÌåA + Body* body_b; ///< ²úÉú½Ó´¥µÄÎïÌåB ContactEndEvent(); ContactEndEvent(Contact const& contact); }; } - - namespace event - { - extern EventType ContactBegin; // ½Ó´¥¿ªÊ¼ - extern EventType ContactEnd; // ½Ó´¥½áÊø - } } diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index 54b1a627..c4b03a4a 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -169,21 +169,21 @@ namespace kiwano if (responsible_) { - if (evt.type == event::MouseMove) + if (evt.IsType()) { - auto mouse_evt = evt.SafeCast(); - if (!mouse_evt->target && ContainsPoint(mouse_evt->pos)) + auto& mouse_evt = evt.SafeCast(); + if (!mouse_evt.target && ContainsPoint(mouse_evt.pos)) { - mouse_evt->target = this; + mouse_evt.target = this; if (!hover_) { hover_ = true; MouseHoverEvent hover; - hover.pos = mouse_evt->pos; - hover.left_btn_down = mouse_evt->left_btn_down; - hover.right_btn_down = mouse_evt->right_btn_down; + hover.pos = mouse_evt.pos; + hover.left_btn_down = mouse_evt.left_btn_down; + hover.right_btn_down = mouse_evt.right_btn_down; hover.target = this; EventDispatcher::Dispatch(hover); } @@ -194,33 +194,33 @@ namespace kiwano pressed_ = false; MouseOutEvent out; - out.pos = mouse_evt->pos; - out.left_btn_down = mouse_evt->left_btn_down; - out.right_btn_down = mouse_evt->right_btn_down; + out.pos = mouse_evt.pos; + out.left_btn_down = mouse_evt.left_btn_down; + out.right_btn_down = mouse_evt.right_btn_down; out.target = this; EventDispatcher::Dispatch(out); } } - if (evt.type == event::MouseDown && hover_) + if (evt.IsType() && hover_) { pressed_ = true; - evt.SafeCast()->target = this; + evt.SafeCast().target = this; } - if (evt.type == event::MouseUp && pressed_) + if (evt.IsType() && pressed_) { pressed_ = false; auto mouse_up_evt = evt.SafeCast(); - mouse_up_evt->target = this; + mouse_up_evt.target = this; MouseClickEvent click; - click.pos = mouse_up_evt->pos; - click.left_btn_down = mouse_up_evt->left_btn_down; - click.right_btn_down = mouse_up_evt->right_btn_down; + click.pos = mouse_up_evt.pos; + click.left_btn_down = mouse_up_evt.left_btn_down; + click.right_btn_down = mouse_up_evt.right_btn_down; click.target = this; - click.button = mouse_up_evt->button; + click.button = mouse_up_evt.button; EventDispatcher::Dispatch(click); } } diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index 94d71106..07c41061 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -66,8 +66,8 @@ namespace kiwano style.line_spacing = 20.f; debug_text_->SetStyle(style); - AddListener(event::MouseHover, [=](Event&) { SetOpacity(0.4f); }); - AddListener(event::MouseOut, [=](Event&) { SetOpacity(1.f); }); + AddListener(events::MouseHover, [=](Event&) { SetOpacity(0.4f); }); + AddListener(events::MouseOut, [=](Event&) { SetOpacity(1.f); }); } DebugActor::~DebugActor() diff --git a/src/kiwano/2d/Layer.cpp b/src/kiwano/2d/Layer.cpp index 7e46fceb..8b4a0640 100644 --- a/src/kiwano/2d/Layer.cpp +++ b/src/kiwano/2d/Layer.cpp @@ -29,14 +29,14 @@ namespace kiwano { auto handler = Closure(this, &Layer::HandleMessages); - AddListener(event::MouseDown, handler); - AddListener(event::MouseUp, handler); - AddListener(event::MouseMove, handler); - AddListener(event::MouseWheel, handler); + AddListener(events::MouseDown, handler); + AddListener(events::MouseUp, handler); + AddListener(events::MouseMove, handler); + AddListener(events::MouseWheel, handler); - AddListener(event::KeyDown, handler); - AddListener(event::KeyUp, handler); - AddListener(event::KeyChar, handler); + AddListener(events::KeyDown, handler); + AddListener(events::KeyUp, handler); + AddListener(events::KeyChar, handler); } Layer::~Layer() @@ -93,40 +93,40 @@ namespace kiwano void Layer::HandleMessages(Event& evt) { - if (evt.type == event::MouseDown) + if (evt.IsType()) { - auto real_evt = evt.SafeCast(); - OnMouseButtonDown(real_evt->button, real_evt->pos); + const auto& real_evt = evt.SafeCast(); + OnMouseButtonDown(real_evt.button, real_evt.pos); } - else if (evt.type == event::MouseUp) + else if (evt.IsType()) { - auto real_evt = evt.SafeCast(); - OnMouseButtonUp(real_evt->button, real_evt->pos); + const auto& real_evt = evt.SafeCast(); + OnMouseButtonUp(real_evt.button, real_evt.pos); } - else if (evt.type == event::MouseMove) + else if (evt.IsType()) { - auto real_evt = evt.SafeCast(); - OnMouseMoved(real_evt->pos); + const auto& real_evt = evt.SafeCast(); + OnMouseMoved(real_evt.pos); } - else if (evt.type == event::MouseWheel) + else if (evt.IsType()) { - auto real_evt = evt.SafeCast(); - OnMouseWheel(real_evt->wheel); + const auto& real_evt = evt.SafeCast(); + OnMouseWheel(real_evt.wheel); } - else if (evt.type == event::KeyDown) + else if (evt.IsType()) { - auto real_evt = evt.SafeCast(); - OnKeyDown(real_evt->code); + const auto& real_evt = evt.SafeCast(); + OnKeyDown(real_evt.code); } - else if (evt.type == event::KeyUp) + else if (evt.IsType()) { - auto real_evt = evt.SafeCast(); - OnKeyUp(real_evt->code); + const auto& real_evt = evt.SafeCast(); + OnKeyUp(real_evt.code); } - else if (evt.type == event::KeyChar) + else if (evt.IsType()) { - auto real_evt = evt.SafeCast(); - OnChar(real_evt->value); + const auto& real_evt = evt.SafeCast(); + OnChar(real_evt.value); } } diff --git a/src/kiwano/core/AsyncTask.h b/src/kiwano/core/AsyncTask.h index 095f4bc7..fa11faa6 100644 --- a/src/kiwano/core/AsyncTask.h +++ b/src/kiwano/core/AsyncTask.h @@ -31,26 +31,46 @@ namespace kiwano typedef Function AsyncTaskFunc; typedef Function AsyncTaskCallback; + /// \~chinese + /// @brief Òì²½ÈÎÎñ + /// @details ÔÚ¶àÏß³ÌÏÂÖ´ÐÐÈÎÎñ²¢·µ»Ø + /// @code + /// AsyncTaskPtr task = new AsyncTask; + /// task->Then(DoSomething); + /// task->Start(); + /// @endcode class AsyncTask : public ObjectBase { public: + /// \~chinese + /// @brief ¹¹ÔìÒì²½ÈÎÎñ AsyncTask(); + /// \~chinese + /// @brief ¹¹ÔìÒì²½ÈÎÎñ + /// @param func Òì²½»Øµ÷º¯Êý AsyncTask( AsyncTaskFunc func ); virtual ~AsyncTask(); + /// \~chinese + /// @brief Ìí¼ÓÒì²½ÈÎÎñÁ´ AsyncTask& Then( AsyncTaskFunc func ); + /// \~chinese + /// @brief ÉèÖÃÈÎÎñÖ´ÐÐÍê³ÉºóµÄ»Øµ÷º¯Êý + /// @note ¸Ãº¯ÊýÔÚ Kiwano Ö÷Ïß³ÌÖÐÖ´ÐÐ AsyncTask& SetCallback( AsyncTaskCallback callback ); + /// \~chinese + /// @brief Æô¶¯Òì²½ÈÎÎñ void Start(); protected: diff --git a/src/kiwano/core/Event.cpp b/src/kiwano/core/Event.cpp index 41a0221c..f907a518 100644 --- a/src/kiwano/core/Event.cpp +++ b/src/kiwano/core/Event.cpp @@ -2,27 +2,29 @@ namespace kiwano { - EventType event::MouseMove = EventType(L"MouseMove"); - EventType event::MouseDown = EventType(L"MouseDown"); - EventType event::MouseUp = EventType(L"MouseUp"); - EventType event::MouseWheel = EventType(L"MouseWheel"); - EventType event::MouseHover = EventType(L"MouseHover"); - EventType event::MouseOut = EventType(L"MouseOut"); - EventType event::MouseClick = EventType(L"MouseClick"); + namespace events + { + KGE_IMPLEMENT_EVENT_TYPE(MouseMove, MouseMoveEvent); + KGE_IMPLEMENT_EVENT_TYPE(MouseDown, MouseDownEvent); + KGE_IMPLEMENT_EVENT_TYPE(MouseUp, MouseUpEvent); + KGE_IMPLEMENT_EVENT_TYPE(MouseWheel, MouseWheelEvent); + KGE_IMPLEMENT_EVENT_TYPE(MouseHover, MouseHoverEvent); + KGE_IMPLEMENT_EVENT_TYPE(MouseOut, MouseOutEvent); + KGE_IMPLEMENT_EVENT_TYPE(MouseClick, MouseClickEvent); - EventType event::KeyDown = EventType(L"KeyDown"); - EventType event::KeyUp = EventType(L"KeyUp"); - EventType event::KeyChar = EventType(L"KeyChar"); - - EventType event::WindowMoved = EventType(L"WindowMoved"); - EventType event::WindowResized = EventType(L"WindowResized"); - EventType event::WindowFocusChanged = EventType(L"WindowFocusChanged"); - EventType event::WindowTitleChanged = EventType(L"WindowTitleChanged"); - EventType event::WindowClosed = EventType(L"WindowClosed"); + KGE_IMPLEMENT_EVENT_TYPE(KeyDown, KeyDownEvent); + KGE_IMPLEMENT_EVENT_TYPE(KeyUp, KeyUpEvent); + KGE_IMPLEMENT_EVENT_TYPE(KeyChar, KeyCharEvent); + KGE_IMPLEMENT_EVENT_TYPE(WindowMoved, WindowMovedEvent); + KGE_IMPLEMENT_EVENT_TYPE(WindowResized, WindowResizedEvent); + KGE_IMPLEMENT_EVENT_TYPE(WindowFocusChanged, WindowFocusChangedEvent); + KGE_IMPLEMENT_EVENT_TYPE(WindowTitleChanged, WindowTitleChangedEvent); + KGE_IMPLEMENT_EVENT_TYPE(WindowClosed, WindowClosedEvent); + } Event::Event(EventType const& type) - : type(type) + : type_(type) { } @@ -40,91 +42,91 @@ namespace kiwano } MouseMoveEvent::MouseMoveEvent() - : MouseEvent(event::MouseMove) + : MouseEvent(events::MouseMove) , button(0) { } MouseDownEvent::MouseDownEvent() - : MouseEvent(event::MouseDown) + : MouseEvent(events::MouseDown) , button(0) { } MouseUpEvent::MouseUpEvent() - : MouseEvent(event::MouseUp) + : MouseEvent(events::MouseUp) , button(0) { } MouseClickEvent::MouseClickEvent() - : MouseEvent(event::MouseClick) + : MouseEvent(events::MouseClick) , button(0) { } MouseHoverEvent::MouseHoverEvent() - : MouseEvent(event::MouseHover) + : MouseEvent(events::MouseHover) { } MouseOutEvent::MouseOutEvent() - : MouseEvent(event::MouseOut) + : MouseEvent(events::MouseOut) { } MouseWheelEvent::MouseWheelEvent() - : MouseEvent(event::MouseWheel) + : MouseEvent(events::MouseWheel) , wheel(0.f) { } KeyDownEvent::KeyDownEvent() - : Event(event::KeyDown) + : Event(events::KeyDown) , code(0) { } KeyUpEvent::KeyUpEvent() - : Event(event::KeyUp) + : Event(events::KeyUp) , code(0) { } KeyCharEvent::KeyCharEvent() - : Event(event::KeyChar) + : Event(events::KeyChar) , value() { } WindowMovedEvent::WindowMovedEvent() - : Event(event::WindowMoved) + : Event(events::WindowMoved) , x(0) , y(0) { } WindowResizedEvent::WindowResizedEvent() - : Event(event::WindowResized) + : Event(events::WindowResized) , width(0) , height(0) { } WindowFocusChangedEvent::WindowFocusChangedEvent() - : Event(event::WindowFocusChanged) + : Event(events::WindowFocusChanged) , focus(false) { } WindowTitleChangedEvent::WindowTitleChangedEvent() - : Event(event::WindowTitleChanged) + : Event(events::WindowTitleChanged) , title() { } WindowClosedEvent::WindowClosedEvent() - : Event(event::WindowClosed) + : Event(events::WindowClosed) { } diff --git a/src/kiwano/core/Event.h b/src/kiwano/core/Event.h index 420b35e9..5a7d000e 100644 --- a/src/kiwano/core/Event.h +++ b/src/kiwano/core/Event.h @@ -23,144 +23,209 @@ #include #include +#include +#include + namespace kiwano { class Actor; - // ʼþÀàÐÍ - struct EventType + /// \~chinese + /// @brief ʼþÀàÐÍ + class EventType + : public std::type_index { - inline EventType() : hash(0), type() - { - } + class Dummy { }; - inline EventType(String const& type) : hash(0), type(type) - { - hash = type.hash(); - } + public: + /// \~chinese + /// @brief ¹¹½¨Ê¼þÀàÐÍ + EventType() : std::type_index(typeid(EventType::Dummy)) {} - inline bool operator==(const EventType& rhs) const - { - return hash == rhs.hash && type == rhs.type; - } + /// \~chinese + /// @brief ¹¹½¨Ê¼þÀàÐÍ + /// @param info ʼþ±êʶ·û + EventType(const type_info& info) : std::type_index(info) {} - size_t hash; - String type; + /// \~chinese + /// @brief ¹¹½¨Ê¼þÀàÐÍ + /// @param index ʼþ±êʶ·û + EventType(const std::type_index& index) : std::type_index(index) {} }; - namespace event +#define KGE_EVENT(EVENT_TYPE) ::kiwano::EventType(typeid(EVENT_TYPE)) + +#define KGE_DECLARE_EVENT_TYPE(EVENT_NAME) extern ::kiwano::EventType EVENT_NAME; + +#define KGE_IMPLEMENT_EVENT_TYPE(EVENT_NAME, EVENT_TYPE) ::kiwano::EventType EVENT_NAME = KGE_EVENT(EVENT_TYPE); + + + namespace events { + /** + * \~chinese + * \defgroup EventTypes ʼþÀàÐÍ + */ + + /** + * \addtogroup EventTypes + * @{ + */ + // Êó±êʼþ - extern EventType MouseMove; // ÒÆ¶¯ - extern EventType MouseDown; // Êó±ê°´Ï - extern EventType MouseUp; // Êó±ȩ̂Æð - extern EventType MouseWheel; // ¹öÂÖ¹ö¶¯ - extern EventType MouseHover; // Êó±êÒÆÈë - extern EventType MouseOut; // Êó±êÒÆ³ö - extern EventType MouseClick; // Êó±êµã»÷ + KGE_DECLARE_EVENT_TYPE(MouseMove); ///< Êó±êÒÆ¶¯ + KGE_DECLARE_EVENT_TYPE(MouseDown); ///< Êó±ê°´Ï + KGE_DECLARE_EVENT_TYPE(MouseUp); ///< Êó±ȩ̂Æð + KGE_DECLARE_EVENT_TYPE(MouseWheel); ///< ¹öÂÖ¹ö¶¯ + KGE_DECLARE_EVENT_TYPE(MouseHover); ///< Êó±êÒÆÈë + KGE_DECLARE_EVENT_TYPE(MouseOut); ///< Êó±êÒÆ³ö + KGE_DECLARE_EVENT_TYPE(MouseClick); ///< Êó±êµã»÷ // °´¼üʼþ - extern EventType KeyDown; // °´¼ü°´Ï - extern EventType KeyUp; // °´¼ü̧Æð - extern EventType KeyChar; // Êä³ö×Ö·û + KGE_DECLARE_EVENT_TYPE(KeyDown); ///< °´¼ü°´Ï + KGE_DECLARE_EVENT_TYPE(KeyUp); ///< °´¼ü̧Æð + KGE_DECLARE_EVENT_TYPE(KeyChar); ///< Êä³ö×Ö·û // ´°¿ÚÏûÏ¢ - extern EventType WindowMoved; // ´°¿ÚÒÆ¶¯ - extern EventType WindowResized; // ´°¿Ú´óС±ä»¯ - extern EventType WindowFocusChanged; // »ñµÃ»òʧȥ½¹µã - extern EventType WindowTitleChanged; // ±êÌâ±ä»¯ - extern EventType WindowClosed; // ´°¿Ú±»¹Ø±Õ + KGE_DECLARE_EVENT_TYPE(WindowMoved); ///< ´°¿ÚÒÆ¶¯ + KGE_DECLARE_EVENT_TYPE(WindowResized); ///< ´°¿Ú´óС±ä»¯ + KGE_DECLARE_EVENT_TYPE(WindowFocusChanged); ///< »ñµÃ»òʧȥ½¹µã + KGE_DECLARE_EVENT_TYPE(WindowTitleChanged); ///< ±êÌâ±ä»¯ + KGE_DECLARE_EVENT_TYPE(WindowClosed); ///< ´°¿Ú±»¹Ø±Õ + + /** @} */ } + /** + * \~chinese + * \defgroup Events ʼþ + */ - // ʼþ + /** + * \addtogroup Events + * @{ + */ + + /// \~chinese + /// @brief ʼþ class KGE_API Event { public: - const EventType type; - + /// \~chinese + /// @brief ¹¹Ôìʼþ Event(EventType const& type); + virtual ~Event(); - template < - typename _Ty, - typename = typename std::enable_if::value, int>::type - > - inline const _Ty* SafeCast() const + /// \~chinese + /// @brief »ñÈ¡ÀàÐÍʼþ + inline const EventType& GetType() const { - const _Ty* ptr = dynamic_cast(this); - if (ptr) - { - return ptr; - } - return nullptr; + return type_; } + /// \~chinese + /// @brief ÅжÏʼþÀàÐÍ + /// @return ÊÇ·ñÊÇÖ¸¶¨Ê¼þÀàÐÍ template < typename _Ty, typename = typename std::enable_if::value, int>::type > - inline _Ty* SafeCast() + inline bool IsType() const { - return const_cast<_Ty*>(const_cast(this)->SafeCast<_Ty>()); + return type_ == KGE_EVENT(_Ty); } + + /// \~chinese + /// @brief °²È«×ª»»ÎªÆäËûÀàÐÍʼþ + /// @throw std::bad_cast ÎÞ·¨×ª»»µÄÀàÐÍ + template < + typename _Ty, + typename = typename std::enable_if::value, int>::type + > + inline const _Ty& SafeCast() const + { + if (!IsType<_Ty>()) throw std::bad_cast(); + return *dynamic_cast(this); + } + + /// \~chinese + /// @brief °²È«×ª»»ÎªÆäËûÀàÐÍʼþ + /// @throw std::bad_cast ÎÞ·¨×ª»»µÄÀàÐÍ + template < + typename _Ty, + typename = typename std::enable_if::value, int>::type + > + inline _Ty& SafeCast() + { + return const_cast<_Ty&>(const_cast(this)->SafeCast<_Ty>()); + } + + protected: + const EventType type_; }; - // Êó±êʼþ + /// \~chinese + /// @brief Êó±êʼþ class KGE_API MouseEvent : public Event { public: - Point pos; - bool left_btn_down; // ×ó¼üÊÇ·ñ°´Ï - bool right_btn_down; // ÓÒ¼üÊÇ·ñ°´Ï - Actor* target; + Point pos; ///< Êó±êλÖà + bool left_btn_down; ///< Êó±ê×ó¼üÊÇ·ñ°´Ï + bool right_btn_down; ///< Êó±êÓÒ¼üÊÇ·ñ°´Ï + Actor* target; ///< Ä¿±ê MouseEvent(EventType const& type); }; - // Êó±êÒÆ¶¯Ê¼þ + /// \~chinese + /// @brief Êó±êÒÆ¶¯Ê¼þ class KGE_API MouseMoveEvent : public MouseEvent { public: - MouseButton::Value button; + MouseButton::Value button; ///< Êó±ê¼üÖµ MouseMoveEvent(); }; - // Êó±ê°´¼ü°´ÏÂʼþ + /// \~chinese + /// @brief Êó±ê°´¼ü°´ÏÂʼþ class KGE_API MouseDownEvent : public MouseEvent { public: - MouseButton::Value button; + MouseButton::Value button; ///< Êó±ê¼üÖµ MouseDownEvent(); }; - // Êó±ê°´¼ü̧Æðʼþ + /// \~chinese + /// @brief Êó±ê°´¼ü̧Æðʼþ class KGE_API MouseUpEvent : public MouseEvent { public: - MouseButton::Value button; + MouseButton::Value button; ///< Êó±ê¼üÖµ MouseUpEvent(); }; - // Êó±êµã»÷ʼþ + /// \~chinese + /// @brief Êó±êµã»÷ʼþ class KGE_API MouseClickEvent : public MouseEvent { public: - MouseButton::Value button; + MouseButton::Value button; ///< Êó±ê¼üÖµ MouseClickEvent(); }; - // Êó±êÒÆÈëʼþ + /// \~chinese + /// @brief Êó±êÒÆÈëʼþ class KGE_API MouseHoverEvent : public MouseEvent { @@ -168,7 +233,8 @@ namespace kiwano MouseHoverEvent(); }; - // Êó±êÒÆ³öʼþ + /// \~chinese + /// @brief Êó±êÒÆ³öʼþ class KGE_API MouseOutEvent : public MouseEvent { @@ -176,89 +242,98 @@ namespace kiwano MouseOutEvent(); }; - // Êó±ê¹öÂÖʼþ + /// \~chinese + /// @brief Êó±ê¹öÂÖʼþ class KGE_API MouseWheelEvent : public MouseEvent { public: - float wheel; + float wheel; ///< ¹öÂÖÖµ MouseWheelEvent(); }; - // ¼üÅ̰´ÏÂʼþ + /// \~chinese + /// @brief ¼üÅ̰´ÏÂʼþ class KGE_API KeyDownEvent : public Event { public: - KeyCode::Value code; + KeyCode::Value code; ///< ¼üÖµ KeyDownEvent(); }; - // ¼üÅÌ̧Æðʼþ + /// \~chinese + /// @brief ¼üÅÌ̧Æðʼþ class KGE_API KeyUpEvent : public Event { public: - KeyCode::Value code; + KeyCode::Value code; ///< ¼üÖµ KeyUpEvent(); }; - // ¼üÅÌ×Ö·ûʼþ + /// \~chinese + /// @brief ¼üÅÌ×Ö·ûʼþ class KGE_API KeyCharEvent : public Event { public: - char value; + char value; ///< ×Ö·û KeyCharEvent(); }; - // ´°¿ÚÒÆ¶¯Ê¼þ + /// \~chinese + /// @brief ´°¿ÚÒÆ¶¯Ê¼þ class KGE_API WindowMovedEvent : public Event { public: - int x; - int y; + int x; ///< ´°¿Ú×óÉÏ½Ç x ×ø±ê + int y; ///< ´°¿Ú×óÉÏ½Ç y ×ø±ê WindowMovedEvent(); }; - // ´°¿Ú´óС±ä»¯Ê¼þ + /// \~chinese + /// @brief ´°¿Ú´óС±ä»¯Ê¼þ class KGE_API WindowResizedEvent : public Event { public: - int width; - int height; + int width; ///< ´°¿Ú¿í¶È + int height; ///< ´°¿Ú¸ß¶È WindowResizedEvent(); }; - // ´°¿Ú½¹µã±ä»¯Ê¼þ + /// \~chinese + /// @brief ´°¿Ú½¹µã±ä»¯Ê¼þ class KGE_API WindowFocusChangedEvent : public Event { public: - bool focus; + bool focus; ///< ÊÇ·ñ»ñÈ¡µ½½¹µã WindowFocusChangedEvent(); }; - // ´°¿Ú±êÌâ¸ü¸Äʼþ + /// \~chinese + /// @brief ´°¿Ú±êÌâ¸ü¸Äʼþ class KGE_API WindowTitleChangedEvent : public Event { public: - String title; + String title; ///< ±êÌâ WindowTitleChangedEvent(); }; - // ´°¿Ú¹Ø±Õʼþ + /// \~chinese + /// @brief ´°¿Ú¹Ø±Õʼþ class KGE_API WindowClosedEvent : public Event { @@ -266,4 +341,6 @@ namespace kiwano WindowClosedEvent(); }; + /** @} */ + } diff --git a/src/kiwano/core/EventDispatcher.cpp b/src/kiwano/core/EventDispatcher.cpp index 5cef85db..bf54d608 100644 --- a/src/kiwano/core/EventDispatcher.cpp +++ b/src/kiwano/core/EventDispatcher.cpp @@ -33,7 +33,7 @@ namespace kiwano { next = listener->next_item(); - if (listener->IsRunning() && listener->type_ == evt.type) + if (listener->IsRunning() && listener->type_ == evt.GetType()) { listener->callback_(evt); } diff --git a/src/kiwano/core/time.h b/src/kiwano/core/time.h index 2e06bd74..d063179f 100644 --- a/src/kiwano/core/time.h +++ b/src/kiwano/core/time.h @@ -29,13 +29,18 @@ namespace kiwano * @brief ʱ¼ä¶Î * @details * ʱ¼ä¶Î±íʾ·¨: - * 5 Ãë: time::Second * 5 - * 1.5 Сʱ: time::Hour * 1.5 - * 3 Сʱ 45 ·Ö 15 Ãë: time::Hour * 3 + time::Minute * 45 + time::Second * 15 + * @code + * time::Second * 5 // 5 Ãë + * time::Hour * 1.5 // 1.5 Сʱ + * time::Hour * 3 + time::Minute * 45 + time::Second * 15 // 3 Сʱ 45 ·Ö 15 Ãë + * @endcode * ÔÚ VS2015 ¼°¸ü¸ß°æ±¾¿ÉÒÔʹÓà time literals: - * 5 Ãë: 5_s - * 1.5 Сʱ: 1.5_h - * 3 Сʱ 45 ·Ö 15 Ãë: 3_h + 45_m + 15_s + * @code + * using namespace kiwano; + * 5_sec // 5 Ãë + * 1.5_hour // 1.5 Сʱ + * 3_hour + 45_min + 15_sec // 3 Сʱ 45 ·Ö 15 Ãë + * @endcode */ struct KGE_API Duration { @@ -217,48 +222,48 @@ namespace kiwano inline bool Time::IsZero() const { return dur_ == 0; } } -#if KGE_VS_VER > KGE_VS_2013 +#if defined(KGE_VS_VER) && KGE_VS_VER > KGE_VS_2013 namespace kiwano { inline namespace literals { - inline const kiwano::Duration operator "" _ms(long double val) + inline const kiwano::Duration operator "" _msec(long double val) { return kiwano::Duration::Ms * val; } - inline const kiwano::Duration operator "" _s(long double val) + inline const kiwano::Duration operator "" _msec(unsigned long long val) + { + return kiwano::Duration::Ms * val; + } + + inline const kiwano::Duration operator "" _sec(long double val) { return kiwano::Duration::Second * val; } - inline const kiwano::Duration operator "" _m(long double val) + inline const kiwano::Duration operator "" _sec(unsigned long long val) + { + return kiwano::Duration::Second * val; + } + + inline const kiwano::Duration operator "" _min(long double val) { return kiwano::Duration::Minute * val; } - inline const kiwano::Duration operator "" _h(long double val) + inline const kiwano::Duration operator "" _min(unsigned long long val) + { + return kiwano::Duration::Minute * val; + } + + inline const kiwano::Duration operator "" _hour(long double val) { return kiwano::Duration::Hour * val; } - inline const kiwano::Duration operator "" _ms(unsigned long long val) - { - return kiwano::Duration::Ms * val; - } - - inline const kiwano::Duration operator "" _s(unsigned long long val) - { - return kiwano::Duration::Second * val; - } - - inline const kiwano::Duration operator "" _m(unsigned long long val) - { - return kiwano::Duration::Minute * val; - } - - inline const kiwano::Duration operator "" _h(unsigned long long val) + inline const kiwano::Duration operator "" _hour(unsigned long long val) { return kiwano::Duration::Hour * val; } diff --git a/src/kiwano/ui/Button.cpp b/src/kiwano/ui/Button.cpp index 9552d605..b905e0a5 100644 --- a/src/kiwano/ui/Button.cpp +++ b/src/kiwano/ui/Button.cpp @@ -32,10 +32,10 @@ namespace kiwano { SetResponsible(true); - AddListener(event::MouseHover, Closure(this, &Button::UpdateStatus)); - AddListener(event::MouseOut, Closure(this, &Button::UpdateStatus)); - AddListener(event::MouseDown, Closure(this, &Button::UpdateStatus)); - AddListener(event::MouseUp, Closure(this, &Button::UpdateStatus)); + AddListener(events::MouseHover, Closure(this, &Button::UpdateStatus)); + AddListener(events::MouseOut, Closure(this, &Button::UpdateStatus)); + AddListener(events::MouseDown, Closure(this, &Button::UpdateStatus)); + AddListener(events::MouseUp, Closure(this, &Button::UpdateStatus)); } Button::Button(const Callback& click) @@ -105,12 +105,12 @@ namespace kiwano void Button::UpdateStatus(Event& evt) { - auto mouse_evt = evt.SafeCast(); - KGE_ASSERT(mouse_evt); + auto mouse_evt = dynamic_cast(&evt); + KGE_ASSERT(mouse_evt != nullptr); if (enabled_ && (mouse_evt->target == this)) { - if (evt.type == event::MouseHover) + if (evt.IsType()) { SetStatus(Status::Hover); Window::instance().SetCursor(CursorType::Hand); @@ -118,7 +118,7 @@ namespace kiwano if (mouse_over_callback_) mouse_over_callback_(); } - else if (evt.type == event::MouseOut) + else if (evt.IsType()) { SetStatus(Status::Normal); Window::instance().SetCursor(CursorType::Arrow); @@ -126,14 +126,14 @@ namespace kiwano if (mouse_out_callback_) mouse_out_callback_(); } - else if (evt.type == event::MouseDown && status_ == Status::Hover) + else if (evt.IsType() && status_ == Status::Hover) { SetStatus(Status::Pressed); if (pressed_callback_) pressed_callback_(); } - else if (evt.type == event::MouseUp && status_ == Status::Pressed) + else if (evt.IsType() && status_ == Status::Pressed) { SetStatus(Status::Hover); From 939fadcb9723510e3b1cda8bae59705aa1d05e0f Mon Sep 17 00:00:00 2001 From: Nomango Date: Sun, 22 Dec 2019 11:04:49 +0800 Subject: [PATCH 05/27] Update Events --- Doxyfile | 11 ++- src/kiwano-imgui/kiwano-imgui.h | 2 +- src/kiwano-physics/ContactEvent.cpp | 11 +-- src/kiwano-physics/ContactEvent.h | 24 +++--- src/kiwano/2d/DebugActor.cpp | 4 +- src/kiwano/2d/Layer.cpp | 14 ++-- src/kiwano/core/Event.cpp | 52 ++++--------- src/kiwano/core/Event.h | 109 ++++++++++++++++------------ src/kiwano/core/EventDispatcher.h | 20 ++++- src/kiwano/core/time.h | 4 +- src/kiwano/platform/FileSystem.h | 2 +- src/kiwano/ui/Button.cpp | 8 +- 12 files changed, 134 insertions(+), 127 deletions(-) diff --git a/Doxyfile b/Doxyfile index c9a4f675..561ccec7 100644 --- a/Doxyfile +++ b/Doxyfile @@ -42,7 +42,7 @@ FILE_PATTERNS = *.c \ *.hh \ *.hxx \ *.hpp \ - *.h++ \ + *.h++ RECURSIVE = YES EXCLUDE = src/3rd-party @@ -60,8 +60,13 @@ PREDEFINED = KGE_API= # preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = +SEARCH_INCLUDES = YES +INCLUDE_PATH = src/ +INCLUDE_FILE_PATTERNS = *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ #--------------------------------------------------------------------------- # Configuration options related to the HTML output diff --git a/src/kiwano-imgui/kiwano-imgui.h b/src/kiwano-imgui/kiwano-imgui.h index 68899fd5..453a1a0c 100644 --- a/src/kiwano-imgui/kiwano-imgui.h +++ b/src/kiwano-imgui/kiwano-imgui.h @@ -24,4 +24,4 @@ #include // ImGui -#include <3rd-party/imgui/imgui.h> +#include diff --git a/src/kiwano-physics/ContactEvent.cpp b/src/kiwano-physics/ContactEvent.cpp index 02fa63c9..9bfbad99 100644 --- a/src/kiwano-physics/ContactEvent.cpp +++ b/src/kiwano-physics/ContactEvent.cpp @@ -22,17 +22,10 @@ namespace kiwano { - namespace physics { - namespace events - { - KGE_IMPLEMENT_EVENT_TYPE(ContactBegin, physics::ContactBeginEvent); - KGE_IMPLEMENT_EVENT_TYPE(ContactEnd, physics::ContactEndEvent); - } - ContactBeginEvent::ContactBeginEvent() - : Event(events::ContactBegin) + : Event(KGE_EVENT(ContactBeginEvent)) , body_a(nullptr) , body_b(nullptr) { @@ -47,7 +40,7 @@ namespace kiwano } ContactEndEvent::ContactEndEvent() - : Event(events::ContactEnd) + : Event(KGE_EVENT(ContactEndEvent)) , body_a(nullptr) , body_b(nullptr) { diff --git a/src/kiwano-physics/ContactEvent.h b/src/kiwano-physics/ContactEvent.h index d154993d..0010bb35 100644 --- a/src/kiwano-physics/ContactEvent.h +++ b/src/kiwano-physics/ContactEvent.h @@ -26,19 +26,6 @@ namespace kiwano { namespace physics { - namespace events - { - /** - * \addtogroup EventTypes - * @{ - */ - - KGE_DECLARE_EVENT_TYPE(ContactBegin); ///< ½Ó´¥¿ªÊ¼ - KGE_DECLARE_EVENT_TYPE(ContactEnd); ///< ½Ó´¥½áÊø - - /** @} */ - } - /// \~chinese /// @brief ½Ó´¥¿ªÊ¼Ê¼þ class KGE_API ContactBeginEvent @@ -67,5 +54,16 @@ namespace kiwano ContactEndEvent(Contact const& contact); }; + /** + * \addtogroup EventTypes + * @{ + */ + + KGE_EVENT_BEGIN(PhysicEvents); + KGE_DEFINE_EVENT(ContactBegin, ContactBeginEvent); ///< ½Ó´¥¿ªÊ¼ @see kiwano::physics::ContactBeginEvent + KGE_DEFINE_EVENT(ContactEnd, ContactEndEvent); ///< ½Ó´¥½áÊø @see kiwano::physics::ContactEndEvent + KGE_EVENT_END; + + /** @} */ } } diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index 07c41061..cbb1e3d7 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -66,8 +66,8 @@ namespace kiwano style.line_spacing = 20.f; debug_text_->SetStyle(style); - AddListener(events::MouseHover, [=](Event&) { SetOpacity(0.4f); }); - AddListener(events::MouseOut, [=](Event&) { SetOpacity(1.f); }); + AddListener(MouseEvents::Hover(), [=](Event&) { SetOpacity(0.4f); }); + AddListener(MouseEvents::Out(), [=](Event&) { SetOpacity(1.f); }); } DebugActor::~DebugActor() diff --git a/src/kiwano/2d/Layer.cpp b/src/kiwano/2d/Layer.cpp index 8b4a0640..abf5e776 100644 --- a/src/kiwano/2d/Layer.cpp +++ b/src/kiwano/2d/Layer.cpp @@ -29,14 +29,14 @@ namespace kiwano { auto handler = Closure(this, &Layer::HandleMessages); - AddListener(events::MouseDown, handler); - AddListener(events::MouseUp, handler); - AddListener(events::MouseMove, handler); - AddListener(events::MouseWheel, handler); + AddListener(MouseEvents::Down(), handler); + AddListener(MouseEvents::Up(), handler); + AddListener(MouseEvents::Move(), handler); + AddListener(MouseEvents::Wheel(), handler); - AddListener(events::KeyDown, handler); - AddListener(events::KeyUp, handler); - AddListener(events::KeyChar, handler); + AddListener(KeyEvents::Down(), handler); + AddListener(KeyEvents::Up(), handler); + AddListener(KeyEvents::Char(), handler); } Layer::~Layer() diff --git a/src/kiwano/core/Event.cpp b/src/kiwano/core/Event.cpp index f907a518..0bf249b6 100644 --- a/src/kiwano/core/Event.cpp +++ b/src/kiwano/core/Event.cpp @@ -2,27 +2,6 @@ namespace kiwano { - namespace events - { - KGE_IMPLEMENT_EVENT_TYPE(MouseMove, MouseMoveEvent); - KGE_IMPLEMENT_EVENT_TYPE(MouseDown, MouseDownEvent); - KGE_IMPLEMENT_EVENT_TYPE(MouseUp, MouseUpEvent); - KGE_IMPLEMENT_EVENT_TYPE(MouseWheel, MouseWheelEvent); - KGE_IMPLEMENT_EVENT_TYPE(MouseHover, MouseHoverEvent); - KGE_IMPLEMENT_EVENT_TYPE(MouseOut, MouseOutEvent); - KGE_IMPLEMENT_EVENT_TYPE(MouseClick, MouseClickEvent); - - KGE_IMPLEMENT_EVENT_TYPE(KeyDown, KeyDownEvent); - KGE_IMPLEMENT_EVENT_TYPE(KeyUp, KeyUpEvent); - KGE_IMPLEMENT_EVENT_TYPE(KeyChar, KeyCharEvent); - - KGE_IMPLEMENT_EVENT_TYPE(WindowMoved, WindowMovedEvent); - KGE_IMPLEMENT_EVENT_TYPE(WindowResized, WindowResizedEvent); - KGE_IMPLEMENT_EVENT_TYPE(WindowFocusChanged, WindowFocusChangedEvent); - KGE_IMPLEMENT_EVENT_TYPE(WindowTitleChanged, WindowTitleChangedEvent); - KGE_IMPLEMENT_EVENT_TYPE(WindowClosed, WindowClosedEvent); - } - Event::Event(EventType const& type) : type_(type) { @@ -42,91 +21,90 @@ namespace kiwano } MouseMoveEvent::MouseMoveEvent() - : MouseEvent(events::MouseMove) - , button(0) + : MouseEvent(KGE_EVENT(MouseMoveEvent)) { } MouseDownEvent::MouseDownEvent() - : MouseEvent(events::MouseDown) + : MouseEvent(KGE_EVENT(MouseDownEvent)) , button(0) { } MouseUpEvent::MouseUpEvent() - : MouseEvent(events::MouseUp) + : MouseEvent(KGE_EVENT(MouseUpEvent)) , button(0) { } MouseClickEvent::MouseClickEvent() - : MouseEvent(events::MouseClick) + : MouseEvent(KGE_EVENT(MouseClickEvent)) , button(0) { } MouseHoverEvent::MouseHoverEvent() - : MouseEvent(events::MouseHover) + : MouseEvent(KGE_EVENT(MouseHoverEvent)) { } MouseOutEvent::MouseOutEvent() - : MouseEvent(events::MouseOut) + : MouseEvent(KGE_EVENT(MouseOutEvent)) { } MouseWheelEvent::MouseWheelEvent() - : MouseEvent(events::MouseWheel) + : MouseEvent(KGE_EVENT(MouseWheelEvent)) , wheel(0.f) { } KeyDownEvent::KeyDownEvent() - : Event(events::KeyDown) + : Event(KGE_EVENT(KeyDownEvent)) , code(0) { } KeyUpEvent::KeyUpEvent() - : Event(events::KeyUp) + : Event(KGE_EVENT(KeyUpEvent)) , code(0) { } KeyCharEvent::KeyCharEvent() - : Event(events::KeyChar) + : Event(KGE_EVENT(KeyCharEvent)) , value() { } WindowMovedEvent::WindowMovedEvent() - : Event(events::WindowMoved) + : Event(KGE_EVENT(WindowMovedEvent)) , x(0) , y(0) { } WindowResizedEvent::WindowResizedEvent() - : Event(events::WindowResized) + : Event(KGE_EVENT(WindowResizedEvent)) , width(0) , height(0) { } WindowFocusChangedEvent::WindowFocusChangedEvent() - : Event(events::WindowFocusChanged) + : Event(KGE_EVENT(WindowFocusChangedEvent)) , focus(false) { } WindowTitleChangedEvent::WindowTitleChangedEvent() - : Event(events::WindowTitleChanged) + : Event(KGE_EVENT(WindowTitleChangedEvent)) , title() { } WindowClosedEvent::WindowClosedEvent() - : Event(events::WindowClosed) + : Event(KGE_EVENT(WindowClosedEvent)) { } diff --git a/src/kiwano/core/Event.h b/src/kiwano/core/Event.h index 5a7d000e..c8388297 100644 --- a/src/kiwano/core/Event.h +++ b/src/kiwano/core/Event.h @@ -19,13 +19,12 @@ // THE SOFTWARE. #pragma once +#include +#include #include #include #include -#include -#include - namespace kiwano { class Actor; @@ -53,49 +52,8 @@ namespace kiwano EventType(const std::type_index& index) : std::type_index(index) {} }; +#define KGE_EVENT(EVENT_TYPE) ::kiwano::EventType(typeid(EVENT_TYPE)) -#define KGE_EVENT(EVENT_TYPE) ::kiwano::EventType(typeid(EVENT_TYPE)) - -#define KGE_DECLARE_EVENT_TYPE(EVENT_NAME) extern ::kiwano::EventType EVENT_NAME; - -#define KGE_IMPLEMENT_EVENT_TYPE(EVENT_NAME, EVENT_TYPE) ::kiwano::EventType EVENT_NAME = KGE_EVENT(EVENT_TYPE); - - - namespace events - { - /** - * \~chinese - * \defgroup EventTypes ʼþÀàÐÍ - */ - - /** - * \addtogroup EventTypes - * @{ - */ - - // Êó±êʼþ - KGE_DECLARE_EVENT_TYPE(MouseMove); ///< Êó±êÒÆ¶¯ - KGE_DECLARE_EVENT_TYPE(MouseDown); ///< Êó±ê°´Ï - KGE_DECLARE_EVENT_TYPE(MouseUp); ///< Êó±ȩ̂Æð - KGE_DECLARE_EVENT_TYPE(MouseWheel); ///< ¹öÂÖ¹ö¶¯ - KGE_DECLARE_EVENT_TYPE(MouseHover); ///< Êó±êÒÆÈë - KGE_DECLARE_EVENT_TYPE(MouseOut); ///< Êó±êÒÆ³ö - KGE_DECLARE_EVENT_TYPE(MouseClick); ///< Êó±êµã»÷ - - // °´¼üʼþ - KGE_DECLARE_EVENT_TYPE(KeyDown); ///< °´¼ü°´Ï - KGE_DECLARE_EVENT_TYPE(KeyUp); ///< °´¼ü̧Æð - KGE_DECLARE_EVENT_TYPE(KeyChar); ///< Êä³ö×Ö·û - - // ´°¿ÚÏûÏ¢ - KGE_DECLARE_EVENT_TYPE(WindowMoved); ///< ´°¿ÚÒÆ¶¯ - KGE_DECLARE_EVENT_TYPE(WindowResized); ///< ´°¿Ú´óС±ä»¯ - KGE_DECLARE_EVENT_TYPE(WindowFocusChanged); ///< »ñµÃ»òʧȥ½¹µã - KGE_DECLARE_EVENT_TYPE(WindowTitleChanged); ///< ±êÌâ±ä»¯ - KGE_DECLARE_EVENT_TYPE(WindowClosed); ///< ´°¿Ú±»¹Ø±Õ - - /** @} */ - } /** * \~chinese @@ -166,6 +124,12 @@ namespace kiwano const EventType type_; }; + /// \~chinese + /// @brief ʼþÌØÐÔ£ºÅжÏÊÇ·ñÊÇʼþÀàÐÍ + template + class IsEvent : public std::bool_constant::value || std::is_same::value> {}; + + /// \~chinese /// @brief Êó±êʼþ class KGE_API MouseEvent @@ -186,8 +150,6 @@ namespace kiwano : public MouseEvent { public: - MouseButton::Value button; ///< Êó±ê¼üÖµ - MouseMoveEvent(); }; @@ -343,4 +305,57 @@ namespace kiwano /** @} */ + + /** + * \~chinese + * \defgroup EventTypes ʼþÀàÐÍ + * + */ + + /** + * \addtogroup EventTypes + * @{ + */ + + +#define KGE_EVENT_BEGIN(NAME) struct NAME { +#define KGE_EVENT_END }; +#define KGE_DEFINE_EVENT(EVENT_NAME, EVENT_TYPE) \ + static inline const EventType& EVENT_NAME() \ + { \ + static EventType event_type = KGE_EVENT(EVENT_TYPE); \ + return event_type; \ + } + + /// \~chinese + /// @brief Êó±êʼþ + KGE_EVENT_BEGIN(MouseEvents); + KGE_DEFINE_EVENT(Move, MouseMoveEvent); ///< Êó±êÒÆ¶¯ + KGE_DEFINE_EVENT(Down, MouseDownEvent); ///< Êó±ê°´Ï + KGE_DEFINE_EVENT(Up, MouseUpEvent); ///< Êó±ȩ̂Æð + KGE_DEFINE_EVENT(Wheel, MouseWheelEvent); ///< ¹öÂÖ¹ö¶¯ + KGE_DEFINE_EVENT(Hover, MouseHoverEvent); ///< Êó±êÒÆÈë + KGE_DEFINE_EVENT(Out, MouseOutEvent); ///< Êó±êÒÆ³ö + KGE_DEFINE_EVENT(Click, MouseClickEvent); ///< Êó±êµã»÷ + KGE_EVENT_END; + + /// \~chinese + /// @brief ¼üÅ̰´¼üʼþ + KGE_EVENT_BEGIN(KeyEvents); + KGE_DEFINE_EVENT(Down, KeyDownEvent); ///< °´¼ü°´Ï + KGE_DEFINE_EVENT(Up, KeyUpEvent); ///< °´¼ü̧Æð + KGE_DEFINE_EVENT(Char, KeyCharEvent); ///< Êä³ö×Ö·û + KGE_EVENT_END; + + /// \~chinese + /// @brief ´°¿Úʼþ + KGE_EVENT_BEGIN(WindowEvents); + KGE_DEFINE_EVENT(Moved, WindowMovedEvent); ///< ´°¿ÚÒÆ¶¯ + KGE_DEFINE_EVENT(Resized, WindowResizedEvent); ///< ´°¿Ú´óС±ä»¯ + KGE_DEFINE_EVENT(FocusChanged, WindowFocusChangedEvent); ///< »ñµÃ»òʧȥ½¹µã + KGE_DEFINE_EVENT(TitleChanged, WindowTitleChangedEvent); ///< ±êÌâ±ä»¯ + KGE_DEFINE_EVENT(Closed, WindowClosedEvent); ///< ´°¿Ú±»¹Ø±Õ + KGE_EVENT_END; + + /** @} */ } diff --git a/src/kiwano/core/EventDispatcher.h b/src/kiwano/core/EventDispatcher.h index f91f70eb..ed511ea3 100644 --- a/src/kiwano/core/EventDispatcher.h +++ b/src/kiwano/core/EventDispatcher.h @@ -40,17 +40,35 @@ namespace kiwano // Ìí¼Ó¼àÌýÆ÷ EventListener* AddListener( - String const& name, EventType type, EventListener::Callback callback ); // Ìí¼Ó¼àÌýÆ÷ EventListener* AddListener( + String const& name, EventType type, EventListener::Callback callback ); + template < + typename _EventTy, + typename = typename std::enable_if::value, int>::type + > + EventListener* AddListener(EventListener::Callback callback) + { + return AddListener(KGE_EVENT(_EventTy), callback); + } + + template < + typename _EventTy, + typename = typename std::enable_if::value, int> + > + EventListener* AddListener(String const& name, EventListener::Callback callback) + { + return AddListener(name, KGE_EVENT(_EventTy), callback); + } + // Æô¶¯¼àÌýÆ÷ void StartListeners( String const& listener_name diff --git a/src/kiwano/core/time.h b/src/kiwano/core/time.h index d063179f..284a8a56 100644 --- a/src/kiwano/core/time.h +++ b/src/kiwano/core/time.h @@ -106,8 +106,8 @@ namespace kiwano String ToString() const; /// \~chinese - /// @brief ʱ¼ä¶Î¸ñʽ»¯ - /// @param format ¸ñʽ + /// @brief ½âÎöʱ¼ä¶Î×Ö·û´® + /// @param str ʱ¼ä¶Î×Ö·û´® /// @details /// ʱ¼ä¶Î×Ö·û´®ÔÊÐíÊÇÓзûºÅµÄ¸¡µãÊý, ²¢ÇÒ´øÓÐʱ¼äµ¥Î»ºó׺ /// ÀýÈç: "300ms", "-1.5h", "2h45m" diff --git a/src/kiwano/platform/FileSystem.h b/src/kiwano/platform/FileSystem.h index 7ac2089c..48245ea3 100644 --- a/src/kiwano/platform/FileSystem.h +++ b/src/kiwano/platform/FileSystem.h @@ -89,7 +89,7 @@ namespace kiwano /** * \~chinese * @brief ɾ³ýÎļþ - * @param path Îļþ·¾¶ + * @param file_path Îļþ·¾¶ * @return ɾ³ýÊÇ·ñ³É¹¦ */ bool RemoveFile(String const& file_path) const; diff --git a/src/kiwano/ui/Button.cpp b/src/kiwano/ui/Button.cpp index b905e0a5..10a74a77 100644 --- a/src/kiwano/ui/Button.cpp +++ b/src/kiwano/ui/Button.cpp @@ -32,10 +32,10 @@ namespace kiwano { SetResponsible(true); - AddListener(events::MouseHover, Closure(this, &Button::UpdateStatus)); - AddListener(events::MouseOut, Closure(this, &Button::UpdateStatus)); - AddListener(events::MouseDown, Closure(this, &Button::UpdateStatus)); - AddListener(events::MouseUp, Closure(this, &Button::UpdateStatus)); + AddListener(MouseEvents::Hover(), Closure(this, &Button::UpdateStatus)); + AddListener(MouseEvents::Out(), Closure(this, &Button::UpdateStatus)); + AddListener(MouseEvents::Down(), Closure(this, &Button::UpdateStatus)); + AddListener(MouseEvents::Up(), Closure(this, &Button::UpdateStatus)); } Button::Button(const Callback& click) From 13cbca8f49f62d2b155c06dd408c0cf29620f613 Mon Sep 17 00:00:00 2001 From: Nomango Date: Sun, 22 Dec 2019 11:24:04 +0800 Subject: [PATCH 06/27] Remove event declare macros --- src/kiwano-physics/ContactEvent.h | 12 ----- src/kiwano/2d/DebugActor.cpp | 4 +- src/kiwano/2d/Layer.cpp | 14 ++--- src/kiwano/core/Event.h | 86 +++++++++++-------------------- src/kiwano/core/EventListener.h | 18 +++++++ src/kiwano/ui/Button.cpp | 13 ++--- 6 files changed, 61 insertions(+), 86 deletions(-) diff --git a/src/kiwano-physics/ContactEvent.h b/src/kiwano-physics/ContactEvent.h index 0010bb35..a01068f3 100644 --- a/src/kiwano-physics/ContactEvent.h +++ b/src/kiwano-physics/ContactEvent.h @@ -53,17 +53,5 @@ namespace kiwano ContactEndEvent(); ContactEndEvent(Contact const& contact); }; - - /** - * \addtogroup EventTypes - * @{ - */ - - KGE_EVENT_BEGIN(PhysicEvents); - KGE_DEFINE_EVENT(ContactBegin, ContactBeginEvent); ///< ½Ó´¥¿ªÊ¼ @see kiwano::physics::ContactBeginEvent - KGE_DEFINE_EVENT(ContactEnd, ContactEndEvent); ///< ½Ó´¥½áÊø @see kiwano::physics::ContactEndEvent - KGE_EVENT_END; - - /** @} */ } } diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index cbb1e3d7..67613533 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -66,8 +66,8 @@ namespace kiwano style.line_spacing = 20.f; debug_text_->SetStyle(style); - AddListener(MouseEvents::Hover(), [=](Event&) { SetOpacity(0.4f); }); - AddListener(MouseEvents::Out(), [=](Event&) { SetOpacity(1.f); }); + AddListener([=](Event&) { SetOpacity(0.4f); }); + AddListener([=](Event&) { SetOpacity(1.f); }); } DebugActor::~DebugActor() diff --git a/src/kiwano/2d/Layer.cpp b/src/kiwano/2d/Layer.cpp index abf5e776..f4b3a454 100644 --- a/src/kiwano/2d/Layer.cpp +++ b/src/kiwano/2d/Layer.cpp @@ -29,14 +29,14 @@ namespace kiwano { auto handler = Closure(this, &Layer::HandleMessages); - AddListener(MouseEvents::Down(), handler); - AddListener(MouseEvents::Up(), handler); - AddListener(MouseEvents::Move(), handler); - AddListener(MouseEvents::Wheel(), handler); + AddListener(handler); + AddListener(handler); + AddListener(handler); + AddListener(handler); - AddListener(KeyEvents::Down(), handler); - AddListener(KeyEvents::Up(), handler); - AddListener(KeyEvents::Char(), handler); + AddListener(handler); + AddListener(handler); + AddListener(handler); } Layer::~Layer() diff --git a/src/kiwano/core/Event.h b/src/kiwano/core/Event.h index c8388297..02a1cbfe 100644 --- a/src/kiwano/core/Event.h +++ b/src/kiwano/core/Event.h @@ -95,22 +95,47 @@ namespace kiwano return type_ == KGE_EVENT(_Ty); } + /// \~chinese + /// @brief ת»»ÎªÆäËûÀàÐÍʼþ + /// @throw std::bad_cast ÀàÐÍÎÞ·¨×ª»»Ê±Å׳ö + template < + typename _Ty, + typename = typename std::enable_if::value, int>::type + > + inline const _Ty& Cast() const + { + return *dynamic_cast(this); + } + + /// \~chinese + /// @brief ת»»ÎªÆäËûÀàÐÍʼþ + /// @throw std::bad_cast ÀàÐÍÎÞ·¨×ª»»Ê±Å׳ö + template < + typename _Ty, + typename = typename std::enable_if::value, int>::type + > + inline _Ty& Cast() + { + return *dynamic_cast<_Ty*>(this); + } + /// \~chinese /// @brief °²È«×ª»»ÎªÆäËûÀàÐÍʼþ - /// @throw std::bad_cast ÎÞ·¨×ª»»µÄÀàÐÍ + /// @throw std::bad_cast ÀàÐÍÎÞ·¨×ª»»Ê±Å׳ö template < typename _Ty, typename = typename std::enable_if::value, int>::type > inline const _Ty& SafeCast() const { - if (!IsType<_Ty>()) throw std::bad_cast(); - return *dynamic_cast(this); + if (!IsType<_Ty>()) + throw std::bad_cast(); + return Cast<_Ty>(); } /// \~chinese /// @brief °²È«×ª»»ÎªÆäËûÀàÐÍʼþ - /// @throw std::bad_cast ÎÞ·¨×ª»»µÄÀàÐÍ + /// @throw std::bad_cast ÀàÐÍÎÞ·¨×ª»»Ê±Å׳ö template < typename _Ty, typename = typename std::enable_if::value, int>::type @@ -305,57 +330,4 @@ namespace kiwano /** @} */ - - /** - * \~chinese - * \defgroup EventTypes ʼþÀàÐÍ - * - */ - - /** - * \addtogroup EventTypes - * @{ - */ - - -#define KGE_EVENT_BEGIN(NAME) struct NAME { -#define KGE_EVENT_END }; -#define KGE_DEFINE_EVENT(EVENT_NAME, EVENT_TYPE) \ - static inline const EventType& EVENT_NAME() \ - { \ - static EventType event_type = KGE_EVENT(EVENT_TYPE); \ - return event_type; \ - } - - /// \~chinese - /// @brief Êó±êʼþ - KGE_EVENT_BEGIN(MouseEvents); - KGE_DEFINE_EVENT(Move, MouseMoveEvent); ///< Êó±êÒÆ¶¯ - KGE_DEFINE_EVENT(Down, MouseDownEvent); ///< Êó±ê°´Ï - KGE_DEFINE_EVENT(Up, MouseUpEvent); ///< Êó±ȩ̂Æð - KGE_DEFINE_EVENT(Wheel, MouseWheelEvent); ///< ¹öÂÖ¹ö¶¯ - KGE_DEFINE_EVENT(Hover, MouseHoverEvent); ///< Êó±êÒÆÈë - KGE_DEFINE_EVENT(Out, MouseOutEvent); ///< Êó±êÒÆ³ö - KGE_DEFINE_EVENT(Click, MouseClickEvent); ///< Êó±êµã»÷ - KGE_EVENT_END; - - /// \~chinese - /// @brief ¼üÅ̰´¼üʼþ - KGE_EVENT_BEGIN(KeyEvents); - KGE_DEFINE_EVENT(Down, KeyDownEvent); ///< °´¼ü°´Ï - KGE_DEFINE_EVENT(Up, KeyUpEvent); ///< °´¼ü̧Æð - KGE_DEFINE_EVENT(Char, KeyCharEvent); ///< Êä³ö×Ö·û - KGE_EVENT_END; - - /// \~chinese - /// @brief ´°¿Úʼþ - KGE_EVENT_BEGIN(WindowEvents); - KGE_DEFINE_EVENT(Moved, WindowMovedEvent); ///< ´°¿ÚÒÆ¶¯ - KGE_DEFINE_EVENT(Resized, WindowResizedEvent); ///< ´°¿Ú´óС±ä»¯ - KGE_DEFINE_EVENT(FocusChanged, WindowFocusChangedEvent); ///< »ñµÃ»òʧȥ½¹µã - KGE_DEFINE_EVENT(TitleChanged, WindowTitleChangedEvent); ///< ±êÌâ±ä»¯ - KGE_DEFINE_EVENT(Closed, WindowClosedEvent); ///< ´°¿Ú±»¹Ø±Õ - KGE_EVENT_END; - - /** @} */ } diff --git a/src/kiwano/core/EventListener.h b/src/kiwano/core/EventListener.h index a7a082a0..1b7b195b 100644 --- a/src/kiwano/core/EventListener.h +++ b/src/kiwano/core/EventListener.h @@ -54,6 +54,24 @@ namespace kiwano Callback const& callback ); + template < + typename _EventTy, + typename = typename std::enable_if::value, int>::type + > + EventListener(Callback const& callback) + : EventListener(KGE_EVENT(_EventTy), callback) + { + } + + template < + typename _EventTy, + typename = typename std::enable_if::value, int>::type + > + EventListener(String const& name, Callback const& callback) + : EventListener(name, KGE_EVENT(_EventTy), callback) + { + } + virtual ~EventListener(); void Start(); diff --git a/src/kiwano/ui/Button.cpp b/src/kiwano/ui/Button.cpp index 10a74a77..83acd556 100644 --- a/src/kiwano/ui/Button.cpp +++ b/src/kiwano/ui/Button.cpp @@ -32,10 +32,10 @@ namespace kiwano { SetResponsible(true); - AddListener(MouseEvents::Hover(), Closure(this, &Button::UpdateStatus)); - AddListener(MouseEvents::Out(), Closure(this, &Button::UpdateStatus)); - AddListener(MouseEvents::Down(), Closure(this, &Button::UpdateStatus)); - AddListener(MouseEvents::Up(), Closure(this, &Button::UpdateStatus)); + AddListener(Closure(this, &Button::UpdateStatus)); + AddListener(Closure(this, &Button::UpdateStatus)); + AddListener(Closure(this, &Button::UpdateStatus)); + AddListener(Closure(this, &Button::UpdateStatus)); } Button::Button(const Callback& click) @@ -105,10 +105,7 @@ namespace kiwano void Button::UpdateStatus(Event& evt) { - auto mouse_evt = dynamic_cast(&evt); - KGE_ASSERT(mouse_evt != nullptr); - - if (enabled_ && (mouse_evt->target == this)) + if (enabled_ && (evt.Cast().target == this)) { if (evt.IsType()) { From 5ba5e4525c461989dcd113e0d4f0a5ac9167b819 Mon Sep 17 00:00:00 2001 From: Nomango Date: Mon, 23 Dec 2019 18:05:08 +0800 Subject: [PATCH 07/27] Add docs for Actors & Actions --- Doxyfile | 10 +- projects/kiwano/kiwano.vcxproj | 7 +- projects/kiwano/kiwano.vcxproj.filters | 24 +- src/kiwano-audio/AudioEngine.h | 6 +- src/kiwano-audio/Sound.h | 2 +- src/kiwano-audio/SoundPlayer.h | 2 +- src/kiwano-audio/Transcoder.cpp | 2 +- src/kiwano-imgui/ImGuiLayer.h | 2 +- src/kiwano-imgui/ImGuiModule.cpp | 2 +- src/kiwano-imgui/ImGuiModule.h | 2 +- src/kiwano-network/HttpClient.h | 2 +- src/kiwano-network/HttpRequest.h | 4 +- src/kiwano-network/HttpResponse.hpp | 2 +- src/kiwano-physics/Body.h | 4 +- src/kiwano-physics/Contact.h | 4 +- src/kiwano-physics/ContactEvent.h | 11 +- src/kiwano-physics/Fixture.h | 2 +- src/kiwano-physics/Joint.cpp | 110 ++--- src/kiwano-physics/Joint.h | 24 +- src/kiwano-physics/Shape.h | 12 +- src/kiwano/2d/Actor.h | 423 +++++++++--------- src/kiwano/2d/Canvas.cpp | 8 +- src/kiwano/2d/Canvas.h | 330 +++++++------- src/kiwano/2d/DebugActor.cpp | 14 +- src/kiwano/2d/DebugActor.h | 20 +- src/kiwano/2d/Frame.h | 74 ++- src/kiwano/2d/FrameSequence.cpp | 1 - src/kiwano/2d/FrameSequence.h | 51 ++- src/kiwano/2d/GifSprite.h | 134 ++++-- src/kiwano/2d/Layer.h | 112 +++-- src/kiwano/2d/ShapeActor.cpp | 2 +- src/kiwano/2d/ShapeActor.h | 337 +++++++++----- src/kiwano/2d/Sprite.h | 92 ++-- src/kiwano/2d/Stage.h | 25 +- src/kiwano/2d/Text.h | 175 -------- src/kiwano/2d/{Text.cpp => TextActor.cpp} | 62 +-- src/kiwano/2d/TextActor.h | 191 ++++++++ src/kiwano/2d/TextStyle.hpp | 56 ++- src/kiwano/2d/Transform.h | 14 +- src/kiwano/2d/Transition.h | 137 +++++- src/kiwano/2d/action/Action.cpp | 10 +- src/kiwano/2d/action/Action.h | 134 ++++-- src/kiwano/2d/action/ActionDelay.h | 21 +- src/kiwano/2d/action/ActionGroup.cpp | 4 +- src/kiwano/2d/action/ActionGroup.h | 89 ++-- src/kiwano/2d/action/ActionHelper.h | 244 +++++----- src/kiwano/2d/action/ActionManager.cpp | 3 +- src/kiwano/2d/action/ActionManager.h | 26 +- src/kiwano/2d/action/ActionTween.cpp | 90 ++-- src/kiwano/2d/action/ActionTween.h | 394 +++++++++------- src/kiwano/2d/action/ActionWalk.cpp | 8 +- src/kiwano/2d/action/ActionWalk.h | 129 +++--- src/kiwano/2d/action/Animation.cpp | 16 +- src/kiwano/2d/action/Animation.h | 47 +- src/kiwano/2d/include-forwards.h | 78 ---- src/kiwano/core/AsyncTask.h | 4 +- src/kiwano/core/Event.h | 4 +- src/kiwano/core/EventDispatcher.h | 2 +- src/kiwano/core/EventListener.h | 4 +- src/kiwano/core/Library.h | 2 +- src/kiwano/core/Logger.h | 2 +- src/kiwano/core/ObjectBase.h | 2 +- src/kiwano/core/RefCounter.hpp | 4 +- src/kiwano/core/Resource.h | 2 +- src/kiwano/core/SmartPtr.hpp | 2 +- src/kiwano/core/Timer.h | 4 +- src/kiwano/core/TimerManager.h | 2 +- src/kiwano/{common => core}/common.h | 0 src/kiwano/core/time.h | 8 +- src/kiwano/core/win32/ComPtr.hpp | 2 +- src/kiwano/kiwano.h | 44 +- src/kiwano/math/math.h | 2 +- src/kiwano/platform/Application.h | 22 +- src/kiwano/platform/Director.h | 16 +- src/kiwano/platform/Input.h | 18 +- src/kiwano/platform/Window.h | 4 +- src/kiwano/renderer/Brush.h | 2 +- src/kiwano/renderer/Color.h | 2 +- src/kiwano/renderer/FontCollection.h | 2 +- src/kiwano/renderer/Geometry.h | 4 +- src/kiwano/renderer/GifImage.h | 4 +- src/kiwano/renderer/LayerArea.h | 2 +- src/kiwano/renderer/RenderTarget.cpp | 7 +- src/kiwano/renderer/RenderTarget.h | 2 +- src/kiwano/renderer/Renderer.cpp | 10 +- src/kiwano/renderer/StrokeStyle.h | 10 +- src/kiwano/renderer/TextLayout.h | 5 +- src/kiwano/renderer/Texture.h | 2 +- src/kiwano/renderer/TextureCache.h | 4 +- .../renderer/win32/D2DDeviceResources.cpp | 2 +- src/kiwano/ui/Button.h | 2 + src/kiwano/ui/Menu.h | 2 + src/kiwano/utils/LocalStorage.h | 4 +- src/kiwano/utils/ResourceCache.cpp | 5 +- src/kiwano/utils/ResourceCache.h | 7 +- src/kiwano/utils/UserData.h | 2 +- 96 files changed, 2317 insertions(+), 1698 deletions(-) delete mode 100644 src/kiwano/2d/Text.h rename src/kiwano/2d/{Text.cpp => TextActor.cpp} (70%) create mode 100644 src/kiwano/2d/TextActor.h delete mode 100644 src/kiwano/2d/include-forwards.h rename src/kiwano/{common => core}/common.h (100%) diff --git a/Doxyfile b/Doxyfile index 561ccec7..000da894 100644 --- a/Doxyfile +++ b/Doxyfile @@ -19,7 +19,7 @@ EXTRACT_PRIVATE = NO EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = NO -HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO SHOW_INCLUDE_FILES = YES @@ -61,12 +61,8 @@ PREDEFINED = KGE_API= # This tag requires that the tag SEARCH_INCLUDES is set to YES. SEARCH_INCLUDES = YES -INCLUDE_PATH = src/ -INCLUDE_FILE_PATTERNS = *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = #--------------------------------------------------------------------------- # Configuration options related to the HTML output diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index 9b035779..5cba8576 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -11,15 +11,14 @@ + - - @@ -28,7 +27,7 @@ - + @@ -102,7 +101,7 @@ - + diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index e78486cc..8429e755 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -25,9 +25,6 @@ {9314f30d-5742-48b6-94e5-e3b4284106f6} - - {86e2d0f2-a9d0-4456-b6a5-d480228bbf82} - {30333461-e9bc-4709-84bd-ce6e0e1a3079} @@ -45,18 +42,12 @@ 2d - - 2d - 2d 2d - - 2d - 2d @@ -150,9 +141,6 @@ 2d - - common - 2d @@ -276,6 +264,12 @@ platform + + 2d + + + core + @@ -293,9 +287,6 @@ 2d - - 2d - 2d @@ -458,5 +449,8 @@ platform + + 2d + \ No newline at end of file diff --git a/src/kiwano-audio/AudioEngine.h b/src/kiwano-audio/AudioEngine.h index 9d0fb384..158810a9 100644 --- a/src/kiwano-audio/AudioEngine.h +++ b/src/kiwano-audio/AudioEngine.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #include #include #include @@ -52,12 +52,12 @@ namespace kiwano void DestroyComponent() override; - protected: + private: AudioEngine(); ~AudioEngine(); - protected: + private: IXAudio2* x_audio2_; IXAudio2MasteringVoice* mastering_voice_; }; diff --git a/src/kiwano-audio/Sound.h b/src/kiwano-audio/Sound.h index 85e4add4..a247d307 100644 --- a/src/kiwano-audio/Sound.h +++ b/src/kiwano-audio/Sound.h @@ -84,7 +84,7 @@ namespace kiwano float volume /* 1 ΪԭʼÒôÁ¿, ´óÓÚ 1 Ϊ·Å´óÒôÁ¿, 0 Ϊ×îСÒôÁ¿ */ ); - protected: + private: bool opened_; bool playing_; Transcoder transcoder_; diff --git a/src/kiwano-audio/SoundPlayer.h b/src/kiwano-audio/SoundPlayer.h index c7d3d91e..1b3f94f8 100644 --- a/src/kiwano-audio/SoundPlayer.h +++ b/src/kiwano-audio/SoundPlayer.h @@ -93,7 +93,7 @@ namespace kiwano // Çå³ý»º´æ void ClearCache(); - protected: + private: float volume_; using SoundMap = Map; diff --git a/src/kiwano-audio/Transcoder.cpp b/src/kiwano-audio/Transcoder.cpp index 4ddd43e4..ed3705dd 100644 --- a/src/kiwano-audio/Transcoder.cpp +++ b/src/kiwano-audio/Transcoder.cpp @@ -23,7 +23,7 @@ #endif #include -#include +#include #include #include #include diff --git a/src/kiwano-imgui/ImGuiLayer.h b/src/kiwano-imgui/ImGuiLayer.h index 59921cc7..f2928783 100644 --- a/src/kiwano-imgui/ImGuiLayer.h +++ b/src/kiwano-imgui/ImGuiLayer.h @@ -54,7 +54,7 @@ namespace kiwano public: void OnRender(RenderTarget* rt) override; - protected: + private: Map pipelines_; }; } diff --git a/src/kiwano-imgui/ImGuiModule.cpp b/src/kiwano-imgui/ImGuiModule.cpp index 1d79f6a7..d0fa9a0f 100644 --- a/src/kiwano-imgui/ImGuiModule.cpp +++ b/src/kiwano-imgui/ImGuiModule.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2019 Nomango -#include +#include #include #include #include diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h index 5ec0e712..17fa3db5 100644 --- a/src/kiwano-imgui/ImGuiModule.h +++ b/src/kiwano-imgui/ImGuiModule.h @@ -19,8 +19,8 @@ // THE SOFTWARE. #pragma once +#include #include -#include namespace kiwano { diff --git a/src/kiwano-network/HttpClient.h b/src/kiwano-network/HttpClient.h index 17ccaf6a..5e69be8d 100644 --- a/src/kiwano-network/HttpClient.h +++ b/src/kiwano-network/HttpClient.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #include #include #include diff --git a/src/kiwano-network/HttpRequest.h b/src/kiwano-network/HttpRequest.h index a2617058..706e66f1 100644 --- a/src/kiwano-network/HttpRequest.h +++ b/src/kiwano-network/HttpRequest.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include +#include #include #include @@ -73,7 +73,7 @@ namespace kiwano void SetResponseCallback(ResponseCallback const& callback); ResponseCallback const& GetResponseCallback() const; - protected: + private: Type type_; String url_; String data_; diff --git a/src/kiwano-network/HttpResponse.hpp b/src/kiwano-network/HttpResponse.hpp index a2d043b0..5de8be60 100644 --- a/src/kiwano-network/HttpResponse.hpp +++ b/src/kiwano-network/HttpResponse.hpp @@ -56,7 +56,7 @@ namespace kiwano String const& GetError() const; void SetError(String const& error_buffer); - protected: + private: bool succeed_; long response_code_; HttpRequestPtr request_; diff --git a/src/kiwano-physics/Body.h b/src/kiwano-physics/Body.h index e9f25989..4a4e575b 100644 --- a/src/kiwano-physics/Body.h +++ b/src/kiwano-physics/Body.h @@ -161,10 +161,10 @@ namespace kiwano void UpdateActor(); void UpdateFromActor(); - protected: + private: void UpdateFixtureFilter(b2Fixture* fixture); - protected: + private: Actor* actor_; World* world_; b2Body* body_; diff --git a/src/kiwano-physics/Contact.h b/src/kiwano-physics/Contact.h index 0f0ee915..cf537862 100644 --- a/src/kiwano-physics/Contact.h +++ b/src/kiwano-physics/Contact.h @@ -72,7 +72,7 @@ namespace kiwano const b2Contact* GetB2Contact() const { return contact_; } void SetB2Contact(b2Contact* contact) { contact_ = contact; } - protected: + private: b2Contact* contact_; }; @@ -104,7 +104,7 @@ namespace kiwano const b2ContactEdge* GetB2ContactEdge() const { return edge_; } void SetB2ContactEdge(b2ContactEdge* edge) { edge_ = edge; } - protected: + private: b2ContactEdge* edge_; }; diff --git a/src/kiwano-physics/ContactEvent.h b/src/kiwano-physics/ContactEvent.h index a01068f3..5dbdb460 100644 --- a/src/kiwano-physics/ContactEvent.h +++ b/src/kiwano-physics/ContactEvent.h @@ -26,8 +26,13 @@ namespace kiwano { namespace physics { + /** + * \addtogroup Events + * @{ + */ + /// \~chinese - /// @brief ½Ó´¥¿ªÊ¼Ê¼þ + /// @brief ÎïÀí½Ó´¥¿ªÊ¼Ê¼þ class KGE_API ContactBeginEvent : public Event { @@ -41,7 +46,7 @@ namespace kiwano }; /// \~chinese - /// @brief ½Ó´¥½áÊøÊ¼þ + /// @brief ÎïÀí½Ó´¥½áÊøÊ¼þ class KGE_API ContactEndEvent : public Event { @@ -53,5 +58,7 @@ namespace kiwano ContactEndEvent(); ContactEndEvent(Contact const& contact); }; + + /** @} */ } } diff --git a/src/kiwano-physics/Fixture.h b/src/kiwano-physics/Fixture.h index 2097d5a2..f1edb18e 100644 --- a/src/kiwano-physics/Fixture.h +++ b/src/kiwano-physics/Fixture.h @@ -91,7 +91,7 @@ namespace kiwano const b2Fixture* GetB2Fixture() const { return fixture_; } void SetB2Fixture(b2Fixture* fixture) { fixture_ = fixture; } - protected: + private: b2Fixture* fixture_; }; } diff --git a/src/kiwano-physics/Joint.cpp b/src/kiwano-physics/Joint.cpp index 05b209d7..c9ecd758 100644 --- a/src/kiwano-physics/Joint.cpp +++ b/src/kiwano-physics/Joint.cpp @@ -126,14 +126,14 @@ namespace kiwano void DistanceJoint::SetLength(float length) { - KGE_ASSERT(raw_joint_ && world_); - raw_joint_->SetLength(world_->Stage2World(length)); + KGE_ASSERT(raw_joint_ && GetWorld()); + raw_joint_->SetLength(GetWorld()->Stage2World(length)); } float DistanceJoint::GetLength() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetLength()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetLength()); } // @@ -181,14 +181,14 @@ namespace kiwano void FrictionJoint::SetMaxTorque(float length) { - KGE_ASSERT(raw_joint_ && world_); - raw_joint_->SetMaxTorque(world_->Stage2World(length)); + KGE_ASSERT(raw_joint_ && GetWorld()); + raw_joint_->SetMaxTorque(GetWorld()->Stage2World(length)); } float FrictionJoint::GetMaxTorque() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetMaxTorque()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetMaxTorque()); } // @@ -279,14 +279,14 @@ namespace kiwano void MotorJoint::SetMaxTorque(float length) { - KGE_ASSERT(raw_joint_ && world_); - raw_joint_->SetMaxTorque(world_->Stage2World(length)); + KGE_ASSERT(raw_joint_ && GetWorld()); + raw_joint_->SetMaxTorque(GetWorld()->Stage2World(length)); } float MotorJoint::GetMaxTorque() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetMaxTorque()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetMaxTorque()); } // @@ -326,32 +326,32 @@ namespace kiwano float PrismaticJoint::GetJointTranslation() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetJointTranslation()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetJointTranslation()); } float PrismaticJoint::GetJointSpeed() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetJointSpeed()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetJointSpeed()); } float PrismaticJoint::GetLowerLimit() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetLowerLimit()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetLowerLimit()); } float PrismaticJoint::GetUpperLimit() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetUpperLimit()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetUpperLimit()); } void PrismaticJoint::SetLimits(float lower, float upper) { - KGE_ASSERT(raw_joint_ && world_); - raw_joint_->SetLimits(world_->Stage2World(lower), world_->Stage2World(upper)); + KGE_ASSERT(raw_joint_ && GetWorld()); + raw_joint_->SetLimits(GetWorld()->Stage2World(lower), GetWorld()->Stage2World(upper)); } // @@ -386,14 +386,14 @@ namespace kiwano Point PulleyJoint::GetGroundAnchorA() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetGroundAnchorA()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetGroundAnchorA()); } Point PulleyJoint::GetGroundAnchorB() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetGroundAnchorB()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetGroundAnchorB()); } float PulleyJoint::GetRatio() const @@ -404,26 +404,26 @@ namespace kiwano float PulleyJoint::GetLengthA() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetLengthA()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetLengthA()); } float PulleyJoint::GetLengthB() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetLengthB()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetLengthB()); } float PulleyJoint::GetCurrentLengthA() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetCurrentLengthA()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetCurrentLengthA()); } float PulleyJoint::GetCurrentLengthB() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetCurrentLengthB()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetCurrentLengthB()); } // @@ -463,44 +463,44 @@ namespace kiwano float RevoluteJoint::GetJointAngle() const { - KGE_ASSERT(raw_joint_ && world_); + KGE_ASSERT(raw_joint_ && GetWorld()); return math::Radian2Degree(raw_joint_->GetJointAngle()); } float RevoluteJoint::GetJointSpeed() const { - KGE_ASSERT(raw_joint_ && world_); + KGE_ASSERT(raw_joint_ && GetWorld()); return math::Radian2Degree(raw_joint_->GetJointSpeed()); } float RevoluteJoint::GetLowerLimit() const { - KGE_ASSERT(raw_joint_ && world_); + KGE_ASSERT(raw_joint_ && GetWorld()); return math::Radian2Degree(raw_joint_->GetLowerLimit()); } float RevoluteJoint::GetUpperLimit() const { - KGE_ASSERT(raw_joint_ && world_); + KGE_ASSERT(raw_joint_ && GetWorld()); return math::Radian2Degree(raw_joint_->GetUpperLimit()); } void RevoluteJoint::SetLimits(float lower, float upper) { - KGE_ASSERT(raw_joint_ && world_); + KGE_ASSERT(raw_joint_ && GetWorld()); raw_joint_->SetLimits(math::Degree2Radian(lower), math::Degree2Radian(upper)); } void RevoluteJoint::SetMaxMotorTorque(float torque) { - KGE_ASSERT(raw_joint_ && world_); - raw_joint_->SetMaxMotorTorque(world_->Stage2World(torque)); + KGE_ASSERT(raw_joint_ && GetWorld()); + raw_joint_->SetMaxMotorTorque(GetWorld()->Stage2World(torque)); } float RevoluteJoint::GetMaxMotorTorque() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetMaxMotorTorque()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetMaxMotorTorque()); } // @@ -538,14 +538,14 @@ namespace kiwano void RopeJoint::SetMaxLength(float length) { - KGE_ASSERT(raw_joint_ && world_); - raw_joint_->SetMaxLength(world_->Stage2World(length)); + KGE_ASSERT(raw_joint_ && GetWorld()); + raw_joint_->SetMaxLength(GetWorld()->Stage2World(length)); } float RopeJoint::GetMaxLength() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetMaxLength()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetMaxLength()); } // @@ -615,26 +615,26 @@ namespace kiwano float WheelJoint::GetJointTranslation() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetJointTranslation()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetJointTranslation()); } float WheelJoint::GetJointLinearSpeed() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetJointLinearSpeed()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetJointLinearSpeed()); } void WheelJoint::SetMaxMotorTorque(float torque) { - KGE_ASSERT(raw_joint_ && world_); - raw_joint_->SetMaxMotorTorque(world_->Stage2World(torque)); + KGE_ASSERT(raw_joint_ && GetWorld()); + raw_joint_->SetMaxMotorTorque(GetWorld()->Stage2World(torque)); } float WheelJoint::GetMaxMotorTorque() const { - KGE_ASSERT(raw_joint_ && world_); - return world_->World2Stage(raw_joint_->GetMaxMotorTorque()); + KGE_ASSERT(raw_joint_ && GetWorld()); + return GetWorld()->World2Stage(raw_joint_->GetMaxMotorTorque()); } // diff --git a/src/kiwano-physics/Joint.h b/src/kiwano-physics/Joint.h index 1168d27f..61bf4660 100644 --- a/src/kiwano-physics/Joint.h +++ b/src/kiwano-physics/Joint.h @@ -86,7 +86,7 @@ namespace kiwano World* GetWorld() { return world_; } const World* GetWorld() const { return world_; } - protected: + private: b2Joint* joint_; World* world_; Type type_; @@ -147,7 +147,7 @@ namespace kiwano void SetDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetDampingRatio(ratio); } float GetDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetDampingRatio(); } - protected: + private: b2DistanceJoint* raw_joint_; }; @@ -199,7 +199,7 @@ namespace kiwano void SetMaxTorque(float torque); float GetMaxTorque() const; - protected: + private: b2FrictionJoint* raw_joint_; }; @@ -243,7 +243,7 @@ namespace kiwano void SetRatio(float ratio); float GetRatio() const; - protected: + private: b2GearJoint* raw_joint_; }; @@ -295,7 +295,7 @@ namespace kiwano void SetMaxTorque(float torque); float GetMaxTorque() const; - protected: + private: b2MotorJoint* raw_joint_; }; @@ -381,7 +381,7 @@ namespace kiwano void SetMaxMotorForce(float force) { KGE_ASSERT(raw_joint_); raw_joint_->SetMaxMotorForce(force); } float GetMaxMotorForce() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetMaxMotorForce(); } - protected: + private: b2PrismaticJoint* raw_joint_; }; @@ -444,7 +444,7 @@ namespace kiwano float GetCurrentLengthA() const; float GetCurrentLengthB() const; - protected: + private: b2PulleyJoint* raw_joint_; }; @@ -526,7 +526,7 @@ namespace kiwano void SetMaxMotorTorque(float torque); float GetMaxMotorTorque() const; - protected: + private: b2RevoluteJoint* raw_joint_; }; @@ -573,7 +573,7 @@ namespace kiwano void SetMaxLength(float length); float GetMaxLength() const; - protected: + private: b2RopeJoint* raw_joint_; }; @@ -625,7 +625,7 @@ namespace kiwano void SetDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetDampingRatio(ratio); } float GetDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetDampingRatio(); } - protected: + private: b2WeldJoint* raw_joint_; }; @@ -707,7 +707,7 @@ namespace kiwano void SetSpringDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetSpringDampingRatio(ratio); } float GetSpringDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetSpringDampingRatio(); } - protected: + private: b2WheelJoint* raw_joint_; }; @@ -768,7 +768,7 @@ namespace kiwano void SetDampingRatio(float ratio) { KGE_ASSERT(raw_joint_); raw_joint_->SetDampingRatio(ratio); } float GetDampingRatio() const { KGE_ASSERT(raw_joint_); return raw_joint_->GetDampingRatio(); } - protected: + private: b2MouseJoint* raw_joint_; }; } diff --git a/src/kiwano-physics/Shape.h b/src/kiwano-physics/Shape.h index 0d891f62..1e629d0c 100644 --- a/src/kiwano-physics/Shape.h +++ b/src/kiwano-physics/Shape.h @@ -40,7 +40,7 @@ namespace kiwano virtual void FitWorld(World* world) {} - protected: + private: b2Shape* shape_; }; @@ -57,7 +57,7 @@ namespace kiwano void FitWorld(World* world) override; - protected: + private: float radius_; Point offset_; b2CircleShape circle_; @@ -76,7 +76,7 @@ namespace kiwano void FitWorld(World* world) override; - protected: + private: float rotation_; Vec2 box_size_; Point offset_; @@ -96,7 +96,7 @@ namespace kiwano void FitWorld(World* world) override; - protected: + private: Vector vertexs_; b2PolygonShape polygon_; }; @@ -114,7 +114,7 @@ namespace kiwano void FitWorld(World* world) override; - protected: + private: Point p_[2]; b2EdgeShape edge_; }; @@ -132,7 +132,7 @@ namespace kiwano void FitWorld(World* world) override; - protected: + private: bool loop_; Vector vertexs_; b2ChainShape chain_; diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index 975c5338..9fcfc9fe 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -19,7 +19,10 @@ // THE SOFTWARE. #pragma once -#include +#include +#include +#include +#include #include #include #include @@ -27,10 +30,27 @@ namespace kiwano { + class Stage; class Director; class RenderTarget; - // ½ÇÉ« + KGE_DECLARE_SMART_PTR(Actor); + + /** + * \~chinese + * \defgroup Actors ½ÇÉ« + */ + + /** + * \addtogroup Actors + * @{ + */ + + /** + * \~chinese + * @brief ½ÇÉ« + * @details ½ÇÉ«ÊÇÎę̀ÉÏ×î»ù±¾µÄÔªËØ£¬ÊÇÍê³ÉäÖȾ¡¢¸üС¢Ê¼þ·Ö·¢µÈ¹¦ÄܵÄ×îСµ¥Î»£¬Ò²ÊǶ¯»­¡¢¶¨Ê±Æ÷¡¢Ê¼þ¼àÌýµÈ¹¦ÄܵÄÔØÌå + */ class KGE_API Actor : public ObjectBase , public TimerManager @@ -48,330 +68,330 @@ namespace kiwano Actor(); - // ¸üнÇÉ« + /// \~chinese + /// @brief ¸üнÇÉ« + /// @details ÿ֡»­ÃæË¢ÐÂǰµ÷Óøú¯Êý£¬ÖØÔظú¯ÊýÒÔʵÏÖ½ÇÉ«µÄ¸üд¦Àí + /// @param dt ¾àÉÏÒ»´Î¸üеÄʱ¼ä¼ä¸ô virtual void OnUpdate(Duration dt); - // äÖȾ½ÇÉ« + /// \~chinese + /// @brief äÖȾ½ÇÉ« + /// @details ÿ֡»­ÃæË¢ÐÂʱµ÷Óøú¯Êý£¬Ä¬Èϲ»½øÐÐäÖȾ£¬ÖØÔظú¯ÊýÒÔʵÏÖ¾ßÌåäÖȾ¹ý³Ì + /// @param rt äÖȾĿ±ê virtual void OnRender(RenderTarget* rt); - // »ñÈ¡ÏÔʾ״̬ + /// \~chinese + /// @brief »ñÈ¡ÏÔʾ״̬ bool IsVisible() const; - // »ñÈ¡ÏìӦ״̬ + /// \~chinese + /// @brief »ñÈ¡ÏìӦ״̬ bool IsResponsible() const; - // ÊÇ·ñÆôÓü¶ÁªÍ¸Ã÷¶È + /// \~chinese + /// @brief ÊÇ·ñÆôÓü¶ÁªÍ¸Ã÷¶È bool IsCascadeOpacityEnabled() const; - // »ñÈ¡Ãû³ÆµÄ Hash Öµ + /// \~chinese + /// @brief »ñÈ¡Ãû³ÆµÄ Hash Öµ size_t GetHashName() const; - // »ñÈ¡ Z Öá˳Ðò + /// \~chinese + /// @brief »ñÈ¡ Z Öá˳Ðò int GetZOrder() const; - // »ñÈ¡×ø±ê + /// \~chinese + /// @brief »ñÈ¡×ø±ê Point const& GetPosition() const; - // »ñÈ¡ x ×ø±ê + /// \~chinese + /// @brief »ñÈ¡ x ×ø±ê float GetPositionX() const; - // »ñÈ¡ y ×ø±ê + /// \~chinese + /// @brief »ñÈ¡ y ×ø±ê float GetPositionY() const; - // »ñÈ¡Ëõ·Å±ÈÀý + /// \~chinese + /// @brief »ñÈ¡Ëõ·Å±ÈÀý Point const& GetScale() const; - // »ñÈ¡ºáÏòËõ·Å±ÈÀý + /// \~chinese + /// @brief »ñÈ¡ºáÏòËõ·Å±ÈÀý float GetScaleX() const; - // »ñÈ¡×ÝÏòËõ·Å±ÈÀý + /// \~chinese + /// @brief »ñÈ¡×ÝÏòËõ·Å±ÈÀý float GetScaleY() const; - // »ñÈ¡´íÇÐ½Ç¶È + /// \~chinese + /// @brief »ñÈ¡´íÇÐ½Ç¶È Point const& GetSkew() const; - // »ñÈ¡ºáÏò´íÇÐ½Ç¶È + /// \~chinese + /// @brief »ñÈ¡ºáÏò´íÇÐ½Ç¶È float GetSkewX() const; - // »ñÈ¡×ÝÏò´íÇÐ½Ç¶È + /// \~chinese + /// @brief »ñÈ¡×ÝÏò´íÇÐ½Ç¶È float GetSkewY() const; - // »ñÈ¡Ðýת½Ç¶È + /// \~chinese + /// @brief »ñÈ¡Ðýת½Ç¶È float GetRotation() const; - // »ñÈ¡¿í¶È + /// \~chinese + /// @brief »ñÈ¡¿í¶È float GetWidth() const; - // »ñÈ¡¸ß¶È + /// \~chinese + /// @brief »ñÈ¡¸ß¶È float GetHeight() const; - // »ñÈ¡´óС + /// \~chinese + /// @brief »ñÈ¡´óС Size const& GetSize() const; - // »ñÈ¡Ëõ·ÅºóµÄ¿í¶È + /// \~chinese + /// @brief »ñÈ¡Ëõ·ÅºóµÄ¿í¶È float GetScaledWidth() const; - // »ñÈ¡Ëõ·ÅºóµÄ¸ß¶È + /// \~chinese + /// @brief »ñÈ¡Ëõ·ÅºóµÄ¸ß¶È float GetScaledHeight() const; - // »ñÈ¡Ëõ·ÅºóµÄ´óС + /// \~chinese + /// @brief »ñÈ¡Ëõ·ÅºóµÄ´óС Size GetScaledSize() const; - // »ñȡêµã + /// \~chinese + /// @brief »ñȡêµã Point const& GetAnchor() const; - // »ñÈ¡ x ·½Ïòêµã + /// \~chinese + /// @brief »ñÈ¡ x ·½Ïòêµã float GetAnchorX() const; - // »ñÈ¡ y ·½Ïòêµã + /// \~chinese + /// @brief »ñÈ¡ y ·½Ïòêµã float GetAnchorY() const; - // »ñȡ͸Ã÷¶È + /// \~chinese + /// @brief »ñȡ͸Ã÷¶È float GetOpacity() const; - // »ñÈ¡ÏÔʾ͸Ã÷¶È + /// \~chinese + /// @brief »ñÈ¡ÏÔʾ͸Ã÷¶È float GetDisplayedOpacity() const; - // »ñÈ¡±ä»» + /// \~chinese + /// @brief »ñÈ¡±ä»» Transform GetTransform() const; - // »ñÈ¡¸¸½ÇÉ« + /// \~chinese + /// @brief »ñÈ¡¸¸½ÇÉ« Actor* GetParent() const; - // »ñÈ¡ËùÔÚÎę̀ + /// \~chinese + /// @brief »ñÈ¡ËùÔÚÎę̀ Stage* GetStage() const; - // »ñÈ¡±ß¿ò + /// \~chinese + /// @brief »ñÈ¡±ß¿ò virtual Rect GetBounds() const; - // »ñÈ¡ÍâÇаüΧºÐ + /// \~chinese + /// @brief »ñÈ¡ÍâÇаüΧºÐ virtual Rect GetBoundingBox() const; - // »ñÈ¡¶þά±ä»»¾ØÕó + /// \~chinese + /// @brief »ñÈ¡¶þά±ä»»¾ØÕó Matrix3x2 const& GetTransformMatrix() const; - // »ñÈ¡¶þά±ä»»µÄÄæ¾ØÕó + /// \~chinese + /// @brief »ñÈ¡¶þά±ä»»µÄÄæ¾ØÕó Matrix3x2 const& GetTransformInverseMatrix() const; - // ÉèÖÃÊÇ·ñÏÔʾ - void SetVisible( - bool val - ); + /// \~chinese + /// @brief ÉèÖýÇÉ«ÊÇ·ñ¿É¼û + void SetVisible(bool val); - // ÉèÖÃÃû³Æ - void SetName( - String const& name - ); + /// \~chinese + /// @brief ÉèÖÃÃû³Æ + void SetName(String const& name); - // ÉèÖÃ×ø±ê - virtual void SetPosition( - Point const& point - ); + /// \~chinese + /// @brief ÉèÖÃ×ø±ê + virtual void SetPosition(Point const& point); - // ÉèÖÃ×ø±ê - void SetPosition( - float x, - float y - ); + /// \~chinese + /// @brief ÉèÖÃ×ø±ê + void SetPosition(float x, float y); - // ÉèÖúá×ø±ê - void SetPositionX( - float x - ); + /// \~chinese + /// @brief ÉèÖúá×ø±ê + void SetPositionX(float x); - // ÉèÖÃ×Ý×ø±ê - void SetPositionY( - float y - ); + /// \~chinese + /// @brief ÉèÖÃ×Ý×ø±ê + void SetPositionY(float y); - // ÒÆ¶¯×ø±ê - void Move( - Vec2 const& v - ); + /// \~chinese + /// @brief ÒÆ¶¯×ø±ê + void Move(Vec2 const& v); - // ÒÆ¶¯×ø±ê - void Move( - float vx, - float vy - ); + /// \~chinese + /// @brief ÒÆ¶¯×ø±ê + void Move(float vx, float vy); - // ÉèÖÃËõ·Å±ÈÀý - // ĬÈÏΪ (1.0, 1.0) - virtual void SetScale( - Vec2 const& scale - ); + /// \~chinese + /// @brief ÉèÖÃËõ·Å±ÈÀý£¬Ä¬ÈÏΪ (1.0, 1.0) + virtual void SetScale(Vec2 const& scale); - // ÉèÖÃËõ·Å±ÈÀý - // ĬÈÏΪ (1.0, 1.0) - void SetScale( - float scalex, - float scaley - ); + /// \~chinese + /// @brief ÉèÖÃËõ·Å±ÈÀý£¬Ä¬ÈÏΪ (1.0, 1.0) + void SetScale(float scalex, float scaley); - // ÉèÖôíÇÐ½Ç¶È - // ĬÈÏΪ (0, 0) - virtual void SetSkew( - Vec2 const& skew - ); + /// \~chinese + /// @brief ÉèÖôíÇнǶȣ¬Ä¬ÈÏΪ (0, 0) + virtual void SetSkew(Vec2 const& skew); - // ÉèÖôíÇÐ½Ç¶È - // ĬÈÏΪ (0, 0) - void SetSkew( - float skewx, - float skewy - ); + /// \~chinese + /// @brief ÉèÖôíÇнǶȣ¬Ä¬ÈÏΪ (0, 0) + void SetSkew(float skewx, float skewy); - // ÉèÖÃÐýת½Ç¶È - // ĬÈÏΪ 0 - virtual void SetRotation( - float rotation - ); + /// \~chinese + /// @brief ÉèÖÃÐýת½Ç¶È£¬Ä¬ÈÏΪ 0 + virtual void SetRotation(float rotation); - // ÉèÖÃêµãλÖà - // ĬÈÏΪ (0, 0), ·¶Î§ [0, 1] - virtual void SetAnchor( - Vec2 const& anchor - ); + /// \~chinese + /// @brief ÉèÖÃêµãλÖã¬Ä¬ÈÏΪ (0, 0), ·¶Î§ [0, 1] + virtual void SetAnchor(Vec2 const& anchor); - // ÉèÖÃêµãλÖà - // ĬÈÏΪ (0, 0), ·¶Î§ [0, 1] - void SetAnchor( - float anchorx, - float anchory - ); + /// \~chinese + /// @brief ÉèÖÃêµãλÖã¬Ä¬ÈÏΪ (0, 0), ·¶Î§ [0, 1] + void SetAnchor(float anchorx, float anchory); - // Ð޸Ŀí¶È - virtual void SetWidth( - float width - ); + /// \~chinese + /// @brief Ð޸Ŀí¶È + virtual void SetWidth(float width); - // ÐÞ¸Ä¸ß¶È - virtual void SetHeight( - float height - ); + /// \~chinese + /// @brief ÐÞ¸Ä¸ß¶È + virtual void SetHeight(float height); - // Ð޸ĴóС - virtual void SetSize( - Size const& size - ); + /// \~chinese + /// @brief Ð޸ĴóС + virtual void SetSize(Size const& size); - // Ð޸ĴóС - void SetSize( - float width, - float height - ); + /// \~chinese + /// @brief Ð޸ĴóС + void SetSize(float width, float height); - // ÉèÖÃ͸Ã÷¶È - // ĬÈÏΪ 1.0, ·¶Î§ [0, 1] - virtual void SetOpacity( - float opacity - ); + /// \~chinese + /// @brief ÉèÖÃ͸Ã÷¶È£¬Ä¬ÈÏΪ 1.0, ·¶Î§ [0, 1] + virtual void SetOpacity(float opacity); - // ÆôÓûò½ûÓü¶ÁªÍ¸Ã÷¶È - void SetCascadeOpacityEnabled( - bool enabled - ); + /// \~chinese + /// @brief ÆôÓûò½ûÓü¶ÁªÍ¸Ã÷¶È + void SetCascadeOpacityEnabled(bool enabled); - // ÉèÖöþά·ÂÉä±ä»» - void SetTransform( - Transform const& transform - ); + /// \~chinese + /// @brief ÉèÖöþά·ÂÉä±ä»» + void SetTransform(Transform const& transform); - // ÉèÖà Z Öá˳Ðò - // ĬÈÏΪ 0 - void SetZOrder( - int zorder - ); + /// \~chinese + /// @brief ÉèÖà Z Öá˳Ðò£¬Ä¬ÈÏΪ 0 + void SetZOrder(int zorder); - // ÊÇ·ñ¿ÉÏìÓ¦ (Êó±ê Hover | Out | Click ÏûÏ¢) - // ĬÈÏΪ false - void SetResponsible( - bool enable - ); + /// \~chinese + /// @brief ÉèÖýÇÉ«ÊÇ·ñ¿ÉÏìÓ¦£¬Ä¬ÈÏΪ false + /// @details ¿ÉÏìÓ¦µÄ½ÇÉ«»áÊÕµ½Êó±êµÄ Hover | Out | Click ÏûÏ¢ + void SetResponsible(bool enable); - // Ìí¼Ó×Ó½ÇÉ« - void AddChild( - ActorPtr child, - int zorder = 0 - ); + /// \~chinese + /// @brief Ìí¼Ó×Ó½ÇÉ« + void AddChild(ActorPtr child, int zorder = 0); - // Ìí¼Ó×Ó½ÇÉ« - void AddChild( - Actor* child, - int zorder = 0 - ); + /// \~chinese + /// @brief Ìí¼Ó×Ó½ÇÉ« + void AddChild(Actor* child, int zorder = 0); - // Ìí¼Ó¶à¸ö×Ó½ÇÉ« - void AddChildren( - Vector const& children - ); + /// \~chinese + /// @brief Ìí¼Ó¶à¸ö×Ó½ÇÉ« + void AddChildren(Vector const& children); - // »ñÈ¡Ãû³ÆÏàͬµÄ×Ó½ÇÉ« - Actor* GetChild( - String const& name - ) const; + /// \~chinese + /// @brief »ñÈ¡Ãû³ÆÏàͬµÄ×Ó½ÇÉ« + Actor* GetChild(String const& name) const; - // »ñÈ¡ËùÓÐÃû³ÆÏàͬµÄ×Ó½ÇÉ« - Vector GetChildren( - String const& name - ) const; + /// \~chinese + /// @brief »ñÈ¡ËùÓÐÃû³ÆÏàͬµÄ×Ó½ÇÉ« + Vector GetChildren(String const& name) const; - // »ñȡȫ²¿×Ó½ÇÉ« + /// \~chinese + /// @brief »ñȡȫ²¿×Ó½ÇÉ« Children& GetAllChildren(); - // »ñȡȫ²¿×Ó½ÇÉ« + /// \~chinese + /// @brief »ñȡȫ²¿×Ó½ÇÉ« Children const& GetAllChildren() const; - // ÒÆ³ý×Ó½ÇÉ« - void RemoveChild( - ActorPtr child - ); + /// \~chinese + /// @brief ÒÆ³ý×Ó½ÇÉ« + void RemoveChild(ActorPtr child); - // ÒÆ³ý×Ó½ÇÉ« - void RemoveChild( - Actor* child - ); + /// \~chinese + /// @brief ÒÆ³ý×Ó½ÇÉ« + void RemoveChild(Actor* child); - // ÒÆ³ýËùÓÐÃû³ÆÏàͬµÄ×Ó½ÇÉ« - void RemoveChildren( - String const& child_name - ); + /// \~chinese + /// @brief ÒÆ³ýËùÓÐÃû³ÆÏàͬµÄ×Ó½ÇÉ« + void RemoveChildren(String const& child_name); - // ÒÆ³ýËùÓнÇÉ« + /// \~chinese + /// @brief ÒÆ³ýËùÓнÇÉ« void RemoveAllChildren(); - // ´Ó¸¸½ÇÉ«ÒÆ³ý + /// \~chinese + /// @brief ´Ó¸¸½ÇÉ«ÒÆ³ý void RemoveFromParent(); - // ÅжϵãÊÇ·ñÔÚ½ÇÉ«ÄÚ + /// \~chinese + /// @brief ÅжϵãÊÇ·ñÔÚ½ÇÉ«ÄÚ virtual bool ContainsPoint(const Point& point) const; - // ÔÝÍ£½ÇÉ«¸üР+ /// \~chinese + /// @brief ÔÝÍ£½ÇÉ«¸üРvoid PauseUpdating(); - // ¼ÌÐø½ÇÉ«¸üР+ /// \~chinese + /// @brief ¼ÌÐø½ÇÉ«¸üРvoid ResumeUpdating(); - // ½ÇÉ«¸üÐÂÊÇ·ñÔÝÍ£ + /// \~chinese + /// @brief ½ÇÉ«¸üÐÂÊÇ·ñÔÝÍ£ bool IsUpdatePausing() const; - // ÉèÖøüÐÂʱµÄ»Øµ÷º¯Êý + /// \~chinese + /// @brief ÉèÖøüÐÂʱµÄ»Øµ÷º¯Êý void SetCallbackOnUpdate(UpdateCallback const& cb); - // »ñÈ¡¸üÐÂʱµÄ»Øµ÷º¯Êý + /// \~chinese + /// @brief »ñÈ¡¸üÐÂʱµÄ»Øµ÷º¯Êý UpdateCallback GetCallbackOnUpdate() const; - // äÖȾ½ÇÉ«±ß½ç + /// \~chinese + /// @brief äÖȾ½ÇÉ«±ß½ç void ShowBorder(bool show); - // ʼþ·Ö·¢ + /// \~chinese + /// @brief ·Ö·¢Ê¼þ void Dispatch(Event& evt) override; - // ÉèÖÃĬÈÏêµã - static void SetDefaultAnchor( - float anchor_x, - float anchor_y - ); + /// \~chinese + /// @brief ÉèÖÃĬÈÏêµã + static void SetDefaultAnchor(float anchor_x, float anchor_y); protected: virtual void Update(Duration dt); @@ -421,6 +441,9 @@ namespace kiwano mutable Matrix3x2 transform_matrix_inverse_; }; + /** @} */ + + inline void Actor::OnUpdate(Duration dt) { KGE_NOT_USED(dt); diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp index 6799fbd0..8caf6a5b 100644 --- a/src/kiwano/2d/Canvas.cpp +++ b/src/kiwano/2d/Canvas.cpp @@ -254,13 +254,17 @@ namespace kiwano } } - void Canvas::DrawText(String const& text, Point const& point) + void Canvas::DrawTextLayout(String const& text, Point const& point) { if (text.empty()) return; TextLayout layout(text, text_font_, text_style_); + DrawTextLayout(layout, point); + } + void Canvas::DrawTextLayout(TextLayout const& layout, Point const& point) + { rt_.DrawTextLayout(layout, point); } @@ -289,7 +293,7 @@ namespace kiwano geo_sink_.AddBezier(point1, point2, point3); } - void Canvas::AddArc(Point const & point, Point const & radius, float rotation, bool clockwise, bool is_small) + void Canvas::AddArc(Point const & point, Size const & radius, float rotation, bool clockwise, bool is_small) { geo_sink_.AddArc(point, radius, rotation, clockwise, is_small); } diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h index b05976e8..46dcc086 100644 --- a/src/kiwano/2d/Canvas.h +++ b/src/kiwano/2d/Canvas.h @@ -22,224 +22,251 @@ #include #include -#ifdef DrawText -# undef DrawText -#endif namespace kiwano { - // »­²¼ + KGE_DECLARE_SMART_PTR(Canvas); + + /** + * \addtogroup Actors + * @{ + */ + + /** + * \~chinese + * @brief »­²¼£¬ÓÃÓÚ»æÖÆÍ¼Ôª + */ class KGE_API Canvas : public Actor { public: + /// \~chinese + /// @brief ¹¹½¨¿Õ»­²¼ Canvas(); virtual ~Canvas(); - // ¿ªÊ¼»æÍ¼ + /// \~chinese + /// @brief ¿ªÊ¼»æÍ¼ void BeginDraw(); - // ½áÊø»æÍ¼ + /// \~chinese + /// @brief ½áÊø»æÍ¼ void EndDraw(); - // »­Ö±Ïß - void DrawLine( - Point const& begin, - Point const& end - ); + /// \~chinese + /// @brief »­Ïß¶Î + /// @param begin Ïß¶ÎÆðµã + /// @param end Ïß¶ÎÖÕµã + void DrawLine(Point const& begin, Point const& end); - // »­Ô²Ðα߿ò - void DrawCircle( - Point const& center, - float radius - ); + /// \~chinese + /// @brief »­Ô²Ðα߿ò + /// @param center Ô²ÐÎÔ­µã + /// @param radius Ô²Ðΰ뾶 + void DrawCircle(Point const& center, float radius); - // »­ÍÖÔ²Ðα߿ò - void DrawEllipse( - Point const& center, - Vec2 const& radius - ); + /// \~chinese + /// @brief »­ÍÖÔ²Ðα߿ò + /// @param center ÍÖÔ²Ô­µã + /// @param radius ÍÖÔ²°ë¾¶ + void DrawEllipse(Point const& center, Vec2 const& radius); - // »­¾ØÐα߿ò - void DrawRect( - Rect const& rect - ); + /// \~chinese + /// @brief »­¾ØÐα߿ò + /// @param rect ¾ØÐÎ + void DrawRect(Rect const& rect); - // »­Ô²½Ç¾ØÐα߿ò - void DrawRoundedRect( - Rect const& rect, - Vec2 const& radius - ); + /// \~chinese + /// @brief »­Ô²½Ç¾ØÐα߿ò + /// @param rect ¾ØÐÎ + /// @param radius ¾ØÐÎÔ²½Ç°ë¾¶ + void DrawRoundedRect(Rect const& rect, Vec2 const& radius); - // Ìî³äÔ²ÐÎ - void FillCircle( - Point const& center, - float radius - ); + /// \~chinese + /// @brief Ìî³äÔ²ÐÎ + /// @param center Ô²ÐÎÔ­µã + /// @param radius Ô²Ðΰ뾶 + void FillCircle(Point const& center, float radius); - // Ìî³äÍÖÔ²ÐÎ - void FillEllipse( - Point const& center, - Vec2 const& radius - ); + /// \~chinese + /// @brief Ìî³äÍÖÔ²ÐÎ + /// @param center ÍÖÔ²Ô­µã + /// @param radius ÍÖÔ²°ë¾¶ + void FillEllipse(Point const& center, Vec2 const& radius); - // Ìî³ä¾ØÐÎ - void FillRect( - Rect const& rect - ); + /// \~chinese + /// @brief Ìî³ä¾ØÐÎ + /// @param rect ¾ØÐÎ + void FillRect(Rect const& rect); - // Ìî³äÔ²½Ç¾ØÐÎ - void FillRoundedRect( - Rect const& rect, - Vec2 const& radius - ); + /// \~chinese + /// @brief Ìî³äÔ²½Ç¾ØÐÎ + /// @param rect ¾ØÐÎ + /// @param radius ¾ØÐÎÔ²½Ç°ë¾¶ + void FillRoundedRect(Rect const& rect, Vec2 const& radius); - // »­Í¼ - void DrawTexture( - Texture const& texture, - const Rect* src_rect = nullptr, - const Rect* dest_rect = nullptr - ); + /// \~chinese + /// @brief »æÖÆÎÆÀí + /// @param texture ÎÆÀí + /// @param src_rect ÎÆÀí²Ã¼ôÇøÓò + /// @param dest_rect »æÖÆÄ¿±êÇøÓò + void DrawTexture(Texture const& texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr); - // »­ÎÄ×Ö - void DrawText( - String const& text, /* ÎÄ×Ö */ - Point const& point /* ÎÄ×ÖλÖà */ - ); + /// \~chinese + /// @brief »æÖÆÎÄ×Ö²¼¾Ö + /// @param text ÎÄ×Ö + /// @param point »æÖÆÎÄ×ÖµÄλÖà + void DrawTextLayout(String const& text, Point const& point); - // ¿ªÊ¼»æÖÆÂ·¾¶ - void BeginPath( - Point const& begin_pos /* ·¾¶Æðʼµã */ - ); + /// \~chinese + /// @brief »æÖÆÎÄ×Ö²¼¾Ö + /// @param layout ÎÄ×Ö²¼¾Ö + /// @param point »æÖƲ¼¾ÖµÄλÖà + void DrawTextLayout(TextLayout const& layout, Point const& point); - // ½áÊøÂ·¾¶ - void EndPath( - bool closed = true /* ·¾¶ÊÇ·ñ±ÕºÏ */ - ); + /// \~chinese + /// @brief ¿ªÊ¼»æÖÆÂ·¾¶ + /// @param begin_pos ·¾¶Æðʼµã + void BeginPath(Point const& begin_pos); - // Ìí¼ÓÒ»ÌõÏß¶Î - void AddLine( - Point const& point /* ¶Ëµã */ - ); + /// \~chinese + /// @brief ½áÊøÂ·¾¶ + /// @param closed ·¾¶ÊÇ·ñ±ÕºÏ + void EndPath(bool closed = true); - // Ìí¼Ó¶àÌõÏß¶Î - void AddLines( - Vector const& points - ); + /// \~chinese + /// @brief Ìí¼ÓÒ»ÌõÏß¶Î + /// @param point ¶Ëµã + void AddLine(Point const& point); - // Ìí¼ÓÒ»ÌõÈý´Î·½±´Èû¶ûÇúÏß - void AddBezier( - Point const& point1, /* ±´Èû¶ûÇúÏߵĵÚÒ»¸ö¿ØÖƵã */ - Point const& point2, /* ±´Èû¶ûÇúÏߵĵڶþ¸ö¿ØÖƵã */ - Point const& point3 /* ±´Èû¶ûÇúÏßµÄÖÕµã */ - ); + /// \~chinese + /// @brief Ìí¼Ó¶àÌõÏß¶Î + /// @param points ¶Ëµã¼¯ºÏ + void AddLines(Vector const& points); - // Ìí¼Ó»¡Ïß - void AddArc( - Point const& point, /* ÖÕµã */ - Point const& radius, /* ÍÖÔ²°ë¾¶ */ - float rotation, /* ÍÖÔ²Ðýת½Ç¶È */ - bool clockwise = true, /* ˳ʱÕë or ÄæÊ±Õë */ - bool is_small = true /* ÊÇ·ñȡСÓÚ 180¡ã µÄ»¡ */ - ); + /// \~chinese + /// @brief Ìí¼ÓÒ»ÌõÈý´Î·½±´Èû¶ûÇúÏß + /// @param point1 ±´Èû¶ûÇúÏߵĵÚÒ»¸ö¿ØÖƵã + /// @param point2 ±´Èû¶ûÇúÏߵĵڶþ¸ö¿ØÖƵã + /// @param point3 ±´Èû¶ûÇúÏßµÄÖÕµã + void AddBezier(Point const& point1, Point const& point2, Point const& point3); - // ·¾¶Ãè±ß + /// \~chinese + /// @brief Ìí¼Ó»¡Ïß + /// @param point ÖÕµã + /// @param radius ÍÖÔ²°ë¾¶ + /// @param rotation ÍÖÔ²Ðýת½Ç¶È + /// @param clockwise ˳ʱÕë or ÄæÊ±Õë + /// @param is_small ÊÇ·ñȡСÓÚ 180¡ã µÄ»¡ + void AddArc(Point const& point, Size const& radius, float rotation, bool clockwise = true, bool is_small = true); + + /// \~chinese + /// @brief ÒÔÃè±ßµÄ·½Ê½»æÖÆÂ·¾¶ void StrokePath(); - // ·¾¶Ìî³ä + /// \~chinese + /// @brief ÒÔÌî³äµÄ·½Ê½»æÖÆÂ·¾¶ void FillPath(); - // Çå¿Õ»­²¼ + /// \~chinese + /// @brief Çå¿Õ»­²¼ void Clear(); - // Çå¿Õ»­²¼ - void Clear( - Color const& clear_color - ); + /// \~chinese + /// @brief Çå¿Õ»­²¼ + /// @param clear_color Çå¿ÕÑÕÉ« + void Clear(Color const& clear_color); - // ÉèÖÃÌî³äÑÕÉ« - void SetFillColor( - Color const& color - ); + /// \~chinese + /// @brief ÉèÖÃÌî³äÑÕÉ« + /// @param color Ìî³äÑÕÉ« + void SetFillColor(Color const& color); - // ÉèÖÃÂÖÀªÑÕÉ« - void SetStrokeColor( - Color const& color - ); + /// \~chinese + /// @brief ÉèÖÃÂÖÀªÑÕÉ« + /// @param color ÂÖÀªÑÕÉ« + void SetStrokeColor(Color const& color); - // ÉèÖÃÂÖÀª¿í¶È - void SetStrokeWidth( - float width - ); + /// \~chinese + /// @brief ÉèÖÃÂÖÀª¿í¶È + /// @param width ÂÖÀª¿í¶È + void SetStrokeWidth(float width); - // ÉèÖÃÂÖÀªÑùʽ - void SetStrokeStyle( - StrokeStyle stroke_style - ); + /// \~chinese + /// @brief ÉèÖÃÂÖÀªÑùʽ + /// @param stroke_style ÂÖÀªÑùʽ + void SetStrokeStyle(StrokeStyle stroke_style); - // ÉèÖÃÎÄ×Ö×ÖÌå - void SetTextFont( - Font const& font - ); + /// \~chinese + /// @brief ÉèÖÃÎÄ×Ö×ÖÌå + /// @param font ÎÄ×Ö×ÖÌå + void SetTextFont(Font const& font); - // ÉèÖÃÎÄ×Ö»­Ë¢Ñùʽ - void SetTextStyle( - TextStyle const& text_style - ); + /// \~chinese + /// @brief ÉèÖÃÎÄ×Ö»­Ë¢Ñùʽ + /// @param text_style ÎÄ×Ö»­Ë¢Ñùʽ + void SetTextStyle(TextStyle const& text_style); - // ÉèÖû­±Ê͸Ã÷¶È - void SetBrushOpacity( - float opacity - ); + /// \~chinese + /// @brief ÉèÖû­±Ê͸Ã÷¶È + /// @param opacity ͸Ã÷¶È£¬·¶Î§ [0.0 - 1.0] + void SetBrushOpacity(float opacity); - // »­±Ê¶þά±ä»» - void SetBrushTransform( - Transform const& transform - ); + /// \~chinese + /// @brief ÉèÖû­±Ê¶þά±ä»» + /// @param transform ¶þά±ä»» + void SetBrushTransform(Transform const& transform); - // »­±Ê¶þά±ä»» - void SetBrushTransform( - Matrix3x2 const& transform - ); + /// \~chinese + /// @brief ÉèÖû­±Ê¶þά±ä»»¾ØÕó + /// @param transform ¶þά±ä»»¾ØÕó + void SetBrushTransform(Matrix3x2 const& transform); - // ÉèÖÃͼ²ã - void PushLayerArea( - LayerArea& area - ); + /// \~chinese + /// @brief Ìí¼ÓÒ»¸öͼ²ã + /// @param area ͼ²ãÇøÓò + void PushLayerArea(LayerArea& area); - // µ¯³öͼ²ã + /// \~chinese + /// @brief ɾ³ý×î½üÌí¼ÓµÄͼ²ã void PopLayerArea(); - // ÉèÖòüôÇøÓò - void PushClipRect( - Rect const& clip_rect - ); + /// \~chinese + /// @brief Ìí¼ÓÒ»¸ö²Ã¼ôÇøÓò + /// @param clip_rect ²Ã¼ô¾ØÐÎ + void PushClipRect(Rect const& clip_rect); - // µ¯³ö²Ã¼ôÇøÓò + /// \~chinese + /// @brief ɾ³ý×î½üÌí¼ÓµÄ²Ã¼ôÇøÓò void PopClipRect(); - // »ñÈ¡Ìî³äÑÕÉ« + /// \~chinese + /// @brief »ñÈ¡Ìî³äÑÕÉ« Color GetFillColor() const; - // »ñÈ¡ÂÖÀªÑÕÉ« + /// \~chinese + /// @brief »ñÈ¡ÂÖÀªÑÕÉ« Color GetStrokeColor() const; - // »ñÈ¡ÂÖÀª¿í¶È + /// \~chinese + /// @brief »ñÈ¡ÂÖÀª¿í¶È float GetStrokeWidth() const; - // »ñÈ¡»­±Ê͸Ã÷¶È + /// \~chinese + /// @brief »ñÈ¡»­±Ê͸Ã÷¶È float GetBrushOpacity() const; - // µ¼³öΪͼƬ + /// \~chinese + /// @brief µ¼³öÎÆÀí Texture ExportToTexture() const; void OnRender(RenderTarget* rt) override; - protected: + private: void UpdateCache() const; - protected: + private: float stroke_width_; Color fill_color_; Color stroke_color_; @@ -252,4 +279,7 @@ namespace kiwano mutable Texture texture_cached_; mutable TextureRenderTarget rt_; }; + + /** @} */ + } diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index 67613533..c64f3380 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -19,7 +19,6 @@ // THE SOFTWARE. #include -#include #include #include @@ -31,7 +30,7 @@ namespace kiwano { class comma_numpunct : public std::numpunct { - protected: + private: virtual wchar_t do_thousands_sep() const override { return L','; @@ -42,6 +41,8 @@ namespace kiwano return "\03"; } }; + + std::locale comma_locale(std::locale(), new comma_numpunct); } DebugActor::DebugActor() @@ -52,7 +53,7 @@ namespace kiwano SetResponsible(true); SetCascadeOpacityEnabled(true); - debug_text_ = new Text; + debug_text_ = new TextActor; debug_text_->SetPosition(Point{ 10, 10 }); this->AddChild(debug_text_); @@ -94,11 +95,8 @@ namespace kiwano StringStream ss; - { - // For formatting integers with commas - static std::locale comma_locale(std::locale(), new comma_numpunct); - (void)ss.imbue(comma_locale); - } + // For formatting integers with commas + (void)ss.imbue(comma_locale); ss << "Fps: " << frame_time_.size() << std::endl; diff --git a/src/kiwano/2d/DebugActor.h b/src/kiwano/2d/DebugActor.h index 7c4299e1..b2a4b996 100644 --- a/src/kiwano/2d/DebugActor.h +++ b/src/kiwano/2d/DebugActor.h @@ -20,9 +20,20 @@ #pragma once #include +#include +#include namespace kiwano { + /** + * \addtogroup Actors + * @{ + */ + + /** + * \~chinese + * @brief µ÷ÊÔ½Úµã + */ class KGE_API DebugActor : public Actor { @@ -35,9 +46,12 @@ namespace kiwano void OnUpdate(Duration dt) override; - protected: - Color background_color_; - TextPtr debug_text_; + private: + Color background_color_; + TextActorPtr debug_text_; Vector