1 /* 2 * Copyright (C) 2021 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 #pragma once 17 18 #include <sstream> 19 20 #include <android-base/expected.h> 21 #include <log/log_main.h> 22 23 /** 24 * Useful macros for working with status codes and base::expected. 25 * 26 * These macros facilitate various kinds of strategies for reduction of error-handling-related 27 * boilerplate. They can be can be classified by the following criteria: 28 * - Whether the argument is a standalone status code vs. base::expected (status or value). In the 29 * latter case, the macro will evaluate to the contained value in the case of success. 30 * - Whether to FATAL or return in response to an error. 31 * - In the latter case, whether the enclosing function returns a status code or a base::expected. 32 * 33 * The table below summarizes which macro serves which case, based on those criteria: 34 * +--------------------+------------------+------------------------------------------------------+ 35 * | Error response | FATAL | Early return | 36 * | | +---------------------------+--------------------------+ 37 * | Expression type | | Function returns expected | Function returns status | 38 * +--------------------+------------------+---------------------------+--------------------------+ 39 * | status code | FATAL_IF_ERROR() | RETURN_IF_ERROR() | RETURN_STATUS_IF_ERROR() | 40 * +--------------------+------------------+---------------------------+--------------------------+ 41 * | expected | VALUE_OR_FATAL() | VALUE_OR_RETURN() | VALUE_OR_RETURN_STATUS() | 42 * +--------------------+------------------+---------------------------+--------------------------+ 43 * 44 * All macros expect that: 45 * - The error type and value value type are movable. 46 * - The macro argument can be assigned to a variable using `auto x = (exp)`. 47 * - The expression errorIsOk(e) for the error type evaluatea to a bool which is true iff the 48 * status is considered success. 49 * - The expression errorToString(e) for a given error type evaluated to a std::string containing a 50 * human-readable version of the status. 51 */ 52 53 #define VALUE_OR_RETURN(exp) \ 54 ({ \ 55 auto _tmp = (exp); \ 56 if (!_tmp.ok()) return ::android::base::unexpected(std::move(_tmp.error())); \ 57 std::move(_tmp.value()); \ 58 }) 59 60 #define VALUE_OR_RETURN_STATUS(exp) \ 61 ({ \ 62 auto _tmp = (exp); \ 63 if (!_tmp.ok()) return std::move(_tmp.error()); \ 64 std::move(_tmp.value()); \ 65 }) 66 67 #define VALUE_OR_FATAL(exp) \ 68 ({ \ 69 auto _tmp = (exp); \ 70 LOG_ALWAYS_FATAL_IF(!_tmp.ok(), "Function: %s Line: %d Failed result (%s)", __FUNCTION__, \ 71 __LINE__, errorToString(_tmp.error()).c_str()); \ 72 std::move(_tmp.value()); \ 73 }) 74 75 #define RETURN_IF_ERROR(exp) \ 76 if (auto _tmp = (exp); !errorIsOk(_tmp)) return ::android::base::unexpected(std::move(_tmp)); 77 78 #define RETURN_STATUS_IF_ERROR(exp) \ 79 if (auto _tmp = (exp); !errorIsOk(_tmp)) return _tmp; 80 81 #define FATAL_IF_ERROR(exp) \ 82 { \ 83 auto _tmp = (exp); \ 84 LOG_ALWAYS_FATAL_IF(!errorIsOk(_tmp), "Function: %s Line: %d Failed result: (%s)", \ 85 __FUNCTION__, __LINE__, errorToString(_tmp).c_str()); \ 86 } 87