[libc-commits] [libc] [libc] Templatize the scanf Reader interface (PR #131037)
Petr Hosek via libc-commits
libc-commits at lists.llvm.org
Wed Mar 12 20:47:29 PDT 2025
================
@@ -9,121 +9,65 @@
#ifndef LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H
#define LLVM_LIBC_SRC_STDIO_SCANF_CORE_READER_H
-#include "hdr/types/FILE.h"
-
-#ifndef LIBC_COPT_STDIO_USE_SYSTEM_FILE
-#include "src/__support/File/file.h"
-#endif
-
-#if defined(LIBC_TARGET_ARCH_IS_GPU)
-#include "src/stdio/getc.h"
-#include "src/stdio/ungetc.h"
-#endif
-
#include "src/__support/macros/attributes.h" // For LIBC_INLINE
#include "src/__support/macros/config.h"
#include <stddef.h>
namespace LIBC_NAMESPACE_DECL {
namespace scanf_core {
-// We use the name "reader_internal" over "internal" because
-// "internal" causes name lookups in files that include the current header to be
-// ambigious i.e. `internal::foo` in those files, will try to lookup in
-// `LIBC_NAMESPACE::scanf_core::internal` over `LIBC_NAMESPACE::internal` for
-// e.g., `internal::ArgList` in `libc/src/stdio/scanf_core/scanf_main.h`
-namespace reader_internal {
-
-#if defined(LIBC_TARGET_ARCH_IS_GPU)
-// The GPU build provides FILE access through the host operating system's
-// library. So here we simply use the public entrypoints like in the SYSTEM_FILE
-// interface. Entrypoints should normally not call others, this is an exception.
-// FIXME: We do not acquire any locks here, so this is not thread safe.
-LIBC_INLINE int getc(void *f) {
- return LIBC_NAMESPACE::getc(reinterpret_cast<::FILE *>(f));
-}
-
-LIBC_INLINE void ungetc(int c, void *f) {
- LIBC_NAMESPACE::ungetc(c, reinterpret_cast<::FILE *>(f));
-}
-
-#elif !defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE)
-
-LIBC_INLINE int getc(void *f) {
- unsigned char c;
- auto result =
- reinterpret_cast<LIBC_NAMESPACE::File *>(f)->read_unlocked(&c, 1);
- size_t r = result.value;
- if (result.has_error() || r != 1)
- return '\0';
-
- return c;
-}
-LIBC_INLINE void ungetc(int c, void *f) {
- reinterpret_cast<LIBC_NAMESPACE::File *>(f)->ungetc_unlocked(c);
-}
-
-#else // defined(LIBC_COPT_STDIO_USE_SYSTEM_FILE)
-
-// Since ungetc_unlocked isn't always available, we don't acquire the lock for
-// system files.
-LIBC_INLINE int getc(void *f) { return ::getc(reinterpret_cast<::FILE *>(f)); }
-
-LIBC_INLINE void ungetc(int c, void *f) {
- ::ungetc(c, reinterpret_cast<::FILE *>(f));
-}
-#endif // LIBC_COPT_STDIO_USE_SYSTEM_FILE
-
-} // namespace reader_internal
+template <typename Derived> struct ReadBuffer {
+ LIBC_INLINE char getc() { return static_cast<Derived *>(this)->getc(); }
+ LIBC_INLINE void ungetc(int c) { static_cast<Derived *>(this)->ungetc(c); }
+};
-// This is intended to be either a raw string or a buffer syncronized with the
-// file's internal buffer.
-struct ReadBuffer {
+class StringBuffer : public ReadBuffer<StringBuffer> {
const char *buffer;
- size_t buff_len;
+ [[maybe_unused]] size_t buff_len;
size_t buff_cur = 0;
+
+public:
+ LIBC_INLINE StringBuffer(const char *buffer, size_t buff_len)
+ : buffer(buffer), buff_len(buff_len) {}
+
+ LIBC_INLINE char getc() {
+ char output = buffer[buff_cur];
+ ++buff_cur;
+ return output;
+ }
+ LIBC_INLINE void ungetc(int) {
+ if (buff_cur > 0) {
+ // While technically c should be written back to the buffer, in scanf we
+ // always write the character that was already there. Additionally, the
+ // buffer is most likely to contain a string that isn't part of a file,
+ // which may not be writable.
+ --buff_cur;
+ }
+ }
};
-class Reader {
- ReadBuffer *rb;
- void *input_stream = nullptr;
+// TODO: We should be able to fold ReadBuffer into Reader.
----------------
petrhosek wrote:
Done.
https://github.com/llvm/llvm-project/pull/131037
More information about the libc-commits
mailing list