| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_DEVELOPER_DEBUG_SHARED_STATUS_H_ |
| #define SRC_DEVELOPER_DEBUG_SHARED_STATUS_H_ |
| |
| #include <iosfwd> |
| #include <string> |
| |
| #if defined(__Fuchsia__) |
| #include <zircon/status.h> |
| #endif |
| |
| #include "src/developer/debug/shared/serialization.h" |
| |
| namespace debug { |
| |
| class Status; |
| |
| #if defined(__Fuchsia__) |
| |
| // If there is an error and no message is given, the ZX_* constant will be queried and used. |
| // If given, the message will be used for most display purposes instead of the platform value, so |
| // if the value is important and you use a custom message, it should be manually included. |
| // |
| // These are split rather than using default values to avoid creating empty std::strings in the |
| // common case. |
| Status ZxStatus(zx_status_t s); |
| Status ZxStatus(zx_status_t s, std::string msg); |
| |
| #else |
| |
| // As with the ZxStatus version above, this will automatically use the strerror() string if no |
| // message is given. |
| Status ErrnoStatus(int en); |
| Status ErrnoStatus(int en, std::string msg); |
| |
| #endif |
| |
| // A cross-platform status value. It has three modes: |
| // |
| // - OK. This is generated by the default constructor and indicates "no error". |
| // |
| // - Platform error: This is generated by one of the above platform-specific helpers. It has a |
| // platform error value (zx_status_t or errno), and it also looks up the corresponding string |
| // from the operating system. |
| // |
| // - Cross-platform error: This can be one of a specific set of enum values that we need to handle |
| // specially from a code perspective, or a generic error with just a message. There is no |
| // platform_error number. There may or may not be a message. |
| class Status { |
| public: |
| enum Type : uint32_t { |
| kSuccess, |
| kGenericError, // There is an error message but no specific enum or platform error. |
| kNotSupported, // The system does not support the requested operation. |
| kNotFound, // For example, the processes to be attached to didn't exist. |
| kAlreadyExists, // For example, attaching to a process or job that's already attached. |
| kNoResources, // Ran out of something (like debug registers). |
| kPlatformError, // An error from the OS in platform_error(). |
| |
| // Not a valid value, used for bounds checking. |
| kLast, |
| }; |
| |
| // No error. For error construction, use one of the helpers above. |
| Status() = default; |
| |
| // Constructor for a generic platform-independent error. The string may or may not be empty. |
| explicit Status(std::string msg); |
| |
| // Constructor for a platform-independent error. The string is optional. |
| // |
| // A type of kSuccess or kPlatformError will assert (use the platform-specific helpers above). |
| explicit Status(Type t, std::string msg = std::string()); |
| |
| // Code creating error should use the platform-specific helpers above. This is for code that |
| // needs to create from some known internal values. The tag structure is to discourage direct use |
| // of this function except when you really need it. |
| // |
| // The |pe| value should be 0 unless the type is a PlatformError. |
| struct InternalValues {}; |
| Status(InternalValues tag, Type t, uint64_t pe, std::string msg); |
| |
| bool ok() const { return type_ == kSuccess; } |
| bool has_error() const { return !ok(); } |
| Type type() const { return type_; } |
| |
| // Assumes the type == kPlatformError. |
| int64_t platform_error() const { return platform_error_; } |
| |
| // The message may or may not be set on error. |
| const std::string& message() const { return message_; } |
| |
| bool operator==(const Status& other) const { |
| return type_ == other.type_ && platform_error_ == other.platform_error_ && |
| message_ == other.message_; |
| } |
| bool operator!=(const Status& other) const { return !operator==(other); } |
| |
| void Serialize(Serializer& ser, uint32_t ver) { ser | type_ | platform_error_ | message_; } |
| |
| private: |
| Type type_ = kSuccess; |
| |
| int64_t platform_error_ = 0; // Valid when type_ == kPlatformError. |
| std::string message_; |
| }; |
| |
| } // namespace debug |
| |
| std::ostream& operator<<(std::ostream& out, const debug::Status& status); |
| |
| #endif // SRC_DEVELOPER_DEBUG_SHARED_STATUS_H_ |