libc.src.__support.CPP.bitset
libc.src.__support.CPP.string_view
)
+
+if(NOT (TARGET libc.src.__support.File.file))
+ # Not all platforms have a file implementation. If file is unvailable,
+ # then we must skip all the parts that need file.
+ return()
+endif()
+
+add_object_library(
+ string_reader
+ SRCS
+ string_reader.cpp
+ HDRS
+ string_reader.h
+)
+
+add_object_library(
+ file_reader
+ SRCS
+ file_reader.cpp
+ HDRS
+ file_reader.h
+ DEPENDS
+ libc.src.__support.File.file
+)
+
+add_object_library(
+ reader
+ SRCS
+ reader.cpp
+ HDRS
+ reader.h
+ DEPENDS
+ .string_reader
+ .file_reader
+)
--- /dev/null
+//===-- FILE Reader implementation 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/file_reader.h"
+#include "src/__support/File/file.h"
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace scanf_core {
+
+char FileReader::get_char() {
+ char tiny_buff = 0;
+ if (file->read_unlocked(&tiny_buff, 1) != 1)
+ return 0;
+ return tiny_buff;
+}
+
+void FileReader::unget_char(char c) { file->ungetc_unlocked(c); }
+
+} // namespace scanf_core
+} // namespace __llvm_libc
--- /dev/null
+//===-- FILE Reader definition 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_FILE_READER_H
+#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_FILE_READER_H
+
+#include "src/__support/File/file.h"
+
+#include <stddef.h>
+#include <stdio.h>
+
+namespace __llvm_libc {
+namespace scanf_core {
+
+class FileReader {
+ __llvm_libc::File *file;
+
+public:
+ FileReader(::FILE *init_file) {
+ file = reinterpret_cast<__llvm_libc::File *>(init_file);
+ file->lock();
+ }
+
+ ~FileReader() { file->unlock(); }
+
+ char get_char();
+ void unget_char(char c);
+};
+
+} // namespace scanf_core
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_FILE_READER_H
--- /dev/null
+//===-- Reader definition 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/reader.h"
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace scanf_core {
+
+char Reader::getc() {
+ if (reader_type == ReaderType::String) {
+ return string_reader->get_char();
+ } else {
+ return file_reader->get_char();
+ }
+}
+
+void Reader::ungetc(char c) {
+ if (reader_type == ReaderType::String) {
+ // The string reader ignores the char c passed to unget since it doesn't
+ // need to place anything back into a buffer, and modifying the source
+ // string would be dangerous.
+ return string_reader->unget_char();
+ } else {
+ return file_reader->unget_char(c);
+ }
+}
+
+} // namespace scanf_core
+} // namespace __llvm_libc
--- /dev/null
+//===-- Reader definition 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H
+#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H
+
+#include "src/stdio/scanf_core/file_reader.h"
+#include "src/stdio/scanf_core/string_reader.h"
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace scanf_core {
+
+enum class ReaderType { String, File };
+
+class Reader final {
+ union {
+ StringReader *string_reader;
+ FileReader *file_reader;
+ };
+
+ const ReaderType reader_type;
+
+public:
+ Reader(StringReader *init_string_reader)
+ : string_reader(init_string_reader), reader_type(ReaderType::String) {}
+
+ Reader(FileReader *init_file_reader)
+ : file_reader(init_file_reader), reader_type(ReaderType::File) {}
+
+ // This returns the next character from the input and advances it by one
+ // character. When it hits the end of the string or file it returns '\0' to
+ // signal to stop parsing.
+ char getc();
+
+ // This moves the input back by one character, placing c into the buffer if
+ // this is a file reader, else c is ignored.
+ void ungetc(char c);
+};
+
+} // namespace scanf_core
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H
--- /dev/null
+//===-- String Reader implementation 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/string_reader.h"
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace scanf_core {
+
+char StringReader::get_char() {
+ char cur_char = string[cur_index];
+ ++cur_index;
+ return cur_char;
+}
+
+void StringReader::unget_char() { --cur_index; }
+
+} // namespace scanf_core
+} // namespace __llvm_libc
--- /dev/null
+//===-- String Reader definition 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_STRING_READER_H
+#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_STRING_READER_H
+
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace scanf_core {
+
+class StringReader {
+ const char *string;
+ size_t cur_index = 0;
+
+public:
+ StringReader(const char *init_string) { string = init_string; }
+
+ ~StringReader() {}
+
+ char get_char();
+ void unget_char();
+};
+
+} // namespace scanf_core
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STDIO_SCANF_CORE_STRING_READER_H
libc.src.__support.CPP.string_view
libc.src.__support.arg_list
)
+
+if(NOT (TARGET libc.src.__support.File.file))
+ # Not all platforms have a file implementation. If file is unvailable,
+ # then we must skip all the parts that need file.
+ return()
+endif()
+
+add_libc_unittest(
+ string_reader_test
+ SUITE
+ libc_stdio_unittests
+ SRCS
+ string_reader_test.cpp
+ DEPENDS
+ libc.src.stdio.scanf_core.reader
+ libc.src.stdio.scanf_core.string_reader
+ libc.src.__support.CPP.string_view
+)
--- /dev/null
+//===-- Unittests for the scanf String Reader -----------------------------===//
+//
+// 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/__support/CPP/string_view.h"
+#include "src/stdio/scanf_core/reader.h"
+#include "src/stdio/scanf_core/string_reader.h"
+
+#include "utils/UnitTest/Test.h"
+
+TEST(LlvmLibcScanfStringReaderTest, Constructor) {
+ char str[10];
+ __llvm_libc::scanf_core::StringReader str_reader(str);
+ __llvm_libc::scanf_core::Reader reader(&str_reader);
+}
+
+TEST(LlvmLibcScanfStringReaderTest, SimpleRead) {
+ const char *str = "abc";
+ __llvm_libc::scanf_core::StringReader str_reader(str);
+ __llvm_libc::scanf_core::Reader reader(&str_reader);
+
+ for (size_t i = 0; i < sizeof(str); ++i) {
+ ASSERT_EQ(str[i], reader.getc());
+ }
+}
+
+TEST(LlvmLibcScanfStringReaderTest, ReadAndReverse) {
+ const char *str = "abcDEF123";
+ __llvm_libc::scanf_core::StringReader str_reader(str);
+ __llvm_libc::scanf_core::Reader reader(&str_reader);
+
+ for (size_t i = 0; i < 5; ++i) {
+ ASSERT_EQ(str[i], reader.getc());
+ }
+
+ // Move back by 3, cursor should now be on 2
+ reader.ungetc(str[4]);
+ reader.ungetc(str[3]);
+ reader.ungetc(str[2]);
+
+ for (size_t i = 2; i < 7; ++i) {
+ ASSERT_EQ(str[i], reader.getc());
+ }
+
+ // Move back by 2, cursor should now be on 5
+ reader.ungetc(str[6]);
+ reader.ungetc(str[5]);
+
+ for (size_t i = 5; i < 10; ++i) {
+ ASSERT_EQ(str[i], reader.getc());
+ }
+
+ // Move back by 10, which should be back to the start.
+ for (size_t i = 0; i < 10; ++i) {
+ reader.ungetc(str[9 - i]);
+ }
+
+ // Check the whole string.
+ for (size_t i = 0; i < sizeof(str); ++i) {
+ ASSERT_EQ(str[i], reader.getc());
+ }
+}