1*993b0882SAndroid Build Coastguard Worker /* 2*993b0882SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project 3*993b0882SAndroid Build Coastguard Worker * 4*993b0882SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*993b0882SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*993b0882SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*993b0882SAndroid Build Coastguard Worker * 8*993b0882SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*993b0882SAndroid Build Coastguard Worker * 10*993b0882SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*993b0882SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*993b0882SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*993b0882SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*993b0882SAndroid Build Coastguard Worker * limitations under the License. 15*993b0882SAndroid Build Coastguard Worker */ 16*993b0882SAndroid Build Coastguard Worker 17*993b0882SAndroid Build Coastguard Worker #ifndef LIBTEXTCLASSIFIER_UTILS_BASE_STATUS_MACROS_H_ 18*993b0882SAndroid Build Coastguard Worker #define LIBTEXTCLASSIFIER_UTILS_BASE_STATUS_MACROS_H_ 19*993b0882SAndroid Build Coastguard Worker 20*993b0882SAndroid Build Coastguard Worker #include <utility> 21*993b0882SAndroid Build Coastguard Worker 22*993b0882SAndroid Build Coastguard Worker #include "utils/base/status.h" 23*993b0882SAndroid Build Coastguard Worker #include "utils/base/statusor.h" 24*993b0882SAndroid Build Coastguard Worker 25*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 { 26*993b0882SAndroid Build Coastguard Worker 27*993b0882SAndroid Build Coastguard Worker // An adapter to enable TC3_RETURN_IF_ERROR to be used with either Status or 28*993b0882SAndroid Build Coastguard Worker // StatusOr. 29*993b0882SAndroid Build Coastguard Worker class StatusAdapter { 30*993b0882SAndroid Build Coastguard Worker public: StatusAdapter(const Status & s)31*993b0882SAndroid Build Coastguard Worker explicit StatusAdapter(const Status& s) : s_(s) {} StatusAdapter(Status && s)32*993b0882SAndroid Build Coastguard Worker explicit StatusAdapter(Status&& s) : s_(std::move(s)) {} 33*993b0882SAndroid Build Coastguard Worker template <typename T> StatusAdapter(const StatusOr<T> & s)34*993b0882SAndroid Build Coastguard Worker explicit StatusAdapter(const StatusOr<T>& s) : s_(s.status()) {} 35*993b0882SAndroid Build Coastguard Worker template <typename T> StatusAdapter(StatusOr<T> && s)36*993b0882SAndroid Build Coastguard Worker explicit StatusAdapter(StatusOr<T>&& s) : s_(std::move(s).status()) {} 37*993b0882SAndroid Build Coastguard Worker ok()38*993b0882SAndroid Build Coastguard Worker bool ok() const { return s_.ok(); } 39*993b0882SAndroid Build Coastguard Worker explicit operator bool() const { return ok(); } 40*993b0882SAndroid Build Coastguard Worker status()41*993b0882SAndroid Build Coastguard Worker const Status& status() const& { return s_; } status()42*993b0882SAndroid Build Coastguard Worker Status status() && { return std::move(s_); } 43*993b0882SAndroid Build Coastguard Worker 44*993b0882SAndroid Build Coastguard Worker private: 45*993b0882SAndroid Build Coastguard Worker Status s_; 46*993b0882SAndroid Build Coastguard Worker }; 47*993b0882SAndroid Build Coastguard Worker 48*993b0882SAndroid Build Coastguard Worker } // namespace libtextclassifier3 49*993b0882SAndroid Build Coastguard Worker 50*993b0882SAndroid Build Coastguard Worker // Evaluates an expression that produces a `libtextclassifier3::Status`. If the 51*993b0882SAndroid Build Coastguard Worker // status is not ok, returns it from the current function. 52*993b0882SAndroid Build Coastguard Worker // 53*993b0882SAndroid Build Coastguard Worker // For example: 54*993b0882SAndroid Build Coastguard Worker // libtextclassifier3::Status MultiStepFunction() { 55*993b0882SAndroid Build Coastguard Worker // TC3_RETURN_IF_ERROR(Function(args...)); 56*993b0882SAndroid Build Coastguard Worker // TC3_RETURN_IF_ERROR(foo.Method(args...)); 57*993b0882SAndroid Build Coastguard Worker // return libtextclassifier3::Status(); 58*993b0882SAndroid Build Coastguard Worker // } 59*993b0882SAndroid Build Coastguard Worker #define TC3_RETURN_IF_ERROR(expr) \ 60*993b0882SAndroid Build Coastguard Worker TC3_RETURN_IF_ERROR_INTERNAL(expr, std::move(adapter).status()) 61*993b0882SAndroid Build Coastguard Worker 62*993b0882SAndroid Build Coastguard Worker #define TC3_RETURN_NULL_IF_ERROR(expr) \ 63*993b0882SAndroid Build Coastguard Worker TC3_RETURN_IF_ERROR_INTERNAL(expr, nullptr) 64*993b0882SAndroid Build Coastguard Worker 65*993b0882SAndroid Build Coastguard Worker #define TC3_RETURN_FALSE_IF_ERROR(expr) \ 66*993b0882SAndroid Build Coastguard Worker TC3_RETURN_IF_ERROR_INTERNAL(expr, false) 67*993b0882SAndroid Build Coastguard Worker 68*993b0882SAndroid Build Coastguard Worker #define TC3_RETURN_IF_ERROR_INTERNAL(expr, return_value) \ 69*993b0882SAndroid Build Coastguard Worker TC3_STATUS_MACROS_IMPL_ELSE_BLOCKER_ \ 70*993b0882SAndroid Build Coastguard Worker if (::libtextclassifier3::StatusAdapter adapter{expr}) { \ 71*993b0882SAndroid Build Coastguard Worker } else /* NOLINT */ \ 72*993b0882SAndroid Build Coastguard Worker return return_value 73*993b0882SAndroid Build Coastguard Worker 74*993b0882SAndroid Build Coastguard Worker // The GNU compiler emits a warning for code like: 75*993b0882SAndroid Build Coastguard Worker // 76*993b0882SAndroid Build Coastguard Worker // if (foo) 77*993b0882SAndroid Build Coastguard Worker // if (bar) { } else baz; 78*993b0882SAndroid Build Coastguard Worker // 79*993b0882SAndroid Build Coastguard Worker // because it thinks you might want the else to bind to the first if. This 80*993b0882SAndroid Build Coastguard Worker // leads to problems with code like: 81*993b0882SAndroid Build Coastguard Worker // 82*993b0882SAndroid Build Coastguard Worker // if (do_expr) TC3_RETURN_IF_ERROR(expr); 83*993b0882SAndroid Build Coastguard Worker // 84*993b0882SAndroid Build Coastguard Worker // The "switch (0) case 0:" idiom is used to suppress this. 85*993b0882SAndroid Build Coastguard Worker #define TC3_STATUS_MACROS_IMPL_ELSE_BLOCKER_ \ 86*993b0882SAndroid Build Coastguard Worker switch (0) \ 87*993b0882SAndroid Build Coastguard Worker case 0: \ 88*993b0882SAndroid Build Coastguard Worker default: // NOLINT 89*993b0882SAndroid Build Coastguard Worker 90*993b0882SAndroid Build Coastguard Worker #endif // LIBTEXTCLASSIFIER_UTILS_BASE_STATUS_MACROS_H_ 91