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