Home | History | Annotate | Download | only in netdutils
      1 /*
      2  * Copyright (C) 2017 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 #ifndef NETUTILS_STATUSOR_H
     18 #define NETUTILS_STATUSOR_H
     19 
     20 #include <cassert>
     21 #include "netdutils/Status.h"
     22 
     23 namespace android {
     24 namespace netdutils {
     25 
     26 // Wrapper around a combination of Status and application value type.
     27 // T may be any copyable or movable type.
     28 template <typename T>
     29 class StatusOr {
     30   public:
     31     StatusOr() = default;
     32     StatusOr(const Status status) : mStatus(status) { assert(!isOk(status)); }
     33     StatusOr(const T& value) : mStatus(status::ok), mValue(value) {}
     34     StatusOr(T&& value) : mStatus(status::ok), mValue(std::move(value)) {}
     35 
     36     // Move constructor ok (if T supports move)
     37     StatusOr(StatusOr&&) = default;
     38     // Move assignment ok (if T supports move)
     39     StatusOr& operator=(StatusOr&&) = default;
     40     // Copy constructor ok (if T supports copy)
     41     StatusOr(const StatusOr&) = default;
     42     // Copy assignment ok (if T supports copy)
     43     StatusOr& operator=(const StatusOr&) = default;
     44 
     45     // Return const references to wrapped type
     46     // It is an error to call value() when !isOk(status())
     47     const T& value() const & { return mValue; }
     48     const T&& value() const && { return mValue; }
     49 
     50     // Return rvalue references to wrapped type
     51     // It is an error to call value() when !isOk(status())
     52     T& value() & { return mValue; }
     53     T&& value() && { return mValue; }
     54 
     55     // Return status assigned in constructor
     56     const Status status() const { return mStatus; }
     57 
     58     // Implict cast to Status
     59     operator Status() const { return status(); }
     60 
     61   private:
     62     Status mStatus = status::undefined;
     63     T mValue;
     64 };
     65 
     66 template <typename T>
     67 inline std::ostream& operator<<(std::ostream& os, const StatusOr<T>& s) {
     68     return os << "StatusOr[status: " << s.status() << "]";
     69 }
     70 
     71 #define ASSIGN_OR_RETURN_IMPL(tmp, lhs, stmt) \
     72     auto tmp = (stmt);                        \
     73     RETURN_IF_NOT_OK(tmp);                    \
     74     lhs = std::move(tmp.value());
     75 
     76 #define ASSIGN_OR_RETURN_CONCAT(line, lhs, stmt) \
     77     ASSIGN_OR_RETURN_IMPL(__CONCAT(_status_or_, line), lhs, stmt)
     78 
     79 // Macro to allow exception-like handling of error return values.
     80 //
     81 // If the evaluation of stmt results in an error, return that error
     82 // from the current function. Otherwise, assign the result to lhs.
     83 //
     84 // This macro supports both move and copy assignment operators. lhs
     85 // may be either a new local variable or an existing non-const
     86 // variable accessible in the current scope.
     87 //
     88 // Example usage:
     89 // StatusOr<MyType> foo() { ... }
     90 //
     91 // ASSIGN_OR_RETURN(auto myVar, foo());
     92 // ASSIGN_OR_RETURN(myExistingVar, foo());
     93 // ASSIGN_OR_RETURN(myMemberVar, foo());
     94 #define ASSIGN_OR_RETURN(lhs, stmt) ASSIGN_OR_RETURN_CONCAT(__LINE__, lhs, stmt)
     95 
     96 }  // namespace netdutils
     97 }  // namespace android
     98 
     99 #endif /* NETUTILS_STATUSOR_H */
    100