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.
Status()27 Status() noexcept : state_(nullptr) {}
~Status()28 ~Status() { delete[] state_; }
29
30 Status(const Status& rhs);
31 Status& operator=(const Status& rhs);
32
Status(Status && rhs)33 Status(Status&& rhs) noexcept : state_(rhs.state_) { rhs.state_ = nullptr; }
34 Status& operator=(Status&& rhs) noexcept;
35
36 // Return a success status.
OK()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.
ok()57 bool ok() const { return (state_ == nullptr); }
58
59 // Returns true iff the status indicates a NotFound error.
IsNotFound()60 bool IsNotFound() const { return code() == kNotFound; }
61
62 // Returns true iff the status indicates a Corruption error.
IsCorruption()63 bool IsCorruption() const { return code() == kCorruption; }
64
65 // Returns true iff the status indicates an IOError.
IsIOError()66 bool IsIOError() const { return code() == kIOError; }
67
68 // Returns true iff the status indicates a NotSupportedError.
IsNotSupportedError()69 bool IsNotSupportedError() const { return code() == kNotSupported; }
70
71 // Returns true iff the status indicates an InvalidArgument.
IsInvalidArgument()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
code()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
Status(const Status & rhs)103 inline Status::Status(const Status& rhs) {
104 state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
105 }
106 inline Status& Status::operator=(const Status& rhs) {
107 // The following condition catches both aliasing (when this == &rhs),
108 // and the common case where both rhs and *this are ok.
109 if (state_ != rhs.state_) {
110 delete[] state_;
111 state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
112 }
113 return *this;
114 }
115 inline Status& Status::operator=(Status&& rhs) noexcept {
116 std::swap(state_, rhs.state_);
117 return *this;
118 }
119
120 } // namespace leveldb
121
122 #endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_
123