1 //===-- PrintfMatcher.cpp ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PrintfMatcher.h"
10 #include "src/stdio/printf_core/core_structs.h"
11 
12 #include "utils/UnitTest/StringUtils.h"
13 
14 #include <stdint.h>
15 
16 namespace __llvm_libc {
17 namespace printf_core {
18 namespace testing {
19 
20 bool FormatSectionMatcher::match(FormatSection actualValue) {
21   actual = actualValue;
22   return expected == actual;
23 }
24 
25 namespace {
26 
27 #define IF_FLAG_SHOW_FLAG(flag_name)                                           \
28   do {                                                                         \
29     if ((form.flags & FormatFlags::flag_name) == FormatFlags::flag_name)       \
30       stream << "\n\t\t" << #flag_name;                                        \
31   } while (false)
32 #define CASE_LM(lm)                                                            \
33   case (LengthModifier::lm):                                                   \
34     stream << #lm;                                                             \
35     break
36 
37 void display(testutils::StreamWrapper &stream, FormatSection form) {
38   stream << "Raw String (len " << form.raw_len << "): \"";
39   for (size_t i = 0; i < form.raw_len; ++i) {
40     stream << form.raw_string[i];
41   }
42   stream << "\"";
43   if (form.has_conv) {
44     stream << "\n\tHas Conv\n\tFlags:";
45     IF_FLAG_SHOW_FLAG(LEFT_JUSTIFIED);
46     IF_FLAG_SHOW_FLAG(FORCE_SIGN);
47     IF_FLAG_SHOW_FLAG(SPACE_PREFIX);
48     IF_FLAG_SHOW_FLAG(ALTERNATE_FORM);
49     IF_FLAG_SHOW_FLAG(LEADING_ZEROES);
50     stream << "\n";
51     stream << "\tmin width: " << form.min_width << "\n";
52     stream << "\tprecision: " << form.precision << "\n";
53     stream << "\tlength modifier: ";
54     switch (form.length_modifier) {
55       CASE_LM(none);
56       CASE_LM(l);
57       CASE_LM(ll);
58       CASE_LM(h);
59       CASE_LM(hh);
60       CASE_LM(j);
61       CASE_LM(z);
62       CASE_LM(t);
63       CASE_LM(L);
64     }
65     stream << "\n";
66     stream << "\tconversion name: " << form.conv_name << "\n";
67     if (form.conv_name == 'p' || form.conv_name == 'n' || form.conv_name == 's')
68       stream << "\tpointer value: "
69              << int_to_hex<uintptr_t>(
70                     reinterpret_cast<uintptr_t>(form.conv_val_ptr))
71              << "\n";
72     else if (form.conv_name != '%')
73       stream << "\tvalue: " << int_to_hex<__uint128_t>(form.conv_val_raw)
74              << "\n";
75   }
76 }
77 } // anonymous namespace
78 
79 void FormatSectionMatcher::explainError(testutils::StreamWrapper &stream) {
80   stream << "expected format section: ";
81   display(stream, expected);
82   stream << '\n';
83   stream << "actual format section  : ";
84   display(stream, actual);
85   stream << '\n';
86 }
87 
88 } // namespace testing
89 } // namespace printf_core
90 } // namespace __llvm_libc
91