ADTF
builds/digitalwerk/solutions/adtf_content/adtf_base/adtf_core/src/libraries/a_utils/include/a_utils/core/result.h
Go to the documentation of this file.
1 
8 #ifndef _A_UTILS_BASE_RESULT_H_
9 #define _A_UTILS_BASE_RESULT_H_
10 
11 // #include <type_traits>
12 #include <a_utils/a_utils_version.h>
13 #include <a_utils/base/types.h>
14 #include <a_utils/base/error.h>
15 #include <a_utils/base/constants.h>
19 
20 #include <cstdio>
21 #include <cstdarg>
22 #ifdef _MSC_VER
23  #include <sal.h>
24 #endif
25 #include <string>
26 #include <string_view>
27 #include <thread>
28 #include <sstream>
29 
30 namespace A_UTILS_NS::detail
31 {
32 static inline std::string filename(std::string_view strPath)
33 {
34  auto nLastSlash = strPath.rfind('/');
35  if (nLastSlash == std::string::npos)
36  {
37  nLastSlash = strPath.rfind('\\');
38  }
39  if (nLastSlash == std::string_view::npos)
40  {
41  return std::string(strPath);
42  }
43  return std::string(strPath.substr(nLastSlash + 1));
44 }
45 
46 static inline std::string filename_with_thread_id(std::string_view strPath)
47 {
48  using namespace std::literals;
49  std::ostringstream strBuffer;
50  strBuffer << "tid="sv << std::this_thread::get_id() << " "sv << filename(strPath);
51  return strBuffer.str();
52 }
53 
54 static inline std::string
55 #ifdef __GNUC__
56  __attribute__((format(printf, 1, 2)))
57 #endif // __GNUC__
58  format(
59 #ifdef _MSC_VER
60  _In_z_ _Printf_format_string_
61 #endif // _MSC_VER
62  const char* strFormat,
63  ...)
64 {
65  va_list args, args_copy;
66  va_start(args, strFormat);
67  va_copy(args_copy, args);
68  std::string strBuffer;
69  strBuffer.resize(static_cast<size_t>(::std::vsnprintf(nullptr, 0, strFormat, args_copy)));
70  va_end(args_copy);
71  ::std::vsnprintf(strBuffer.data(), strBuffer.size() + 1, strFormat, args);
72  va_end(args);
73  return strBuffer;
74 }
75 } // namespace A_UTILS_NS::detail
76 
78 #define IS_OK(s) ((s).IsOk())
79 
81 #define IS_FAILED(s) ((s).IsFailed())
82 
84 #define DETAILED_RESULT(_errcode, ...) \
85  tResult(_errcode, A_UTILS_NS::detail::format(__VA_ARGS__).c_str(), __LINE__, \
86  A_UTILS_NS::detail::filename_with_thread_id(__FILE__).c_str(), __FUNC__)
90 #define RETURN_NOERROR return ERR_NOERROR
91 
92 #if (__UCOM_ASSERT_WHEN_LOGGING_ERRORS == 1)
94  #define RETURN_ERROR(_code) \
95  assert(IS_OK(_code)); \
96  return (_code)
98  #define RETURN_ERROR_DESC(_code, ...) \
99  assert(IS_OK(_code)); \
100  return DETAILED_RESULT(_code, __VA_ARGS__)
101 #else
103  #define RETURN_ERROR(code) return (code)
105  #define RETURN_ERROR_DESC(_code, ...) return DETAILED_RESULT(_code, __VA_ARGS__)
106 
107 #endif
108 
110 #define RETURN_IF_FAILED(s) \
111  { \
112  tResult _errcode(s); \
113  if (_errcode.IsFailed()) \
114  { \
115  return (_errcode); \
116  } \
117  }
118 
119 #define RETURN_IF_FAILED_DESC(s, ...) \
120  { \
121  tResult _errcode(s); \
122  if (_errcode.IsFailed()) \
123  { \
124  return DETAILED_RESULT(_errcode.GetErrorCode().value, __VA_ARGS__); \
125  } \
126  }
127 
129 #define RETURN_IF_POINTER_NULL(_ptr) \
130  if (nullptr == _ptr) \
131  { \
132  RETURN_ERROR(ERR_POINTER); \
133  }
134 
137 #define RETURN_IF_POINTER_NULL_DESC(_ptr, ...) \
138  if (nullptr == _ptr) \
139  { \
140  return DETAILED_RESULT(ERR_POINTER, __VA_ARGS__); \
141  }
142 
143 namespace A_UTILS_NS
144 {
145 
149 class cResult
150 {
151 public: // construction
161  constexpr cResult() noexcept;
162 
170  constexpr cResult(decltype(ERR_NOERROR)) noexcept;
171 
176  template<tErrorCode::error_code_type ErrorCode>
177  constexpr cResult(const tError<ErrorCode>& i_oError) noexcept;
178 
183  constexpr cResult(tErrorCode i_oError) noexcept;
184 
194  template<tErrorCode::error_code_type ErrorCode>
195  explicit cResult(tError<ErrorCode> i_oError,
196  const tChar* i_strErrorDescription,
197  tInt32 i_nLine,
198  const tChar* i_strFile,
199  const tChar* i_strFunction) noexcept;
200 
205  constexpr explicit cResult(tErrorCode::error_code_type i_nErrorCode) noexcept;
206 
215  explicit cResult(tErrorCode::error_code_type i_nErrorCode,
216  const tChar* i_strErrorDescription,
217  tInt32 i_nLine,
218  const tChar* i_strFile,
219  const tChar* i_strFunction) noexcept;
220 
229  explicit cResult(const cResult& i_oResult,
230  const tChar* i_strErrorDescription,
231  tInt32 i_nLine,
232  const tChar* i_strFile,
233  const tChar* i_strFunction) noexcept;
234 
238  ~cResult() noexcept;
239 
246  cResult(const cResult& i_oOther) noexcept;
247 
256  cResult& operator=(decltype(ERR_NOERROR)) noexcept;
257 
264  cResult& operator=(cResult i_oOther) noexcept;
265 
270  constexpr cResult(cResult&& i_oOther) noexcept;
271 
272 public: // access
277  tErrorCode GetErrorCode() const noexcept;
278 
283  const tChar* GetErrorString() const noexcept;
284 
289  const tChar* GetDescription() const noexcept;
290 
295  tInt32 GetLine() const noexcept;
296 
301  const tChar* GetFile() const noexcept;
302 
307  const tChar* GetFunction() const noexcept;
308 
315  template<tErrorCode::error_code_type ErrorCode>
316  tBool IsEqual(const tError<ErrorCode>& i_oErrorVal) const noexcept;
317 
324  template<typename... ErrorTypes>
325  tBool IsEqual(const ErrorTypes&... i_oErrorVals) const noexcept;
326 
331  tBool IsOk() const noexcept;
332 
337  tBool IsFailed() const noexcept;
338 
344  friend void swap(cResult& i_oLHS, cResult& i_oRHS) noexcept;
345 
352  friend tBool operator==(const cResult& i_oLHS, const cResult& i_oRHS) noexcept;
353 
354 private: // private constructor
364  explicit cResult(tErrorCode i_nErrorCode,
365  const tChar* i_strErrorDescription,
366  tInt32 i_nLine,
367  const tChar* i_strFile,
368  const tChar* i_strFunction,
369  const tChar* i_strErrorCode) noexcept;
370 
380  static cResult CreateFrom(tErrorCode::error_code_type i_nErrorCode,
381  const tChar* i_strErrorDescription,
382  tInt32 i_nLine,
383  const tChar* i_strFile,
384  const tChar* i_strFunction) noexcept;
385 
392  static constexpr tErrorString GetErrorString(const tErrorCode& i_oErrorCode) noexcept;
393 
394 private: // private member data
395  typedef detail::result_description<detail::IErrorDescription> description_type;
396  description_type m_oResultHandler;
397 
398 private: // helper types
404  template<typename ErrorType, typename... ErrorTypes>
405  struct sErrorEval;
406 
407  template<typename ErrorType>
408  struct sErrorEval<ErrorType>;
409 }; // class cResult
410 
417 tBool operator!=(const cResult& i_oLHS, const cResult& i_oRHS) noexcept;
418 
419 inline constexpr cResult::cResult() noexcept
420 {
421 }
422 
423 inline constexpr cResult::cResult(decltype(ERR_NOERROR)) noexcept: cResult()
424 {
425 }
426 
427 template<tErrorCode::error_code_type ErrorCode>
428 inline constexpr cResult::cResult(const tError<ErrorCode>& i_oError) noexcept:
429  cResult(static_cast<tErrorCode>(i_oError))
430 {
431 }
432 
433 inline constexpr cResult::cResult(tErrorCode i_oError) noexcept:
434  m_oResultHandler(description_type::make_result_description(i_oError))
435 {
436 }
437 
438 template<tErrorCode::error_code_type ErrorCode>
440  const tChar* i_strErrorDescription,
441  tInt32 i_nLine,
442  const tChar* i_strFile,
443  const tChar* i_strFunction) noexcept:
444  cResult(static_cast<tErrorCode>(i_oError),
445  i_strErrorDescription,
446  i_nLine,
447  i_strFile,
448  i_strFunction,
450 {
451 }
452 
453 inline constexpr cResult::cResult(tErrorCode::error_code_type i_nErrorCode) noexcept: cResult(tErrorCode{i_nErrorCode})
454 {
455 }
456 
458  const tChar* i_strErrorDescription,
459  tInt32 i_nLine,
460  const tChar* i_strFile,
461  const tChar* i_strFunction) noexcept:
462  cResult(CreateFrom(i_nErrorCode, i_strErrorDescription, i_nLine, i_strFile, i_strFunction))
463 {
464 }
465 
466 inline cResult::cResult(const cResult& i_oResult,
467  const tChar* i_strErrorDescription,
468  tInt32 i_nLine,
469  const tChar* i_strFile,
470  const tChar* i_strFunction) noexcept:
471  cResult(
472  i_oResult.GetErrorCode(), i_strErrorDescription, i_nLine, i_strFile, i_strFunction, i_oResult.GetErrorString())
473 {
474 }
475 
476 inline cResult& cResult::operator=(cResult i_oOther) noexcept
477 {
478  swap(*this, i_oOther);
479  return *this;
480 }
481 
482 inline cResult& cResult::operator=(decltype(ERR_NOERROR)) noexcept
483 {
484  return cResult::operator=(cResult());
485 }
486 
487 inline constexpr cResult::cResult(cResult&& i_oOther) noexcept: m_oResultHandler(std::move(i_oOther.m_oResultHandler))
488 {
489 }
490 
491 inline tBool operator==(const cResult& i_oLHS, const cResult& i_oRHS) noexcept
492 {
493  return i_oLHS.m_oResultHandler == i_oRHS.m_oResultHandler;
494 }
495 
496 inline tBool operator!=(const cResult& i_oLHS, const cResult& i_oRHS) noexcept
497 {
498  return !(i_oLHS == i_oRHS);
499 }
500 
501 inline tBool cResult::IsOk() const noexcept
502 {
503  return tErrorCode{} == GetErrorCode();
504 }
505 
506 inline tBool cResult::IsFailed() const noexcept
507 {
508  return !IsOk();
509 }
510 
511 template<tErrorCode::error_code_type ErrorCode>
512 inline tBool cResult::IsEqual(const tError<ErrorCode>& i_oErrorVal) const noexcept
513 {
514  return GetErrorCode() == static_cast<tErrorCode>(i_oErrorVal);
515 }
516 
517 template<typename... ErrorTypes>
518 inline tBool cResult::IsEqual(const ErrorTypes&... i_oErrorVals) const noexcept
519 {
520  return sErrorEval<ErrorTypes...>::dispatch(GetErrorCode(), i_oErrorVals...);
521 }
522 
530 template<tErrorCode::error_code_type ErrorCode>
531 inline tBool operator==(const cResult& oResult, const tError<ErrorCode>& sCode) noexcept
532 {
533  return oResult.IsEqual(sCode);
534 }
535 
543 template<tErrorCode::error_code_type ErrorCode>
544 inline tBool operator!=(const cResult& oResult, const tError<ErrorCode>& sCode) noexcept
545 {
546  return !oResult.IsEqual(sCode);
547 }
548 
556 template<tErrorCode::error_code_type ErrorCode>
557 inline tBool operator==(const tError<ErrorCode>& sCode, const cResult& oResult) noexcept
558 {
559  return oResult.IsEqual(sCode);
560 }
561 
569 template<tErrorCode::error_code_type ErrorCode>
570 inline tBool operator!=(const tError<ErrorCode>& sCode, const cResult& oResult) noexcept
571 {
572  return !oResult.IsEqual(sCode);
573 }
574 
575 inline void swap(cResult& i_oLHS, cResult& i_oRHS) noexcept
576 { // enable ADL
577  using std::swap;
578  swap(i_oLHS.m_oResultHandler, i_oRHS.m_oResultHandler);
579 }
580 
581 template<typename ErrorType, typename... ErrorTypes>
583 {
591  static constexpr bool
592  dispatch(tErrorCode i_oErrorCode, const ErrorType& i_oErrorVal, const ErrorTypes&... i_oErrorVals) noexcept
593  {
594  if (static_cast<tErrorCode>(i_oErrorVal) == i_oErrorCode)
595  {
596  return true;
597  }
598  else
599  {
600  return sErrorEval<ErrorTypes...>::dispatch(i_oErrorCode, i_oErrorVals...);
601  }
602  }
603 }; // template<typename ErrorType, typename ... ErrorTypes> struct sErrorEval
604 
609 template<typename ErrorType>
610 struct cResult::sErrorEval<ErrorType>
611 {
618  static constexpr bool dispatch(tErrorCode i_oErrorCode, const ErrorType& i_oErrorVal) noexcept
619  {
620  return static_cast<tErrorCode>(i_oErrorVal) == i_oErrorCode;
621  }
622 }; // template<typename ErrorType> struct sErrorEval<ErrorType>
623 
624 namespace detail
625 {
626 std::string to_string(const cResult& i_oResult);
627 }
628 
629 } // namespace A_UTILS_NS
630 
633 
634 namespace std
635 {
641 template<>
642 inline void swap<A_UTILS_NS::cResult>(A_UTILS_NS::cResult& i_oLHS, A_UTILS_NS::cResult& i_oRHS) noexcept
643 {
644  A_UTILS_NS::swap(i_oLHS, i_oRHS);
645 }
646 } // namespace std
647 
648 #endif // _A_UTILS_BASE_RESULT_H_
Copyright © Audi Electronics Venture GmbH.
char tChar
The tChar defines the type for platform character set (platform and compiler dependent type).
int32_t tInt32
type definition for signed integer values (32bit) (platform and compiler independent type).
bool tBool
The tBool defines the type for the Values tTrue and tFalse (platform and compiler dependent).
Copyright © Audi Electronics Venture GmbH.
Copyright © Audi Electronics Venture GmbH.
Copyright © Audi Electronics Venture GmbH.
~cResult() noexcept
Destructor.
tErrorCode GetErrorCode() const noexcept
Get error code.
const tChar * GetErrorString() const noexcept
Get error code as string representation.
tBool IsFailed() const noexcept
Check whether this result object contains an error != ERR_NOERROR.
tBool IsEqual(const tError< ErrorCode > &i_oErrorVal) const noexcept
Check whether an error code is equal to the contained one.
Copyright © Audi Electronics Venture GmbH.
ADTF A_UTIL Namespace - Within adtf this is used as adtf::util or adtf_util.
Definition: d_ptr.h:11
tBool operator==(const cMultiArrayIndex &o_A, const cMultiArrayIndex &o_B)
Comparison operator.
cString to_string(const tResult &i_oResult, eResultFormatFlags i_eFormatFlags=eResultFormatFlags::RFF_DisableNone, const tChar *i_strFormat=nullptr)
Copy all information of an assigned result object to a (formatted) string.
tBool operator!=(const cMultiArrayIndex &o_A, const cMultiArrayIndex &o_B)
Comparison operator.
Copyright © Audi Electronics Venture GmbH.
static constexpr bool dispatch(tErrorCode i_oErrorCode, const ErrorType &i_oErrorVal) noexcept
Exit point for compile time dispatching of error codes.
static constexpr bool dispatch(tErrorCode i_oErrorCode, const ErrorType &i_oErrorVal, const ErrorTypes &... i_oErrorVals) noexcept
Compile time dispatching of error codes.
Basic error type template, specialized by _MAKE_ERROR() to create concrete error types.