114 lines · c
1//===-- Format specifier converter 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_H10#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_H11 12#include "src/__support/CPP/string_view.h"13#include "src/__support/ctype_utils.h"14#include "src/__support/macros/config.h"15#include "src/stdio/scanf_core/core_structs.h"16#include "src/stdio/scanf_core/reader.h"17 18#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT19#include "src/stdio/scanf_core/float_converter.h"20#endif // LIBC_COPT_SCANF_DISABLE_FLOAT21#include "src/stdio/scanf_core/current_pos_converter.h"22#include "src/stdio/scanf_core/int_converter.h"23#include "src/stdio/scanf_core/ptr_converter.h"24#include "src/stdio/scanf_core/string_converter.h"25 26#include <stddef.h>27 28namespace LIBC_NAMESPACE_DECL {29namespace scanf_core {30 31// convert will call a conversion function to convert the FormatSection into32// its string representation, and then that will write the result to the33// reader.34template <typename T>35int convert(Reader<T> *reader, const FormatSection &to_conv) {36 int ret_val = 0;37 switch (to_conv.conv_name) {38 case '%':39 return raw_match(reader, "%");40 case 's':41 ret_val = raw_match(reader, " ");42 if (ret_val != READ_OK)43 return ret_val;44 return convert_string(reader, to_conv);45 case 'c':46 case '[':47 return convert_string(reader, to_conv);48 case 'd':49 case 'i':50 case 'u':51 case 'o':52 case 'x':53 case 'X':54 ret_val = raw_match(reader, " ");55 if (ret_val != READ_OK)56 return ret_val;57 return convert_int(reader, to_conv);58#ifndef LIBC_COPT_SCANF_DISABLE_FLOAT59 case 'f':60 case 'F':61 case 'e':62 case 'E':63 case 'a':64 case 'A':65 case 'g':66 case 'G':67 ret_val = raw_match(reader, " ");68 if (ret_val != READ_OK)69 return ret_val;70 return convert_float(reader, to_conv);71#endif // LIBC_COPT_SCANF_DISABLE_FLOAT72 case 'n':73 return convert_current_pos(reader, to_conv);74 case 'p':75 ret_val = raw_match(reader, " ");76 if (ret_val != READ_OK)77 return ret_val;78 return convert_pointer(reader, to_conv);79 default:80 return raw_match(reader, to_conv.raw_string);81 }82 return -1;83}84 85// raw_match takes a raw string and matches it to the characters obtained from86// the reader.87template <typename T>88int raw_match(Reader<T> *reader, cpp::string_view raw_string) {89 char cur_char = reader->getc();90 int ret_val = READ_OK;91 for (size_t i = 0; i < raw_string.size(); ++i) {92 // Any space character matches any number of space characters.93 if (internal::isspace(raw_string[i])) {94 while (internal::isspace(cur_char)) {95 cur_char = reader->getc();96 }97 } else {98 if (raw_string[i] == cur_char) {99 cur_char = reader->getc();100 } else {101 ret_val = MATCHING_FAILURE;102 break;103 }104 }105 }106 reader->ungetc(cur_char);107 return ret_val;108}109 110} // namespace scanf_core111} // namespace LIBC_NAMESPACE_DECL112 113#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_CONVERTER_H114