| OLD | NEW |
| (Empty) | |
| 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ |
| 4 // |
| 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are |
| 7 // met: |
| 8 // |
| 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. |
| 11 // * Redistributions in binary form must reproduce the above |
| 12 // copyright notice, this list of conditions and the following disclaimer |
| 13 // in the documentation and/or other materials provided with the |
| 14 // distribution. |
| 15 // * Neither the name of Google Inc. nor the names of its |
| 16 // contributors may be used to endorse or promote products derived from |
| 17 // this software without specific prior written permission. |
| 18 // |
| 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 |
| 31 // StatusOr<T> is the union of a Status object and a T |
| 32 // object. StatusOr models the concept of an object that is either a |
| 33 // usable value, or an error Status explaining why such a value is |
| 34 // not present. To this end, StatusOr<T> does not allow its Status |
| 35 // value to be Status::OK. Further, StatusOr<T*> does not allow the |
| 36 // contained pointer to be NULL. |
| 37 // |
| 38 // The primary use-case for StatusOr<T> is as the return value of a |
| 39 // function which may fail. |
| 40 // |
| 41 // Example client usage for a StatusOr<T>, where T is not a pointer: |
| 42 // |
| 43 // StatusOr<float> result = DoBigCalculationThatCouldFail(); |
| 44 // if (result.ok()) { |
| 45 // float answer = result.ValueOrDie(); |
| 46 // printf("Big calculation yielded: %f", answer); |
| 47 // } else { |
| 48 // LOG(ERROR) << result.status(); |
| 49 // } |
| 50 // |
| 51 // Example client usage for a StatusOr<T*>: |
| 52 // |
| 53 // StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg); |
| 54 // if (result.ok()) { |
| 55 // std::unique_ptr<Foo> foo(result.ValueOrDie()); |
| 56 // foo->DoSomethingCool(); |
| 57 // } else { |
| 58 // LOG(ERROR) << result.status(); |
| 59 // } |
| 60 // |
| 61 // Example client usage for a StatusOr<std::unique_ptr<T>>: |
| 62 // |
| 63 // StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); |
| 64 // if (result.ok()) { |
| 65 // std::unique_ptr<Foo> foo = result.ConsumeValueOrDie(); |
| 66 // foo->DoSomethingCool(); |
| 67 // } else { |
| 68 // LOG(ERROR) << result.status(); |
| 69 // } |
| 70 // |
| 71 // Example factory implementation returning StatusOr<T*>: |
| 72 // |
| 73 // StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) { |
| 74 // if (arg <= 0) { |
| 75 // return ::util::Status(::util::error::INVALID_ARGUMENT, |
| 76 // "Arg must be positive"); |
| 77 // } else { |
| 78 // return new Foo(arg); |
| 79 // } |
| 80 // } |
| 81 // |
| 82 |
| 83 #ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ |
| 84 #define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ |
| 85 |
| 86 #include <new> |
| 87 #include <string> |
| 88 #include <utility> |
| 89 |
| 90 #include <google/protobuf/stubs/status.h> |
| 91 |
| 92 namespace google { |
| 93 namespace protobuf { |
| 94 namespace util { |
| 95 |
| 96 template<typename T> |
| 97 class StatusOr { |
| 98 template<typename U> friend class StatusOr; |
| 99 |
| 100 public: |
| 101 // Construct a new StatusOr with Status::UNKNOWN status |
| 102 StatusOr(); |
| 103 |
| 104 // Construct a new StatusOr with the given non-ok status. After calling |
| 105 // this constructor, calls to ValueOrDie() will CHECK-fail. |
| 106 // |
| 107 // NOTE: Not explicit - we want to use StatusOr<T> as a return |
| 108 // value, so it is convenient and sensible to be able to do 'return |
| 109 // Status()' when the return type is StatusOr<T>. |
| 110 // |
| 111 // REQUIRES: status != Status::OK. This requirement is DCHECKed. |
| 112 // In optimized builds, passing Status::OK here will have the effect |
| 113 // of passing PosixErrorSpace::EINVAL as a fallback. |
| 114 StatusOr(const Status& status); // NOLINT |
| 115 |
| 116 // Construct a new StatusOr with the given value. If T is a plain pointer, |
| 117 // value must not be NULL. After calling this constructor, calls to |
| 118 // ValueOrDie() will succeed, and calls to status() will return OK. |
| 119 // |
| 120 // NOTE: Not explicit - we want to use StatusOr<T> as a return type |
| 121 // so it is convenient and sensible to be able to do 'return T()' |
| 122 // when when the return type is StatusOr<T>. |
| 123 // |
| 124 // REQUIRES: if T is a plain pointer, value != NULL. This requirement is |
| 125 // DCHECKed. In optimized builds, passing a NULL pointer here will have |
| 126 // the effect of passing PosixErrorSpace::EINVAL as a fallback. |
| 127 StatusOr(const T& value); // NOLINT |
| 128 |
| 129 // Copy constructor. |
| 130 StatusOr(const StatusOr& other); |
| 131 |
| 132 // Conversion copy constructor, T must be copy constructible from U |
| 133 template<typename U> |
| 134 StatusOr(const StatusOr<U>& other); |
| 135 |
| 136 // Assignment operator. |
| 137 StatusOr& operator=(const StatusOr& other); |
| 138 |
| 139 // Conversion assignment operator, T must be assignable from U |
| 140 template<typename U> |
| 141 StatusOr& operator=(const StatusOr<U>& other); |
| 142 |
| 143 // Returns a reference to our status. If this contains a T, then |
| 144 // returns Status::OK. |
| 145 const Status& status() const; |
| 146 |
| 147 // Returns this->status().ok() |
| 148 bool ok() const; |
| 149 |
| 150 // Returns a reference to our current value, or CHECK-fails if !this->ok(). |
| 151 // If you need to initialize a T object from the stored value, |
| 152 // ConsumeValueOrDie() may be more efficient. |
| 153 const T& ValueOrDie() const; |
| 154 |
| 155 private: |
| 156 Status status_; |
| 157 T value_; |
| 158 }; |
| 159 |
| 160 //////////////////////////////////////////////////////////////////////////////// |
| 161 // Implementation details for StatusOr<T> |
| 162 |
| 163 namespace internal { |
| 164 |
| 165 class LIBPROTOBUF_EXPORT StatusOrHelper { |
| 166 public: |
| 167 // Move type-agnostic error handling to the .cc. |
| 168 static void Crash(const util::Status& status); |
| 169 |
| 170 // Customized behavior for StatusOr<T> vs. StatusOr<T*> |
| 171 template<typename T> |
| 172 struct Specialize; |
| 173 }; |
| 174 |
| 175 template<typename T> |
| 176 struct StatusOrHelper::Specialize { |
| 177 // For non-pointer T, a reference can never be NULL. |
| 178 static inline bool IsValueNull(const T& t) { return false; } |
| 179 }; |
| 180 |
| 181 template<typename T> |
| 182 struct StatusOrHelper::Specialize<T*> { |
| 183 static inline bool IsValueNull(const T* t) { return t == NULL; } |
| 184 }; |
| 185 |
| 186 } // namespace internal |
| 187 |
| 188 template<typename T> |
| 189 inline StatusOr<T>::StatusOr() |
| 190 : status_(util::Status::UNKNOWN) { |
| 191 } |
| 192 |
| 193 template<typename T> |
| 194 inline StatusOr<T>::StatusOr(const Status& status) { |
| 195 if (status.ok()) { |
| 196 status_ = Status(error::INTERNAL, "Status::OK is not a valid argument."); |
| 197 } else { |
| 198 status_ = status; |
| 199 } |
| 200 } |
| 201 |
| 202 template<typename T> |
| 203 inline StatusOr<T>::StatusOr(const T& value) { |
| 204 if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) { |
| 205 status_ = Status(error::INTERNAL, "NULL is not a vaild argument."); |
| 206 } else { |
| 207 status_ = Status::OK; |
| 208 value_ = value; |
| 209 } |
| 210 } |
| 211 |
| 212 template<typename T> |
| 213 inline StatusOr<T>::StatusOr(const StatusOr<T>& other) |
| 214 : status_(other.status_), value_(other.value_) { |
| 215 } |
| 216 |
| 217 template<typename T> |
| 218 inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) { |
| 219 status_ = other.status_; |
| 220 value_ = other.value_; |
| 221 return *this; |
| 222 } |
| 223 |
| 224 template<typename T> |
| 225 template<typename U> |
| 226 inline StatusOr<T>::StatusOr(const StatusOr<U>& other) |
| 227 : status_(other.status_), value_(other.value_) { |
| 228 } |
| 229 |
| 230 template<typename T> |
| 231 template<typename U> |
| 232 inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) { |
| 233 status_ = other.status_; |
| 234 value_ = other.value_; |
| 235 return *this; |
| 236 } |
| 237 |
| 238 template<typename T> |
| 239 inline const Status& StatusOr<T>::status() const { |
| 240 return status_; |
| 241 } |
| 242 |
| 243 template<typename T> |
| 244 inline bool StatusOr<T>::ok() const { |
| 245 return status().ok(); |
| 246 } |
| 247 |
| 248 template<typename T> |
| 249 inline const T& StatusOr<T>::ValueOrDie() const { |
| 250 if (!status_.ok()) { |
| 251 internal::StatusOrHelper::Crash(status_); |
| 252 } |
| 253 return value_; |
| 254 } |
| 255 } // namespace util |
| 256 } // namespace protobuf |
| 257 } // namespace google |
| 258 |
| 259 #endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ |
| OLD | NEW |