summaryrefslogtreecommitdiff
path: root/abseil-cpp/absl/status/status.h
diff options
context:
space:
mode:
Diffstat (limited to 'abseil-cpp/absl/status/status.h')
-rw-r--r--abseil-cpp/absl/status/status.h176
1 files changed, 130 insertions, 46 deletions
diff --git a/abseil-cpp/absl/status/status.h b/abseil-cpp/absl/status/status.h
index 42f634e..595064c 100644
--- a/abseil-cpp/absl/status/status.h
+++ b/abseil-cpp/absl/status/status.h
@@ -24,11 +24,11 @@
// * A set of helper functions for creating status codes and checking their
// values
//
-// Within Google, `absl::Status` is the primary mechanism for gracefully
-// handling errors across API boundaries (and in particular across RPC
-// boundaries). Some of these errors may be recoverable, but others may not.
-// Most functions that can produce a recoverable error should be designed to
-// return an `absl::Status` (or `absl::StatusOr`).
+// Within Google, `absl::Status` is the primary mechanism for communicating
+// errors in C++, and is used to represent error state in both in-process
+// library calls as well as RPC calls. Some of these errors may be recoverable,
+// but others may not. Most functions that can produce a recoverable error
+// should be designed to return an `absl::Status` (or `absl::StatusOr`).
//
// Example:
//
@@ -51,12 +51,14 @@
#ifndef ABSL_STATUS_STATUS_H_
#define ABSL_STATUS_STATUS_H_
-#include <iostream>
+#include <ostream>
#include <string>
+#include <utility>
-#include "absl/container/inlined_vector.h"
+#include "absl/functional/function_ref.h"
#include "absl/status/internal/status_internal.h"
#include "absl/strings/cord.h"
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
namespace absl {
@@ -79,7 +81,7 @@ ABSL_NAMESPACE_BEGIN
// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or
// `kAlreadyExists` over `kFailedPrecondition`.
//
-// Because these errors may travel RPC boundaries, these codes are tied to the
+// Because these errors may cross RPC boundaries, these codes are tied to the
// `google.rpc.Code` definitions within
// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
// The string value of these RPC codes is denoted within each enum below.
@@ -98,7 +100,7 @@ enum class StatusCode : int {
// StatusCode::kCancelled
//
- // kCanelled (gRPC code "CANCELLED") indicates the operation was cancelled,
+ // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled,
// typically by the caller.
kCancelled = 1,
@@ -113,10 +115,10 @@ enum class StatusCode : int {
// StatusCode::kInvalidArgument
//
// kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller
- // specified an invalid argument, such a malformed filename. Note that such
- // errors should be narrowly limited to indicate to the invalid nature of the
- // arguments themselves. Errors with validly formed arguments that may cause
- // errors with the state of the receiving system should be denoted with
+ // specified an invalid argument, such as a malformed filename. Note that use
+ // of such errors should be narrowly limited to indicate the invalid nature of
+ // the arguments themselves. Errors with validly formed arguments that may
+ // cause errors with the state of the receiving system should be denoted with
// `kFailedPrecondition` instead.
kInvalidArgument = 3,
@@ -136,14 +138,15 @@ enum class StatusCode : int {
//
// `kNotFound` is useful if a request should be denied for an entire class of
// users, such as during a gradual feature rollout or undocumented allow list.
- // If, instead, a request should be denied for specific sets of users, such as
- // through user-based access control, use `kPermissionDenied` instead.
+ // If a request should be denied for specific sets of users, such as through
+ // user-based access control, use `kPermissionDenied` instead.
kNotFound = 5,
// StatusCode::kAlreadyExists
//
- // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a
- // caller attempted to create (such as file or directory) is already present.
+ // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates that the entity a
+ // caller attempted to create (such as a file or directory) is already
+ // present.
kAlreadyExists = 6,
// StatusCode::kPermissionDenied
@@ -182,7 +185,7 @@ enum class StatusCode : int {
// level (such as when a client-specified test-and-set fails, indicating
// the client should restart a read-modify-write sequence).
// (c) Use `kFailedPrecondition` if the client should not retry until
- // the system state has been explicitly fixed. For example, if an "rmdir"
+ // the system state has been explicitly fixed. For example, if a "rmdir"
// fails because the directory is non-empty, `kFailedPrecondition`
// should be returned since the client should not retry unless
// the files are deleted from the directory.
@@ -198,9 +201,9 @@ enum class StatusCode : int {
// `kAborted`, and `kUnavailable`.
kAborted = 10,
- // StatusCode::kOutofRange
+ // StatusCode::kOutOfRange
//
- // kOutofRange (gRPC code "OUT_OF_RANGE") indicates the operation was
+ // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was
// attempted past the valid range, such as seeking or reading past an
// end-of-file.
//
@@ -279,6 +282,59 @@ std::string StatusCodeToString(StatusCode code);
// Streams StatusCodeToString(code) to `os`.
std::ostream& operator<<(std::ostream& os, StatusCode code);
+// absl::StatusToStringMode
+//
+// An `absl::StatusToStringMode` is an enumerated type indicating how
+// `absl::Status::ToString()` should construct the output string for a non-ok
+// status.
+enum class StatusToStringMode : int {
+ // ToString will not contain any extra data (such as payloads). It will only
+ // contain the error code and message, if any.
+ kWithNoExtraData = 0,
+ // ToString will contain the payloads.
+ kWithPayload = 1 << 0,
+ // ToString will include all the extra data this Status has.
+ kWithEverything = ~kWithNoExtraData,
+ // Default mode used by ToString. Its exact value might change in the future.
+ kDefault = kWithPayload,
+};
+
+// absl::StatusToStringMode is specified as a bitmask type, which means the
+// following operations must be provided:
+inline constexpr StatusToStringMode operator&(StatusToStringMode lhs,
+ StatusToStringMode rhs) {
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) &
+ static_cast<int>(rhs));
+}
+inline constexpr StatusToStringMode operator|(StatusToStringMode lhs,
+ StatusToStringMode rhs) {
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) |
+ static_cast<int>(rhs));
+}
+inline constexpr StatusToStringMode operator^(StatusToStringMode lhs,
+ StatusToStringMode rhs) {
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) ^
+ static_cast<int>(rhs));
+}
+inline constexpr StatusToStringMode operator~(StatusToStringMode arg) {
+ return static_cast<StatusToStringMode>(~static_cast<int>(arg));
+}
+inline StatusToStringMode& operator&=(StatusToStringMode& lhs,
+ StatusToStringMode rhs) {
+ lhs = lhs & rhs;
+ return lhs;
+}
+inline StatusToStringMode& operator|=(StatusToStringMode& lhs,
+ StatusToStringMode rhs) {
+ lhs = lhs | rhs;
+ return lhs;
+}
+inline StatusToStringMode& operator^=(StatusToStringMode& lhs,
+ StatusToStringMode rhs) {
+ lhs = lhs ^ rhs;
+ return lhs;
+}
+
// absl::Status
//
// The `absl::Status` class is generally used to gracefully handle errors
@@ -291,7 +347,7 @@ std::ostream& operator<<(std::ostream& os, StatusCode code);
// API developers should construct their functions to return `absl::OkStatus()`
// upon success, or an `absl::StatusCode` upon another type of error (e.g
// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience
-// functions to constuct each status code.
+// functions to construct each status code.
//
// Example:
//
@@ -342,7 +398,7 @@ std::ostream& operator<<(std::ostream& os, StatusCode code);
//
// * It may provide more fine-grained semantic information about the error to
// facilitate actionable remedies.
-// * It may provide human-readable contexual information that is more
+// * It may provide human-readable contextual information that is more
// appropriate to display to an end user.
//
// Example:
@@ -360,7 +416,12 @@ std::ostream& operator<<(std::ostream& os, StatusCode code);
// return result;
// }
//
-class ABSL_MUST_USE_RESULT Status final {
+// For documentation see https://abseil.io/docs/cpp/guides/status.
+//
+// Returned Status objects may not be ignored. status_internal.h has a forward
+// declaration of the form
+// class ABSL_MUST_USE_RESULT Status;
+class Status final {
public:
// Constructors
@@ -370,10 +431,10 @@ class ABSL_MUST_USE_RESULT Status final {
Status();
// Creates a status in the canonical error space with the specified
- // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`,
+ // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, // NOLINT
// `msg` is ignored and an object identical to an OK status is constructed.
//
- // The `msg` string must be in UTF-8. The implementation may complain (e.g.,
+ // The `msg` string must be in UTF-8. The implementation may complain (e.g., // NOLINT
// by printing a warning) if it is not.
Status(absl::StatusCode code, absl::string_view msg);
@@ -408,8 +469,9 @@ class ABSL_MUST_USE_RESULT Status final {
// Status::ok()
//
- // Returns `true` if `this->ok()`. Prefer checking for an OK status using this
- // member function.
+ // Returns `true` if `this->code()` == `absl::StatusCode::kOk`,
+ // indicating the absence of an error.
+ // Prefer checking for an OK status using this member function.
ABSL_MUST_USE_RESULT bool ok() const;
// Status::code()
@@ -434,7 +496,7 @@ class ABSL_MUST_USE_RESULT Status final {
// Returns the error message associated with this error code, if available.
// Note that this message rarely describes the error code. It is not unusual
// for the error message to be the empty string. As a result, prefer
- // `Status::ToString()` for debug logging.
+ // `operator<<` or `Status::ToString()` for debug logging.
absl::string_view message() const;
friend bool operator==(const Status&, const Status&);
@@ -442,15 +504,17 @@ class ABSL_MUST_USE_RESULT Status final {
// Status::ToString()
//
- // Returns a combination of the error code name, the message and any
- // associated payload messages. This string is designed simply to be human
- // readable and its exact format should not be load bearing. Do not depend on
- // the exact format of the result of `ToString()` which is subject to change.
+ // Returns a string based on the `mode`. By default, it returns combination of
+ // the error code name, the message and any associated payload messages. This
+ // string is designed simply to be human readable and its exact format should
+ // not be load bearing. Do not depend on the exact format of the result of
+ // `ToString()` which is subject to change.
//
// The printed code name and the message are generally substrings of the
// result, and the payloads to be printed use the status payload printer
// mechanism (which is internal).
- std::string ToString() const;
+ std::string ToString(
+ StatusToStringMode mode = StatusToStringMode::kDefault) const;
// Status::IgnoreError()
//
@@ -469,12 +533,12 @@ class ABSL_MUST_USE_RESULT Status final {
//----------------------------------------------------------------------------
// A payload may be attached to a status to provide additional context to an
- // error that may not be satisifed by an existing `absl::StatusCode`.
+ // error that may not be satisfied by an existing `absl::StatusCode`.
// Typically, this payload serves one of several purposes:
//
// * It may provide more fine-grained semantic information about the error
// to facilitate actionable remedies.
- // * It may provide human-readable contexual information that is more
+ // * It may provide human-readable contextual information that is more
// appropriate to display to an end user.
//
// A payload consists of a [key,value] pair, where the key is a string
@@ -528,7 +592,7 @@ class ABSL_MUST_USE_RESULT Status final {
// NOTE: Any mutation on the same 'absl::Status' object during visitation is
// forbidden and could result in undefined behavior.
void ForEachPayload(
- const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
+ absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)
const;
private:
@@ -549,9 +613,6 @@ class ABSL_MUST_USE_RESULT Status final {
const status_internal::Payloads* GetPayloads() const;
status_internal::Payloads* GetPayloads();
- // Takes ownership of payload.
- static uintptr_t NewRep(absl::StatusCode code, absl::string_view msg,
- std::unique_ptr<status_internal::Payloads> payload);
static bool EqualsSlow(const absl::Status& a, const absl::Status& b);
// MSVC 14.0 limitation requires the const.
@@ -580,8 +641,7 @@ class ABSL_MUST_USE_RESULT Status final {
static uintptr_t PointerToRep(status_internal::StatusRep* r);
static status_internal::StatusRep* RepToPointer(uintptr_t r);
- // Returns string for non-ok Status.
- std::string ToStringSlow() const;
+ std::string ToStringSlow(StatusToStringMode mode) const;
// Status supports two different representations.
// - When the low bit is off it is an inlined representation.
@@ -678,6 +738,19 @@ Status UnavailableError(absl::string_view message);
Status UnimplementedError(absl::string_view message);
Status UnknownError(absl::string_view message);
+// ErrnoToStatusCode()
+//
+// Returns the StatusCode for `error_number`, which should be an `errno` value.
+// See https://en.cppreference.com/w/cpp/error/errno_macros and similar
+// references.
+absl::StatusCode ErrnoToStatusCode(int error_number);
+
+// ErrnoToStatus()
+//
+// Convenience function that creates a `absl::Status` using an `error_number`,
+// which should be an `errno` value.
+Status ErrnoToStatus(int error_number, absl::string_view message);
+
//------------------------------------------------------------------------------
// Implementation details follow
//------------------------------------------------------------------------------
@@ -704,9 +777,11 @@ inline Status::Status(Status&& x) noexcept : rep_(x.rep_) {
inline Status& Status::operator=(Status&& x) {
uintptr_t old_rep = rep_;
- rep_ = x.rep_;
- x.rep_ = MovedFromRep();
- Unref(old_rep);
+ if (x.rep_ != old_rep) {
+ rep_ = x.rep_;
+ x.rep_ = MovedFromRep();
+ Unref(old_rep);
+ }
return *this;
}
@@ -743,8 +818,8 @@ inline bool operator!=(const Status& lhs, const Status& rhs) {
return !(lhs == rhs);
}
-inline std::string Status::ToString() const {
- return ok() ? "OK" : ToStringSlow();
+inline std::string Status::ToString(StatusToStringMode mode) const {
+ return ok() ? "OK" : ToStringSlow(mode);
}
inline void Status::IgnoreError() const {
@@ -811,6 +886,15 @@ inline Status OkStatus() { return Status(); }
// message-less kCancelled errors are common in the infrastructure.
inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
+// Retrieves a message's status as a null terminated C string. The lifetime of
+// this string is tied to the lifetime of the status object itself.
+//
+// If the status's message is empty, the empty string is returned.
+//
+// StatusMessageAsCStr exists for C support. Use `status.message()` in C++.
+const char* StatusMessageAsCStr(
+ const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND);
+
ABSL_NAMESPACE_END
} // namespace absl