brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · 3879f8c Raw
82 lines · c
1//===-- String type specifier converters 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_STRING_CONVERTER_H10#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_STRING_CONVERTER_H11 12#include "src/__support/CPP/limits.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#include <stddef.h>19 20namespace LIBC_NAMESPACE_DECL {21namespace scanf_core {22 23template <typename T>24int convert_string(Reader<T> *reader, const FormatSection &to_conv) {25  // %s "Matches a sequence of non-white-space characters"26 27  // %c "Matches a sequence of characters of exactly the number specified by the28  // field width (1 if no field width is present in the directive)"29 30  // %[ "Matches a nonempty sequence of characters from a set of expected31  // characters (the scanset)."32  size_t max_width = 0;33  if (to_conv.max_width > 0) {34    max_width = to_conv.max_width;35  } else {36    if (to_conv.conv_name == 'c') {37      max_width = 1;38    } else {39      max_width = cpp::numeric_limits<size_t>::max();40    }41  }42 43  char *output = reinterpret_cast<char *>(to_conv.output_ptr);44 45  char cur_char = reader->getc();46  size_t i = 0;47  for (; i < max_width && cur_char != '\0'; ++i) {48    // If this is %s and we've hit a space, or if this is %[] and we've found49    // something not in the scanset.50    if ((to_conv.conv_name == 's' && internal::isspace(cur_char)) ||51        (to_conv.conv_name == '[' && !to_conv.scan_set.test(cur_char))) {52      break;53    }54    // if the NO_WRITE flag is not set, write to the output.55    if ((to_conv.flags & NO_WRITE) == 0)56      output[i] = cur_char;57    cur_char = reader->getc();58  }59 60  // We always read one more character than will be used, so we have to put the61  // last one back.62  reader->ungetc(cur_char);63 64  // If this is %s or %[]65  if (to_conv.conv_name != 'c' && (to_conv.flags & NO_WRITE) == 0) {66    // Always null terminate the string. This may cause a write to the67    // (max_width + 1) byte, which is correct. The max width describes the max68    // number of characters read from the input string, and doesn't necessarily69    // correspond to the output.70    output[i] = '\0';71  }72 73  if (i == 0)74    return MATCHING_FAILURE;75  return READ_OK;76}77 78} // namespace scanf_core79} // namespace LIBC_NAMESPACE_DECL80 81#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_STRING_CONVERTER_H82