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 | 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 | |