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/config.h"
21 #include "absl/base/internal/raw_logging.h"
22 #include "absl/status/internal/statusor_internal.h"
23 #include "absl/status/status.h"
24 #include "absl/strings/str_cat.h"
25
26 namespace absl {
27 ABSL_NAMESPACE_BEGIN
28
BadStatusOrAccess(absl::Status status)29 BadStatusOrAccess::BadStatusOrAccess(absl::Status status)
30 : status_(std::move(status)) {}
31
BadStatusOrAccess(const BadStatusOrAccess & other)32 BadStatusOrAccess::BadStatusOrAccess(const BadStatusOrAccess& other)
33 : status_(other.status_) {}
34
operator =(const BadStatusOrAccess & other)35 BadStatusOrAccess& BadStatusOrAccess::operator=(
36 const BadStatusOrAccess& other) {
37 // Ensure assignment is correct regardless of whether this->InitWhat() has
38 // already been called.
39 other.InitWhat();
40 status_ = other.status_;
41 what_ = other.what_;
42 return *this;
43 }
44
operator =(BadStatusOrAccess && other)45 BadStatusOrAccess& BadStatusOrAccess::operator=(BadStatusOrAccess&& other) {
46 // Ensure assignment is correct regardless of whether this->InitWhat() has
47 // already been called.
48 other.InitWhat();
49 status_ = std::move(other.status_);
50 what_ = std::move(other.what_);
51 return *this;
52 }
53
BadStatusOrAccess(BadStatusOrAccess && other)54 BadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other)
55 : status_(std::move(other.status_)) {}
56
what() const57 const char* BadStatusOrAccess::what() const noexcept {
58 InitWhat();
59 return what_.c_str();
60 }
61
status() const62 const absl::Status& BadStatusOrAccess::status() const { return status_; }
63
InitWhat() const64 void BadStatusOrAccess::InitWhat() const {
65 absl::call_once(init_what_, [this] {
66 what_ = absl::StrCat("Bad StatusOr access: ", status_.ToString());
67 });
68 }
69
70 namespace internal_statusor {
71
HandleInvalidStatusCtorArg(absl::Status * status)72 void Helper::HandleInvalidStatusCtorArg(absl::Status* status) {
73 const char* kMessage =
74 "An OK status is not a valid constructor argument to StatusOr<T>";
75 #ifdef NDEBUG
76 ABSL_INTERNAL_LOG(ERROR, kMessage);
77 #else
78 ABSL_INTERNAL_LOG(FATAL, kMessage);
79 #endif
80 // In optimized builds, we will fall back to InternalError.
81 *status = absl::InternalError(kMessage);
82 }
83
Crash(const absl::Status & status)84 void Helper::Crash(const absl::Status& status) {
85 ABSL_INTERNAL_LOG(
86 FATAL,
87 absl::StrCat("Attempting to fetch value instead of handling error ",
88 status.ToString()));
89 }
90
ThrowBadStatusOrAccess(absl::Status status)91 void ThrowBadStatusOrAccess(absl::Status status) {
92 #ifdef ABSL_HAVE_EXCEPTIONS
93 throw absl::BadStatusOrAccess(std::move(status));
94 #else
95 ABSL_INTERNAL_LOG(
96 FATAL,
97 absl::StrCat("Attempting to fetch value instead of handling error ",
98 status.ToString()));
99 std::abort();
100 #endif
101 }
102
103 } // namespace internal_statusor
104 ABSL_NAMESPACE_END
105 } // namespace absl
106