osquery-1/osquery/utils/status/status.h

176 lines
4.6 KiB
C
Raw Normal View History

/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
2014-07-31 00:35:19 +00:00
#pragma once
2014-07-31 00:35:19 +00:00
#include <osquery/utils/error/error.h>
#include <osquery/utils/expected/expected.h>
#include <sstream>
2014-07-31 00:35:19 +00:00
#include <string>
namespace osquery {
2014-07-31 00:35:19 +00:00
/**
* @brief A utility class which is used to express the state of operations.
2014-09-15 20:23:28 +00:00
*
* @code{.cpp}
* osquery::Status foobar() {
* auto na = doSomeWork();
* if (na->itWorked()) {
* return osquery::Status(0, "OK");
* } else {
* return osquery::Status(1, na->getErrorString());
* }
* }
* @endcode
2014-09-15 20:23:28 +00:00
*/
2014-07-31 00:35:19 +00:00
class Status {
2014-08-15 07:25:30 +00:00
public:
static constexpr int kSuccessCode = 0;
/**
* @brief Default constructor
2014-09-15 20:23:28 +00:00
*
* Note that the default constructor initialized an osquery::Status instance
* to a state such that a successful operation is indicated.
2014-09-15 20:23:28 +00:00
*/
explicit Status(int c = Status::kSuccessCode) : code_(c), message_("OK") {}
/**
* @brief A constructor which can be used to concisely express the status of
* an operation.
2014-09-15 20:23:28 +00:00
*
* @param c a status code. The idiom is that a zero status code indicates a
* successful operation and a non-zero status code indicates a failed
* operation.
* @param m a message indicating some extra detail regarding the operation.
* If all operations were successful, this message should be "OK".
* Otherwise, it doesn't matter what the string is, as long as both the
* setter and caller agree.
2014-09-15 20:23:28 +00:00
*/
Status(int c, std::string m) : code_(c), message_(std::move(m)) {}
2014-08-15 07:25:30 +00:00
Status(const ErrorBase& error)
: code_(1), message_(error.getFullMessageRecursive()) {}
2014-08-15 07:25:30 +00:00
public:
/**
* @brief A getter for the status code property
2014-09-15 20:23:28 +00:00
*
* @return an integer representing the status code of the operation.
2014-09-15 20:23:28 +00:00
*/
int getCode() const {
return code_;
}
/**
* @brief A getter for the message property
2014-09-15 20:23:28 +00:00
*
* @return a string representing arbitrary additional information about the
* success or failure of an operation. On successful operations, the idiom
* is for the message to be "OK"
2014-09-15 20:23:28 +00:00
*/
std::string getMessage() const {
return message_;
}
/**
* @brief A convenience method to check if the return code is
* Status::kSuccessCode
2014-09-15 20:23:28 +00:00
*
* @code{.cpp}
* auto s = doSomething();
* if (s.ok()) {
* LOG(INFO) << "doing work";
* } else {
* LOG(ERROR) << s.toString();
* }
* @endcode
2014-09-15 20:23:28 +00:00
*
* @return a boolean which is true if the status code is Status::kSuccessCode,
* false otherwise.
2014-09-15 20:23:28 +00:00
*/
bool ok() const {
return getCode() == Status::kSuccessCode;
}
/**
* @brief A synonym for osquery::Status::getMessage()
2014-09-15 20:23:28 +00:00
*
* @see getMessage()
2014-09-15 20:23:28 +00:00
*/
std::string toString() const {
return getMessage();
}
std::string what() const {
return getMessage();
}
2014-07-31 00:35:19 +00:00
/**
* @brief implicit conversion to bool
*
* Allows easy use of Status in an if statement, as below:
*
* @code{.cpp}
* if (doSomethingThatReturnsStatus()) {
* LOG(INFO) << "Success!";
* }
* @endcode
*/
/* explicit */ explicit operator bool() const {
return ok();
}
static Status success() {
return Status(kSuccessCode);
}
static Status failure(std::string message) {
return Status(1, std::move(message));
}
static Status failure(int code, std::string message);
// Below operator implementations useful for testing with gtest
// Enables use of gtest (ASSERT|EXPECT)_EQ
bool operator==(const Status& rhs) const {
return (code_ == rhs.getCode()) && (message_ == rhs.getMessage());
}
// Enables use of gtest (ASSERT|EXPECT)_NE
bool operator!=(const Status& rhs) const {
return !operator==(rhs);
}
// Enables pretty-printing in gtest (ASSERT|EXPECT)_(EQ|NE)
friend ::std::ostream& operator<<(::std::ostream& os, const Status& s);
2014-08-15 07:25:30 +00:00
private:
2014-09-15 20:23:28 +00:00
/// the internal storage of the status code
2014-08-15 07:25:30 +00:00
int code_;
2014-09-15 20:23:28 +00:00
/// the internal storage of the status message
2014-08-15 07:25:30 +00:00
std::string message_;
};
::std::ostream& operator<<(::std::ostream& os, const Status& s);
template <typename ToType, typename ValueType, typename ErrorCodeEnumType>
inline
typename std::enable_if<std::is_same<ToType, Status>::value, Status>::type
to(const Expected<ValueType, ErrorCodeEnumType>& expected) {
return expected
? Status::success()
: Status::failure(expected.getError().getFullMessageRecursive());
}
} // namespace osquery