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