//===-- Format specifier converter implmentation for scanf -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "src/stdio/scanf_core/converter.h" #include "src/__support/ctype_utils.h" #include "src/__support/macros/config.h" #include "src/stdio/scanf_core/core_structs.h" #include "src/stdio/scanf_core/reader.h" #ifndef LIBC_COPT_SCANF_DISABLE_FLOAT #include "src/stdio/scanf_core/float_converter.h" #endif // LIBC_COPT_SCANF_DISABLE_FLOAT #include "src/stdio/scanf_core/current_pos_converter.h" #include "src/stdio/scanf_core/int_converter.h" #include "src/stdio/scanf_core/ptr_converter.h" #include "src/stdio/scanf_core/string_converter.h" #include namespace LIBC_NAMESPACE_DECL { namespace scanf_core { int convert(Reader *reader, const FormatSection &to_conv) { int ret_val = 0; switch (to_conv.conv_name) { case '%': return raw_match(reader, "%"); case 's': ret_val = raw_match(reader, " "); if (ret_val != READ_OK) return ret_val; return convert_string(reader, to_conv); case 'c': case '[': return convert_string(reader, to_conv); case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': ret_val = raw_match(reader, " "); if (ret_val != READ_OK) return ret_val; return convert_int(reader, to_conv); #ifndef LIBC_COPT_SCANF_DISABLE_FLOAT case 'f': case 'F': case 'e': case 'E': case 'a': case 'A': case 'g': case 'G': ret_val = raw_match(reader, " "); if (ret_val != READ_OK) return ret_val; return convert_float(reader, to_conv); #endif // LIBC_COPT_SCANF_DISABLE_FLOAT case 'n': return convert_current_pos(reader, to_conv); case 'p': ret_val = raw_match(reader, " "); if (ret_val != READ_OK) return ret_val; return convert_pointer(reader, to_conv); default: return raw_match(reader, to_conv.raw_string); } return -1; } // raw_string is assumed to have a positive size. int raw_match(Reader *reader, cpp::string_view raw_string) { char cur_char = reader->getc(); int ret_val = READ_OK; for (size_t i = 0; i < raw_string.size(); ++i) { // Any space character matches any number of space characters. if (internal::isspace(raw_string[i])) { while (internal::isspace(cur_char)) { cur_char = reader->getc(); } } else { if (raw_string[i] == cur_char) { cur_char = reader->getc(); } else { ret_val = MATCHING_FAILURE; break; } } } reader->ungetc(cur_char); return ret_val; } } // namespace scanf_core } // namespace LIBC_NAMESPACE_DECL