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_STATUS_H
     18 #define NETUTILS_STATUS_H
     19 
     20 #include <cassert>
     21 #include <ostream>
     22 
     23 namespace android {
     24 namespace netdutils {
     25 
     26 // Simple status implementation suitable for use on the stack in low
     27 // or moderate performance code. This can definitely be improved but
     28 // for now short string optimization is expected to keep the common
     29 // success case fast.
     30 class Status {
     31   public:
     32     Status() = default;
     33 
     34     Status(int code) : mCode(code) {}
     35 
     36     Status(int code, const std::string& msg) : mCode(code), mMsg(msg) { assert(!ok()); }
     37 
     38     int code() const { return mCode; }
     39 
     40     bool ok() const { return code() == 0; }
     41 
     42     const std::string& msg() const { return mMsg; }
     43 
     44     bool operator==(const Status& other) const { return code() == other.code(); }
     45     bool operator!=(const Status& other) const { return !(*this == other); }
     46 
     47   private:
     48     int mCode = 0;
     49     std::string mMsg;
     50 };
     51 
     52 namespace status {
     53 
     54 const Status ok{0};
     55 // EOF is not part of errno space, we'll place it far above the
     56 // highest existing value.
     57 const Status eof{0x10001, "end of file"};
     58 const Status undefined{std::numeric_limits<int>::max(), "undefined"};
     59 
     60 }  // namespace status
     61 
     62 // Return true if status is "OK". This is sometimes preferable to
     63 // status.ok() when we want to check the state of Status-like objects
     64 // that implicitly cast to Status.
     65 inline bool isOk(const Status& status) {
     66     return status.ok();
     67 }
     68 
     69 // Document that status is expected to be ok. This function may log
     70 // (or assert when running in debug mode) if status has an unexpected
     71 // value.
     72 void expectOk(const Status& status);
     73 
     74 // Convert POSIX errno to a Status object.
     75 // If Status is extended to have more features, this mapping may
     76 // become more complex.
     77 Status statusFromErrno(int err, const std::string& msg);
     78 
     79 // Helper that checks Status-like object (notably StatusOr) against a
     80 // value in the errno space.
     81 bool equalToErrno(const Status& status, int err);
     82 
     83 // Helper that converts Status-like object (notably StatusOr) to a
     84 // message.
     85 std::string toString(const Status& status);
     86 
     87 std::ostream& operator<<(std::ostream& os, const Status& s);
     88 
     89 #define RETURN_IF_NOT_OK_IMPL(tmp, stmt)           \
     90     do {                                           \
     91         ::android::netdutils::Status tmp = (stmt); \
     92         if (!isOk(tmp)) {                          \
     93             return tmp;                            \
     94         }                                          \
     95     } while (false)
     96 
     97 #define RETURN_IF_NOT_OK_CONCAT(line, stmt) RETURN_IF_NOT_OK_IMPL(__CONCAT(_status_, line), stmt)
     98 
     99 // Macro to allow exception-like handling of error return values.
    100 //
    101 // If the evaluation of stmt results in an error, return that error
    102 // from current function.
    103 //
    104 // Example usage:
    105 // Status bar() { ... }
    106 //
    107 // RETURN_IF_NOT_OK(status);
    108 // RETURN_IF_NOT_OK(bar());
    109 #define RETURN_IF_NOT_OK(stmt) RETURN_IF_NOT_OK_CONCAT(__LINE__, stmt)
    110 
    111 }  // namespace netdutils
    112 }  // namespace android
    113 
    114 #endif /* NETUTILS_STATUS_H */
    115