From 422305a3fa0afd054cc621fc79ec0a9cd1cad93d Mon Sep 17 00:00:00 2001 From: vczh Date: Sun, 30 Apr 2023 02:21:30 -0700 Subject: [PATCH] Update release --- Import/GacUI.Windows.h | 3 +- Import/GacUI.cpp | 5 - Import/GacUI.h | 28 +- Import/Vlpp.cpp | 34 +- Import/Vlpp.h | 2301 ++++++++++-------- Import/VlppGlrParser.h | 15 +- Import/VlppOS.Linux.cpp | 51 +- Import/VlppOS.Windows.cpp | 49 - Import/VlppOS.cpp | 51 + Import/VlppOS.h | 8 +- Import/VlppParser.h | 48 +- Import/VlppReflection.h | 63 +- Import/VlppRegex.h | 8 +- Import/VlppWorkflowCompiler.cpp | 3 +- Import/VlppWorkflowRuntime.cpp | 4 +- Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x64 | Bin 25176 -> 25176 bytes Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x86 | Bin 25176 -> 25176 bytes 17 files changed, 1407 insertions(+), 1264 deletions(-) diff --git a/Import/GacUI.Windows.h b/Import/GacUI.Windows.h index fc0a87f0..7037ea92 100644 --- a/Import/GacUI.Windows.h +++ b/Import/GacUI.Windows.h @@ -461,6 +461,7 @@ Renderers ColorItemResource selectedFocused; ColorItemResource selectedUnfocused; + std::partial_ordering operator<=>(const ColorEntryResource&) const { return std::partial_ordering::unordered; } bool operator==(const ColorEntryResource& value) const { return false; } }; @@ -1687,8 +1688,8 @@ Renderers ColorItemResource selectedFocused; ColorItemResource selectedUnfocused; + std::partial_ordering operator<=>(const ColorEntryResource&) const { return std::partial_ordering::unordered; } bool operator==(const ColorEntryResource& value){return false;} - bool operator!=(const ColorEntryResource& value){return true;} }; typedef collections::Array ColorArray; diff --git a/Import/GacUI.cpp b/Import/GacUI.cpp index ff57eeb0..f6a813bf 100644 --- a/Import/GacUI.cpp +++ b/Import/GacUI.cpp @@ -15259,11 +15259,6 @@ TextItem { } - bool TextItem::operator==(const TextItem& value)const - { - return text == value.text; - } - const WString& TextItem::GetText() { return text; diff --git a/Import/GacUI.h b/Import/GacUI.h index 96c1670d..b3cb1c49 100644 --- a/Import/GacUI.h +++ b/Import/GacUI.h @@ -74,8 +74,7 @@ Enumerations }; #define GUI_DEFINE_COMPARE_OPERATORS(TYPE)\ - std::strong_ordering operator<=>(const TYPE&) const = default;\ - bool operator==(const TYPE&) const = default;\ + auto operator<=>(const TYPE&) const = default;\ /*********************************************************************** TextPos @@ -1581,8 +1580,7 @@ INativeWindow BoolOption TitleBarOption = BoolOption::Customizable; BoolOption CustomFrameEnabled = BoolOption::Customizable; - std::strong_ordering operator<=>(const NativeWindowFrameConfig&) const = default; - bool operator==(const NativeWindowFrameConfig&) const = default; + auto operator<=>(const NativeWindowFrameConfig&) const = default; static const NativeWindowFrameConfig Default; }; @@ -5109,7 +5107,7 @@ Flow Compositions /// The distance value. vint distance = 0; - bool operator==(const GuiFlowOption& value) const = default; + GUI_DEFINE_COMPARE_OPERATORS(GuiFlowOption) }; /// @@ -5936,7 +5934,7 @@ Table Compositions { } - bool operator==(const GuiCellOption& value) const = default; + GUI_DEFINE_COMPARE_OPERATORS(GuiCellOption) /// Creates an absolute sizing option /// The created option. @@ -6492,13 +6490,15 @@ Helpers {\ TVALUE resource;\ vint counter;\ - bool operator==(const Package& package)const{return false;}\ + std::partial_ordering operator<=>(const Package&) const { return std::partial_ordering::unordered; }\ + bool operator==(const Package&)const{return false;}\ };\ struct DeadPackage\ {\ TKEY key;\ TVALUE value;\ - bool operator==(const DeadPackage& package)const{return false;}\ + std::partial_ordering operator<=>(const DeadPackage&) const { return std::partial_ordering::unordered; }\ + bool operator==(const DeadPackage&)const{return false;}\ };\ Dictionary aliveResources;\ List deadResources;\ @@ -10540,8 +10540,7 @@ Rich Content Document (style) static DocumentFontSize Parse(const WString& value); WString ToString()const; - std::partial_ordering operator<=>(const DocumentFontSize&) const = default; - bool operator==(const DocumentFontSize&) const = default; + auto operator<=>(const DocumentFontSize&) const = default; }; /// Represents a text style. @@ -10922,7 +10921,7 @@ Elements int radiusX = 0; int radiusY = 0; - bool operator==(const ElementShape& value) const = default; + GUI_DEFINE_COMPARE_OPERATORS(ElementShape) }; /// @@ -11914,6 +11913,8 @@ Colorized Plain Text (model) ~TextLine(); static vint CalculateBufferLength(vint dataLength); + + std::partial_ordering operator<=>(const TextLine&) const { return std::partial_ordering::unordered; } bool operator==(const TextLine& value) const { return false; } /// @@ -14279,7 +14280,8 @@ TextItemProvider TextItem(const WString& _text, bool _checked=false); ~TextItem(); - bool operator==(const TextItem& value)const; + std::strong_ordering operator<=>(const TextItem& value) const { return text <=> value.text; } + bool operator==(const TextItem& value) const { return text == value.text; } /// Get the text of this item. /// The text of this item. @@ -21684,6 +21686,8 @@ namespace vl vint column = 0; vint rowSpan = 1; vint columnSpan = 1; + + auto operator<=>(const SiteValue&) const = default; }; class LocalizedStrings diff --git a/Import/Vlpp.cpp b/Import/Vlpp.cpp index a6736fcc..031086f2 100644 --- a/Import/Vlpp.cpp +++ b/Import/Vlpp.cpp @@ -947,6 +947,7 @@ namespace vl char* endptr = 0; vint result = strtol(string.Buffer(), &endptr, 10); success = endptr == string.Buffer() + string.Length() && itoa(result) == string; + if (success) success &= (_I32_MIN <= result && result <= _I32_MAX); return result; } @@ -955,6 +956,7 @@ namespace vl wchar_t* endptr = 0; vint result = wcstol(string.Buffer(), &endptr, 10); success = endptr == string.Buffer() + string.Length() && itow(result) == string; + if (success) success &= (_I32_MIN <= result && result <= _I32_MAX); return result; } @@ -979,6 +981,7 @@ namespace vl char* endptr = 0; vuint result = strtoul(string.Buffer(), &endptr, 10); success = endptr == string.Buffer() + string.Length() && utoa(result) == string; + if (success) success &= (result <= _UI32_MAX); return result; } @@ -987,6 +990,7 @@ namespace vl wchar_t* endptr = 0; vuint result = wcstoul(string.Buffer(), &endptr, 10); success = endptr == string.Buffer() + string.Length() && utow(result) == string; + if (success) success &= (result <= _UI32_MAX); return result; } @@ -1025,61 +1029,71 @@ namespace vl vint atoi(const AString& string) { bool success = false; - return atoi_test(string, success); + vint result = atoi_test(string, success); + return success ? result : 0; } vint wtoi(const WString& string) { bool success = false; - return wtoi_test(string, success); + vint result = wtoi_test(string, success); + return success ? result : 0; } vint64_t atoi64(const AString& string) { bool success = false; - return atoi64_test(string, success); + vint64_t result = atoi64_test(string, success); + return success ? result : 0; } vint64_t wtoi64(const WString& string) { bool success = false; - return wtoi64_test(string, success); + vint64_t result = wtoi64_test(string, success); + return success ? result : 0; } vuint atou(const AString& string) { bool success = false; - return atou_test(string, success); + vuint result = atou_test(string, success); + return success ? result : 0; } vuint wtou(const WString& string) { bool success = false; - return wtou_test(string, success); + vuint result = wtou_test(string, success); + return success ? result : 0; } vuint64_t atou64(const AString& string) { bool success = false; - return atou64_test(string, success); + vuint64_t result = atou64_test(string, success); + return success ? result : 0; } vuint64_t wtou64(const WString& string) { bool success = false; - return wtou64_test(string, success); + vuint64_t result = wtou64_test(string, success); + return success ? result : 0; } double atof(const AString& string) { bool success = false; - return atof_test(string, success); + double result = atof_test(string, success); + return success ? result : 0; } double wtof(const WString& string) { bool success = false; - return wtof_test(string, success); + double result = wtof_test(string, success); + return success ? result : 0; } AString itoa(vint number) diff --git a/Import/Vlpp.h b/Import/Vlpp.h index 24c5ad9f..60b8f85d 100644 --- a/Import/Vlpp.h +++ b/Import/Vlpp.h @@ -14,9 +14,10 @@ Licensed under https://github.com/vczh-libraries/License #ifndef VCZH_BASIC #define VCZH_BASIC +#include + #ifdef VCZH_CHECK_MEMORY_LEAKS #define _CRTDBG_MAP_ALLOC -#include #include #define VCZH_CHECK_MEMORY_LEAKS_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new VCZH_CHECK_MEMORY_LEAKS_NEW @@ -53,13 +54,6 @@ static_assert(sizeof(wchar_t) == sizeof(char32_t), "wchar_t is not UTF-32."); static_assert(false, "wchar_t configuration is not right."); #endif -#if defined VCZH_ARM -#elif defined VCZH_MSVC -#include -#elif defined VCZH_GCC -#include -#endif - #if defined VCZH_GCC #include #include @@ -89,9 +83,7 @@ static_assert(false, "wchar_t configuration is not right."); #include #include #include - -#define L_(x) L__(x) -#define L__(x) L ## x +#include namespace vl { @@ -145,6 +137,11 @@ x86 and x64 Compatbility #endif /// Signed interger representing position. typedef vint64_t pos_t; + /// Signed atomic integer. + typedef std::atomic atomic_vint; + +#define INCRC(ATOMIC) ((ATOMIC)->fetch_add(1) + 1) +#define DECRC(ATOMIC) ((ATOMIC)->fetch_sub(1) - 1) #ifdef VCZH_64 #define ITOA_S _i64toa_s @@ -155,16 +152,6 @@ x86 and x64 Compatbility #define UITOW_S _ui64tow_s #define UI64TOA_S _ui64toa_s #define UI64TOW_S _ui64tow_s -#if defined VCZH_MSVC -#define INCRC(x) (_InterlockedIncrement64(x)) -#define DECRC(x) (_InterlockedDecrement64(x)) -#elif defined VCZH_ARM -#define INCRC(x) (__atomic_add_fetch(x, 1, __ATOMIC_SEQ_CST)) -#define DECRC(x) (__atomic_sub_fetch(x, 1, __ATOMIC_SEQ_CST)) -#elif defined VCZH_GCC -#define INCRC(x) (__sync_add_and_fetch(x, 1)) -#define DECRC(x) (__sync_sub_and_fetch(x, 1)) -#endif #else #define ITOA_S _itoa_s #define ITOW_S _itow_s @@ -174,16 +161,6 @@ x86 and x64 Compatbility #define UITOW_S _ui64tow_s #define UI64TOA_S _ui64toa_s #define UI64TOW_S _ui64tow_s -#if defined VCZH_MSVC -#define INCRC(x) (_InterlockedIncrement((volatile long*)(x))) -#define DECRC(x) (_InterlockedDecrement((volatile long*)(x))) -#elif defined VCZH_ARM -#define INCRC(x) (__atomic_add_fetch(x, 1, __ATOMIC_SEQ_CST)) -#define DECRC(x) (__atomic_sub_fetch(x, 1, __ATOMIC_SEQ_CST)) -#elif defined VCZH_GCC -#define INCRC(x) (__sync_add_and_fetch(x, 1)) -#define DECRC(x) (__sync_sub_and_fetch(x, 1)) -#endif #endif /*********************************************************************** @@ -236,6 +213,12 @@ Basic Types template using TypeTupleElement = typename TypeTupleItemRetriver::Type; + template + struct RemoveCVRefArrayCtad { using Type = std::remove_cvref_t; }; + + template + struct RemoveCVRefArrayCtad { using Type = T*; }; + /// /// Base type of all classes. /// This type has a virtual destructor, making all derived classes destructors virtual. @@ -276,6 +259,41 @@ Type Traits } }; + namespace ordering_decision + { + template + struct OrderingSelection + { + using Type = std::partial_ordering; + }; + + template + struct OrderingSelection + { + using Type = std::weak_ordering; + }; + + template + struct OrderingSelection + { + using Type = std::partial_ordering; + }; + + template + struct OrderingDecision + { + static constexpr const vint POs = (0 + ... + (std::is_same_v, std::partial_ordering>)); + static constexpr const vint WOs = (0 + ... + (std::is_same_v, std::weak_ordering>)); + static constexpr const vint SOs = (0 + ... + (std::is_same_v, std::strong_ordering>)); + static_assert(POs + WOs + SOs == sizeof...(TOrderings), "vl::OrderingDecision can only be used on std::(strong|weak|partial)_ordering."); + + using Type = typename OrderingSelection<(POs > 0), (WOs > 0), (SOs > 0)>::Type; + }; + } + + template + using OrderingOf = typename ordering_decision::OrderingDecision::Type; + /*********************************************************************** Interface ***********************************************************************/ @@ -300,6 +318,161 @@ Interface #endif +/*********************************************************************** +.\COLLECTIONS\PAIR.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_COLLECTIONS_PAIR +#define VCZH_COLLECTIONS_PAIR + + +namespace vl +{ + namespace collections + { + template + class Pair; + + namespace pair_internal + { + template + struct AddConstInsideReference + { + using Type = const T; + }; + + template + struct AddConstInsideReference + { + using Type = const T&; + }; + + template + struct TypePairElementRetriver; + + template + struct TypePairElementRetriver> + { + using Type = TypeTupleElement>; + }; + + template + struct TypePairElementRetriver> + { + using Type = typename AddConstInsideReference>>::Type; + }; + } + + /// A type representing a pair of key and value. + /// Type of the key. + /// Type of the value. + template + class Pair + { + public: + /// The key. + K key; + /// The value. + V value; + + Pair() = default; + Pair(const Pair&) = default; + Pair(Pair&&) = default; + + template + Pair(TKey&& _key, TValue&& _value) + requires(std::is_constructible_v && std::is_constructible_v) + : key(std::forward(_key)) + , value(std::forward(_value)) + { + } + + template + Pair(const Pair& p) + requires(std::is_constructible_v && std::is_constructible_v) + : key(p.key) + , value(p.value) + { + } + + template + Pair(Pair&& p) + requires(std::is_constructible_v && std::is_constructible_v) + : key(std::move(p.key)) + , value(std::move(p.value)) + { + } + + Pair& operator=(const Pair&) = default; + Pair& operator=(Pair&&) = default; + + template + auto operator<=>(const Pair& p) const + requires(std::three_way_comparable_with && std::three_way_comparable_with) + { + using TOrdering = OrderingOf p.key), decltype(value <=> p.value)>; + { auto result = key <=> p.key; if (result != 0) return (TOrdering)result; } + { auto result = value <=> p.value; if (result != 0) return (TOrdering)result; } + return (TOrdering)std::strong_ordering::equal; + } + + template + bool operator==(const Pair& p) const + requires(std::equality_comparable_with&& std::equality_comparable_with) + { + return key == p.key && value == p.value; + } + + ///////////////////////////////////////////////////////////////////// + + template + typename pair_internal::TypePairElementRetriver>::Type& get() = delete; + + template<> + typename pair_internal::TypePairElementRetriver<0, Pair>::Type& get<0>() { return key; } + + template<> + typename pair_internal::TypePairElementRetriver<1, Pair>::Type& get<1>() { return value; } + + template + typename pair_internal::TypePairElementRetriver>::Type& get() const = delete; + + template<> + typename pair_internal::TypePairElementRetriver<0, const Pair>::Type& get<0>() const { return key; } + + template<> + typename pair_internal::TypePairElementRetriver<1, const Pair>::Type& get<1>() const { return value; } + }; + + template + Pair(K&&, V&&) -> Pair::Type, typename RemoveCVRefArrayCtad::Type>; + } +} + +namespace std +{ + template + struct tuple_size> : integral_constant {}; + + template + struct tuple_element> + { + using type = decltype(std::declval>().template get()); + }; + + template + struct tuple_element> + { + using type = decltype(std::declval>().template get()); + }; +} + +#endif + /*********************************************************************** .\PRIMITIVES\DATETIME.H ***********************************************************************/ @@ -405,7 +578,7 @@ Date and Time bool operator==(const DateTime& value) const { - return operator<=>(value) == 0; + return filetime == value.filetime; } }; } @@ -606,20 +779,23 @@ namespace vl /// Comparing two nullable values. /// - /// Returns std::strong_ordering indicating the order of the two values. + /// Returns a value indicating the order of the two values, the type is decided by T. /// When one is null and another one is not, the non-null one is greater. /// /// The first nullable value to compare. /// The second nullable value to compare. - std::strong_ordering operator<=>(const Nullable& b)const + auto operator<=>(const Nullable& b) const + requires(std::three_way_comparable) { + using TOrdering = decltype(object <=> b.object); if (initialized && b.initialized) return object <=> b.object; - if (initialized) return std::strong_ordering::greater; - if (b.initialized) return std::strong_ordering::less; - return std::strong_ordering::equal; + if (initialized) return (TOrdering)std::strong_ordering::greater; + if (b.initialized) return (TOrdering)std::strong_ordering::less; + return (TOrdering)std::strong_ordering::equal; } bool operator==(const Nullable& b)const + requires(std::equality_comparable) { if (initialized && b.initialized) return object == b.object; return initialized == b.initialized; @@ -689,15 +865,15 @@ ReferenceCounterOperator /// Create the reference counter of an object. /// The pointer to the reference counter. /// The object. - static __forceinline volatile vint* CreateCounter(T* reference) + static __forceinline atomic_vint* CreateCounter(T* reference) { - return new vint(0); + return new atomic_vint(0); } /// Delete the reference counter from an object. /// The pointer to the reference counter. /// The object. - static __forceinline void DeleteReference(volatile vint* counter, void* reference) + static __forceinline void DeleteReference(atomic_vint* counter, void* reference) { delete counter; delete (T*)reference; @@ -726,9 +902,9 @@ Ptr template friend class Ptr; protected: - typedef void(*Destructor)(volatile vint*, void*); + typedef void(*Destructor)(atomic_vint*, void*); - volatile vint* counter = nullptr; + atomic_vint* counter = nullptr; T* reference = nullptr; void* originalReference = nullptr; Destructor originalDestructor = nullptr; @@ -764,12 +940,12 @@ Ptr } } - volatile vint* Counter()const + atomic_vint* Counter()const { return counter; } - Ptr(volatile vint* _counter, T* _reference, void* _originalReference, Destructor _originalDestructor) + Ptr(atomic_vint* _counter, T* _reference, void* _originalReference, Destructor _originalDestructor) :counter(_counter) , reference(_reference) , originalReference(_originalReference) @@ -934,14 +1110,14 @@ Ptr return reference <=> pointer.reference; } - bool operator==(const T* value) const + bool operator==(const T* pointer) const { - return operator<=>(value) == 0; + return reference == pointer; } - bool operator==(const Ptr& value) const + bool operator==(const Ptr& pointer) const { - return operator<=>(value) == 0; + return reference == pointer.reference; } /// Test if it is an empty shared pointer. @@ -977,7 +1153,7 @@ ComPtr class ComPtr { protected: - volatile vint* counter = nullptr; + atomic_vint* counter = nullptr; T* reference = nullptr; void SetEmpty() @@ -1007,12 +1183,12 @@ ComPtr } } - volatile vint* Counter()const + atomic_vint* Counter()const { return counter; } - ComPtr(volatile vint* _counter, T* _reference) + ComPtr(atomic_vint* _counter, T* _reference) :counter(_counter) , reference(_reference) { @@ -1027,7 +1203,7 @@ ComPtr { if (pointer) { - counter = new volatile vint(1); + counter = new atomic_vint(1); reference = pointer; } else @@ -1067,7 +1243,7 @@ ComPtr Dec(); if (pointer) { - counter = new vint(1); + counter = new atomic_vint(1); reference = pointer; } else @@ -1169,631 +1345,6 @@ Traits #endif -/*********************************************************************** -.\PRIMITIVES\FUNCTION.H -***********************************************************************/ -/*********************************************************************** -Author: Zihan Chen (vczh) -Licensed under https://github.com/vczh-libraries/License -***********************************************************************/ - -#ifndef VCZH_FUNCTION -#define VCZH_FUNCTION -#include -namespace vl -{ - template - class Func; - -/*********************************************************************** -vl::Func -***********************************************************************/ - - namespace internal_invokers - { - template - class Invoker : public Object - { - public: - virtual R Invoke(TArgs&& ...args) = 0; - }; - - //------------------------------------------------------ - - template - class StaticInvoker : public Invoker - { - protected: - R(*function)(TArgs ...args); - - public: - StaticInvoker(R(*_function)(TArgs...)) - :function(_function) - { - } - - R Invoke(TArgs&& ...args)override - { - return function(std::forward(args)...); - } - }; - - //------------------------------------------------------ - - template - class MemberInvoker : public Invoker - { - protected: - C* sender; - R(C::*function)(TArgs ...args); - - public: - MemberInvoker(C* _sender, R(C::*_function)(TArgs ...args)) - :sender(_sender) - ,function(_function) - { - } - - R Invoke(TArgs&& ...args)override - { - return (sender->*function)(std::forward(args)...); - } - }; - - //------------------------------------------------------ - - template - class ObjectInvoker : public Invoker - { - protected: - C function; - - public: - ObjectInvoker(const C& _function) - :function(_function) - { - } - - ObjectInvoker(C&& _function) - :function(std::move(_function)) - { - } - - R Invoke(TArgs&& ...args)override - { - return function(std::forward(args)...); - } - }; - - //------------------------------------------------------ - - template - class ObjectInvoker : public Invoker - { - protected: - C function; - - public: - ObjectInvoker(const C& _function) - :function(_function) - { - } - - ObjectInvoker(C&& _function) - :function(std::move(_function)) - { - } - - void Invoke(TArgs&& ...args)override - { - function(std::forward(args)...); - } - }; - } - - /// A type for functors. - /// The return type. - /// Types of parameters. - template - class Func : public Object - { - protected: - Ptr> invoker; - - template - static bool IsEmptyFunc(const Func& function) - { - return !function; - } - - template - static bool IsEmptyFunc(Func& function) - { - return !function; - } - - template - static bool IsEmptyFunc(C&&) - { - return false; - } - public: - typedef R FunctionType(TArgs...); - typedef R ResultType; - - /// Create a null functor. - Func() = default; - - /// Copy a functor. - /// The functor to copy. - Func(const Func& function) = default; - - /// Move a functor. - /// The functor to move. - Func(Func&& function) = default; - - /// Create a functor from a function pointer. - /// The function pointer. - Func(R(*function)(TArgs...)) - { - invoker = Ptr(new internal_invokers::StaticInvoker(function)); - } - - /// Create a functor from a method. - /// Type of the class that this method belongs to. - /// The object that this method belongs to. - /// The method pointer. - template - Func(C* sender, R(C::*function)(TArgs...)) - { - invoker = Ptr(new internal_invokers::MemberInvoker(sender, function)); - } - - /// Create a functor from another compatible functor. - /// Type of the functor to copy. - /// The functor to copy. It could be a lambda expression, or any types that has operator() members. - template - Func(C&& function) - requires ( - std::is_invocable_v - ) && ( - std::is_same_v || - std::is_convertible_v()(std::declval()...)), R> - ) - { - if (!IsEmptyFunc(function)) - { - invoker = Ptr(new internal_invokers::ObjectInvoker, R, TArgs...>(std::forward(function))); - } - } - - /// Create a functor from another compatible functor. - /// Type of the functor to copy. - /// The functor to copy. It could be a lambda expression, or any types that has operator() members. - template - Func(C* function) - requires ( - std::is_invocable_v - ) && ( - std::is_same_v || - std::is_convertible_v()(std::declval()...)), R> - ) - { - if (!IsEmptyFunc(function)) - { - invoker = Ptr(new internal_invokers::ObjectInvoker(function)); - } - } - - /// Invoke the function. - /// Returns the function result. It crashes when the functor is null. - /// Arguments to invoke the function. - R operator()(TArgs ...args)const - { - return invoker->Invoke(std::forward(args)...); - } - - Func& operator=(const Func& function) - { - invoker = function.invoker; - return *this; - } - - Func& operator=(const Func&& function) - { - invoker = std::move(function.invoker); - return *this; - } - - bool operator==(const Func& function)const - { - return invoker == function.invoker; - } - - bool operator!=(const Func& function)const - { - return invoker != function.invoker; - } - - /// Test is the functor is non-null. - /// Returns true if the functor is non-null. - operator bool()const - { - return invoker; - } - }; - -/*********************************************************************** -vl::function_lambda::LambdaRetriveType -***********************************************************************/ - - namespace function_lambda - { - template - struct LambdaRetriveType - { - }; - - template - struct LambdaRetriveType - { - typedef R(FunctionType)(TArgs...); - typedef R ResultType; - typedef TypeTuple ParameterTypes; - }; - - template - struct LambdaRetriveType - { - typedef R(FunctionType)(TArgs...); - typedef R ResultType; - typedef TypeTuple ParameterTypes; - }; - -#define LAMBDA vl::function_lambda::Lambda - } - - template - Func(C&&) -> Func::FunctionType>; - - template - Func(R(*)(TArgs...)) -> Func; - - template - Func(C*, R(C::*)(TArgs...)) -> Func; -} -#endif - -/*********************************************************************** -.\PRIMITIVES\TUPLE.H -***********************************************************************/ -/*********************************************************************** -Author: Zihan Chen (vczh) -Licensed under https://github.com/vczh-libraries/License -***********************************************************************/ -#ifndef VCZH_TUPLE -#define VCZH_TUPLE - - -namespace vl -{ - namespace tuple_internal - { - template - struct TupleElement - { - T element; - - TupleElement() = default; - - template - TupleElement(U&& _element) - :element(std::forward(_element)) - { - } - }; - - template - struct TupleElementComparison - { - const T& t; - const U& u; - - TupleElementComparison(const T& _t, const U& _u) - : t(_t) - , u(_u) - { - } - - friend std::strong_ordering operator*(std::strong_ordering order, const TupleElementComparison& t) - { - if (order != 0) return order; - return t.t <=> t.u; - } - }; - - struct TupleCtorElementsTag {}; - struct TupleCtorTupleTag {}; - - template - struct TupleBase; - - template requires(sizeof...(Is) == sizeof...(TArgs)) - struct TupleBase, TArgs...> - : TupleElement... - { - private: - using TSelf = TupleBase, TArgs...>; - - template requires(sizeof...(TArgs) == sizeof...(UArgs)) - using TCompatible = TupleBase, UArgs...>; - - public: - TupleBase() = default; - - template - TupleBase(TupleCtorElementsTag, UArgs&& ...xs) - : TupleElement(std::forward(xs)) ... - { - } - - template - TupleBase(TupleCtorTupleTag, const TCompatible& t) - : TupleElement(static_cast&>(t).element) ... - { - } - - template - TupleBase(TupleCtorTupleTag, TCompatible&& t) - : TupleElement(std::move(static_cast&>(t).element)) ... - { - } - - template - void AssignCopy(const TCompatible& t) - { - (( - static_cast*>(this)->element = - static_cast&>(t).element - ), ...); - } - - template - void AssignMove(TCompatible&& t) - { - (( - static_cast*>(this)->element = - std::move(static_cast&&>(t).element) - ), ...); - } - - template - bool AreEqual(const TCompatible& t) const - { - return (true && ... && ( - static_cast*>(this)->element == - static_cast&>(t).element - )); - } - - template - std::strong_ordering Compare(const TCompatible& t) const - { - return (std::strong_ordering::equal * ... * (TupleElementComparison( - static_cast*>(this)->element, - static_cast&>(t).element - ))); - } - }; - } - - template - class Tuple : private tuple_internal::TupleBase, TArgs...> - { - template - friend class Tuple; - - using TSelf = Tuple; - using TBase = tuple_internal::TupleBase, TArgs...>; - - template requires(sizeof...(TArgs) == sizeof...(UArgs)) - using TCompatible = Tuple; - - template requires(sizeof...(TArgs) == sizeof...(UArgs)) - using TCompatibleBase = tuple_internal::TupleBase, UArgs...>; - - public: - Tuple() = default; - - template - Tuple(UArgs&& ...xs) requires(sizeof...(TArgs) == sizeof...(UArgs)) - : TBase( - tuple_internal::TupleCtorElementsTag{}, - std::forward(xs)... - ) - { - } - - template - Tuple(const TCompatible& t) requires(sizeof...(TArgs) == sizeof...(UArgs)) - : TBase( - tuple_internal::TupleCtorTupleTag{}, - static_cast&>(t) - ) - { - } - - template - Tuple(TCompatible&& t) requires(sizeof...(TArgs) == sizeof...(UArgs)) - : TBase( - tuple_internal::TupleCtorTupleTag{}, - static_cast&&>(t) - ) - { - } - - template - TSelf& operator=(const TCompatible& t) - { - AssignCopy(t); - return *this; - } - - template - TSelf& operator=(TCompatible&& t) - { - AssignMove(std::move(t)); - return *this; - } - - template - std::strong_ordering operator<=>(const TCompatible& t)const - { - return this->Compare(t); - } - - template - bool operator==(const TCompatible& t)const - { - return this->AreEqual(t); - } - - template - TypeTupleElement>& get() - { - return static_cast>>*>(this)->element; - } - - template - const TypeTupleElement>& get()const - { - return static_cast>>*>(this)->element; - } - }; - - template - struct TupleElementCtad { using Type = std::remove_cvref_t; }; - - template - struct TupleElementCtad { using Type = T*; }; - - template - Tuple(TArgs&&...) -> Tuple::Type...>; - - template - TypeTupleElement>& get(Tuple& t) - { - return t.template get(); - } - - template - const TypeTupleElement>& get(const Tuple& t) - { - return t.template get(); - } -} - -namespace std -{ - template - struct tuple_size> : integral_constant {}; - - template - struct tuple_element> - { - using type = vl::TypeTupleElement>; - }; -} - -#endif - -/*********************************************************************** -.\COLLECTIONS\PAIR.H -***********************************************************************/ -/*********************************************************************** -Author: Zihan Chen (vczh) -Licensed under https://github.com/vczh-libraries/License -***********************************************************************/ - -#ifndef VCZH_COLLECTIONS_PAIR -#define VCZH_COLLECTIONS_PAIR - - -namespace vl -{ - namespace collections - { - template - class Pair; - - /// A type representing a pair of key and value. - /// Type of the key. - /// Type of the value. - template - class Pair - { - public: - /// The key. - K key; - /// The value. - V value; - - Pair() = default; - Pair(const Pair&) = default; - Pair(Pair&&) = default; - - template - Pair(TKey&& _key, TValue&& _value) - requires(std::is_constructible_v && std::is_constructible_v) - : key(std::forward(_key)) - , value(std::forward(_value)) - { - } - - template - Pair(const Pair& p) - requires(std::is_constructible_v && std::is_constructible_v) - : key(p.key) - , value(p.value) - { - } - - template - Pair(Pair&& p) - requires(std::is_constructible_v && std::is_constructible_v) - : key(std::move(p.key)) - , value(std::move(p.value)) - { - } - - Pair& operator=(const Pair&) = default; - Pair& operator=(Pair&&) = default; - - template - std::strong_ordering operator<=>(const Pair& p) const - requires(std::three_way_comparable_with && std::three_way_comparable_with) - { - std::strong_ordering - result = key <=> p.key; if (result != 0) return result; - result = value <=> p.value; if (result != 0) return result; - return std::strong_ordering::equal; - } - - template - bool operator==(const Pair& p) const - requires(std::equality_comparable_with&& std::equality_comparable_with) - { - return key == p.key && value == p.value; - } - }; - - template - Pair(K&&, V&&) -> Pair::Type, typename TupleElementCtad::Type>; - } -} - -#endif - /*********************************************************************** .\COLLECTIONS\INTERFACES.H ***********************************************************************/ @@ -2732,17 +2283,23 @@ SortedList while (start <= end) { index = start + (end - start) / 2; - if (this->buffer[index] == item) + auto ordering = this->buffer[index] <=> item; + if constexpr (std::is_same_v) { - return index; + CHECK_ERROR(ordering != std::partial_ordering::unordered, L"vl::collections::SortedList::IndexOfInternal(Key&, vint&)#This function could not apply on elements in partial ordering."); } - else if (this->buffer[index] > item) + + if (ordering < 0) + { + start = index + 1; + } + else if (ordering > 0) { end = index - 1; } else { - start = index + 1; + return index; } } return -1; @@ -4165,7 +3722,7 @@ CompareEnumerable /// In other cases, the results represents the comparison result of the first pair of inequal values in enumerables. /// template - std::strong_ordering CompareEnumerable(const IEnumerable& a, const IEnumerable& b) + auto CompareEnumerable(const IEnumerable& a, const IEnumerable& b) -> decltype(std::declval() <=> std::declval()) { auto ator = Ptr(a.CreateEnumerator()); auto btor = Ptr(b.CreateEnumerator()); @@ -4179,7 +3736,7 @@ CompareEnumerable const T& ac = ator->Current(); const U& bc = btor->Current(); - std::strong_ordering ordering = ac <=> bc; + auto ordering = ac <=> bc; if (ordering != 0) return ordering; } return std::strong_ordering::equal; @@ -4313,187 +3870,6 @@ Concat #endif -/*********************************************************************** -.\COLLECTIONS\OPERATIONFOREACH.H -***********************************************************************/ -/*********************************************************************** -Author: Zihan Chen (vczh) -Licensed under https://github.com/vczh-libraries/License -***********************************************************************/ - -#ifndef VCZH_COLLECTIONS_FOREACH -#define VCZH_COLLECTIONS_FOREACH - -namespace vl -{ - namespace collections - { - struct RangeBasedForLoopEnding - { - }; - -/*********************************************************************** -Range-Based For-Loop Iterator -***********************************************************************/ - - template - struct RangeBasedForLoopIterator - { - private: - IEnumerator* iterator; - - public: - RangeBasedForLoopIterator(const IEnumerable& enumerable) - : iterator(enumerable.CreateEnumerator()) - { - operator++(); - } - - ~RangeBasedForLoopIterator() - { - if (iterator) delete iterator; - } - - void operator++() - { - if (!iterator->Next()) - { - delete iterator; - iterator = nullptr; - } - } - - const T& operator*() const - { - return iterator->Current(); - } - - bool operator==(const RangeBasedForLoopEnding&) const - { - return iterator == nullptr; - } - - bool operator!=(const RangeBasedForLoopEnding&) const - { - return iterator != nullptr; - } - - friend bool operator==(const RangeBasedForLoopEnding&, const RangeBasedForLoopIterator& iterator) - { - return iterator.iterator == nullptr; - } - - friend bool operator!=(const RangeBasedForLoopEnding&, const RangeBasedForLoopIterator& iterator) - { - return iterator.iterator != nullptr; - } - }; - - template - RangeBasedForLoopIterator begin(const IEnumerable& enumerable) - { - return { enumerable }; - } - - template - RangeBasedForLoopEnding end(const IEnumerable& enumerable) - { - return {}; - } - -/*********************************************************************** -Range-Based For-Loop Iterator with Index -***********************************************************************/ - - template - struct RangeBasedForLoopIteratorWithIndex - { - private: - IEnumerator* iterator; - vint index; - - public: - RangeBasedForLoopIteratorWithIndex(const IEnumerable& enumerable) - : iterator(enumerable.CreateEnumerator()) - , index(-1) - { - operator++(); - } - - ~RangeBasedForLoopIteratorWithIndex() - { - if (iterator) delete iterator; - } - - void operator++() - { - if (!iterator->Next()) - { - delete iterator; - iterator = nullptr; - } - index++; - } - - Tuple operator*() const - { - return { iterator->Current(),index }; - } - - bool operator==(const RangeBasedForLoopEnding&) const - { - return iterator == nullptr; - } - - bool operator!=(const RangeBasedForLoopEnding&) const - { - return iterator != nullptr; - } - - friend bool operator==(const RangeBasedForLoopEnding&, const RangeBasedForLoopIteratorWithIndex& iterator) - { - return iterator.iterator == nullptr; - } - - friend bool operator!=(const RangeBasedForLoopEnding&, const RangeBasedForLoopIteratorWithIndex& iterator) - { - return iterator.iterator != nullptr; - } - }; - - template - struct EnumerableWithIndex - { - const IEnumerable& enumerable; - - EnumerableWithIndex(const IEnumerable& _enumerable) - : enumerable(_enumerable) - { - } - }; - - template - EnumerableWithIndex indexed(const IEnumerable& enumerable) - { - return { enumerable }; - } - - template - RangeBasedForLoopIteratorWithIndex begin(const EnumerableWithIndex& enumerable) - { - return { enumerable.enumerable }; - } - - template - RangeBasedForLoopEnding end(const EnumerableWithIndex& enumerable) - { - return {}; - } - } -} - -#endif - /*********************************************************************** .\COLLECTIONS\OPERATIONPAIR.H ***********************************************************************/ @@ -4580,85 +3956,6 @@ Pairwise #endif -/*********************************************************************** -.\COLLECTIONS\OPERATIONSELECT.H -***********************************************************************/ -/*********************************************************************** -Author: Zihan Chen (vczh) -Licensed under https://github.com/vczh-libraries/License -***********************************************************************/ - -#ifndef VCZH_COLLECTIONS_OPERATIONSELECT -#define VCZH_COLLECTIONS_OPERATIONSELECT - - -namespace vl -{ - namespace collections - { - -/*********************************************************************** -Select -***********************************************************************/ - - template - class SelectEnumerator : public virtual IEnumerator - { - protected: - IEnumerator* enumerator; - Func selector; - Nullable current; - public: - SelectEnumerator(IEnumerator* _enumerator, const Func& _selector, Nullable _current = {}) - :enumerator(_enumerator) - ,selector(_selector) - ,current(_current) - { - } - - ~SelectEnumerator() - { - delete enumerator; - } - - IEnumerator* Clone()const override - { - return new SelectEnumerator(enumerator->Clone(), selector, current); - } - - const K& Current()const override - { - return current.Value(); - } - - vint Index()const override - { - return enumerator->Index(); - } - - bool Next()override - { - if (enumerator->Next()) - { - current = selector(enumerator->Current()); - return true; - } - else - { - return false; - } - } - - void Reset()override - { - enumerator->Reset(); - } - }; - } -} - -#endif - /*********************************************************************** .\COLLECTIONS\OPERATIONSEQUENCE.H ***********************************************************************/ @@ -5183,86 +4480,6 @@ Intersect/Except #endif -/*********************************************************************** -.\COLLECTIONS\OPERATIONWHERE.H -***********************************************************************/ -/*********************************************************************** -Author: Zihan Chen (vczh) -Licensed under https://github.com/vczh-libraries/License -***********************************************************************/ - -#ifndef VCZH_COLLECTIONS_OPERATIONWHERE -#define VCZH_COLLECTIONS_OPERATIONWHERE - - -namespace vl -{ - namespace collections - { -/*********************************************************************** -Where -***********************************************************************/ - - template - class WhereEnumerator : public virtual IEnumerator - { - protected: - IEnumerator* enumerator; - Func selector; - vint index; - - public: - WhereEnumerator(IEnumerator* _enumerator, const Func& _selector, vint _index=-1) - :enumerator(_enumerator) - ,selector(_selector) - ,index(_index) - { - } - - ~WhereEnumerator() - { - delete enumerator; - } - - IEnumerator* Clone()const override - { - return new WhereEnumerator(enumerator->Clone(), selector, index); - } - - const T& Current()const override - { - return enumerator->Current(); - } - - vint Index()const override - { - return index; - } - - bool Next()override - { - while(enumerator->Next()) - { - if(selector(enumerator->Current())) - { - index++; - return true; - } - } - return false; - } - - void Reset()override - { - enumerator->Reset(); - index=-1; - } - }; - } -} - -#endif - /*********************************************************************** .\COLLECTIONS\PARTIALORDERING.H ***********************************************************************/ @@ -5751,6 +4968,458 @@ Partial Ordering #endif +/*********************************************************************** +.\PRIMITIVES\FUNCTION.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_FUNCTION +#define VCZH_FUNCTION +#include +namespace vl +{ + template + class Func; + +/*********************************************************************** +vl::Func +***********************************************************************/ + + namespace internal_invokers + { + template + class Invoker : public Object + { + public: + virtual R Invoke(TArgs&& ...args) = 0; + }; + + //------------------------------------------------------ + + template + class StaticInvoker : public Invoker + { + protected: + R(*function)(TArgs ...args); + + public: + StaticInvoker(R(*_function)(TArgs...)) + :function(_function) + { + } + + R Invoke(TArgs&& ...args)override + { + return function(std::forward(args)...); + } + }; + + //------------------------------------------------------ + + template + class MemberInvoker : public Invoker + { + protected: + C* sender; + R(C::*function)(TArgs ...args); + + public: + MemberInvoker(C* _sender, R(C::*_function)(TArgs ...args)) + :sender(_sender) + ,function(_function) + { + } + + R Invoke(TArgs&& ...args)override + { + return (sender->*function)(std::forward(args)...); + } + }; + + //------------------------------------------------------ + + template + class ObjectInvoker : public Invoker + { + protected: + C function; + + public: + ObjectInvoker(const C& _function) + :function(_function) + { + } + + ObjectInvoker(C&& _function) + :function(std::move(_function)) + { + } + + R Invoke(TArgs&& ...args)override + { + return function(std::forward(args)...); + } + }; + + //------------------------------------------------------ + + template + class ObjectInvoker : public Invoker + { + protected: + C function; + + public: + ObjectInvoker(const C& _function) + :function(_function) + { + } + + ObjectInvoker(C&& _function) + :function(std::move(_function)) + { + } + + void Invoke(TArgs&& ...args)override + { + function(std::forward(args)...); + } + }; + } + + /// A type for functors. + /// The return type. + /// Types of parameters. + template + class Func : public Object + { + protected: + Ptr> invoker; + + template + static bool IsEmptyFunc(const Func& function) + { + return !function; + } + + template + static bool IsEmptyFunc(Func& function) + { + return !function; + } + + template + static bool IsEmptyFunc(C&&) + { + return false; + } + public: + typedef R FunctionType(TArgs...); + typedef R ResultType; + + /// Create a null functor. + Func() = default; + + /// Copy a functor. + /// The functor to copy. + Func(const Func& function) = default; + + /// Move a functor. + /// The functor to move. + Func(Func&& function) = default; + + /// Create a functor from a function pointer. + /// The function pointer. + Func(R(*function)(TArgs...)) + { + invoker = Ptr(new internal_invokers::StaticInvoker(function)); + } + + /// Create a functor from a method. + /// Type of the class that this method belongs to. + /// The object that this method belongs to. + /// The method pointer. + template + Func(C* sender, R(C::*function)(TArgs...)) + { + invoker = Ptr(new internal_invokers::MemberInvoker(sender, function)); + } + + /// Create a functor from another compatible functor. + /// Type of the functor to copy. + /// The functor to copy. It could be a lambda expression, or any types that has operator() members. + template + Func(C&& function) + requires ( + std::is_invocable_v + ) && ( + std::is_same_v || + std::is_convertible_v()(std::declval()...)), R> + ) + { + if (!IsEmptyFunc(function)) + { + invoker = Ptr(new internal_invokers::ObjectInvoker, R, TArgs...>(std::forward(function))); + } + } + + /// Create a functor from another compatible functor. + /// Type of the functor to copy. + /// The functor to copy. It could be a lambda expression, or any types that has operator() members. + template + Func(C* function) + requires ( + std::is_invocable_v + ) && ( + std::is_same_v || + std::is_convertible_v()(std::declval()...)), R> + ) + { + if (!IsEmptyFunc(function)) + { + invoker = Ptr(new internal_invokers::ObjectInvoker(function)); + } + } + + /// Invoke the function. + /// Returns the function result. It crashes when the functor is null. + /// Arguments to invoke the function. + R operator()(TArgs ...args)const + { + return invoker->Invoke(std::forward(args)...); + } + + Func& operator=(const Func& function) + { + invoker = function.invoker; + return *this; + } + + Func& operator=(const Func&& function) + { + invoker = std::move(function.invoker); + return *this; + } + + bool operator==(const Func& function)const + { + return invoker == function.invoker; + } + + bool operator!=(const Func& function)const + { + return invoker != function.invoker; + } + + /// Test is the functor is non-null. + /// Returns true if the functor is non-null. + operator bool()const + { + return invoker; + } + }; + +/*********************************************************************** +vl::function_lambda::LambdaRetriveType +***********************************************************************/ + + namespace function_lambda + { + template + struct LambdaRetriveType + { + }; + + template + struct LambdaRetriveType + { + typedef R(FunctionType)(TArgs...); + typedef R ResultType; + typedef TypeTuple ParameterTypes; + }; + + template + struct LambdaRetriveType + { + typedef R(FunctionType)(TArgs...); + typedef R ResultType; + typedef TypeTuple ParameterTypes; + }; + } + + template + Func(C&&) -> Func::FunctionType>; + + template + Func(R(*)(TArgs...)) -> Func; + + template + Func(C*, R(C::*)(TArgs...)) -> Func; +} +#endif + +/*********************************************************************** +.\COLLECTIONS\OPERATIONSELECT.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_COLLECTIONS_OPERATIONSELECT +#define VCZH_COLLECTIONS_OPERATIONSELECT + + +namespace vl +{ + namespace collections + { + +/*********************************************************************** +Select +***********************************************************************/ + + template + class SelectEnumerator : public virtual IEnumerator + { + protected: + IEnumerator* enumerator; + Func selector; + Nullable current; + public: + SelectEnumerator(IEnumerator* _enumerator, const Func& _selector, Nullable _current = {}) + :enumerator(_enumerator) + ,selector(_selector) + ,current(_current) + { + } + + ~SelectEnumerator() + { + delete enumerator; + } + + IEnumerator* Clone()const override + { + return new SelectEnumerator(enumerator->Clone(), selector, current); + } + + const K& Current()const override + { + return current.Value(); + } + + vint Index()const override + { + return enumerator->Index(); + } + + bool Next()override + { + if (enumerator->Next()) + { + current = selector(enumerator->Current()); + return true; + } + else + { + return false; + } + } + + void Reset()override + { + enumerator->Reset(); + } + }; + } +} + +#endif + +/*********************************************************************** +.\COLLECTIONS\OPERATIONWHERE.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_COLLECTIONS_OPERATIONWHERE +#define VCZH_COLLECTIONS_OPERATIONWHERE + + +namespace vl +{ + namespace collections + { +/*********************************************************************** +Where +***********************************************************************/ + + template + class WhereEnumerator : public virtual IEnumerator + { + protected: + IEnumerator* enumerator; + Func selector; + vint index; + + public: + WhereEnumerator(IEnumerator* _enumerator, const Func& _selector, vint _index=-1) + :enumerator(_enumerator) + ,selector(_selector) + ,index(_index) + { + } + + ~WhereEnumerator() + { + delete enumerator; + } + + IEnumerator* Clone()const override + { + return new WhereEnumerator(enumerator->Clone(), selector, index); + } + + const T& Current()const override + { + return enumerator->Current(); + } + + vint Index()const override + { + return index; + } + + bool Next()override + { + while(enumerator->Next()) + { + if(selector(enumerator->Current())) + { + index++; + return true; + } + } + return false; + } + + void Reset()override + { + enumerator->Reset(); + index=-1; + } + }; + } +} + +#endif + /*********************************************************************** .\PRIMITIVES\EVENT.H ***********************************************************************/ @@ -5860,6 +5529,510 @@ namespace vl #endif +/*********************************************************************** +.\PRIMITIVES\TUPLE.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ +#ifndef VCZH_TUPLE +#define VCZH_TUPLE + + +namespace vl +{ + namespace tuple_internal + { + template + struct TupleElement + { + T element; + + TupleElement() = default; + + template + TupleElement(U&& _element) + :element(std::forward(_element)) + { + } + + template + void AssignCopy(const TupleElement& value) + { + element = value.GetElement(); + } + + template + void AssignMove(TupleElement&& value) + { + element = std::move(value.GetElement()); + } + + template + bool operator==(const TupleElement& value) const + { + return element == value.GetElement(); + } + + T& GetElement() + { + return element; + } + + const T& GetElement() const + { + return element; + } + }; + + template + struct TupleElement + { + T* element; + + TupleElement() = delete; + + template + TupleElement(U&& _element) + :element(&_element) + { + } + + template + void AssignCopy(const TupleElement& value) + { + element = &value.GetElement(); + } + + template + void AssignMove(TupleElement&& value) + { + element = &value.GetElement(); + } + + template + bool operator==(const TupleElement& value) const + { + return *element == value.GetElement(); + } + + T& GetElement() + { + return *element; + } + + const T& GetElement() const + { + return *element; + } + }; + + template + struct TupleElementComparison + { + const T& t; + const U& u; + + TupleElementComparison(const T& _t, const U& _u) + : t(_t) + , u(_u) + { + } + + template + friend TOrdering operator*(TPreviousOrdering order, const TupleElementComparison& t) + { + if (order != 0) return (TOrdering)order; + return (TOrdering)(t.t <=> t.u); + } + }; + + struct TupleCtorElementsTag {}; + struct TupleCtorTupleTag {}; + + template + struct TupleBase; + + template requires(sizeof...(Is) == sizeof...(TArgs)) + struct TupleBase, TArgs...> + : TupleElement... + { + private: + using TSelf = TupleBase, TArgs...>; + + template requires(sizeof...(TArgs) == sizeof...(UArgs)) + using TCompatible = TupleBase, UArgs...>; + + public: + TupleBase() = default; + + template + TupleBase(TupleCtorElementsTag, UArgs&& ...xs) + : TupleElement(std::forward(xs)) ... + { + } + + template + TupleBase(TupleCtorTupleTag, const TCompatible& t) + : TupleElement(static_cast&>(t).GetElement()) ... + { + } + + template + TupleBase(TupleCtorTupleTag, TCompatible&& t) + : TupleElement(std::move(static_cast&>(t).GetElement())) ... + { + } + + template + void AssignCopy(const TCompatible& t) + { + (( + static_cast*>(this)->AssignCopy + ( + static_cast&>(t) + ) + ), ...); + } + + template + void AssignMove(TCompatible&& t) + { + (( + static_cast*>(this)->AssignMove + ( + std::move(static_cast&&>(t)) + ) + ), ...); + } + + template + bool AreEqual(const TCompatible& t) const + { + return (true && ... && ( + *static_cast*>(this) == static_cast&>(t) + )); + } + + template + auto Compare(const TCompatible& t) const + { +#define LEFT_ELEMENT (static_cast*>(this)->GetElement()) +#define RIGHT_ELEMENT (static_cast&>(t).GetElement()) + using TOrdering = OrderingOf RIGHT_ELEMENT)...>; + return (std::strong_ordering::equal * ... * (TupleElementComparison(LEFT_ELEMENT, RIGHT_ELEMENT))); +#undef LEFT_ELEMENT +#undef RIGHT_ELEMENT + } + }; + } + + template + class Tuple : private tuple_internal::TupleBase, TArgs...> + { + template + friend class Tuple; + + using TSelf = Tuple; + using TBase = tuple_internal::TupleBase, TArgs...>; + + template requires(sizeof...(TArgs) == sizeof...(UArgs)) + using TCompatible = Tuple; + + template requires(sizeof...(TArgs) == sizeof...(UArgs)) + using TCompatibleBase = tuple_internal::TupleBase, UArgs...>; + + public: + Tuple() = default; + + template + Tuple(UArgs&& ...xs) requires(sizeof...(TArgs) == sizeof...(UArgs)) + : TBase( + tuple_internal::TupleCtorElementsTag{}, + std::forward(xs)... + ) + { + } + + template + Tuple(const TCompatible& t) requires(sizeof...(TArgs) == sizeof...(UArgs)) + : TBase( + tuple_internal::TupleCtorTupleTag{}, + static_cast&>(t) + ) + { + } + + template + Tuple(TCompatible&& t) requires(sizeof...(TArgs) == sizeof...(UArgs)) + : TBase( + tuple_internal::TupleCtorTupleTag{}, + static_cast&&>(t) + ) + { + } + + template + TSelf& operator=(const TCompatible& t) + { + this->AssignCopy(t); + return *this; + } + + template + TSelf& operator=(TCompatible&& t) + { + this->AssignMove(std::move(t)); + return *this; + } + + template + auto operator<=>(const TCompatible& t)const + requires (true && ... && std::three_way_comparable_with) + { + return this->Compare(t); + } + + template + bool operator==(const TCompatible& t)const + requires (true && ... && std::equality_comparable_with) + { + return this->AreEqual(t); + } + + template + decltype(auto) get() + { + using TElement = tuple_internal::TupleElement>>; + return static_cast(this)->GetElement(); + } + + template + decltype(auto) get() const + { + using TElement = tuple_internal::TupleElement>>; + return static_cast(this)->GetElement(); + } + }; + + template + Tuple(TArgs&&...) -> Tuple::Type...>; + + template + decltype(auto) get(Tuple& t) + { + return t.template get(); + } + + template + decltype(auto) get(const Tuple& t) + { + return t.template get(); + } +} + +namespace std +{ + template + struct tuple_size> : integral_constant {}; + + template + struct tuple_element> + { + using type = decltype(std::declval>().template get()); + }; + + template + struct tuple_element> + { + using type = decltype(std::declval>().template get()); + }; +} + +#endif + +/*********************************************************************** +.\COLLECTIONS\OPERATIONFOREACH.H +***********************************************************************/ +/*********************************************************************** +Author: Zihan Chen (vczh) +Licensed under https://github.com/vczh-libraries/License +***********************************************************************/ + +#ifndef VCZH_COLLECTIONS_FOREACH +#define VCZH_COLLECTIONS_FOREACH + +namespace vl +{ + namespace collections + { + struct RangeBasedForLoopEnding + { + }; + +/*********************************************************************** +Range-Based For-Loop Iterator +***********************************************************************/ + + template + struct RangeBasedForLoopIterator + { + private: + IEnumerator* iterator; + + public: + RangeBasedForLoopIterator(const IEnumerable& enumerable) + : iterator(enumerable.CreateEnumerator()) + { + operator++(); + } + + ~RangeBasedForLoopIterator() + { + if (iterator) delete iterator; + } + + void operator++() + { + if (!iterator->Next()) + { + delete iterator; + iterator = nullptr; + } + } + + const T& operator*() const + { + return iterator->Current(); + } + + bool operator==(const RangeBasedForLoopEnding&) const + { + return iterator == nullptr; + } + + bool operator!=(const RangeBasedForLoopEnding&) const + { + return iterator != nullptr; + } + + friend bool operator==(const RangeBasedForLoopEnding&, const RangeBasedForLoopIterator& iterator) + { + return iterator.iterator == nullptr; + } + + friend bool operator!=(const RangeBasedForLoopEnding&, const RangeBasedForLoopIterator& iterator) + { + return iterator.iterator != nullptr; + } + }; + + template + RangeBasedForLoopIterator begin(const IEnumerable& enumerable) + { + return { enumerable }; + } + + template + RangeBasedForLoopEnding end(const IEnumerable& enumerable) + { + return {}; + } + +/*********************************************************************** +Range-Based For-Loop Iterator with Index +***********************************************************************/ + + template + struct RangeBasedForLoopIteratorWithIndex + { + private: + IEnumerator* iterator; + vint index; + + public: + RangeBasedForLoopIteratorWithIndex(const IEnumerable& enumerable) + : iterator(enumerable.CreateEnumerator()) + , index(-1) + { + operator++(); + } + + ~RangeBasedForLoopIteratorWithIndex() + { + if (iterator) delete iterator; + } + + void operator++() + { + if (!iterator->Next()) + { + delete iterator; + iterator = nullptr; + } + index++; + } + + Tuple operator*() const + { + return { iterator->Current(),index }; + } + + bool operator==(const RangeBasedForLoopEnding&) const + { + return iterator == nullptr; + } + + bool operator!=(const RangeBasedForLoopEnding&) const + { + return iterator != nullptr; + } + + friend bool operator==(const RangeBasedForLoopEnding&, const RangeBasedForLoopIteratorWithIndex& iterator) + { + return iterator.iterator == nullptr; + } + + friend bool operator!=(const RangeBasedForLoopEnding&, const RangeBasedForLoopIteratorWithIndex& iterator) + { + return iterator.iterator != nullptr; + } + }; + + template + struct EnumerableWithIndex + { + const IEnumerable& enumerable; + + EnumerableWithIndex(const IEnumerable& _enumerable) + : enumerable(_enumerable) + { + } + }; + + template + EnumerableWithIndex indexed(const IEnumerable& enumerable) + { + return { enumerable }; + } + + template + RangeBasedForLoopIteratorWithIndex begin(const EnumerableWithIndex& enumerable) + { + return { enumerable.enumerable }; + } + + template + RangeBasedForLoopEnding end(const EnumerableWithIndex& enumerable) + { + return {}; + } + } +} + +#endif + /*********************************************************************** .\STRINGS\STRING.H ***********************************************************************/ @@ -5888,7 +6061,7 @@ namespace vl static const T zero; mutable T* buffer = (T*)&zero; - mutable volatile vint* counter = nullptr; + mutable atomic_vint* counter = nullptr; mutable vint start = 0; mutable vint length = 0; mutable vint realLength = 0; @@ -5983,7 +6156,7 @@ namespace vl if (index == 0 && count == length) return source; ObjectString str; - str.counter = new vint(1); + str.counter = new atomic_vint(1); str.start = 0; str.length = length - count + source.length; str.realLength = str.length; @@ -6039,7 +6212,7 @@ namespace vl ObjectString(const T* _buffer) { CHECK_ERROR(_buffer != 0, L"ObjectString::ObjectString(const T*)#Cannot construct a string from nullptr."); - counter = new vint(1); + counter = new atomic_vint(1); start = 0; length = CalculateLength(_buffer); buffer = new T[length + 1]; @@ -6056,7 +6229,7 @@ namespace vl CHECK_ERROR(_length >= 0, L"ObjectString::TakeOver(T*, vint)#Length should not be negative."); CHECK_ERROR(_buffer[_length] == 0, L"ObjectString::TakeOver(T*, vint)#Buffer is not properly zero-terminated."); ObjectString str; - str.counter = new vint(1); + str.counter = new atomic_vint(1); str.length = _length; str.realLength = _length; str.buffer = _buffer; @@ -6087,7 +6260,7 @@ namespace vl str.buffer = new T[_length + 1]; memcpy(str.buffer, _buffer, _length * sizeof(T)); str.buffer[_length] = 0; - str.counter = new vint(1); + str.counter = new atomic_vint(1); str.start = 0; str.length = _length; str.realLength = _length; @@ -6150,7 +6323,7 @@ namespace vl newBuffer[length]=0; Dec(); buffer=newBuffer; - counter=new vint(1); + counter=new atomic_vint(1); start=0; realLength=length; } @@ -6403,52 +6576,52 @@ namespace vl extern double wtof_test(const WString& string, bool& success); /// Convert a string to a signed integer. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern vint atoi(const AString& string); /// Convert a string to a signed integer. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern vint wtoi(const WString& string); /// Convert a string to a signed 64-bits integer. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern vint64_t atoi64(const AString& string); /// Convert a string to a signed 64-bits integer. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern vint64_t wtoi64(const WString& string); /// Convert a string to an usigned integer. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern vuint atou(const AString& string); /// Convert a string to an usigned integer. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern vuint wtou(const WString& string); /// Convert a string to an usigned 64-bits integer. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern vuint64_t atou64(const AString& string); /// Convert a string to an usigned 64-bits integer. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern vuint64_t wtou64(const WString& string); /// Convert a string to a 64-bits floating point number. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern double atof(const AString& string); /// Convert a string to a 64-bits floating point number. - /// The converted number. If the conversion failed, the result is undefined. + /// The converted number. If the conversion failed, the result is 0. /// The string to convert. /// If you need to know whether the conversion is succeeded or not, please use instead. extern double wtof(const WString& string); @@ -6661,7 +6834,7 @@ Quick Sort /// Pointer to element array to sort. /// The number of elements to sort. /// - /// The comparar for two elements returning std::string_ordering. + /// The comparar for two elements returning std::(strong|weak|partial)_ordering. /// template void SortLambda(T* items, vint length, F&& orderer) @@ -6682,10 +6855,13 @@ Quick Sort vint candidate = (flag ? left : length - right - 1); vint factor = (flag ? -1 : 1); - if ( - std::strong_ordering ordering = orderer(items[pivot], items[candidate]); - (factor == 1 && ordering <= 0) || (factor == -1 && ordering >= 0) - ) + auto ordering = orderer(items[pivot], items[candidate]); + if constexpr (std::is_same_v) + { + CHECK_ERROR(ordering != std::partial_ordering::unordered, L"vl::collections::SortLambda(T*, vint, F&&)#This function could not apply on elements in partial ordering."); + } + + if ((factor == 1 && ordering <= 0) || (factor == -1 && ordering >= 0)) { mine++; } @@ -6706,10 +6882,13 @@ Quick Sort vint writing = reading; while (reading >= 0) { - if ( - std::strong_ordering ordering = orderer(items[pivot], items[reading]); - ordering == 0 - ) + auto ordering = orderer(items[pivot], items[reading]); + if constexpr (std::is_same_v) + { + CHECK_ERROR(ordering != std::partial_ordering::unordered, L"vl::collections::SortLambda(T*, vint, F&&)#This function could not apply on elements in partial ordering."); + } + + if (ordering == 0) { if (reading != writing) { @@ -6763,7 +6942,7 @@ Quick Sort /// Pointer to element array to sort. /// The number of elements to sort. /// - /// The comparar for two elements returning std::string_ordering. + /// The comparar for two elements returning std::(strong|weak|partial)_ordering. /// template void Sort(T* items, vint length, F&& orderer) @@ -6804,7 +6983,14 @@ LazyList IEnumerator* xs()const { - return enumeratorPrototype->Clone(); + if (enumeratorPrototype) + { + return enumeratorPrototype->Clone(); + } + else + { + return new EmptyEnumerator(); + } } using TInput = decltype(std::declval>().Current()); @@ -6857,7 +7043,6 @@ LazyList /// Create an empty lazy list. LazyList() - :enumeratorPrototype(new EmptyEnumerator()) { } @@ -6877,7 +7062,7 @@ LazyList IEnumerator* CreateEnumerator()const { - return enumeratorPrototype->Clone(); + return xs(); } //------------------------------------------------------- @@ -6951,7 +7136,7 @@ LazyList /// Type of the comparer. /// The created lazy list. /// - /// The comparar for two elements returning std::string_ordering. + /// The comparar for two elements returning std::(strong|weak|partial)_ordering. /// /// LazyList Evaluate(bool forceCopy = false)const { - if (!forceCopy && enumeratorPrototype->Evaluated()) + if (!enumeratorPrototype) + { + return *this; + } + else if (!forceCopy && enumeratorPrototype->Evaluated()) { return *this; } @@ -8396,7 +8585,7 @@ namespace vl try{STATEMENT; throw ::vl::unittest::UnitTestAssertError(L"Expect an error but nothing occurred: " #STATEMENT);}\ catch(const ::vl::Error&){}\ catch(const ::vl::unittest::UnitTestAssertError&) { throw; }\ - catch (const ::vl::unittest::UnitTestConfigError&) { throw; }\ + catch(const ::vl::unittest::UnitTestConfigError&) { throw; }\ }while(0)\ #define TEST_EXCEPTION(STATEMENT,EXCEPTION,ASSERT_FUNCTION)\ diff --git a/Import/VlppGlrParser.h b/Import/VlppGlrParser.h index 5766d69c..bab744ec 100644 --- a/Import/VlppGlrParser.h +++ b/Import/VlppGlrParser.h @@ -154,10 +154,21 @@ ParsingTextRange { } - bool operator==(const ParsingTextRange& range)const { return start == range.start && end == range.end; } - bool operator!=(const ParsingTextRange& range)const { return start != range.start || end != range.end; } bool Contains(const ParsingTextPos& pos)const { return start <= pos && pos <= end; } bool Contains(const ParsingTextRange& range)const { return start <= range.start && range.end <= end; } + + friend std::strong_ordering operator<=>(const ParsingTextRange& a, const ParsingTextRange& b) + { + std::strong_ordering + result = a.start <=> b.start; if (result != 0) return result; + result = a.end <=> b.end; if (result != 0) return result; + return std::strong_ordering::equal; + } + + friend bool operator==(const ParsingTextRange& a, const ParsingTextRange& b) + { + return (a <=> b) == 0; + } }; /*********************************************************************** diff --git a/Import/VlppOS.Linux.cpp b/Import/VlppOS.Linux.cpp index e30b3210..73bdd3bb 100644 --- a/Import/VlppOS.Linux.cpp +++ b/Import/VlppOS.Linux.cpp @@ -1085,7 +1085,7 @@ EventObject volatile bool signaled; CriticalSection mutex; ConditionVariable cond; - volatile vint counter = 0; + atomic_vint counter = 0; }; } @@ -1503,55 +1503,6 @@ ConditionVariable pthread_cond_broadcast(&internalData->cond); } -/*********************************************************************** -SpinLock -***********************************************************************/ - - SpinLock::Scope::Scope(SpinLock& _spinLock) - :spinLock(&_spinLock) - { - spinLock->Enter(); - } - - SpinLock::Scope::~Scope() - { - spinLock->Leave(); - } - - SpinLock::SpinLock() - :token(0) - { - } - - SpinLock::~SpinLock() - { - } - - bool SpinLock::TryEnter() - { - return __sync_lock_test_and_set(&token, 1)==0; - } - - void SpinLock::Enter() - { - while(__sync_val_compare_and_swap(&token, 0, 1)!=0) - { - while (token != 0) - { -#ifdef VCZH_ARM - __yield(); -#else - _mm_pause(); -#endif - } - } - } - - void SpinLock::Leave() - { - __sync_lock_test_and_set(&token, 0); - } - /*********************************************************************** ThreadLocalStorage ***********************************************************************/ diff --git a/Import/VlppOS.Windows.cpp b/Import/VlppOS.Windows.cpp index f64f079a..1f610a49 100644 --- a/Import/VlppOS.Windows.cpp +++ b/Import/VlppOS.Windows.cpp @@ -1710,55 +1710,6 @@ ConditionVariable WakeAllConditionVariable(&internalData->variable); } -/*********************************************************************** -SpinLock -***********************************************************************/ - - SpinLock::Scope::Scope(SpinLock& _spinLock) - :spinLock(&_spinLock) - { - spinLock->Enter(); - } - - SpinLock::Scope::~Scope() - { - spinLock->Leave(); - } - - SpinLock::SpinLock() - :token(0) - { - } - - SpinLock::~SpinLock() - { - } - - bool SpinLock::TryEnter() - { - return _InterlockedExchange(&token, 1)==0; - } - - void SpinLock::Enter() - { - while(_InterlockedCompareExchange(&token, 1, 0)!=0) - { - while (token != 0) - { -#ifdef VCZH_ARM - __yield(); -#else - _mm_pause(); -#endif - } - } - } - - void SpinLock::Leave() - { - _InterlockedExchange(&token, 0); - } - /*********************************************************************** ThreadLocalStorage ***********************************************************************/ diff --git a/Import/VlppOS.cpp b/Import/VlppOS.cpp index 9db69343..db48ab7f 100644 --- a/Import/VlppOS.cpp +++ b/Import/VlppOS.cpp @@ -460,8 +460,59 @@ Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ +#if defined VCZH_ARM +#elif defined VCZH_MSVC || defined VCZH_GCC +#include +#endif + namespace vl { + +/*********************************************************************** +SpinLock +***********************************************************************/ + + SpinLock::Scope::Scope(SpinLock& _spinLock) + :spinLock(&_spinLock) + { + spinLock->Enter(); + } + + SpinLock::Scope::~Scope() + { + spinLock->Leave(); + } + + bool SpinLock::TryEnter() + { + return token.exchange(1) == 0; + } + + void SpinLock::Enter() + { + vint expected = 0; + while (!token.compare_exchange_strong(expected, 1)) + { + while (token != 0) + { +#ifdef VCZH_ARM + __yield(); +#else + _mm_pause(); +#endif + } + } + } + + void SpinLock::Leave() + { + token.exchange(0); + } + +/*********************************************************************** +ThreadLocalStorage +***********************************************************************/ + void ThreadLocalStorage::Clear() { CHECK_ERROR(!disposed, L"vl::ThreadLocalStorage::Clear()#Cannot access a disposed ThreadLocalStorage."); diff --git a/Import/VlppOS.h b/Import/VlppOS.h index f9e5fd75..6c9e688c 100644 --- a/Import/VlppOS.h +++ b/Import/VlppOS.h @@ -865,8 +865,6 @@ Kernel Mode Objects in Process /*********************************************************************** User Mode Objects ***********************************************************************/ - - typedef long LockedInt; /// /// Spin lock. It is similar to mutex, but it does not occupy resource in the system. @@ -881,12 +879,12 @@ User Mode Objects class SpinLock : public Object { protected: - volatile LockedInt token; + atomic_vint token = 0; public: NOT_COPYABLE(SpinLock); /// Create a spin lock. - SpinLock(); - ~SpinLock(); + SpinLock() = default; + ~SpinLock() = default; /// Try enter a spin lock. This function will return immediately. /// Returns true if the current thread owned the spin lock. diff --git a/Import/VlppParser.h b/Import/VlppParser.h index 6d5056b7..cdf03270 100644 --- a/Import/VlppParser.h +++ b/Import/VlppParser.h @@ -128,8 +128,8 @@ Location ParsingTextRange() :codeIndex(-1) { - end.index=-1; - end.column=-1; + end.index = -1; + end.column = -1; } ParsingTextRange(const ParsingTextPos& _start, const ParsingTextPos& _end, vint _codeIndex = -1) @@ -142,18 +142,29 @@ Location ParsingTextRange(const regex::RegexToken* startToken, const regex::RegexToken* endToken) :codeIndex(startToken->codeIndex) { - start.index=startToken->start; - start.row=startToken->rowStart; - start.column=startToken->columnStart; - end.index=endToken->start+endToken->length-1; - end.row=endToken->rowEnd; - end.column=endToken->columnEnd; + start.index = startToken->start; + start.row = startToken->rowStart; + start.column = startToken->columnStart; + end.index = endToken->start + endToken->length - 1; + end.row = endToken->rowEnd; + end.column = endToken->columnEnd; } - bool operator==(const ParsingTextRange& range)const{return start==range.start && end==range.end;} - bool operator!=(const ParsingTextRange& range)const{return start!=range.start || end!=range.end;} - bool Contains(const ParsingTextPos& pos)const{return start<=pos && pos<=end;} - bool Contains(const ParsingTextRange& range)const{return start<=range.start && range.end<=end;} + bool Contains(const ParsingTextPos& pos)const { return start <= pos && pos <= end; } + bool Contains(const ParsingTextRange& range)const { return start <= range.start && range.end <= end; } + + friend std::strong_ordering operator<=>(const ParsingTextRange& a, const ParsingTextRange& b) + { + std::strong_ordering + result = a.start <=> b.start; if (result != 0) return result; + result = a.end <=> b.end; if (result != 0) return result; + return std::strong_ordering::equal; + } + + friend bool operator==(const ParsingTextRange& a, const ParsingTextRange& b) + { + return (a <=> b) == 0; + } }; } @@ -1122,18 +1133,7 @@ DefinitionTypeScopePair { } - std::strong_ordering operator<=>(const DefinitionTypeScopePair& pair)const - { - std::strong_ordering - result = type <=> pair.type; if (result != 0) return result; - result = scope <=> pair.scope; if (result != 0) return result; - return result; - } - - bool operator==(const DefinitionTypeScopePair& pair)const - { - return (*this <=> pair) == 0; - } + auto operator<=>(const DefinitionTypeScopePair&) const = default; }; /*********************************************************************** diff --git a/Import/VlppReflection.h b/Import/VlppReflection.h index d2350342..4589f990 100644 --- a/Import/VlppReflection.h +++ b/Import/VlppReflection.h @@ -107,7 +107,7 @@ DescriptableObject typedef collections::Dictionary> InternalPropertyMap; typedef bool(*DestructorProc)(DescriptableObject* obj, bool forceDisposing); private: - volatile vint referenceCounter; + atomic_vint referenceCounter; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA size_t objectSize; @@ -181,6 +181,12 @@ DescriptableObject DescriptableObject(); virtual ~DescriptableObject(); + // all fields are describing the object, it would be incorrect if they are copied from one to another. + DescriptableObject(const DescriptableObject&) : DescriptableObject() {} + DescriptableObject(DescriptableObject&&) : DescriptableObject() {} + DescriptableObject& operator=(const DescriptableObject&) { return *this; } + DescriptableObject& operator=(DescriptableObject&&) { return *this; } + #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA /// ///

