xref: /aosp_15_r20/external/llvm-libc/src/stdio/scanf_core/converter.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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