30#if FMT_VERSION < 80000
54 kLongExpression =
'E',
62 kPrettyFunction =
'F',
66 kShortExpression =
'e',
83 StackTraceEntry(std::string file,
size_t line, std::string pretty_function,
84 std::string function);
86 StackTraceEntry(std::string file,
size_t line, std::string pretty_function,
87 std::string function, std::string expression);
97 message_ << std::forward<T>(message_ext);
100 template <
typename T>
102 message_ << std::forward<T>(message_ext);
103 return std::move(*
this);
107 template <
typename T>
119 fmt::format_context::iterator
format(
120 fmt::format_context& ctx,
const std::vector<FormatSpecifier>& specifiers,
121 std::optional<int> index)
const;
134#define CF_STACK_TRACE_ENTRY(expression) \
135 StackTraceEntry(__FILE__, __LINE__, __PRETTY_FUNCTION__, __func__, expression)
150 constexpr auto parse(format_parse_context& ctx)
151 -> format_parse_context::iterator {
152 auto it = ctx.begin();
153 while (it != ctx.end() && *it !=
'}') {
156 fmt_specs_.push_back(specifier);
158 }
else if (*it ==
'V') {
159 for (
const auto& specifier :
161 fmt_specs_.push_back(specifier);
164 fmt_specs_.push_back(
173 format_context& ctx)
const -> format_context::iterator {
174 return entry.format(ctx, fmt_specs_, std::nullopt);
178 std::vector<cuttlefish::StackTraceEntry::FormatSpecifier>
fmt_specs_;
186 stack_.emplace_back(std::move(entry));
190 stack_.emplace_back(std::move(entry));
191 return std::move(*
this);
193 const std::vector<StackTraceEntry>&
Stack()
const {
return stack_; }
205 template <
typename T>
240 constexpr auto parse(format_parse_context& ctx)
241 -> format_parse_context::iterator {
242 auto it = ctx.begin();
243 while (it != ctx.end() && *it !=
'}') {
245 for (
const auto& spec : StackTraceEntry::kVerbose) {
246 (has_inner_fmt_spec_ ? inner_fmt_specs_ : fmt_specs_).push_back(spec);
248 }
else if (*it ==
'V') {
249 for (
const auto& spec : StackTraceEntry::kVeryVerbose) {
250 (has_inner_fmt_spec_ ? inner_fmt_specs_ : fmt_specs_).push_back(spec);
252 }
else if (*it ==
'/') {
253 has_inner_fmt_spec_ =
true;
254 }
else if (*it ==
'^') {
255 inner_to_outer_ =
true;
257 (has_inner_fmt_spec_ ? inner_fmt_specs_ : fmt_specs_)
266 format_context& ctx)
const;
272 bool inner_to_outer_ =
false;
273 bool has_inner_fmt_spec_ =
false;
301#define CF_ERR(MSG) (CF_STACK_TRACE_ENTRY("") << MSG)
302#define CF_ERRNO(MSG) (CF_STACK_TRACE_ENTRY("") << MSG)
303#define CF_ERRF(MSG, ...) \
304 (CF_STACK_TRACE_ENTRY("") << fmt::format(FMT_STRING(MSG), __VA_ARGS__))
308 return std::move(*value);
314 if constexpr (std::is_void<T>::value) {
317 return std::move(*result);
322typename std::enable_if<std::is_convertible_v<T, bool>, T>
::type
324 return std::forward<T>(value);
331 return value.has_value();
353 return value.
error();
358 return value.error();
361#define CF_EXPECT_OVERLOAD(_1, _2, NAME, ...) NAME
363#define CF_EXPECT2(RESULT, MSG) \
365 decltype(RESULT)&& macro_intermediate_result = RESULT; \
366 if (!TypeIsSuccess(macro_intermediate_result)) { \
367 auto current_entry = CF_STACK_TRACE_ENTRY(#RESULT); \
368 current_entry << MSG; \
369 auto error = ErrorFromType(macro_intermediate_result); \
370 error.PushEntry(std::move(current_entry)); \
371 return std::move(error); \
373 OutcomeDereference(std::move(macro_intermediate_result)); \
376#define CF_EXPECT1(RESULT) CF_EXPECT2(RESULT, "")
414#define CF_EXPECT(...) \
415 CF_EXPECT_OVERLOAD(__VA_ARGS__, CF_EXPECT2, CF_EXPECT1)(__VA_ARGS__)
417#define CF_EXPECTF(RESULT, MSG, ...) \
418 CF_EXPECT(RESULT, fmt::format(FMT_STRING(MSG), __VA_ARGS__))
420#define CF_COMPARE_EXPECT4(COMPARE_OP, LHS_RESULT, RHS_RESULT, MSG) \
422 auto&& lhs_macro_intermediate_result = LHS_RESULT; \
423 auto&& rhs_macro_intermediate_result = RHS_RESULT; \
424 bool comparison_result = lhs_macro_intermediate_result COMPARE_OP \
425 rhs_macro_intermediate_result; \
426 if (!comparison_result) { \
427 auto current_entry = CF_STACK_TRACE_ENTRY(""); \
428 current_entry << "Expected \"" << #LHS_RESULT << "\" " << #COMPARE_OP \
429 << " \"" << #RHS_RESULT << "\" but was " \
430 << lhs_macro_intermediate_result << " vs " \
431 << rhs_macro_intermediate_result << ". "; \
432 current_entry << MSG; \
433 auto error = ErrorFromType(false); \
434 error.PushEntry(std::move(current_entry)); \
435 return std::move(error); \
440#define CF_COMPARE_EXPECT3(COMPARE_OP, LHS_RESULT, RHS_RESULT) \
441 CF_COMPARE_EXPECT4(COMPARE_OP, LHS_RESULT, RHS_RESULT, "")
443#define CF_COMPARE_EXPECT_OVERLOAD(_1, _2, _3, _4, NAME, ...) NAME
445#define CF_COMPARE_EXPECT(...) \
446 CF_COMPARE_EXPECT_OVERLOAD(__VA_ARGS__, CF_COMPARE_EXPECT4, \
447 CF_COMPARE_EXPECT3) \
450#define CF_EXPECT_EQ(LHS_RESULT, RHS_RESULT, ...) \
451 CF_COMPARE_EXPECT(==, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
452#define CF_EXPECT_NE(LHS_RESULT, RHS_RESULT, ...) \
453 CF_COMPARE_EXPECT(!=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
454#define CF_EXPECT_LE(LHS_RESULT, RHS_RESULT, ...) \
455 CF_COMPARE_EXPECT(<=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
456#define CF_EXPECT_LT(LHS_RESULT, RHS_RESULT, ...) \
457 CF_COMPARE_EXPECT(<, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
458#define CF_EXPECT_GE(LHS_RESULT, RHS_RESULT, ...) \
459 CF_COMPARE_EXPECT(>=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
460#define CF_EXPECT_GT(LHS_RESULT, RHS_RESULT, ...) \
461 CF_COMPARE_EXPECT(>, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
Definition: expected.h:86
constexpr const E & error() const &
Definition: expected.h:341
constexpr bool ok() const noexcept
Definition: expected.h:334
static constexpr auto kVeryVerbose
Definition: result.h:76
std::string pretty_function_
Definition: result.h:126
static constexpr auto kVerbose
Definition: result.h:70
StackTraceEntry & operator=(const StackTraceEntry &other)
Definition: result.cpp:55
StackTraceEntry operator<<(T &&message_ext) &&
Definition: result.h:101
size_t line_
Definition: result.h:125
std::stringstream message_
Definition: result.h:129
FormatSpecifier
Definition: result.h:46
std::string file_
Definition: result.h:124
bool HasMessage() const
Definition: result.cpp:65
StackTraceEntry & operator=(StackTraceEntry &&)=default
StackTraceEntry(std::string file, size_t line, std::string pretty_function, std::string function)
Definition: result.cpp:30
std::string expression_
Definition: result.h:128
fmt::format_context::iterator format(fmt::format_context &ctx, const std::vector< FormatSpecifier > &specifiers, std::optional< int > index) const
Definition: result.cpp:74
std::string function_
Definition: result.h:127
StackTraceEntry(StackTraceEntry &&)=default
StackTraceEntry & operator<<(T &&message_ext) &
Definition: result.h:96
std::string Message() const
Definition: result.h:195
std::vector< StackTraceEntry > stack_
Definition: result.h:211
const std::vector< StackTraceEntry > & Stack() const
Definition: result.h:193
std::string Trace() const
Definition: result.h:199
StackTraceError PushEntry(StackTraceEntry entry) &&
Definition: result.h:189
std::string FormatForEnv(bool color=(isatty(STDERR_FILENO)==1)) const
Definition: result.h:201
StackTraceError & PushEntry(StackTraceEntry entry) &
Definition: result.h:185
#define error(format, args...)
Definition: fec_private.h:201
unexpected(E) -> unexpected< E >
EventFormat format
Definition: kernel_log_server.cc:57
Definition: alloc_utils.cpp:23
std::string ResultErrorFormat(bool color)
Definition: result.cpp:202
T OutcomeDereference(std::optional< T > &&value)
Definition: result.h:307
auto ErrorFromType(bool)
Definition: result.h:344
bool TypeIsSuccess(bool value)
Definition: result.h:327
const T & runtime(const T ¶m)
Definition: result.h:34
uint8_t type
Definition: pairing_connection.h:0
auto format(const cuttlefish::StackTraceEntry &entry, format_context &ctx) const -> format_context::iterator
Definition: result.h:172
constexpr auto parse(format_parse_context &ctx) -> format_parse_context::iterator
Definition: result.h:150
std::vector< cuttlefish::StackTraceEntry::FormatSpecifier > fmt_specs_
Definition: result.h:178
#define isatty
Definition: sysdeps.h:594