status.h
1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. See the AUTHORS file for names of contributors. 4 // 5 // A Status encapsulates the result of an operation. It may indicate success, 6 // or it may indicate an error with an associated error message. 7 // 8 // Multiple threads can invoke const methods on a Status without 9 // external synchronization, but if any of the threads may call a 10 // non-const method, all threads accessing the same Status must use 11 // external synchronization. 12 13 #ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_ 14 #define STORAGE_LEVELDB_INCLUDE_STATUS_H_ 15 16 #include <algorithm> 17 #include <string> 18 19 #include "leveldb/export.h" 20 #include "leveldb/slice.h" 21 22 namespace leveldb { 23 24 class LEVELDB_EXPORT Status { 25 public: 26 // Create a success status. 27 Status() noexcept : state_(nullptr) {} 28 ~Status() { delete[] state_; } 29 30 Status(const Status& rhs); 31 Status& operator=(const Status& rhs); 32 33 Status(Status&& rhs) noexcept : state_(rhs.state_) { rhs.state_ = nullptr; } 34 Status& operator=(Status&& rhs) noexcept; 35 36 // Return a success status. 37 static Status OK() { return Status(); } 38 39 // Return error status of an appropriate type. 40 static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { 41 return Status(kNotFound, msg, msg2); 42 } 43 static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) { 44 return Status(kCorruption, msg, msg2); 45 } 46 static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) { 47 return Status(kNotSupported, msg, msg2); 48 } 49 static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) { 50 return Status(kInvalidArgument, msg, msg2); 51 } 52 static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { 53 return Status(kIOError, msg, msg2); 54 } 55 56 // Returns true iff the status indicates success. 57 bool ok() const { return (state_ == nullptr); } 58 59 // Returns true iff the status indicates a NotFound error. 60 bool IsNotFound() const { return code() == kNotFound; } 61 62 // Returns true iff the status indicates a Corruption error. 63 bool IsCorruption() const { return code() == kCorruption; } 64 65 // Returns true iff the status indicates an IOError. 66 bool IsIOError() const { return code() == kIOError; } 67 68 // Returns true iff the status indicates a NotSupportedError. 69 bool IsNotSupportedError() const { return code() == kNotSupported; } 70 71 // Returns true iff the status indicates an InvalidArgument. 72 bool IsInvalidArgument() const { return code() == kInvalidArgument; } 73 74 // Return a string representation of this status suitable for printing. 75 // Returns the string "OK" for success. 76 std::string ToString() const; 77 78 private: 79 enum Code { 80 kOk = 0, 81 kNotFound = 1, 82 kCorruption = 2, 83 kNotSupported = 3, 84 kInvalidArgument = 4, 85 kIOError = 5 86 }; 87 88 Code code() const { 89 return (state_ == nullptr) ? kOk : static_cast<Code>(state_[4]); 90 } 91 92 Status(Code code, const Slice& msg, const Slice& msg2); 93 static const char* CopyState(const char* s); 94 95 // OK status has a null state_. Otherwise, state_ is a new[] array 96 // of the following form: 97 // state_[0..3] == length of message 98 // state_[4] == code 99 // state_[5..] == message 100 const char* state_; 101 }; 102 103 inline Status::Status(const Status& rhs) { 104 state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_); 105 } 106 107 // NOLINTBEGIN(bugprone-unhandled-self-assignment) 108 inline Status& Status::operator=(const Status& rhs) { 109 // The following condition catches both aliasing (when this == &rhs), 110 // and the common case where both rhs and *this are ok. 111 if (state_ != rhs.state_) { 112 delete[] state_; 113 state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_); 114 } 115 return *this; 116 } 117 // NOLINTEND(bugprone-unhandled-self-assignment) 118 119 inline Status& Status::operator=(Status&& rhs) noexcept { 120 std::swap(state_, rhs.state_); 121 return *this; 122 } 123 124 } // namespace leveldb 125 126 #endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_