xref: /llvm-project/libc/src/stdio/scanf_core/converter.cpp (revision 5ff3ff33ff930e4ec49da7910612d8a41eb068cb)
11c40d5ecSMichael Jones //===-- Format specifier converter implmentation for scanf -----*- C++ -*-===//
21c40d5ecSMichael Jones //
31c40d5ecSMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41c40d5ecSMichael Jones // See https://llvm.org/LICENSE.txt for license information.
51c40d5ecSMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61c40d5ecSMichael Jones //
71c40d5ecSMichael Jones //===----------------------------------------------------------------------===//
81c40d5ecSMichael Jones 
91c40d5ecSMichael Jones #include "src/stdio/scanf_core/converter.h"
101c40d5ecSMichael Jones 
111c40d5ecSMichael Jones #include "src/__support/ctype_utils.h"
12*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
131c40d5ecSMichael Jones #include "src/stdio/scanf_core/core_structs.h"
141c40d5ecSMichael Jones #include "src/stdio/scanf_core/reader.h"
151c40d5ecSMichael Jones 
16c3228714SGuillaume Chatelet #ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
179a32e539SMichael Jones #include "src/stdio/scanf_core/float_converter.h"
18c3228714SGuillaume Chatelet #endif // LIBC_COPT_SCANF_DISABLE_FLOAT
19afa764c9SMichael Jones #include "src/stdio/scanf_core/current_pos_converter.h"
2065f4cc63SMichael Jones #include "src/stdio/scanf_core/int_converter.h"
21edf964e0SMichael Jones #include "src/stdio/scanf_core/ptr_converter.h"
221c40d5ecSMichael Jones #include "src/stdio/scanf_core/string_converter.h"
231c40d5ecSMichael Jones 
241c40d5ecSMichael Jones #include <stddef.h>
251c40d5ecSMichael Jones 
26*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
271c40d5ecSMichael Jones namespace scanf_core {
281c40d5ecSMichael Jones 
291c40d5ecSMichael Jones int convert(Reader *reader, const FormatSection &to_conv) {
301c40d5ecSMichael Jones   int ret_val = 0;
311c40d5ecSMichael Jones   switch (to_conv.conv_name) {
321c40d5ecSMichael Jones   case '%':
331c40d5ecSMichael Jones     return raw_match(reader, "%");
341c40d5ecSMichael Jones   case 's':
351c40d5ecSMichael Jones     ret_val = raw_match(reader, " ");
361c40d5ecSMichael Jones     if (ret_val != READ_OK)
371c40d5ecSMichael Jones       return ret_val;
381c40d5ecSMichael Jones     return convert_string(reader, to_conv);
391c40d5ecSMichael Jones   case 'c':
401c40d5ecSMichael Jones   case '[':
411c40d5ecSMichael Jones     return convert_string(reader, to_conv);
4265f4cc63SMichael Jones   case 'd':
4365f4cc63SMichael Jones   case 'i':
4465f4cc63SMichael Jones   case 'u':
4565f4cc63SMichael Jones   case 'o':
4665f4cc63SMichael Jones   case 'x':
4765f4cc63SMichael Jones   case 'X':
4865f4cc63SMichael Jones     ret_val = raw_match(reader, " ");
4965f4cc63SMichael Jones     if (ret_val != READ_OK)
5065f4cc63SMichael Jones       return ret_val;
5165f4cc63SMichael Jones     return convert_int(reader, to_conv);
52c3228714SGuillaume Chatelet #ifndef LIBC_COPT_SCANF_DISABLE_FLOAT
539a32e539SMichael Jones   case 'f':
549a32e539SMichael Jones   case 'F':
559a32e539SMichael Jones   case 'e':
569a32e539SMichael Jones   case 'E':
579a32e539SMichael Jones   case 'a':
589a32e539SMichael Jones   case 'A':
599a32e539SMichael Jones   case 'g':
609a32e539SMichael Jones   case 'G':
619a32e539SMichael Jones     ret_val = raw_match(reader, " ");
629a32e539SMichael Jones     if (ret_val != READ_OK)
639a32e539SMichael Jones       return ret_val;
649a32e539SMichael Jones     return convert_float(reader, to_conv);
65c3228714SGuillaume Chatelet #endif // LIBC_COPT_SCANF_DISABLE_FLOAT
66afa764c9SMichael Jones   case 'n':
67afa764c9SMichael Jones     return convert_current_pos(reader, to_conv);
68edf964e0SMichael Jones   case 'p':
69edf964e0SMichael Jones     ret_val = raw_match(reader, " ");
70edf964e0SMichael Jones     if (ret_val != READ_OK)
71edf964e0SMichael Jones       return ret_val;
72edf964e0SMichael Jones     return convert_pointer(reader, to_conv);
731c40d5ecSMichael Jones   default:
741c40d5ecSMichael Jones     return raw_match(reader, to_conv.raw_string);
751c40d5ecSMichael Jones   }
761c40d5ecSMichael Jones   return -1;
771c40d5ecSMichael Jones }
781c40d5ecSMichael Jones 
791c40d5ecSMichael Jones // raw_string is assumed to have a positive size.
801c40d5ecSMichael Jones int raw_match(Reader *reader, cpp::string_view raw_string) {
811c40d5ecSMichael Jones   char cur_char = reader->getc();
821c40d5ecSMichael Jones   int ret_val = READ_OK;
831c40d5ecSMichael Jones   for (size_t i = 0; i < raw_string.size(); ++i) {
841c40d5ecSMichael Jones     // Any space character matches any number of space characters.
851c40d5ecSMichael Jones     if (internal::isspace(raw_string[i])) {
861c40d5ecSMichael Jones       while (internal::isspace(cur_char)) {
871c40d5ecSMichael Jones         cur_char = reader->getc();
881c40d5ecSMichael Jones       }
891c40d5ecSMichael Jones     } else {
901c40d5ecSMichael Jones       if (raw_string[i] == cur_char) {
911c40d5ecSMichael Jones         cur_char = reader->getc();
921c40d5ecSMichael Jones       } else {
931c40d5ecSMichael Jones         ret_val = MATCHING_FAILURE;
941c40d5ecSMichael Jones         break;
951c40d5ecSMichael Jones       }
961c40d5ecSMichael Jones     }
971c40d5ecSMichael Jones   }
981c40d5ecSMichael Jones   reader->ungetc(cur_char);
991c40d5ecSMichael Jones   return ret_val;
1001c40d5ecSMichael Jones }
1011c40d5ecSMichael Jones 
1021c40d5ecSMichael Jones } // namespace scanf_core
103*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
104