Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package aws-crt-cpp for openSUSE:Factory checked in at 2024-04-02 16:43:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/aws-crt-cpp (Old) and /work/SRC/openSUSE:Factory/.aws-crt-cpp.new.1905 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "aws-crt-cpp" Tue Apr 2 16:43:25 2024 rev:2 rq:1163975 version:0.26.4 Changes: -------- --- /work/SRC/openSUSE:Factory/aws-crt-cpp/aws-crt-cpp.changes 2024-03-18 16:46:44.483788975 +0100 +++ /work/SRC/openSUSE:Factory/.aws-crt-cpp.new.1905/aws-crt-cpp.changes 2024-04-02 16:45:21.415460505 +0200 @@ -1,0 +2,10 @@ +Thu Mar 28 10:34:22 UTC 2024 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to version 0.26.4 + * Basic version of variant type using C++11 by @SergeyRyabinin in (#599) +- from version 0.26.3 + * Add in-place constructor and emplace method + to optional by @SergeyRyabinin in (#600) + * Latest submodules by @sbSteveK in (#601) + +------------------------------------------------------------------- Old: ---- v0.26.2.tar.gz New: ---- v0.26.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ aws-crt-cpp.spec ++++++ --- /var/tmp/diff_new_pack.bwdTY5/_old 2024-04-02 16:45:22.939514906 +0200 +++ /var/tmp/diff_new_pack.bwdTY5/_new 2024-04-02 16:45:22.955515477 +0200 @@ -19,7 +19,7 @@ %define library_soversion 1 Name: aws-crt-cpp -Version: 0.26.2 +Version: 0.26.4 Release: 0 Summary: AWS C++ wrapper for AWS SDK C libraries License: Apache-2.0 ++++++ v0.26.2.tar.gz -> v0.26.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.2/VERSION new/aws-crt-cpp-0.26.4/VERSION --- old/aws-crt-cpp-0.26.2/VERSION 2024-02-15 00:01:58.000000000 +0100 +++ new/aws-crt-cpp-0.26.4/VERSION 2024-03-18 17:52:53.000000000 +0100 @@ -1 +1 @@ -0.26.2 +0.26.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.2/include/aws/crt/Optional.h new/aws-crt-cpp-0.26.4/include/aws/crt/Optional.h --- old/aws-crt-cpp-0.26.2/include/aws/crt/Optional.h 2024-02-15 00:01:58.000000000 +0100 +++ new/aws-crt-cpp-0.26.4/include/aws/crt/Optional.h 2024-03-18 17:52:53.000000000 +0100 @@ -3,6 +3,7 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ +#include <aws/crt/Utility.h> #include <utility> namespace Aws @@ -77,6 +78,12 @@ } } + template <typename... Args> explicit Optional(Aws::Crt::InPlaceT, Args &&...args) + { + new (m_storage) T(std::forward<Args>(args)...); + m_value = reinterpret_cast<T *>(m_storage); + } + Optional &operator=(const Optional &other) { if (this == &other) @@ -170,6 +177,16 @@ return *this; } + template <typename... Args> T &emplace(Args &&...args) + { + reset(); + + new (m_storage) T(std::forward<Args>(args)...); + m_value = reinterpret_cast<T *>(m_storage); + + return *m_value; + } + const T *operator->() const { return m_value; } T *operator->() { return m_value; } const T &operator*() const & { return *m_value; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.2/include/aws/crt/Utility.h new/aws-crt-cpp-0.26.4/include/aws/crt/Utility.h --- old/aws-crt-cpp-0.26.2/include/aws/crt/Utility.h 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.26.4/include/aws/crt/Utility.h 2024-03-18 17:52:53.000000000 +0100 @@ -0,0 +1,31 @@ +#pragma once +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +namespace Aws +{ + namespace Crt + { + /** + * Custom implementation of an in_place type tag for constructor parameter list + */ + struct InPlaceT + { + explicit InPlaceT() = default; + }; + static constexpr InPlaceT InPlace{}; + + template <typename T> struct InPlaceTypeT + { + explicit InPlaceTypeT() = default; + }; + /** Variable templates are only available since C++14 + * Use a dummy object "Aws::Crt::InPlaceTypeT<T>() in-place instead in C++11"*/ +#if defined(__cplusplus) && __cplusplus > 201103L // + template <class T> static constexpr InPlaceTypeT<T> InPlaceType{}; +#endif + + } // namespace Crt +} // namespace Aws diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.2/include/aws/crt/Variant.h new/aws-crt-cpp-0.26.4/include/aws/crt/Variant.h --- old/aws-crt-cpp-0.26.2/include/aws/crt/Variant.h 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.26.4/include/aws/crt/Variant.h 2024-03-18 17:52:53.000000000 +0100 @@ -0,0 +1,584 @@ +#pragma once +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/common/assert.h> +#include <aws/crt/Utility.h> + +#include <algorithm> +#include <type_traits> +#include <utility> + +namespace Aws +{ + namespace Crt + { + namespace VariantDetail + { + template <typename T> constexpr const T &ConstExprMax(const T &a, const T &b) { return (a < b) ? b : a; } + + namespace ParameterPackSize + { + // Returns a max of sizeof(T) over all T in a template parameter pack + template <typename Last> constexpr std::size_t GetMaxSizeOf(std::size_t curMax = 0) + { + return ConstExprMax(curMax, sizeof(Last)); + } + + template <typename First, typename Second, typename... Rest> + constexpr std::size_t GetMaxSizeOf(std::size_t curMax = 0) + { + return ConstExprMax(curMax, GetMaxSizeOf<Second, Rest...>(ConstExprMax(curMax, sizeof(First)))); + } + + // some old gcc versions does not work with alignas(Ts..) + template <typename Last> constexpr std::size_t AlignAsPack(std::size_t curMax = 0) + { + return ConstExprMax(curMax, alignof(Last)); + } + + template <typename First, typename Second, typename... Rest> + constexpr std::size_t AlignAsPack(std::size_t curMax = 0) + { + return ConstExprMax(curMax, AlignAsPack<Second, Rest...>(ConstExprMax(curMax, alignof(First)))); + } + } // namespace ParameterPackSize + + namespace Index + { + using VariantIndex = short; + + template <typename T, typename Last> constexpr VariantIndex GetIndexOf(VariantIndex curIndex = -1) + { + return std::is_same<T, Last>::value ? curIndex : -1; + } + + template <typename T, typename First, typename Second, typename... Rest> + constexpr VariantIndex GetIndexOf(VariantIndex curIndex = 0) + { + return std::is_same<T, First>::value ? curIndex : GetIndexOf<T, Second, Rest...>(++curIndex); + } + } // namespace Index + + namespace Checker + { + // Returns True if the template parameter pack Ts has a type T, i.e. ContainsType<T, Ts>() == true if T + // is in the list of Ts + template <typename T, typename Last> constexpr bool ContainsType() + { + return std::is_same<T, Last>::value; + } + + template <typename T, typename First, typename Second, typename... Rest> constexpr bool ContainsType() + { + return std::is_same<T, First>::value || ContainsType<T, Second, Rest...>(); + } + + // a case when the template parameter pack is empty (i.e. Variant<>) + template <typename T> constexpr bool ContainsType() { return false; } + + template <typename T, typename... Ts> struct HasType + { + static const bool value = ContainsType<T, Ts...>(); + }; + } // namespace Checker +#if defined(AWS_CRT_ENABLE_VARIANT_DEBUG) + namespace VariantDebug + { + template <typename... Ts> class VariantDebugBrowser + { + public: + VariantDebugBrowser(char *storage) { InitTuple<0, Ts...>(storage); } + std::tuple<typename std::add_pointer<Ts>::type...> as_tuple; + + private: + template <IndexT Index, typename First, typename Second, typename... Rest> + void InitTuple(char *storage) + { + First *value = reinterpret_cast<First *>(storage); + std::get<Index>(as_tuple) = value; + InitTuple<Index + 1, Second, Rest...>(storage); + } + + template <IndexT Index, typename Last> void InitTuple(char *storage) + { + Last *value = reinterpret_cast<Last *>(storage); + std::get<Index>(as_tuple) = value; + } + }; + } // namespace VariantDebug +#endif /* defined(AWS_CRT_ENABLE_VARIANT_DEBUG) */ + } // namespace VariantDetail + + template <std::size_t Index, typename... Ts> class VariantAlternative; + + /** + * Custom implementation of a Variant type. std::variant requires C++17 + * @tparam Ts types of the variant value + */ + template <typename... Ts> class Variant + { + private: + template <std::size_t Index> using ThisVariantAlternative = VariantAlternative<Index, Ts...>; + + template <typename OtherT> + using EnableIfOtherIsThisVariantAlternative = typename std:: + enable_if<VariantDetail::Checker::HasType<typename std::decay<OtherT>::type, Ts...>::value, int>::type; + + public: + using IndexT = VariantDetail::Index::VariantIndex; + static constexpr std::size_t AlternativeCount = sizeof...(Ts); + + Variant() + { + using FirstAlternative = typename ThisVariantAlternative<0>::type; + new (m_storage) FirstAlternative(); + m_index = 0; + } + + Variant(const Variant &other) + { + AWS_FATAL_ASSERT(other.m_index != -1); + m_index = other.m_index; + VisitorUtil<0, Ts...>::VisitBinary(this, other, CopyMoveConstructor()); + } + + Variant(Variant &&other) + { + AWS_FATAL_ASSERT(other.m_index != -1); + m_index = other.m_index; + VisitorUtil<0, Ts...>::VisitBinary(this, std::move(other), CopyMoveConstructor()); + } + + template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> Variant(const T &val) + { + static_assert( + VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value, + "This variant does not have such alternative T."); + static_assert( + sizeof(T) <= STORAGE_SIZE, + "Attempting to instantiate a Variant with a type bigger than all alternatives."); + + using PlainT = typename std::decay<T>::type; + new (m_storage) PlainT(val); + m_index = VariantDetail::Index::GetIndexOf<PlainT, Ts...>(); + AWS_ASSERT(m_index != -1); + } + + template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> Variant(T &&val) + { + static_assert( + VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value, + "This variant does not have such alternative T."); + static_assert( + sizeof(T) <= STORAGE_SIZE, + "Attempting to instantiate a Variant with a type bigger than all alternatives."); + + using PlainT = typename std::decay<T>::type; + new (m_storage) PlainT(std::forward<T>(val)); + m_index = VariantDetail::Index::GetIndexOf<PlainT, Ts...>(); + AWS_ASSERT(m_index != -1); + } + + // An overload to initialize with an Alternative T in-place + template <typename T, typename... Args> explicit Variant(Aws::Crt::InPlaceTypeT<T>, Args &&...args) + { + static_assert( + VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value, + "This variant does not have such alternative T."); + static_assert( + sizeof(T) <= STORAGE_SIZE, + "Attempting to instantiate a Variant with a type bigger than all alternatives."); + + using PlainT = typename std::decay<T>::type; + new (m_storage) PlainT(std::forward<Args>(args)...); + m_index = VariantDetail::Index::GetIndexOf<PlainT, Ts...>(); + AWS_ASSERT(m_index != -1); + } + + Variant &operator=(const Variant &other) + { + if (this != &other) + { + AWS_FATAL_ASSERT(other.m_index != -1); + if (m_index != other.m_index) + { + Destroy(); + m_index = other.m_index; + VisitorUtil<0, Ts...>::VisitBinary(this, other, CopyMoveConstructor()); + } + else + { + VisitorUtil<0, Ts...>::VisitBinary(this, other, CopyMoveAssigner()); + } + } + return *this; + } + + Variant &operator=(Variant &&other) + { + if (this != &other) + { + AWS_FATAL_ASSERT(other.m_index != -1); + if (m_index != other.m_index) + { + Destroy(); + m_index = other.m_index; + VisitorUtil<0, Ts...>::VisitBinary(this, std::move(other), CopyMoveConstructor()); + } + else + { + VisitorUtil<0, Ts...>::VisitBinary(this, std::move(other), CopyMoveAssigner()); + }; + } + return *this; + } + + /* emplace */ + template <typename T, typename... Args, EnableIfOtherIsThisVariantAlternative<T> = 1> + T &emplace(Args &&...args) + { + static_assert( + VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value, + "This variant does not have such alternative T."); + static_assert( + sizeof(T) <= STORAGE_SIZE, + "Attempting to instantiate a Variant with a type bigger than all alternatives."); + + Destroy(); + + using PlainT = typename std::decay<T>::type; + new (m_storage) PlainT(std::forward<Args>(args)...); + m_index = VariantDetail::Index::GetIndexOf<PlainT, Ts...>(); + AWS_ASSERT(m_index != -1); + + T *value = reinterpret_cast<T *>(m_storage); + return *value; + } + + template <std::size_t Index, typename... Args> + auto emplace(Args &&...args) -> typename ThisVariantAlternative<Index>::type & + { + static_assert(Index < AlternativeCount, "Unknown alternative index to emplace"); + using AlternativeT = typename ThisVariantAlternative<Index>::type; + + return emplace<AlternativeT, Args...>(std::forward<Args>(args)...); + } + + template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> bool holds_alternative() const + { + AWS_ASSERT(m_index != -1); + return m_index == VariantDetail::Index::GetIndexOf<T, Ts...>(); + } + + /* non-const get */ + template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> T &get() + { + AWS_FATAL_ASSERT(holds_alternative<T>()); + T *value = reinterpret_cast<T *>(m_storage); + return *value; + } + + template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> T *get_if() + { + if (holds_alternative<T>()) + { + T *value = reinterpret_cast<T *>(m_storage); + return value; + } + else + { + return nullptr; + } + } + + template <std::size_t Index> auto get() -> typename ThisVariantAlternative<Index>::type & + { + static_assert(Index < AlternativeCount, "Unknown alternative index to get"); + AWS_FATAL_ASSERT(holds_alternative<Index>()); + using AlternativeT = typename ThisVariantAlternative<Index>::type; + AlternativeT *ret = reinterpret_cast<AlternativeT *>(m_storage); + return *ret; + } + + /* const get */ + template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> const T &get() const + { + AWS_FATAL_ASSERT(holds_alternative<T>()); + const T *value = reinterpret_cast<const T *>(m_storage); + return *value; + } + + template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> const T *get_if() const + { + if (holds_alternative<T>()) + { + T *value = reinterpret_cast<T *>(m_storage); + return value; + } + else + { + return nullptr; + } + } + + template <std::size_t Index> auto get() const -> const typename ThisVariantAlternative<Index>::type & + { + static_assert(Index < AlternativeCount, "Unknown alternative index to get"); + AWS_ASSERT(Index == m_index); + using AlternativeT = typename ThisVariantAlternative<Index>::type; + const AlternativeT *ret = reinterpret_cast<const AlternativeT *>(m_storage); + return *ret; + } + + /* This is just a templated way to say + * "int*" for + * a VariantAlternative<0, Variant<int, char, long>()>*/ + template <std::size_t Index> + using RawAlternativePointerT = + typename std::add_pointer<typename ThisVariantAlternative<Index>::type>::type; + + template <std::size_t Index> auto get_if() -> RawAlternativePointerT<Index> + { + static_assert(Index < AlternativeCount, "Unknown alternative index to get"); + if (holds_alternative<Index>()) + { + using AlternativePtrT = RawAlternativePointerT<Index>; + AlternativePtrT value = reinterpret_cast<AlternativePtrT>(m_storage); + return value; + } + else + { + return nullptr; + } + } + + template <std::size_t Index> + using ConstRawAlternativePointerT = typename std::add_pointer< + typename std::add_const<typename ThisVariantAlternative<Index>::type>::type>::type; + + template <std::size_t Index> auto get_if() const -> ConstRawAlternativePointerT<Index> + { + static_assert(Index < AlternativeCount, "Unknown alternative index to get"); + if (holds_alternative<Index>()) + { + using AlternativePtrT = ConstRawAlternativePointerT<Index>; + AlternativePtrT value = reinterpret_cast<AlternativePtrT>(m_storage); + return value; + } + else + { + return nullptr; + } + } + + std::size_t index() const { return m_index; } + + ~Variant() { Destroy(); } + + template <typename VisitorT> void Visit(VisitorT &&visitor) + { + return VisitorUtil<0, Ts...>::Visit(this, std::forward<VisitorT>(visitor)); + } + + private: + static constexpr std::size_t STORAGE_SIZE = VariantDetail::ParameterPackSize::GetMaxSizeOf<Ts...>(); + + alignas(VariantDetail::ParameterPackSize::AlignAsPack<Ts...>()) char m_storage[STORAGE_SIZE]; + IndexT m_index = -1; +#if defined(AWS_CRT_ENABLE_VARIANT_DEBUG) + VariantDetail::VariantDebug::VariantDebugBrowser<Ts...> browser = m_storage; +#endif /* defined(AWS_CRT_ENABLE_VARIANT_DEBUG) */ + + template <size_t Index> constexpr bool holds_alternative() const { return Index == m_index; } + + struct Destroyer + { + template <typename AlternativeT> void operator()(AlternativeT &&value) const + { + using PlaintT = typename std::remove_reference<AlternativeT>::type; + value.~PlaintT(); + } + }; + + void Destroy() + { + AWS_FATAL_ASSERT(m_index != -1); + Visit(Destroyer()); + + m_index = -1; + } + + struct CopyMoveConstructor + { + template <typename AlternativeT> void operator()(AlternativeT &&value, AlternativeT &&other) const + { + using PlaintT = typename std::remove_reference<AlternativeT>::type; + new (&value) PlaintT(std::move<AlternativeT>(other)); + } + + template <typename AlternativeT, typename ConstAlternativeT> + void operator()(AlternativeT &&value, ConstAlternativeT &other) const + { + using PlaintT = typename std::remove_reference<AlternativeT>::type; + using PlaintOtherT = + typename std::remove_const<typename std::remove_reference<AlternativeT>::type>::type; + static_assert(std::is_same<PlaintT, PlaintOtherT>::value, "Incompatible types"); + + new (&value) PlaintT(other); + } + }; + + struct CopyMoveAssigner + { + template <typename AlternativeT> void operator()(AlternativeT &&value, AlternativeT &&other) const + { + value = std::move(other); + } + + template <typename AlternativeT, typename ConstAlternativeT> + void operator()(AlternativeT &&value, ConstAlternativeT &other) const + { + using PlaintT = typename std::remove_reference<AlternativeT>::type; + using PlaintOtherT = + typename std::remove_const<typename std::remove_reference<AlternativeT>::type>::type; + static_assert(std::is_same<PlaintT, PlaintOtherT>::value, "Incompatible types"); + + value = other; + } + }; + + template <IndexT Index, typename... Args> struct VisitorUtil; + + template <IndexT Index, typename First, typename Second, typename... Rest> + struct VisitorUtil<Index, First, Second, Rest...> + { + template <typename VisitorStruct> static void Visit(Variant *pThis, VisitorStruct &&visitor) + { + static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type"); + + if (Index == pThis->m_index) + { + using AlternativeT = typename ThisVariantAlternative<Index>::type; + AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage); + visitor(*value); + } + else + { + VisitorUtil<Index + 1, Second, Rest...>::Visit(pThis, std::forward<VisitorStruct>(visitor)); + } + } + + template <typename VisitorStruct> + static void VisitBinary(Variant<Ts...> *pThis, Variant<Ts...> &&other, VisitorStruct &&visitor) + { + static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type"); + + if (Index == pThis->m_index) + { + using AlternativeT = typename ThisVariantAlternative<Index>::type; + AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage); + visitor(*value, other.get<AlternativeT>()); + } + else + { + VisitorUtil<Index + 1, Second, Rest...>::VisitBinary( + pThis, std::forward<Variant<Ts...>>(other), std::forward<VisitorStruct>(visitor)); + } + } + + template <typename VisitorStruct> + static void VisitBinary(Variant<Ts...> *pThis, const Variant<Ts...> &other, VisitorStruct &&visitor) + { + static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type"); + + if (Index == pThis->m_index) + { + using AlternativeT = typename ThisVariantAlternative<Index>::type; + AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage); + const AlternativeT &otherValue = other.get<AlternativeT>(); + visitor(*value, otherValue); + } + else + { + VisitorUtil<Index + 1, Second, Rest...>::VisitBinary( + pThis, other, std::forward<VisitorStruct>(visitor)); + } + } + }; + + template <IndexT Index, typename Last> struct VisitorUtil<Index, Last> + { + template <typename VisitorStruct> static void Visit(Variant *pThis, VisitorStruct &&visitor) + { + static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type"); + + if (Index == pThis->m_index) + { + using AlternativeT = typename ThisVariantAlternative<Index>::type; + AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage); + visitor(*value); + } + else + { + AWS_FATAL_ASSERT(!"Unknown variant alternative to visit!"); + } + } + + template <typename VisitorStruct> + static void VisitBinary(Variant<Ts...> *pThis, Variant<Ts...> &&other, VisitorStruct &&visitor) + { + static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type"); + + if (Index == pThis->m_index) + { + using AlternativeT = typename ThisVariantAlternative<Index>::type; + AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage); + visitor(*value, other.get<AlternativeT>()); + } + else + { + AWS_FATAL_ASSERT(!"Unknown variant alternative to visit!"); + } + } + + template <typename VisitorStruct> + static void VisitBinary(Variant<Ts...> *pThis, const Variant<Ts...> &other, VisitorStruct &&visitor) + { + static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type"); + + if (Index == pThis->m_index) + { + using AlternativeT = typename ThisVariantAlternative<Index>::type; + AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage); + const AlternativeT &otherValue = other.get<AlternativeT>(); + visitor(*value, otherValue); + } + else + { + AWS_FATAL_ASSERT(!"Unknown variant alternative to visit!"); + } + } + }; + }; + + /* Helper template to get an actual type from an Index */ + template <std::size_t Index, typename... Ts> class VariantAlternative + { + public: + // uses std::tuple as a helper struct to provide index-based access of a parameter pack + using type = typename std::tuple_element<Index, std::tuple<Ts...>>::type; + + VariantAlternative(const Variant<Ts...> &) {} + + VariantAlternative(const Variant<Ts...> *) {} + }; + + template <typename T> class VariantSize + { + constexpr static const std::size_t Value = T::AlternativeCount; + }; + } // namespace Crt +} // namespace Aws diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.2/tests/CMakeLists.txt new/aws-crt-cpp-0.26.4/tests/CMakeLists.txt --- old/aws-crt-cpp-0.26.2/tests/CMakeLists.txt 2024-02-15 00:01:58.000000000 +0100 +++ new/aws-crt-cpp-0.26.4/tests/CMakeLists.txt 2024-03-18 17:52:53.000000000 +0100 @@ -91,7 +91,13 @@ add_test_case(DefaultResolution) add_test_case(OptionalCopySafety) add_test_case(OptionalMoveSafety) +add_test_case(OptionalEmplace) add_test_case(OptionalCopyAndMoveSemantics) +add_test_case(VariantCompiles) +add_test_case(VariantConstructor) +add_test_case(VariantOperatorEquals) +add_test_case(VariantEmplace) +add_test_case(VariantVisitor) add_test_case(StreamTestCreateDestroyWrapper) add_test_case(StreamTestLength) add_test_case(StreamTestRead) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.2/tests/OptionalMemorySafetyTest.cpp new/aws-crt-cpp-0.26.4/tests/OptionalMemorySafetyTest.cpp --- old/aws-crt-cpp-0.26.2/tests/OptionalMemorySafetyTest.cpp 2024-02-15 00:01:58.000000000 +0100 +++ new/aws-crt-cpp-0.26.4/tests/OptionalMemorySafetyTest.cpp 2024-03-18 17:52:53.000000000 +0100 @@ -56,6 +56,54 @@ AWS_TEST_CASE(OptionalMoveSafety, s_OptionalMoveSafety) +class EmplaceTester +{ + public: + int a; + static size_t ctorCallCount; + static size_t dtorCallCount; + EmplaceTester(int val) : a(val) { ctorCallCount += 1; } + ~EmplaceTester() + { + a = -1337; + dtorCallCount += 1; + } + EmplaceTester(const EmplaceTester &) = delete; + EmplaceTester(EmplaceTester &&) = delete; +}; +size_t EmplaceTester::ctorCallCount = 0; +size_t EmplaceTester::dtorCallCount = 0; + +static int s_OptionalEmplace(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + + Aws::Crt::Optional<Aws::Crt::String> str1{Aws::Crt::InPlace, s_test_str}; + ASSERT_STR_EQUALS(s_test_str, str1->c_str()); + + ASSERT_INT_EQUALS(0, EmplaceTester::ctorCallCount); + ASSERT_INT_EQUALS(0, EmplaceTester::dtorCallCount); + // Aws::Crt::Optional<MyTestClass> opt1(MyTestClass(5)); // error: call to deleted constructor of 'MyTestClass' + Aws::Crt::Optional<EmplaceTester> opt1{Aws::Crt::InPlace, 5}; // but this is allowed + ASSERT_INT_EQUALS(5, opt1->a); + ASSERT_INT_EQUALS(1, EmplaceTester::ctorCallCount); + ASSERT_INT_EQUALS(0, EmplaceTester::dtorCallCount); + + opt1.emplace(100); + ASSERT_INT_EQUALS(100, opt1->a); + // If optional already contains a value before the call, the contained value is destroyed. + ASSERT_INT_EQUALS(2, EmplaceTester::ctorCallCount); + ASSERT_INT_EQUALS(1, EmplaceTester::dtorCallCount); + } + ASSERT_INT_EQUALS(2, EmplaceTester::dtorCallCount); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(OptionalEmplace, s_OptionalEmplace) + class CopyMoveTester { public: @@ -128,4 +176,4 @@ return AWS_OP_SUCCESS; } -AWS_TEST_CASE(OptionalCopyAndMoveSemantics, s_OptionalCopyAndMoveSemantics) +AWS_TEST_CASE(OptionalCopyAndMoveSemantics, s_OptionalCopyAndMoveSemantics) \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.2/tests/VariantTest.cpp new/aws-crt-cpp-0.26.4/tests/VariantTest.cpp --- old/aws-crt-cpp-0.26.2/tests/VariantTest.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.26.4/tests/VariantTest.cpp 2024-03-18 17:52:53.000000000 +0100 @@ -0,0 +1,367 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/crt/Api.h> +#include <aws/crt/Variant.h> +#include <aws/testing/aws_test_harness.h> + +const char *s_variant_test_str = "This is a string, that should be long enough to avoid small string optimizations"; + +static int s_VariantBasicOperandsCompile(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + + { + using MyTestVariant1 = Aws::Crt::Variant<int, char, Aws::Crt::String>; + MyTestVariant1 var1; + MyTestVariant1 var1CpyAssigned; + var1CpyAssigned = var1; + MyTestVariant1 var1CpyConstructedVariant(var1CpyAssigned); + + MyTestVariant1 var1a = Aws::Crt::String(s_variant_test_str); + var1 = var1a; + MyTestVariant1 var1aCpyAssigned; + var1CpyAssigned = var1a; + MyTestVariant1 var1aCpyConstructedVariant(var1aCpyAssigned); + } + + { + // just a different order or types + using MyTestVariant2 = Aws::Crt::Variant<Aws::Crt::String, int, char>; + MyTestVariant2 var2; + MyTestVariant2 var2CpyAssigned; + var2CpyAssigned = var2; + MyTestVariant2 var2CpyConstructedVariant(var2CpyAssigned); + + MyTestVariant2 var2a = Aws::Crt::String(s_variant_test_str); + var2 = var2a; + MyTestVariant2 var2aCpyAssigned; + var2CpyAssigned = var2a; + MyTestVariant2 var2aCpyConstructedVariant(var2aCpyAssigned); + } + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(VariantCompiles, s_VariantBasicOperandsCompile) + +static int s_VariantConstructor(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + + { + using VariantIntCharString = Aws::Crt::Variant<int, char, Aws::Crt::String>; + VariantIntCharString var1 = Aws::Crt::String(s_variant_test_str); + ASSERT_STR_EQUALS(s_variant_test_str, var1.get<2>().c_str()); + ASSERT_STR_EQUALS(s_variant_test_str, var1.get<Aws::Crt::String>().c_str()); + + VariantIntCharString var1copy = var1; + ASSERT_STR_EQUALS(s_variant_test_str, var1copy.get<2>().c_str()); + ASSERT_STR_EQUALS(s_variant_test_str, var1copy.get<Aws::Crt::String>().c_str()); + + VariantIntCharString var1move = std::move(var1); + ASSERT_STR_EQUALS(s_variant_test_str, var1move.get<2>().c_str()); + ASSERT_STR_EQUALS(s_variant_test_str, var1move.get<Aws::Crt::String>().c_str()); + } + { + using VariantStringCharInt = Aws::Crt::Variant<Aws::Crt::String, int, char>; + VariantStringCharInt var1{Aws::Crt::InPlaceTypeT<Aws::Crt::String>(), s_variant_test_str}; + ASSERT_STR_EQUALS(s_variant_test_str, var1.get<0>().c_str()); + ASSERT_STR_EQUALS(s_variant_test_str, var1.get<Aws::Crt::String>().c_str()); + + VariantStringCharInt var1copy = var1; + ASSERT_STR_EQUALS(s_variant_test_str, var1copy.get<0>().c_str()); + ASSERT_STR_EQUALS(s_variant_test_str, var1copy.get<Aws::Crt::String>().c_str()); + + VariantStringCharInt var1move = std::move(var1); + ASSERT_STR_EQUALS(s_variant_test_str, var1move.get<0>().c_str()); + ASSERT_STR_EQUALS(s_variant_test_str, var1move.get<Aws::Crt::String>().c_str()); + + VariantStringCharInt var1default; + ASSERT_STR_EQUALS("", var1default.get<0>().c_str()); + ASSERT_STR_EQUALS("", var1default.get<Aws::Crt::String>().c_str()); + } + + { + class MyTestVirtualClass + { + public: + int *m_pState; + + MyTestVirtualClass(int *state) : m_pState(state) { *m_pState += 1; } + + virtual ~MyTestVirtualClass() { *m_pState -= 10; } + }; + class MyTestVirtualClassChild : MyTestVirtualClass + { + public: + int *m_pStateChild; + + MyTestVirtualClassChild(int *state, int *childState) + : MyTestVirtualClass(state), m_pStateChild(childState) + { + *m_pStateChild += 2; + } + + virtual ~MyTestVirtualClassChild() { *m_pStateChild -= 20; } + }; + + using MyTestVariant = Aws::Crt::Variant<MyTestVirtualClass, MyTestVirtualClassChild, Aws::Crt::String>; + // Test for constructing from one of alternative types with a virtual destructor + { + int parentState = 0; + int childState = 0; + { + MyTestVariant myTestVariant{MyTestVirtualClassChild(&parentState, &childState)}; + // original MyTestVirtualClassChild was constructed, implicitly moved to variant and destructed + ASSERT_INT_EQUALS(-9, parentState); + ASSERT_INT_EQUALS(-18, childState); + } + // destructor of move-constructed MyTestVirtualClassChild has updated the values by pointers one more + // time + ASSERT_INT_EQUALS(-19, parentState); + ASSERT_INT_EQUALS(-38, childState); + } + // Test for in-place (without moving or copying) constructing from one of alternative types with a virtual + // destructor + { + int parentState = 0; + int childState = 0; + { + MyTestVariant myTestVariant{ + Aws::Crt::InPlaceTypeT<MyTestVirtualClassChild>(), &parentState, &childState}; + // constructor of MyTestVirtualClassChild was called only once, destructor was not called (yet) + ASSERT_INT_EQUALS(1, parentState); + ASSERT_INT_EQUALS(2, childState); + } + // destructor MyTestVirtualClassChild has been called once + ASSERT_INT_EQUALS(-9, parentState); + ASSERT_INT_EQUALS(-18, childState); + } + // Test for in-place assignment + { + int parentState = 0; + int childState = 0; + { + MyTestVariant myTestVariant{ + Aws::Crt::InPlaceTypeT<MyTestVirtualClassChild>(), &parentState, &childState}; + myTestVariant.emplace<MyTestVirtualClass>(&parentState); + // both were destructed but only a parent got constructed once again + ASSERT_INT_EQUALS(-8, parentState); + ASSERT_INT_EQUALS(-18, childState); + + myTestVariant.emplace<Aws::Crt::String>("A replacement string"); + ASSERT_STR_EQUALS("A replacement string", myTestVariant.get_if<2>()->c_str()); + } + ASSERT_INT_EQUALS(-18, parentState); + ASSERT_INT_EQUALS(-18, childState); // destructor of child was not called + } + } + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(VariantConstructor, s_VariantConstructor) + +static int s_VariantOperatorEquals(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + + { + using VariantIntCharString = Aws::Crt::Variant<int, char, Aws::Crt::String>; + + VariantIntCharString var1(int(5)); + ASSERT_INT_EQUALS(5, var1.get<int>()); + + VariantIntCharString var2(int(10)); + ASSERT_INT_EQUALS(10, var2.get<int>()); + + var1 = var2; + ASSERT_INT_EQUALS(10, var1.get<int>()); + + VariantIntCharString varStr1{Aws::Crt::InPlaceTypeT<Aws::Crt::String>(), s_variant_test_str}; + ASSERT_STR_EQUALS(s_variant_test_str, varStr1.get<2>().c_str()); + VariantIntCharString varStr2; + ASSERT_INT_EQUALS(0, varStr2.get<int>()); + varStr2 = varStr1; + ASSERT_STR_EQUALS(s_variant_test_str, varStr1.get<Aws::Crt::String>().c_str()); + ASSERT_STR_EQUALS(s_variant_test_str, varStr2.get<2>().c_str()); + + const VariantIntCharString varStr3(std::move(varStr1)); + ASSERT_STR_EQUALS(s_variant_test_str, varStr3.get<Aws::Crt::String>().c_str()); + ASSERT_STR_EQUALS(s_variant_test_str, varStr3.get_if<2>()->c_str()); + ASSERT_TRUE(varStr1.get<Aws::Crt::String>().empty()); + + VariantIntCharString varStr4(varStr3); + ASSERT_STR_EQUALS(s_variant_test_str, varStr3.get_if<2>()->c_str()); // not moved + ASSERT_STR_EQUALS(s_variant_test_str, varStr4.get_if<2>()->c_str()); // copied + + varStr1 = std::move(varStr4); + ASSERT_TRUE(varStr4.get<2>().empty()); // moved from + ASSERT_STR_EQUALS(s_variant_test_str, varStr1.get<2>().c_str()); // moved here + } + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(VariantOperatorEquals, s_VariantOperatorEquals) + +struct TestStringOnlyVisitor +{ + /* can't specialize member function templates, so using such syntax of dummy structs */ + template <typename... Args> struct MyVisitUtil + { + static void Visit(Args &...) + { + ; // not a string + } + }; + + template <typename AlternativeT> void operator()(AlternativeT &val) const + { + MyVisitUtil<typename std::remove_reference<AlternativeT>::type>::Visit(val); + } +}; + +template <> struct TestStringOnlyVisitor::MyVisitUtil<Aws::Crt::String> +{ + static void Visit(Aws::Crt::String &val) + { + auto index = val.find("another"); + val.replace(index, 7, "visited"); + } +}; + +static int s_VariantEmplace(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + + { + using VariantIntCharString = Aws::Crt::Variant<int, char, Aws::Crt::String>; + + VariantIntCharString var1(char('a')); + ASSERT_INT_EQUALS('a', var1.get<char>()); + + var1.emplace<int>(65535); + ASSERT_INT_EQUALS(65535, var1.get<int>()); + + var1.emplace<0>(1337); + ASSERT_INT_EQUALS(1337, var1.get<int>()); + + var1.emplace<Aws::Crt::String>(Aws::Crt::String("This is a string.")); + ASSERT_STR_EQUALS("This is a string.", var1.get<Aws::Crt::String>().c_str()); + + var1.emplace<2>(Aws::Crt::String("This is another string.")); + ASSERT_STR_EQUALS("This is another string.", var1.get<Aws::Crt::String>().c_str()); + + var1.Visit(TestStringOnlyVisitor()); + ASSERT_STR_EQUALS("This is visited string.", var1.get<Aws::Crt::String>().c_str()); + } + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(VariantEmplace, s_VariantEmplace) + +/* This is an example of a template visitor that accepts an alternative template and handles as a template */ +struct TestVisitor +{ + Aws::Crt::String m_visitorResult; + + template <typename AlternativeT> void operator()(AlternativeT &val) + { + Aws::Crt::StringStream stringStream; + stringStream << "Alternative value: " << val; + m_visitorResult = stringStream.str(); + } +}; + +/* This is an example of a visitor that accepts an alternative template and has a specialization for types for custom + * logic per type */ +struct TestVisitorCustomizedPerType +{ + Aws::Crt::String m_visitorResult; + /* can't specialize member function templates, so using such syntax of dummy structs */ + template <typename... Args> struct MyVisitUtil + { + }; + + template <typename AlternativeT> void operator()(AlternativeT &val) + { + using TypedRealVisitor = MyVisitUtil<typename std::remove_reference<AlternativeT>::type>; + m_visitorResult = TypedRealVisitor::Visit(val); + } +}; + +template <> struct TestVisitorCustomizedPerType::MyVisitUtil<Aws::Crt::String> +{ + static Aws::Crt::String Visit(Aws::Crt::String &val) { return Aws::Crt::String("String has: " + val); } +}; +template <> struct TestVisitorCustomizedPerType::MyVisitUtil<int> +{ + static Aws::Crt::String Visit(int &val) + { + Aws::Crt::StringStream stringStream; + stringStream << "Int has: " << val; + return stringStream.str(); + } +}; +template <> struct TestVisitorCustomizedPerType::MyVisitUtil<char> +{ + static Aws::Crt::String Visit(char &val) + { + Aws::Crt::StringStream stringStream; + stringStream << "Char has: " << val; + return stringStream.str(); + } +}; + +static int s_VariantVisitor(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + + { + using VariantStringIntChar = Aws::Crt::Variant<int, char, Aws::Crt::String>; + TestVisitor visitor; + TestVisitorCustomizedPerType specializedVisitor; + + VariantStringIntChar var1(char('a')); + + var1.Visit(visitor); + ASSERT_STR_EQUALS("Alternative value: a", visitor.m_visitorResult.c_str()); + var1.Visit(specializedVisitor); + ASSERT_STR_EQUALS("Char has: a", specializedVisitor.m_visitorResult.c_str()); + + var1.emplace<int>(5061992); + var1.Visit(visitor); + ASSERT_STR_EQUALS("Alternative value: 5061992", visitor.m_visitorResult.c_str()); + var1.Visit(specializedVisitor); + ASSERT_STR_EQUALS("Int has: 5061992", specializedVisitor.m_visitorResult.c_str()); + + var1.emplace<Aws::Crt::String>("Meow"); + var1.Visit(visitor); + ASSERT_STR_EQUALS("Alternative value: Meow", visitor.m_visitorResult.c_str()); + var1.Visit(specializedVisitor); + ASSERT_STR_EQUALS("String has: Meow", specializedVisitor.m_visitorResult.c_str()); + } + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(VariantVisitor, s_VariantVisitor) \ No newline at end of file