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 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. 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