Get the type descriptor that describe the real type of this object.

@@ -680,7 +686,7 @@ ReferenceCounterOperator template struct ReferenceCounterOperator>> { - static __forceinline volatile vint* CreateCounter(T* reference) + static __forceinline atomic_vint* CreateCounter(T* reference) { reflection::DescriptableObject* obj=reference; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA @@ -695,7 +701,7 @@ ReferenceCounterOperator return &obj->referenceCounter; } - static __forceinline void DeleteReference(volatile vint* counter, void* reference) + static __forceinline void DeleteReference(atomic_vint* counter, void* reference) { reflection::DescriptableObject* obj=(T*)reference; obj->Dispose(false); @@ -1968,21 +1974,14 @@ ValueType { if (auto typedBox = boxedValue.Cast>()) { - if constexpr (std::three_way_comparable) + auto r = value <=> typedBox->value; + if constexpr (std::is_same_v) { - auto r = value <=> typedBox->value; - if (r < 0) return IBoxedValue::Smaller; - if (r > 0) return IBoxedValue::Greater; - return IBoxedValue::Equal; - } - else if constexpr (std::three_way_comparable) - { - auto r = value <=> typedBox->value; if (r == std::partial_ordering::unordered) return IBoxedValue::NotComparable; - if (r < 0) return IBoxedValue::Smaller; - if (r > 0) return IBoxedValue::Greater; - return IBoxedValue::Equal; } + if (r < 0) return IBoxedValue::Smaller; + if (r > 0) return IBoxedValue::Greater; + return IBoxedValue::Equal; } return IBoxedValue::NotComparable; } @@ -7269,40 +7268,20 @@ namespace vl vint data[4]; - static inline vint Compare(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b) + friend std::strong_ordering operator<=>(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b) { + for (vint i = 0; i < sizeof(data) / sizeof(*data); i++) { - auto result = a.data[0] - b.data[0]; + auto result = a.data[i] <=> b.data[i]; if (result != 0) return result; } - { - auto result = a.data[1] - b.data[1]; - if (result != 0) return result; - } - { - auto result = a.data[2] - b.data[2]; - if (result != 0) return result; - } - { - auto result = a.data[3] - b.data[3]; - if (result != 0) return result; - } - return 0; + return std::strong_ordering::equal; } -#define COMPARE(OPERATOR)\ - inline bool operator OPERATOR(const MethodPointerBinaryData& d)const\ - {\ - return Compare(*this, d) OPERATOR 0;\ + friend bool operator==(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b) + { + return (a <=> b) == 0; } - - COMPARE(<) - COMPARE(<=) - COMPARE(>) - COMPARE(>=) - COMPARE(==) - COMPARE(!=) -#undef COMPARE }; template diff --git a/Import/VlppRegex.h b/Import/VlppRegex.h index c2d806df..9b12b9cf 100644 --- a/Import/VlppRegex.h +++ b/Import/VlppRegex.h @@ -1387,11 +1387,11 @@ CharRange return begin == cr.begin && end == cr.end; } - std::strong_ordering operator<=>(char32_t item)const + std::weak_ordering operator<=>(char32_t item)const { - if (end < item) return std::strong_ordering::less; - if (begin > item) return std::strong_ordering::greater; - return std::strong_ordering::equal; + if (end < item) return std::weak_ordering::less; + if (begin > item) return std::weak_ordering::greater; + return std::weak_ordering::equivalent; } bool operator==(char32_t item)const diff --git a/Import/VlppWorkflowCompiler.cpp b/Import/VlppWorkflowCompiler.cpp index ba98712f..7ff77cc3 100644 --- a/Import/VlppWorkflowCompiler.cpp +++ b/Import/VlppWorkflowCompiler.cpp @@ -23422,8 +23422,7 @@ namespace vl { writer.WriteLine(L""); } - writer.WriteLine(prefix + L"\tstd::strong_ordering operator<=>(const " + name + L"&) const = default;"); - writer.WriteLine(prefix + L"\tbool operator==(const " + name + L"&) const = default;"); + writer.WriteLine(prefix + L"\tauto operator<=>(const " + name + L"&) const = default;"); writer.WriteLine(prefix + L"};"); } else diff --git a/Import/VlppWorkflowRuntime.cpp b/Import/VlppWorkflowRuntime.cpp index 04bc389b..c69916e2 100644 --- a/Import/VlppWorkflowRuntime.cpp +++ b/Import/VlppWorkflowRuntime.cpp @@ -5681,12 +5681,12 @@ WfStructInstance } auto result = af <=> bf; - if (result < 0) return IBoxedValue::Smaller; - if (result > 0) return IBoxedValue::Greater; if constexpr (std::is_same_v) { if (result == std::partial_ordering::unordered) return IBoxedValue::NotComparable; } + if (result < 0) return IBoxedValue::Smaller; + if (result > 0) return IBoxedValue::Greater; if (p == ap) ai++; if (p == bp) bi++; diff --git a/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x64 b/Tutorial/GacUI_HelloWorlds/UIRes/Xml.bin.x64 index fe03c3e4c08bc8afa9b8e9bf4bcb4afcf6092da5..aeed856403df53b22b2279de8aca81a6b8c3fce3 100644 GIT binary patch delta 699 zcmah`O=uHA6wYk+XLh6Ml!)2X*lyZl7Y|8VL}L-9R`Fs&FA7a|H<>~}CAJ3-{vdjh zfFKR>dCI|~f`_7b@>Zo#1gY0}DR}5X2yMNoNbAebp*IKKn|(Xq`@V1Hwboc`jlEr0 zFsqE3sZejF@b20;enxGi!w=C4PvK2CZ94r^2j9cP+Euwwt-(^yVoBXZQ=3Fy%hUG| zwzL>t8d-hYb3^Y~K| zC`f^}Z<|V=A%v_yfn=G(qfk5>j?S^{2`qXXPv-@hU-jbM>H}3O;WPL>FR)$V5QKf~ z3s{8zf8Pa+mj&Tn43=h4rarUipy6{oqyNp43pEfp<2zkH?V#r;y}$`$W78Sv-uxhU`?u#u$RhF|U09gWVdYs7ttVnf=U7eGM%?~;cGMTR^K z6UQUTiC5rIc@FI$M{iQWY3VW-w+G{h@}84qh|!yV)&NETl<`Vq1}l z;6)LOd|vdT2Pq;VLJ#6ir1*oNC!vA}9z+VMHxG(fXE$s0=7X8<&3p5{_sz`8vb3@+ zJ$fPIr5eXKxf^L`JKjqM^5OIN5YFR%xP(4s0J@SxL-~mLNEzkGF5Y+HbEFNY)FQH~ zz&-UE;({<3J?5hm?ZgtB?P_=z9l#}9;EhWVs^Q-ct8{%;_)pEGz|Sh7gL<*(3QXyp zc&z7eQO{!^6(kvVsE7R|mDqowop?<>xGBf6MQfK73{nRUYZ+Y8jv}|2@E}Rdp`fO> zgZ`KeuLo$b zEwGvbvu_4-lDHH?MGZAXwM0?Adum`1=zBsAxfQeoLd1Wn zsUaF%3WOktXmDw2ZD?s~i6EM4sjqTq=-~VRzdQc-`;NPBvil}Gue;Sm+wV%?(H(*0 zozVCY>h2sIzKloS)7#NXeEVi~vr;If(^HO9EaYtrd7}8>Da?7^n1)G3!rviqs$AgO zt2PQ=FJl}fF+h4CQlw8JM%pCxKvUx=3W1Ee04pzW64X)Fg3N_+(cQRJV+^V<(cj*h zul@0L$F5B0OB=;%8<^7N+WIk8#g5OwwlB(3)WwMO8VEHWe5E;jWDFRJfMtfUx1uvQ zZp;vDQ{a+z97#C=bv5_T`7mx*58=o-YFQmenK)kZI!2^{zN~;rM-f>Q hxUxi}mYs4TLZPz8F)RJBbKh6XGDJ`v!%|Q*{ROmSjduV5 delta 488 zcmZut&nrYx6rTI$&2#1l^ZXtSdNV966h^|7L`e!O(eUnjGiu7h7{!8(9~-4a(`UoN zA0Q1iDauWBqj`ZH7bS}c{=uj;k z_Z&OVbI{Kx7W}EHuRm>UenIYB-fwW)k zZjF53?d5eTxH2#CS!!+INTy41mL;ZH>Q$1^Fl03%&(n^}5I58@%Z9flakY*v=GH~R gjkUxL4Fv3ga!!Q>