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