Device interface library for multiple platforms including Mbed.
Dependents: DeepCover Embedded Security in IoT MaximInterface MAXREFDES155#
Result.hpp
00001 /******************************************************************************* 00002 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00020 * OTHER DEALINGS IN THE SOFTWARE. 00021 * 00022 * Except as contained in this notice, the name of Maxim Integrated 00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00024 * Products, Inc. Branding Policy. 00025 * 00026 * The mere transfer of this software does not imply any licenses 00027 * of trade secrets, proprietary technology, copyrights, patents, 00028 * trademarks, maskwork rights, or any other form of intellectual 00029 * property whatsoever. Maxim Integrated Products, Inc. retains all 00030 * ownership rights. 00031 *******************************************************************************/ 00032 00033 #ifndef MaximInterfaceCore_Result_hpp 00034 #define MaximInterfaceCore_Result_hpp 00035 00036 #include "None.hpp" 00037 #include "Optional.hpp" 00038 #include "SafeBool.hpp" 00039 #include "system_error.hpp" 00040 00041 // Include for std::swap. 00042 #include <algorithm> 00043 #include <utility> 00044 00045 namespace MaximInterfaceCore { 00046 00047 /// @brief Expected value container that holds either a value or an error. 00048 /// @details 00049 /// Result can be used to multiplex errors and values returned from functions 00050 /// that may fail as an alternative to exceptions. 00051 /// @tparam T 00052 /// Must be void or meet the requirements for DefaultConstructible, 00053 /// CopyConstructible, and CopyAssignable. 00054 template <typename T> class Result { 00055 public: 00056 typedef T value_type; 00057 00058 Result() : value_(), error_(), hasValue_(false) {} 00059 00060 Result(const T & value) : value_(value), error_(), hasValue_(true) {} 00061 00062 Result(const error_code & error) 00063 : value_(), error_(error), hasValue_(false) {} 00064 00065 template <typename ErrorCodeEnum> 00066 Result(ErrorCodeEnum error, 00067 typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type * = 00068 NULL) 00069 : value_(), error_(error), hasValue_(false) {} 00070 00071 template <typename U> 00072 explicit Result(const Result<U> & other) 00073 : value_(other.value()), error_(other.error()), 00074 hasValue_(other.hasValue()) {} 00075 00076 Result & operator=(const T & value) { 00077 value_ = value; 00078 error_.clear(); 00079 hasValue_ = true; 00080 return *this; 00081 } 00082 00083 Result & operator=(const error_code & error) { 00084 error_ = error; 00085 clearValue(); 00086 return *this; 00087 } 00088 00089 template <typename ErrorCodeEnum> 00090 typename enable_if<is_error_code_enum<ErrorCodeEnum>::value, Result &>::type 00091 operator=(ErrorCodeEnum error) { 00092 error_ = error; 00093 clearValue(); 00094 return *this; 00095 } 00096 00097 template <typename U> Result & operator=(const Result<U> & other) { 00098 assign(other); 00099 return *this; 00100 } 00101 00102 Result & operator=(const Result & other) { 00103 assign(other); 00104 return *this; 00105 } 00106 00107 bool hasValue() const { return hasValue_; } 00108 00109 operator SafeBool() const { return makeSafeBool(hasValue()); } 00110 00111 const T & value() const { return value_; } 00112 00113 T & value() { 00114 return const_cast<T &>(static_cast<const Result &>(*this).value()); 00115 } 00116 00117 const error_code & error() const { return error_; } 00118 00119 error_code & error() { 00120 return const_cast<error_code &>(static_cast<const Result &>(*this).error()); 00121 } 00122 00123 void swap(Result & other) { 00124 using std::swap; 00125 if (hasValue_ || other.hasValue_) { 00126 swap(value_, other.value_); 00127 swap(hasValue_, other.hasValue_); 00128 } 00129 swap(error_, other.error_); 00130 } 00131 00132 private: 00133 void clearValue() { 00134 if (hasValue_) { 00135 hasValue_ = false; 00136 value_ = T(); 00137 } 00138 } 00139 00140 template <typename U> void assign(const Result<U> & other) { 00141 if (hasValue_ || other.hasValue()) { 00142 value_ = other.value(); 00143 hasValue_ = other.hasValue(); 00144 } 00145 error_ = other.error(); 00146 } 00147 00148 T value_; 00149 error_code error_; 00150 bool hasValue_; 00151 }; 00152 00153 template <typename T> Result<T> makeResult(const T & value) { return value; } 00154 00155 template <typename T> void swap(Result<T> & lhs, Result<T> & rhs) { 00156 lhs.swap(rhs); 00157 } 00158 00159 template <typename T, typename U> 00160 bool operator==(const Result<T> & lhs, const Result<U> & rhs) { 00161 if (lhs.hasValue() != rhs.hasValue()) { 00162 return false; 00163 } 00164 if (!lhs.hasValue()) { 00165 return lhs.error() == rhs.error(); 00166 } 00167 return lhs.value() == rhs.value(); 00168 } 00169 00170 template <typename T, typename U> 00171 bool operator!=(const Result<T> & lhs, const Result<U> & rhs) { 00172 if (lhs.hasValue() != rhs.hasValue()) { 00173 return true; 00174 } 00175 if (!lhs.hasValue()) { 00176 return lhs.error() != rhs.error(); 00177 } 00178 return lhs.value() != rhs.value(); 00179 } 00180 00181 template <typename T, typename U> 00182 typename enable_if<!is_error_code_enum<U>::value, bool>::type 00183 operator==(const Result<T> & exp, const U & value) { 00184 return exp.hasValue() ? exp.value() == value : false; 00185 } 00186 00187 template <typename T, typename U> 00188 typename enable_if<!is_error_code_enum<T>::value, bool>::type 00189 operator==(const T & value, const Result<U> & exp) { 00190 return operator==(exp, value); 00191 } 00192 00193 template <typename T, typename U> 00194 typename enable_if<!is_error_code_enum<U>::value, bool>::type 00195 operator!=(const Result<T> & exp, const U & value) { 00196 return exp.hasValue() ? exp.value() != value : true; 00197 } 00198 00199 template <typename T, typename U> 00200 typename enable_if<!is_error_code_enum<T>::value, bool>::type 00201 operator!=(const T & value, const Result<U> & exp) { 00202 return operator!=(exp, value); 00203 } 00204 00205 template <typename T> 00206 bool operator==(const Result<T> & exp, const error_code & error) { 00207 return exp.hasValue() ? false : exp.error() == error; 00208 } 00209 00210 template <typename T> 00211 bool operator==(const error_code & error, const Result<T> & exp) { 00212 return operator==(exp, error); 00213 } 00214 00215 template <typename T> 00216 bool operator!=(const Result<T> & exp, const error_code & error) { 00217 return exp.hasValue() ? true : exp.error() != error; 00218 } 00219 00220 template <typename T> 00221 bool operator!=(const error_code & error, const Result<T> & exp) { 00222 return operator!=(exp, error); 00223 } 00224 00225 // Specialization for void. 00226 template <> class Result<void> { 00227 public: 00228 typedef void value_type; 00229 00230 Result() : error_(), hasValue_(false) {} 00231 00232 Result(None) : error_(), hasValue_(true) {} 00233 00234 Result(const error_code & error) : error_(error), hasValue_(false) {} 00235 00236 template <typename ErrorCodeEnum> 00237 Result(ErrorCodeEnum error, 00238 typename enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type * = 00239 NULL) 00240 : error_(error), hasValue_(false) {} 00241 00242 bool hasValue() const { return hasValue_; } 00243 00244 operator SafeBool() const { return makeSafeBool(hasValue()); } 00245 00246 void value() const {} 00247 00248 const error_code & error() const { return error_; } 00249 00250 error_code & error() { 00251 return const_cast<error_code &>(static_cast<const Result &>(*this).error()); 00252 } 00253 00254 void swap(Result & other) { 00255 using std::swap; 00256 swap(hasValue_, other.hasValue_); 00257 swap(error_, other.error_); 00258 } 00259 00260 private: 00261 error_code error_; 00262 bool hasValue_; 00263 }; 00264 00265 inline Result<void> makeResult(None) { return none; } 00266 00267 template <> 00268 inline bool operator==(const Result<void> & lhs, const Result<void> & rhs) { 00269 if (lhs.hasValue() != rhs.hasValue()) { 00270 return false; 00271 } 00272 if (!lhs.hasValue()) { 00273 return lhs.error() == rhs.error(); 00274 } 00275 return true; 00276 } 00277 00278 template <> 00279 inline bool operator!=(const Result<void> & lhs, const Result<void> & rhs) { 00280 if (lhs.hasValue() != rhs.hasValue()) { 00281 return true; 00282 } 00283 if (!lhs.hasValue()) { 00284 return lhs.error() != rhs.error(); 00285 } 00286 return false; 00287 } 00288 00289 template <> inline bool operator==(const Result<void> & exp, const None &) { 00290 return exp.hasValue(); 00291 } 00292 00293 template <> inline bool operator==(const None &, const Result<void> & exp) { 00294 return operator==(exp, none); 00295 } 00296 00297 template <> inline bool operator!=(const Result<void> & exp, const None &) { 00298 return !operator==(exp, none); 00299 } 00300 00301 template <> inline bool operator!=(const None &, const Result<void> & exp) { 00302 return operator!=(exp, none); 00303 } 00304 00305 namespace detail { 00306 00307 template <typename T> Optional<error_code> TRY_helper(const Result<T> & expr) { 00308 Optional<error_code> error; 00309 if (!expr) { 00310 error = expr.error(); 00311 } 00312 return error; 00313 } 00314 00315 template <typename T, typename U> 00316 Optional<error_code> TRY_VALUE_helper(T & var, const Result<U> & expr) { 00317 Optional<error_code> error; 00318 if (expr) { 00319 var = expr.value(); 00320 } else { 00321 error = expr.error(); 00322 } 00323 return error; 00324 } 00325 00326 } // namespace detail 00327 } // namespace MaximInterfaceCore 00328 00329 // clang-format off 00330 00331 /// @brief 00332 /// Evaluates an expression returning a Result type by continuing execution if 00333 /// successful or returning the error to the calling function if unsuccessful. 00334 #define MaximInterfaceCore_TRY(expr) \ 00335 if (const ::MaximInterfaceCore::Optional< ::MaximInterfaceCore::error_code> \ 00336 MaximInterfaceCore_TRY_error = \ 00337 ::MaximInterfaceCore::detail::TRY_helper(expr)) \ 00338 return MaximInterfaceCore_TRY_error.value() 00339 00340 /// @brief 00341 /// Evaluates an expression returning a non-void Result type by assigning the 00342 /// value to the specified variable if successful or returning the error to the 00343 /// calling function if unsuccessful. 00344 #define MaximInterfaceCore_TRY_VALUE(var, expr) \ 00345 if (const ::MaximInterfaceCore::Optional< ::MaximInterfaceCore::error_code> \ 00346 MaximInterfaceCore_TRY_VALUE_error = \ 00347 ::MaximInterfaceCore::detail::TRY_VALUE_helper(var, expr)) \ 00348 return MaximInterfaceCore_TRY_VALUE_error.value() 00349 00350 #endif
Generated on Tue Jul 12 2022 11:13:15 by 1.7.2