1 //===-- Format specifier converter implmentation 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 #include "src/stdio/scanf_core/converter.h"
10
11 #include "src/__support/ctype_utils.h"
12 #include "src/__support/macros/config.h"
13 #include "src/stdio/scanf_core/core_structs.h"
14 #include "src/stdio/scanf_core/reader.h"
15
16 #ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
17 #include "src/stdio/scanf_core/float_converter.h"
18 #endif // LIBC_COPT_SCANF_DISABLE_FLOAT
19 #include "src/stdio/scanf_core/current_pos_converter.h"
20 #include "src/stdio/scanf_core/int_converter.h"
21 #include "src/stdio/scanf_core/ptr_converter.h"
22 #include "src/stdio/scanf_core/string_converter.h"
23
24 #include <stddef.h>
25
26 namespace LIBC_NAMESPACE_DECL {
27 namespace scanf_core {
28
convert(Reader * reader,const FormatSection & to_conv)29 int convert(Reader *reader, const FormatSection &to_conv) {
30 int ret_val = 0;
31 switch (to_conv.conv_name) {
32 case '%':
33 return raw_match(reader, "%");
34 case 's':
35 ret_val = raw_match(reader, " ");
36 if (ret_val != READ_OK)
37 return ret_val;
38 return convert_string(reader, to_conv);
39 case 'c':
40 case '[':
41 return convert_string(reader, to_conv);
42 case 'd':
43 case 'i':
44 case 'u':
45 case 'o':
46 case 'x':
47 case 'X':
48 ret_val = raw_match(reader, " ");
49 if (ret_val != READ_OK)
50 return ret_val;
51 return convert_int(reader, to_conv);
52 #ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
53 case 'f':
54 case 'F':
55 case 'e':
56 case 'E':
57 case 'a':
58 case 'A':
59 case 'g':
60 case 'G':
61 ret_val = raw_match(reader, " ");
62 if (ret_val != READ_OK)
63 return ret_val;
64 return convert_float(reader, to_conv);
65 #endif // LIBC_COPT_SCANF_DISABLE_FLOAT
66 case 'n':
67 return convert_current_pos(reader, to_conv);
68 case 'p':
69 ret_val = raw_match(reader, " ");
70 if (ret_val != READ_OK)
71 return ret_val;
72 return convert_pointer(reader, to_conv);
73 default:
74 return raw_match(reader, to_conv.raw_string);
75 }
76 return -1;
77 }
78
79 // raw_string is assumed to have a positive size.
raw_match(Reader * reader,cpp::string_view raw_string)80 int raw_match(Reader *reader, cpp::string_view raw_string) {
81 char cur_char = reader->getc();
82 int ret_val = READ_OK;
83 for (size_t i = 0; i < raw_string.size(); ++i) {
84 // Any space character matches any number of space characters.
85 if (internal::isspace(raw_string[i])) {
86 while (internal::isspace(cur_char)) {
87 cur_char = reader->getc();
88 }
89 } else {
90 if (raw_string[i] == cur_char) {
91 cur_char = reader->getc();
92 } else {
93 ret_val = MATCHING_FAILURE;
94 break;
95 }
96 }
97 }
98 reader->ungetc(cur_char);
99 return ret_val;
100 }
101
102 } // namespace scanf_core
103 } // namespace LIBC_NAMESPACE_DECL
104