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