16 #ifndef A_UTIL_UTIL_RESULT_DETAIL_DESCRIPTION_IMPL_HEADER_INCLUDED
17 #define A_UTIL_UTIL_RESULT_DETAIL_DESCRIPTION_IMPL_HEADER_INCLUDED
31 template <
typename DescriptionIntf>
33 const std::uint64_t value)
36 return (!isErrorCodeSet(value)) &&
37 0 != (value & error_code_bitmask);
40 template <
typename DescriptionIntf>
44 return error_code_bit == (value & error_code_bit);
47 template <
typename DescriptionIntf>
49 const std::int32_t error_code) noexcept
54 (
static_cast<std::uint64_t
>(error_code) & error_code_serialize_bitmask) |
59 template <
typename DescriptionIntf>
61 const std::uint64_t error_code) noexcept
63 return static_cast<std::int32_t
>(
67 (error_code | error_code_deserialize_bitmask));
70 template <
typename DescriptionIntf>
72 DescriptionIntf>::toInternalErrorPointer(
const std::uint64_t error_code) noexcept
77 template <
typename DescriptionIntf>
83 constexpr
auto minus_one_representation = toInternalErrorCode(-1);
84 constexpr
auto plus_one_representation = toInternalErrorCode(1);
86 #if defined(__GNUC__) && ((__GNUC__ == 5) && (__GNUC_MINOR__ == 2))
87 #pragma GCC diagnostic push
88 #pragma GCC diagnostic ignored "-Wattributes"
90 constexpr
auto min_val_representation =
91 toInternalErrorCode((numeric_limits<std::int32_t>::min)());
92 constexpr
auto max_val_representation =
93 toInternalErrorCode((numeric_limits<std::int32_t>::max)());
94 #if defined(__GNUC__) && ((__GNUC__ == 5) && (__GNUC_MINOR__ == 2))
95 #pragma GCC diagnostic pop
101 static_assert(0x8000000000000000 == error_code_bit,
"error_code_bit must not be changed!");
102 static_assert(~0x8000000000000000 == error_code_bitmask,
103 "error_code_bitmask must not be changed!");
104 static_assert(0xFFFFFFFF00000000 == error_code_deserialize_bitmask,
105 "error_code_deserialize_bitmask must not be changed!");
106 static_assert(0xFFFFFFFF == error_code_serialize_bitmask,
107 "error_code_serialize_bitmask must not be changed!");
108 static_assert(0x80000000ffffffff == minus_one_representation,
109 "Calculation of internal error code representation must not be changed!");
110 static_assert(0x8000000000000001 == plus_one_representation,
111 "Calculation of internal error code representation must not be changed!");
112 static_assert(0x8000000080000000 == min_val_representation,
113 "Calculation of internal error code representation must not be changed!");
114 static_assert(0x800000007fffffff == max_val_representation,
115 "Calculation of internal error code representation must not be changed!");
118 template <
typename DescriptionIntf>
123 template <
typename DescriptionIntf>
125 : _pointer_to_result_or_error_code{}
130 template <
typename DescriptionIntf>
134 if (&other !=
this) {
135 if (TraitsType::isDetailedDescriptionSet(_pointer_to_result_or_error_code)) {
136 TraitsType::toInternalErrorPointer(_pointer_to_result_or_error_code)->removeReference();
139 _pointer_to_result_or_error_code = other._pointer_to_result_or_error_code;
140 if (TraitsType::isDetailedDescriptionSet(_pointer_to_result_or_error_code)) {
141 TraitsType::toInternalErrorPointer(_pointer_to_result_or_error_code)->addReference();
147 template <
typename DescriptionIntf>
149 : _pointer_to_result_or_error_code{}
151 std::swap(other._pointer_to_result_or_error_code, _pointer_to_result_or_error_code);
154 template <
typename DescriptionIntf>
158 if (&other !=
this) {
159 if (TraitsType::isDetailedDescriptionSet(_pointer_to_result_or_error_code)) {
160 TraitsType::toInternalErrorPointer(_pointer_to_result_or_error_code)->removeReference();
163 _pointer_to_result_or_error_code = {};
164 std::swap(other._pointer_to_result_or_error_code, _pointer_to_result_or_error_code);
169 template <
typename DescriptionIntf>
172 if (TraitsType::isDetailedDescriptionSet(_pointer_to_result_or_error_code)) {
173 TraitsType::toInternalErrorPointer(_pointer_to_result_or_error_code)->removeReference();
176 static_assert(
sizeof(std::uintptr_t) <= 8,
177 "ResultDescription pointers must always have a size of 8 Byte or less!");
180 template <
typename DescriptionIntf>
181 template <
typename DescriptionImpl,
typename... Args>
189 const auto reference_counted_error_object =
190 new ReferenceCountedErrorType(error_code, std::forward<Args>(args)...);
191 SelfType result_description(*reference_counted_error_object);
192 if (TraitsType::isErrorCodeSet(result_description._pointer_to_result_or_error_code)) {
194 reference_counted_error_object->removeReference();
195 assert((
false) &&
"The MSB of the pointer to the heap allocated memory is set to 1, "
196 "but it is reserved for the error code bit. This is inplausible and "
200 return result_description;
203 catch (
const std::bad_alloc&) {
207 return SelfType::makeResultDescription(error_code);
210 template <
typename DescriptionIntf>
211 template <
typename T>
213 DescriptionIntf>::makeResultDescription(const ::a_util::result::ResultInfo<T>&) noexcept
216 SelfType result_description(uncounted_error);
220 if (!TraitsType::isErrorCodeSet(result_description._pointer_to_result_or_error_code)) {
221 return result_description;
227 template <
typename DescriptionIntf>
229 std::int32_t error_code)
236 template <
typename DescriptionIntf>
240 if (TraitsType::isDetailedDescriptionSet(_pointer_to_result_or_error_code)) {
241 return &TraitsType::toInternalErrorPointer(_pointer_to_result_or_error_code)->getObject();
246 template <
typename DescriptionIntf>
250 if (TraitsType::isErrorCodeSet(_pointer_to_result_or_error_code)) {
251 return TraitsType::toExternalErrorCode(_pointer_to_result_or_error_code);
256 template <
typename DescriptionIntf>
258 std::int32_t error_code) noexcept
259 : _pointer_to_result_or_error_code(TraitsType::toInternalErrorCode(error_code))
263 template <
typename DescriptionIntf>
266 : _pointer_to_result_or_error_code(
reinterpret_cast<std::uintptr_t
>(&error_object))
268 static_assert(
sizeof(std::uintptr_t) ==
sizeof(decltype(&error_object)),
269 "ResultDescription pointers must match the size of std::uintptr_t!");
270 assert((!TraitsType::isErrorCodeSet(_pointer_to_result_or_error_code)) &&
271 "The cast of the pointer to the internal error code set the MSB to 1, but it is "
272 "reserved for the error code bit. This is inplausible and must not happen.");
273 error_object.addReference();
276 template <
typename T>
286 template <
typename T>
289 return !(lhs == rhs);
Default implementation of a reference counter.
An internal stable interface to ensure binary compatibility of reference counting.
Wrapper for either a pointer to a detailed description object or simply a numeric error code.
ResultDescription & operator=(const ResultDescription &other)
Copy assignment operator.
std::int32_t getErrorCode() const
Get the error code if only the error code was set.
DescriptionIntf const * getDetailedDescription() const
Get the detailed description if any was allocated.
~ResultDescription()
DTOR.
static SelfType makeResultDescription(std::int32_t error_code, Args &&... args)
Allocate an object being able to store detailed error information.
ResultDescription< DescriptionIntf > SelfType
Self type.
Default implementation of a non-counting reference counter.
tVoid swap(A_UTILS_NS::d_ptr< _PARENT, _PRIVATE_D > &i_oLHS, A_UTILS_NS::d_ptr< _PARENT, _PRIVATE_D > &i_oRHS)
std::swap specialization for AUTILSDPtr for perfect fit on ADL
Declare the default error description class for Result return values.
bool operator==(const ResultDescription< T > &lhs, const ResultDescription< T > &rhs)
Compare two result description objects for equality.
bool operator!=(const ResultDescription< T > &lhs, const ResultDescription< T > &rhs)
Compare two result description objects for inequality.
Serves as the root component, with common functionality documented in core functionality.
Implements the default reference counted object.
Private API for ResultDescription type and functions.
Basic result information template, used by a_util::result::Result.
Traits type for the result description.
static bool isDetailedDescriptionSet(std::uint64_t value)
Check whether the detailed description was allocated.
constexpr static std::int32_t toExternalErrorCode(std::uint64_t error_code) noexcept
Get the external error code from the internal error code representation.
~ResultDescriptionTraits()
To implement various static checks.
constexpr static std::uint64_t toInternalErrorCode(std::int32_t error_code) noexcept
Get the internal error code representation from the external error code.
static bool isErrorCodeSet(std::uint64_t value)
Check whether only the error code was set.