Files
clang-p2996/libc/utils/UnitTest/ScanfMatcher.cpp
Michael Jones 7a129f0756 [libc] add scanf parser and core utilities
This is the first piece of scanf. It's very similar in design to printf,
and so much of the code is copied from that. There were potential issues
with conflicting macros so I've also renamed the "ASSERT_FORMAT_EQ"
macro for printf to "ASSERT_PFORMAT_EQ".

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D136288
2022-10-28 10:52:51 -07:00

100 lines
3.0 KiB
C++

//===-- ScanfMatcher.cpp ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "ScanfMatcher.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/stdio/scanf_core/core_structs.h"
#include "utils/UnitTest/StringUtils.h"
#include <stdint.h>
namespace __llvm_libc {
namespace scanf_core {
namespace testing {
bool FormatSectionMatcher::match(FormatSection actualValue) {
actual = actualValue;
return expected == actual;
}
namespace {
#define IF_FLAG_SHOW_FLAG(flag_name) \
do { \
if ((form.flags & FormatFlags::flag_name) == FormatFlags::flag_name) \
stream << "\n\t\t" << #flag_name; \
} while (false)
#define CASE_LM(lm) \
case (LengthModifier::lm): \
stream << #lm; \
break
void display(testutils::StreamWrapper &stream, FormatSection form) {
stream << "Raw String (len " << form.raw_string.size() << "): \"";
for (size_t i = 0; i < form.raw_string.size(); ++i) {
stream << form.raw_string[i];
}
stream << "\"";
if (form.has_conv) {
stream << "\n\tHas Conv\n\tFlags:";
IF_FLAG_SHOW_FLAG(NO_WRITE);
IF_FLAG_SHOW_FLAG(ALLOCATE);
stream << "\n";
stream << "\tmax width: " << form.max_width << "\n";
stream << "\tlength modifier: ";
switch (form.length_modifier) {
CASE_LM(NONE);
CASE_LM(l);
CASE_LM(ll);
CASE_LM(h);
CASE_LM(hh);
CASE_LM(j);
CASE_LM(z);
CASE_LM(t);
CASE_LM(L);
}
stream << "\n";
// If the pointer is used (NO_WRITE is not set and the conversion isn't %).
if (((form.flags & FormatFlags::NO_WRITE) == 0) &&
(form.conv_name != '%')) {
stream << "\tpointer value: "
<< int_to_hex<uintptr_t>(
reinterpret_cast<uintptr_t>(form.output_ptr))
<< "\n";
}
stream << "\tconversion name: " << form.conv_name << "\n";
if (form.conv_name == '[') {
stream << "\t\t";
for (size_t i = 0; i < 256 /* char max */; ++i) {
if (form.scan_set.test(i)) {
stream << static_cast<char>(i);
}
}
stream << "\n\t]\n";
}
}
}
} // anonymous namespace
void FormatSectionMatcher::explainError(testutils::StreamWrapper &stream) {
stream << "expected format section: ";
display(stream, expected);
stream << '\n';
stream << "actual format section : ";
display(stream, actual);
stream << '\n';
}
} // namespace testing
} // namespace scanf_core
} // namespace __llvm_libc