tree: 57e320661c92025b7d8efd07bee533c6c1c79284 [path history] [tgz]
  1. caller_info.h
  2. error.h
  3. error_message.h
  4. error_test.cc
  5. README.md
  6. testing_helper.h
libhwsec-foundation/error/README.md

ErrorBase object

An error object with error information in it.

It supports multiple layers of error messages, custom contents, custom function and printable.

This would be helpful to convert the error into some actions and logging the error message.

How to add a new error type?

  1. The custom error object needs to inherit the ErrorBaseObj.
  2. It needs to implement the constructor.
  3. It needs to implement ToReadableString to convert the error object to a readable string.
  4. It needs to implement SelfCopy to copy itself.
  5. Optional: Define CustomError to simplify the usage.
  6. Optional: Override the CreateError helper function to create some special error type, for example: nullptr.
  7. Optional: Override the CreateErrorWrap helper function to create some special error.
  8. Optional: Implement the move operator to add the support of caller info.
class CustomErrorObj : public ErrorBaseObj {
 public:
  explicit ErrorObj(const std::string& error_message)
      : error_message_(error_message) {}
  explicit ErrorObj(std::string&& error_message)
      : error_message_(std::move(error_message)) {}
  virtual ~ErrorObj() = default;

  hwsec_foundation::error::ErrorBase SelfCopy() const {
    return std::make_unique<ErrorObj>(error_message_);
  }

  std::string ToReadableString() const { return error_message_; }

 protected:
  ErrorObj(ErrorObj&&) = default;

 private:
  const std::string error_message_;
};
using CustomError = std::unique_ptr<CustomErrorObj>;

template <typename ErrorType,
          typename T,
          typename std::enable_if<
              std::is_same<ErrorType, CustomError>::value>::type* =
              nullptr,
          decltype(CustomErrorObj(
              std::forward<T>(std::declval<T&&>())))* = nullptr>
CustomError CreateError(T&& error_msg) {
  if (error_msg == "") {
      return nullptr;
  }
  return std::make_unique<CustomError>(std::forward<T>(error_msg));
}

Recommended coding style

  1. When should we use auto? Similar to the style of unique_ptr.
    1. Use auto when the error is created by CreateError<> or CreateErrorWrap<>
      if (auto err = CreateError<TPM1Error>(0x99)) {
        /* Do some error handlings... */
      }
      
    2. Specify the error type in other cases.
      if (TPM1Error err = SomeMagicFunction()) {
        /* Do some error handlings... */
      }
      
  2. Use Error in the if expression:
    1. It's fine to do implicit bool conversions when the error is declared inside the if expression.
      if (TPM1Error err = SomeMagicFunction()) {
        /* Do some error handlings... */
      }
      
    2. But we should prevent doing implicit bool conversions when the error isn’t declared in the if expression.
      if (SomeMagicFunction()) {
        /* Don’t do this. */
      }
      
      Please use:
      if (SomeMagicFunction() != nullptr) {
          /* This it better */
          /* But should think about why we need to drop the extra error information in this case. */
          /* For example: Should we log more messages in this case? */
      }