Warning: This file is not a C or C++ file. It does not have highlighting.

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//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_STRING_CONVERTER_H
10#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_STRING_CONVERTER_H
11
12#include "src/__support/CPP/limits.h"
13#include "src/__support/ctype_utils.h"
14#include "src/__support/macros/config.h"
15#include "src/stdio/scanf_core/core_structs.h"
16#include "src/stdio/scanf_core/reader.h"
17
18#include <stddef.h>
19
20namespace LIBC_NAMESPACE_DECL {
21namespace scanf_core {
22
23template <typename T>
24int convert_string(Reader<T> *reader, const FormatSection &to_conv) {
25 // %s "Matches a sequence of non-white-space characters"
26
27 // %c "Matches a sequence of characters of exactly the number specified by the
28 // field width (1 if no field width is present in the directive)"
29
30 // %[ "Matches a nonempty sequence of characters from a set of expected
31 // characters (the scanset)."
32 size_t max_width = 0;
33 if (to_conv.max_width > 0) {
34 max_width = to_conv.max_width;
35 } else {
36 if (to_conv.conv_name == 'c') {
37 max_width = 1;
38 } else {
39 max_width = cpp::numeric_limits<size_t>::max();
40 }
41 }
42
43 char *output = reinterpret_cast<char *>(to_conv.output_ptr);
44
45 char cur_char = reader->getc();
46 size_t i = 0;
47 for (; i < max_width && cur_char != '\0'; ++i) {
48 // If this is %s and we've hit a space, or if this is %[] and we've found
49 // something not in the scanset.
50 if ((to_conv.conv_name == 's' && internal::isspace(cur_char)) ||
51 (to_conv.conv_name == '[' && !to_conv.scan_set.test(cur_char))) {
52 break;
53 }
54 // if the NO_WRITE flag is not set, write to the output.
55 if ((to_conv.flags & NO_WRITE) == 0)
56 output[i] = cur_char;
57 cur_char = reader->getc();
58 }
59
60 // We always read one more character than will be used, so we have to put the
61 // last one back.
62 reader->ungetc(cur_char);
63
64 // If this is %s or %[]
65 if (to_conv.conv_name != 'c' && (to_conv.flags & NO_WRITE) == 0) {
66 // Always null terminate the string. This may cause a write to the
67 // (max_width + 1) byte, which is correct. The max width describes the max
68 // number of characters read from the input string, and doesn't necessarily
69 // correspond to the output.
70 output[i] = '\0';
71 }
72
73 if (i == 0)
74 return MATCHING_FAILURE;
75 return READ_OK;
76}
77
78} // namespace scanf_core
79} // namespace LIBC_NAMESPACE_DECL
80
81#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_STRING_CONVERTER_H
82

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of libc/src/stdio/scanf_core/string_converter.h