xref: /aosp_15_r20/external/angle/third_party/abseil-cpp/absl/status/status.cc (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 // Copyright 2019 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/status.h"
15 
16 #include <errno.h>
17 
18 #include <atomic>
19 #include <cstddef>
20 #include <cstdint>
21 #include <cstring>
22 #include <memory>
23 #include <ostream>
24 #include <string>
25 
26 #include "absl/base/attributes.h"
27 #include "absl/base/config.h"
28 #include "absl/base/internal/raw_logging.h"
29 #include "absl/base/internal/strerror.h"
30 #include "absl/base/macros.h"
31 #include "absl/base/no_destructor.h"
32 #include "absl/base/nullability.h"
33 #include "absl/debugging/stacktrace.h"
34 #include "absl/debugging/symbolize.h"
35 #include "absl/status/internal/status_internal.h"
36 #include "absl/strings/str_cat.h"
37 #include "absl/strings/str_format.h"
38 #include "absl/strings/str_split.h"
39 #include "absl/strings/string_view.h"
40 #include "absl/types/optional.h"
41 
42 namespace absl {
43 ABSL_NAMESPACE_BEGIN
44 
45 static_assert(
46     alignof(status_internal::StatusRep) >= 4,
47     "absl::Status assumes it can use the bottom 2 bits of a StatusRep*.");
48 
StatusCodeToString(StatusCode code)49 std::string StatusCodeToString(StatusCode code) {
50   switch (code) {
51     case StatusCode::kOk:
52       return "OK";
53     case StatusCode::kCancelled:
54       return "CANCELLED";
55     case StatusCode::kUnknown:
56       return "UNKNOWN";
57     case StatusCode::kInvalidArgument:
58       return "INVALID_ARGUMENT";
59     case StatusCode::kDeadlineExceeded:
60       return "DEADLINE_EXCEEDED";
61     case StatusCode::kNotFound:
62       return "NOT_FOUND";
63     case StatusCode::kAlreadyExists:
64       return "ALREADY_EXISTS";
65     case StatusCode::kPermissionDenied:
66       return "PERMISSION_DENIED";
67     case StatusCode::kUnauthenticated:
68       return "UNAUTHENTICATED";
69     case StatusCode::kResourceExhausted:
70       return "RESOURCE_EXHAUSTED";
71     case StatusCode::kFailedPrecondition:
72       return "FAILED_PRECONDITION";
73     case StatusCode::kAborted:
74       return "ABORTED";
75     case StatusCode::kOutOfRange:
76       return "OUT_OF_RANGE";
77     case StatusCode::kUnimplemented:
78       return "UNIMPLEMENTED";
79     case StatusCode::kInternal:
80       return "INTERNAL";
81     case StatusCode::kUnavailable:
82       return "UNAVAILABLE";
83     case StatusCode::kDataLoss:
84       return "DATA_LOSS";
85     default:
86       return "";
87   }
88 }
89 
operator <<(std::ostream & os,StatusCode code)90 std::ostream& operator<<(std::ostream& os, StatusCode code) {
91   return os << StatusCodeToString(code);
92 }
93 
EmptyString()94 absl::Nonnull<const std::string*> Status::EmptyString() {
95   static const absl::NoDestructor<std::string> kEmpty;
96   return kEmpty.get();
97 }
98 
99 #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
100 constexpr const char Status::kMovedFromString[];
101 #endif
102 
MovedFromString()103 absl::Nonnull<const std::string*> Status::MovedFromString() {
104   static const absl::NoDestructor<std::string> kMovedFrom(kMovedFromString);
105   return kMovedFrom.get();
106 }
107 
Status(absl::StatusCode code,absl::string_view msg)108 Status::Status(absl::StatusCode code, absl::string_view msg)
109     : rep_(CodeToInlinedRep(code)) {
110   if (code != absl::StatusCode::kOk && !msg.empty()) {
111     rep_ = PointerToRep(new status_internal::StatusRep(code, msg, nullptr));
112   }
113 }
114 
PrepareToModify(uintptr_t rep)115 absl::Nonnull<status_internal::StatusRep*> Status::PrepareToModify(
116     uintptr_t rep) {
117   if (IsInlined(rep)) {
118     return new status_internal::StatusRep(InlinedRepToCode(rep),
119                                           absl::string_view(), nullptr);
120   }
121   return RepToPointer(rep)->CloneAndUnref();
122 }
123 
ToStringSlow(uintptr_t rep,StatusToStringMode mode)124 std::string Status::ToStringSlow(uintptr_t rep, StatusToStringMode mode) {
125   if (IsInlined(rep)) {
126     return absl::StrCat(absl::StatusCodeToString(InlinedRepToCode(rep)), ": ");
127   }
128   return RepToPointer(rep)->ToString(mode);
129 }
130 
operator <<(std::ostream & os,const Status & x)131 std::ostream& operator<<(std::ostream& os, const Status& x) {
132   os << x.ToString(StatusToStringMode::kWithEverything);
133   return os;
134 }
135 
AbortedError(absl::string_view message)136 Status AbortedError(absl::string_view message) {
137   return Status(absl::StatusCode::kAborted, message);
138 }
139 
AlreadyExistsError(absl::string_view message)140 Status AlreadyExistsError(absl::string_view message) {
141   return Status(absl::StatusCode::kAlreadyExists, message);
142 }
143 
CancelledError(absl::string_view message)144 Status CancelledError(absl::string_view message) {
145   return Status(absl::StatusCode::kCancelled, message);
146 }
147 
DataLossError(absl::string_view message)148 Status DataLossError(absl::string_view message) {
149   return Status(absl::StatusCode::kDataLoss, message);
150 }
151 
DeadlineExceededError(absl::string_view message)152 Status DeadlineExceededError(absl::string_view message) {
153   return Status(absl::StatusCode::kDeadlineExceeded, message);
154 }
155 
FailedPreconditionError(absl::string_view message)156 Status FailedPreconditionError(absl::string_view message) {
157   return Status(absl::StatusCode::kFailedPrecondition, message);
158 }
159 
InternalError(absl::string_view message)160 Status InternalError(absl::string_view message) {
161   return Status(absl::StatusCode::kInternal, message);
162 }
163 
InvalidArgumentError(absl::string_view message)164 Status InvalidArgumentError(absl::string_view message) {
165   return Status(absl::StatusCode::kInvalidArgument, message);
166 }
167 
NotFoundError(absl::string_view message)168 Status NotFoundError(absl::string_view message) {
169   return Status(absl::StatusCode::kNotFound, message);
170 }
171 
OutOfRangeError(absl::string_view message)172 Status OutOfRangeError(absl::string_view message) {
173   return Status(absl::StatusCode::kOutOfRange, message);
174 }
175 
PermissionDeniedError(absl::string_view message)176 Status PermissionDeniedError(absl::string_view message) {
177   return Status(absl::StatusCode::kPermissionDenied, message);
178 }
179 
ResourceExhaustedError(absl::string_view message)180 Status ResourceExhaustedError(absl::string_view message) {
181   return Status(absl::StatusCode::kResourceExhausted, message);
182 }
183 
UnauthenticatedError(absl::string_view message)184 Status UnauthenticatedError(absl::string_view message) {
185   return Status(absl::StatusCode::kUnauthenticated, message);
186 }
187 
UnavailableError(absl::string_view message)188 Status UnavailableError(absl::string_view message) {
189   return Status(absl::StatusCode::kUnavailable, message);
190 }
191 
UnimplementedError(absl::string_view message)192 Status UnimplementedError(absl::string_view message) {
193   return Status(absl::StatusCode::kUnimplemented, message);
194 }
195 
UnknownError(absl::string_view message)196 Status UnknownError(absl::string_view message) {
197   return Status(absl::StatusCode::kUnknown, message);
198 }
199 
IsAborted(const Status & status)200 bool IsAborted(const Status& status) {
201   return status.code() == absl::StatusCode::kAborted;
202 }
203 
IsAlreadyExists(const Status & status)204 bool IsAlreadyExists(const Status& status) {
205   return status.code() == absl::StatusCode::kAlreadyExists;
206 }
207 
IsCancelled(const Status & status)208 bool IsCancelled(const Status& status) {
209   return status.code() == absl::StatusCode::kCancelled;
210 }
211 
IsDataLoss(const Status & status)212 bool IsDataLoss(const Status& status) {
213   return status.code() == absl::StatusCode::kDataLoss;
214 }
215 
IsDeadlineExceeded(const Status & status)216 bool IsDeadlineExceeded(const Status& status) {
217   return status.code() == absl::StatusCode::kDeadlineExceeded;
218 }
219 
IsFailedPrecondition(const Status & status)220 bool IsFailedPrecondition(const Status& status) {
221   return status.code() == absl::StatusCode::kFailedPrecondition;
222 }
223 
IsInternal(const Status & status)224 bool IsInternal(const Status& status) {
225   return status.code() == absl::StatusCode::kInternal;
226 }
227 
IsInvalidArgument(const Status & status)228 bool IsInvalidArgument(const Status& status) {
229   return status.code() == absl::StatusCode::kInvalidArgument;
230 }
231 
IsNotFound(const Status & status)232 bool IsNotFound(const Status& status) {
233   return status.code() == absl::StatusCode::kNotFound;
234 }
235 
IsOutOfRange(const Status & status)236 bool IsOutOfRange(const Status& status) {
237   return status.code() == absl::StatusCode::kOutOfRange;
238 }
239 
IsPermissionDenied(const Status & status)240 bool IsPermissionDenied(const Status& status) {
241   return status.code() == absl::StatusCode::kPermissionDenied;
242 }
243 
IsResourceExhausted(const Status & status)244 bool IsResourceExhausted(const Status& status) {
245   return status.code() == absl::StatusCode::kResourceExhausted;
246 }
247 
IsUnauthenticated(const Status & status)248 bool IsUnauthenticated(const Status& status) {
249   return status.code() == absl::StatusCode::kUnauthenticated;
250 }
251 
IsUnavailable(const Status & status)252 bool IsUnavailable(const Status& status) {
253   return status.code() == absl::StatusCode::kUnavailable;
254 }
255 
IsUnimplemented(const Status & status)256 bool IsUnimplemented(const Status& status) {
257   return status.code() == absl::StatusCode::kUnimplemented;
258 }
259 
IsUnknown(const Status & status)260 bool IsUnknown(const Status& status) {
261   return status.code() == absl::StatusCode::kUnknown;
262 }
263 
ErrnoToStatusCode(int error_number)264 StatusCode ErrnoToStatusCode(int error_number) {
265   switch (error_number) {
266     case 0:
267       return StatusCode::kOk;
268     case EINVAL:        // Invalid argument
269     case ENAMETOOLONG:  // Filename too long
270     case E2BIG:         // Argument list too long
271     case EDESTADDRREQ:  // Destination address required
272     case EDOM:          // Mathematics argument out of domain of function
273     case EFAULT:        // Bad address
274     case EILSEQ:        // Illegal byte sequence
275     case ENOPROTOOPT:   // Protocol not available
276     case ENOTSOCK:      // Not a socket
277     case ENOTTY:        // Inappropriate I/O control operation
278     case EPROTOTYPE:    // Protocol wrong type for socket
279     case ESPIPE:        // Invalid seek
280       return StatusCode::kInvalidArgument;
281     case ETIMEDOUT:  // Connection timed out
282       return StatusCode::kDeadlineExceeded;
283     case ENODEV:  // No such device
284     case ENOENT:  // No such file or directory
285 #ifdef ENOMEDIUM
286     case ENOMEDIUM:  // No medium found
287 #endif
288     case ENXIO:  // No such device or address
289     case ESRCH:  // No such process
290       return StatusCode::kNotFound;
291     case EEXIST:         // File exists
292     case EADDRNOTAVAIL:  // Address not available
293     case EALREADY:       // Connection already in progress
294 #ifdef ENOTUNIQ
295     case ENOTUNIQ:  // Name not unique on network
296 #endif
297       return StatusCode::kAlreadyExists;
298     case EPERM:   // Operation not permitted
299     case EACCES:  // Permission denied
300 #ifdef ENOKEY
301     case ENOKEY:  // Required key not available
302 #endif
303     case EROFS:  // Read only file system
304       return StatusCode::kPermissionDenied;
305     case ENOTEMPTY:   // Directory not empty
306     case EISDIR:      // Is a directory
307     case ENOTDIR:     // Not a directory
308     case EADDRINUSE:  // Address already in use
309     case EBADF:       // Invalid file descriptor
310 #ifdef EBADFD
311     case EBADFD:  // File descriptor in bad state
312 #endif
313     case EBUSY:    // Device or resource busy
314     case ECHILD:   // No child processes
315     case EISCONN:  // Socket is connected
316 #ifdef EISNAM
317     case EISNAM:  // Is a named type file
318 #endif
319 #ifdef ENOTBLK
320     case ENOTBLK:  // Block device required
321 #endif
322     case ENOTCONN:  // The socket is not connected
323     case EPIPE:     // Broken pipe
324 #ifdef ESHUTDOWN
325     case ESHUTDOWN:  // Cannot send after transport endpoint shutdown
326 #endif
327     case ETXTBSY:  // Text file busy
328 #ifdef EUNATCH
329     case EUNATCH:  // Protocol driver not attached
330 #endif
331       return StatusCode::kFailedPrecondition;
332     case ENOSPC:  // No space left on device
333 #ifdef EDQUOT
334     case EDQUOT:  // Disk quota exceeded
335 #endif
336     case EMFILE:   // Too many open files
337     case EMLINK:   // Too many links
338     case ENFILE:   // Too many open files in system
339     case ENOBUFS:  // No buffer space available
340     case ENOMEM:   // Not enough space
341 #ifdef EUSERS
342     case EUSERS:  // Too many users
343 #endif
344       return StatusCode::kResourceExhausted;
345 #ifdef ECHRNG
346     case ECHRNG:  // Channel number out of range
347 #endif
348     case EFBIG:      // File too large
349     case EOVERFLOW:  // Value too large to be stored in data type
350     case ERANGE:     // Result too large
351       return StatusCode::kOutOfRange;
352 #ifdef ENOPKG
353     case ENOPKG:  // Package not installed
354 #endif
355     case ENOSYS:        // Function not implemented
356     case ENOTSUP:       // Operation not supported
357     case EAFNOSUPPORT:  // Address family not supported
358 #ifdef EPFNOSUPPORT
359     case EPFNOSUPPORT:  // Protocol family not supported
360 #endif
361     case EPROTONOSUPPORT:  // Protocol not supported
362 #ifdef ESOCKTNOSUPPORT
363     case ESOCKTNOSUPPORT:  // Socket type not supported
364 #endif
365     case EXDEV:  // Improper link
366       return StatusCode::kUnimplemented;
367     case EAGAIN:  // Resource temporarily unavailable
368 #ifdef ECOMM
369     case ECOMM:  // Communication error on send
370 #endif
371     case ECONNREFUSED:  // Connection refused
372     case ECONNABORTED:  // Connection aborted
373     case ECONNRESET:    // Connection reset
374     case EINTR:         // Interrupted function call
375 #ifdef EHOSTDOWN
376     case EHOSTDOWN:  // Host is down
377 #endif
378     case EHOSTUNREACH:  // Host is unreachable
379     case ENETDOWN:      // Network is down
380     case ENETRESET:     // Connection aborted by network
381     case ENETUNREACH:   // Network unreachable
382     case ENOLCK:        // No locks available
383     case ENOLINK:       // Link has been severed
384 #ifdef ENONET
385     case ENONET:  // Machine is not on the network
386 #endif
387       return StatusCode::kUnavailable;
388     case EDEADLK:  // Resource deadlock avoided
389 #ifdef ESTALE
390     case ESTALE:  // Stale file handle
391 #endif
392       return StatusCode::kAborted;
393     case ECANCELED:  // Operation cancelled
394       return StatusCode::kCancelled;
395     default:
396       return StatusCode::kUnknown;
397   }
398 }
399 
400 namespace {
MessageForErrnoToStatus(int error_number,absl::string_view message)401 std::string MessageForErrnoToStatus(int error_number,
402                                     absl::string_view message) {
403   return absl::StrCat(message, ": ",
404                       absl::base_internal::StrError(error_number));
405 }
406 }  // namespace
407 
ErrnoToStatus(int error_number,absl::string_view message)408 Status ErrnoToStatus(int error_number, absl::string_view message) {
409   return Status(ErrnoToStatusCode(error_number),
410                 MessageForErrnoToStatus(error_number, message));
411 }
412 
StatusMessageAsCStr(const Status & status)413 absl::Nonnull<const char*> StatusMessageAsCStr(const Status& status) {
414   // As an internal implementation detail, we guarantee that if status.message()
415   // is non-empty, then the resulting string_view is null terminated.
416   auto sv_message = status.message();
417   return sv_message.empty() ? "" : sv_message.data();
418 }
419 
420 ABSL_NAMESPACE_END
421 }  // namespace absl
422