1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Portable error handling functions. This is only necessary for host-side 18 // code that needs to be cross-platform; code that is only run on Unix should 19 // just use errno and strerror() for simplicity. 20 // 21 // There is some complexity since Windows has (at least) three different error 22 // numbers, not all of which share the same type: 23 // * errno: for C runtime errors. 24 // * GetLastError(): Windows non-socket errors. 25 // * WSAGetLastError(): Windows socket errors. 26 // errno can be passed to strerror() on all platforms, but the other two require 27 // special handling to get the error string. Refer to Microsoft documentation 28 // to determine which error code to check for each function. 29 30 #pragma once 31 32 #include <assert.h> 33 34 #include <string> 35 36 namespace android { 37 namespace base { 38 39 // Returns a string describing the given system error code. |error_code| must 40 // be errno on Unix or GetLastError()/WSAGetLastError() on Windows. Passing 41 // errno on Windows has undefined behavior. 42 std::string SystemErrorCodeToString(int error_code); 43 44 } // namespace base 45 } // namespace android 46 47 // Convenient macros for evaluating a statement, checking if the result is error, and returning it 48 // to the caller. 49 // 50 // Usage with Result<T>: 51 // 52 // Result<Foo> getFoo() {...} 53 // 54 // Result<Bar> getBar() { 55 // Foo foo = OR_RETURN(getFoo()); 56 // return Bar{foo}; 57 // } 58 // 59 // Usage with status_t: 60 // 61 // status_t getFoo(Foo*) {...} 62 // 63 // status_t getBar(Bar* bar) { 64 // Foo foo; 65 // OR_RETURN(getFoo(&foo)); 66 // *bar = Bar{foo}; 67 // return OK; 68 // } 69 // 70 // Actually this can be used for any type as long as the OkOrFail<T> contract is satisfied. See 71 // below. 72 // If implicit conversion compilation errors occur involving a value type with a templated 73 // forwarding ref ctor, compilation with cpp20 or explicitly converting to the desired 74 // return type is required. 75 #define OR_RETURN(expr) \ 76 ({ \ 77 decltype(expr)&& tmp = (expr); \ 78 typedef android::base::OkOrFail<std::remove_reference_t<decltype(tmp)>> ok_or_fail; \ 79 if (!ok_or_fail::IsOk(tmp)) { \ 80 return ok_or_fail::Fail(std::move(tmp)); \ 81 } \ 82 ok_or_fail::Unwrap(std::move(tmp)); \ 83 }) 84 85 // Same as OR_RETURN, but aborts if expr is a failure. 86 #if defined(__BIONIC__) 87 #define OR_FATAL(expr) \ 88 ({ \ 89 decltype(expr)&& tmp = (expr); \ 90 typedef android::base::OkOrFail<std::remove_reference_t<decltype(tmp)>> ok_or_fail; \ 91 if (!ok_or_fail::IsOk(tmp)) { \ 92 __assert(__FILE__, __LINE__, ok_or_fail::ErrorMessage(tmp).c_str()); \ 93 } \ 94 ok_or_fail::Unwrap(std::move(tmp)); \ 95 }) 96 #else 97 #define OR_FATAL(expr) \ 98 ({ \ 99 decltype(expr)&& tmp = (expr); \ 100 typedef android::base::OkOrFail<std::remove_reference_t<decltype(tmp)>> ok_or_fail; \ 101 if (!ok_or_fail::IsOk(tmp)) { \ 102 fprintf(stderr, "%s:%d: assertion \"%s\" failed", __FILE__, __LINE__, \ 103 ok_or_fail::ErrorMessage(tmp).c_str()); \ 104 abort(); \ 105 } \ 106 ok_or_fail::Unwrap(std::move(tmp)); \ 107 }) 108 #endif 109 110 namespace android { 111 namespace base { 112 113 // The OkOrFail contract for a type T. This must be implemented for a type T if you want to use 114 // OR_RETURN(stmt) where stmt evalues to a value of type T. 115 template <typename T, typename = void> 116 struct OkOrFail { 117 // Checks if T is ok or fail. 118 static bool IsOk(const T&); 119 120 // Turns T into the success value. 121 template <typename U> 122 static U Unwrap(T&&); 123 124 // Moves T into OkOrFail<T>, so that we can convert it to other types 125 OkOrFail(T&& v); 126 OkOrFail() = delete; 127 OkOrFail(const T&) = delete; 128 129 // And there need to be one or more conversion operators that turns the error value of T into a 130 // target type. For example, for T = Result<V, E>, there can be ... 131 // 132 // // for the case where OR_RETURN is called in a function expecting E 133 // operator E()&& { return val_.error().code(); } 134 // 135 // // for the case where OR_RETURN is called in a function expecting Result<U, E> 136 // template <typename U> 137 // operator Result<U, E>()&& { return val_.error(); } 138 139 // Returns the string representation of the fail value. 140 static std::string ErrorMessage(const T& v); 141 }; 142 143 } // namespace base 144 } // namespace android 145