1 // Copyright 2020 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "absl/status/statusor.h"
15
16 #include <cstdlib>
17 #include <utility>
18
19 #include "absl/base/call_once.h"
20 #include "absl/base/internal/raw_logging.h"
21 #include "absl/status/status.h"
22 #include "absl/strings/str_cat.h"
23
24 namespace absl {
25 ABSL_NAMESPACE_BEGIN
26
BadStatusOrAccess(absl::Status status)27 BadStatusOrAccess::BadStatusOrAccess(absl::Status status)
28 : status_(std::move(status)) {}
29
BadStatusOrAccess(const BadStatusOrAccess & other)30 BadStatusOrAccess::BadStatusOrAccess(const BadStatusOrAccess& other)
31 : status_(other.status_) {}
32
operator =(const BadStatusOrAccess & other)33 BadStatusOrAccess& BadStatusOrAccess::operator=(
34 const BadStatusOrAccess& other) {
35 // Ensure assignment is correct regardless of whether this->InitWhat() has
36 // already been called.
37 other.InitWhat();
38 status_ = other.status_;
39 what_ = other.what_;
40 return *this;
41 }
42
operator =(BadStatusOrAccess && other)43 BadStatusOrAccess& BadStatusOrAccess::operator=(BadStatusOrAccess&& other) {
44 // Ensure assignment is correct regardless of whether this->InitWhat() has
45 // already been called.
46 other.InitWhat();
47 status_ = std::move(other.status_);
48 what_ = std::move(other.what_);
49 return *this;
50 }
51
BadStatusOrAccess(BadStatusOrAccess && other)52 BadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other)
53 : status_(std::move(other.status_)) {}
54
what() const55 const char* BadStatusOrAccess::what() const noexcept {
56 InitWhat();
57 return what_.c_str();
58 }
59
status() const60 const absl::Status& BadStatusOrAccess::status() const { return status_; }
61
InitWhat() const62 void BadStatusOrAccess::InitWhat() const {
63 absl::call_once(init_what_, [this] {
64 what_ = absl::StrCat("Bad StatusOr access: ", status_.ToString());
65 });
66 }
67
68 namespace internal_statusor {
69
HandleInvalidStatusCtorArg(absl::Status * status)70 void Helper::HandleInvalidStatusCtorArg(absl::Status* status) {
71 const char* kMessage =
72 "An OK status is not a valid constructor argument to StatusOr<T>";
73 #ifdef NDEBUG
74 ABSL_INTERNAL_LOG(ERROR, kMessage);
75 #else
76 ABSL_INTERNAL_LOG(FATAL, kMessage);
77 #endif
78 // In optimized builds, we will fall back to InternalError.
79 *status = absl::InternalError(kMessage);
80 }
81
Crash(const absl::Status & status)82 void Helper::Crash(const absl::Status& status) {
83 ABSL_INTERNAL_LOG(
84 FATAL,
85 absl::StrCat("Attempting to fetch value instead of handling error ",
86 status.ToString()));
87 }
88
ThrowBadStatusOrAccess(absl::Status status)89 void ThrowBadStatusOrAccess(absl::Status status) {
90 #ifdef ABSL_HAVE_EXCEPTIONS
91 throw absl::BadStatusOrAccess(std::move(status));
92 #else
93 ABSL_INTERNAL_LOG(
94 FATAL,
95 absl::StrCat("Attempting to fetch value instead of handling error ",
96 status.ToString()));
97 std::abort();
98 #endif
99 }
100
101 } // namespace internal_statusor
102 ABSL_NAMESPACE_END
103 } // namespace absl
104