1 //===-- String type specifier converters for scanf --------------*- C++ -*-===//
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
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/__support/macros/config.h"
14 #include "src/stdio/scanf_core/core_structs.h"
15 #include "src/stdio/scanf_core/reader.h"
19 namespace LIBC_NAMESPACE_DECL
{
20 namespace scanf_core
{
22 int convert_string(Reader
*reader
, const FormatSection
&to_conv
) {
23 // %s "Matches a sequence of non-white-space characters"
25 // %c "Matches a sequence of characters of exactly the number specified by the
26 // field width (1 if no field width is present in the directive)"
28 // %[ "Matches a nonempty sequence of characters from a set of expected
29 // characters (the scanset)."
31 if (to_conv
.max_width
> 0) {
32 max_width
= to_conv
.max_width
;
34 if (to_conv
.conv_name
== 'c') {
37 max_width
= cpp::numeric_limits
<size_t>::max();
41 char *output
= reinterpret_cast<char *>(to_conv
.output_ptr
);
43 char cur_char
= reader
->getc();
45 for (; i
< max_width
&& cur_char
!= '\0'; ++i
) {
46 // If this is %s and we've hit a space, or if this is %[] and we've found
47 // something not in the scanset.
48 if ((to_conv
.conv_name
== 's' && internal::isspace(cur_char
)) ||
49 (to_conv
.conv_name
== '[' && !to_conv
.scan_set
.test(cur_char
))) {
52 // if the NO_WRITE flag is not set, write to the output.
53 if ((to_conv
.flags
& NO_WRITE
) == 0)
55 cur_char
= reader
->getc();
58 // We always read one more character than will be used, so we have to put the
60 reader
->ungetc(cur_char
);
62 // If this is %s or %[]
63 if (to_conv
.conv_name
!= 'c' && (to_conv
.flags
& NO_WRITE
) == 0) {
64 // Always null terminate the string. This may cause a write to the
65 // (max_width + 1) byte, which is correct. The max width describes the max
66 // number of characters read from the input string, and doesn't necessarily
67 // correspond to the output.
72 return MATCHING_FAILURE
;
76 } // namespace scanf_core
77 } // namespace LIBC_NAMESPACE_DECL