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