Check Errorf()/ErrnoErrorf() format string at compile time
fmtlib provides compile time checking of format strings that we're not currently using. This change makes Errorf() and ErrnoErrorf() into macros such that we can take advantage of this capability. Test: build successfully normally Test: fail the build if using an invalid format string Change-Id: Icb8ba8cb973bbd1fa4755a62e7598bdbb0113757
This commit is contained in:
parent
c19b08a66a
commit
f8e6bf6d81
3 changed files with 17 additions and 11 deletions
|
@ -156,11 +156,11 @@ class Error {
|
|||
Error& operator=(const Error&) = delete;
|
||||
Error& operator=(Error&&) = delete;
|
||||
|
||||
template <typename... Args>
|
||||
friend Error Errorf(const char* fmt, const Args&... args);
|
||||
template <typename T, typename... Args>
|
||||
friend Error ErrorfImpl(const T&& fmt, const Args&... args);
|
||||
|
||||
template <typename... Args>
|
||||
friend Error ErrnoErrorf(const char* fmt, const Args&... args);
|
||||
template <typename T, typename... Args>
|
||||
friend Error ErrnoErrorfImpl(const T&& fmt, const Args&... args);
|
||||
|
||||
private:
|
||||
Error(bool append_errno, int errno_to_append, const std::string& message)
|
||||
|
@ -191,16 +191,24 @@ inline int ErrorCode(int code, T&& t, const Args&... args) {
|
|||
return ErrorCode(code, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline Error Errorf(const char* fmt, const Args&... args) {
|
||||
// TODO(tomcherry): Remove this once we've removed all `using android::base::Errorf` and `using
|
||||
// android::base::ErrnoErrorf` lines.
|
||||
enum Errorf {};
|
||||
enum ErrnoErrorf {};
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline Error ErrorfImpl(const T&& fmt, const Args&... args) {
|
||||
return Error(false, ErrorCode(0, args...), fmt::format(fmt, args...));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline Error ErrnoErrorf(const char* fmt, const Args&... args) {
|
||||
template <typename T, typename... Args>
|
||||
inline Error ErrnoErrorfImpl(const T&& fmt, const Args&... args) {
|
||||
return Error(true, errno, fmt::format(fmt, args...));
|
||||
}
|
||||
|
||||
#define Errorf(fmt, ...) android::base::ErrorfImpl(FMT_STRING(fmt), ##__VA_ARGS__)
|
||||
#define ErrnoErrorf(fmt, ...) android::base::ErrnoErrorfImpl(FMT_STRING(fmt), ##__VA_ARGS__)
|
||||
|
||||
template <typename T>
|
||||
using Result = android::base::expected<T, ResultError>;
|
||||
|
||||
|
|
|
@ -362,7 +362,7 @@ TEST(result, error_with_fmt) {
|
|||
result = Errorf("{} {}!", std::string("hello"), std::string("world"));
|
||||
EXPECT_EQ("hello world!", result.error().message());
|
||||
|
||||
result = Errorf("{h} {w}!", fmt::arg("w", "world"), fmt::arg("h", "hello"));
|
||||
result = Errorf("{1} {0}!", "world", "hello");
|
||||
EXPECT_EQ("hello world!", result.error().message());
|
||||
|
||||
result = Errorf("hello world!");
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
#include <android-base/result.h>
|
||||
|
||||
using android::base::ErrnoError;
|
||||
using android::base::ErrnoErrorf;
|
||||
using android::base::Error;
|
||||
using android::base::Errorf;
|
||||
using android::base::Result;
|
||||
using android::base::ResultError;
|
||||
|
|
Loading…
Reference in a new issue