Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libc / src / stdio / scanf_core / string_converter.cpp
blob94a7fc4e5fe0d3d369311181c11e2c5d569084ad
1 //===-- String type specifier converters for scanf --------------*- 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 //===----------------------------------------------------------------------===//
9 #include "src/stdio/scanf_core/string_converter.h"
11 #include "src/__support/CPP/limits.h"
12 #include "src/__support/ctype_utils.h"
13 #include "src/stdio/scanf_core/core_structs.h"
14 #include "src/stdio/scanf_core/reader.h"
16 #include <stddef.h>
18 namespace LIBC_NAMESPACE {
19 namespace scanf_core {
21 int convert_string(Reader *reader, const FormatSection &to_conv) {
22 // %s "Matches a sequence of non-white-space characters"
24 // %c "Matches a sequence of characters of exactly the number specified by the
25 // field width (1 if no field width is present in the directive)"
27 // %[ "Matches a nonempty sequence of characters from a set of expected
28 // characters (the scanset)."
29 size_t max_width = 0;
30 if (to_conv.max_width > 0) {
31 max_width = to_conv.max_width;
32 } else {
33 if (to_conv.conv_name == 'c') {
34 max_width = 1;
35 } else {
36 max_width = cpp::numeric_limits<size_t>::max();
40 char *output = reinterpret_cast<char *>(to_conv.output_ptr);
42 char cur_char = reader->getc();
43 size_t i = 0;
44 for (; i < max_width && cur_char != '\0'; ++i) {
45 // If this is %s and we've hit a space, or if this is %[] and we've found
46 // something not in the scanset.
47 if ((to_conv.conv_name == 's' && internal::isspace(cur_char)) ||
48 (to_conv.conv_name == '[' && !to_conv.scan_set.test(cur_char))) {
49 break;
51 // if the NO_WRITE flag is not set, write to the output.
52 if ((to_conv.flags & NO_WRITE) == 0)
53 output[i] = cur_char;
54 cur_char = reader->getc();
57 // We always read one more character than will be used, so we have to put the
58 // last one back.
59 reader->ungetc(cur_char);
61 // If this is %s or %[]
62 if (to_conv.conv_name != 'c' && (to_conv.flags & NO_WRITE) == 0) {
63 // Always null terminate the string. This may cause a write to the
64 // (max_width + 1) byte, which is correct. The max width describes the max
65 // number of characters read from the input string, and doesn't necessarily
66 // correspond to the output.
67 output[i] = '\0';
70 if (i == 0)
71 return MATCHING_FAILURE;
72 return READ_OK;
75 } // namespace scanf_core
76 } // namespace LIBC_NAMESPACE