[libc-commits] [libc] [libc][NFC] Add FieldTokenizer and FlatFileDatabase (PR #214720)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Thu Sep 3 00:08:34 PDT 2026


================
@@ -0,0 +1,200 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Generic flat-file database template engine.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_PWD_FLAT_FILE_DB_H
+#define LLVM_LIBC_SRC_PWD_FLAT_FILE_DB_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/stdio_macros.h"
+#include "hdr/types/size_t.h"
+#include "src/__support/CPP/functional.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/File/file.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace pwd {
+
+struct ReadLineResult {
+  size_t bytes_read;
+  bool truncated;
+};
+
+// Forward declaration of record parser for flat database files.
+template <typename EntryType>
+bool parse_line(cpp::span<char> line, EntryType *entry);
+
+// Generic flat colon-delimited database engine.
+template <typename EntryType> class FlatFileDatabase {
+public:
+  using Matcher = cpp::function<bool(const EntryType &)>;
+
+private:
+  const char *file_path;
+  File *file = nullptr;
+
+  // Reads a single line from the given file into the provided buffer, stripping
+  // any trailing '\n' and ensuring the result is null-terminated.
+  // Note: POSIX getline/getdelim cannot be used here because user database
+  // lookups (including reentrant _r variants) must operate in-place within a
+  // fixed, bounded buffer without dynamic heap allocations or realloc.
+  LIBC_INLINE static ErrorOr<ReadLineResult> read_line(File *f,
+                                                       cpp::span<char> buf) {
+    if (!f || buf.size() < 2)
+      return Error(EINVAL);
+
+    f->lock();
+    size_t bytes_read = 0;
+    FileIOResult result(0);
+    bool truncated = false;
+
+    for (char &ch : buf.first(buf.size() - 1)) {
+      result = f->read_unlocked(&ch, 1);
+      if (result.has_error()) {
+        f->unlock();
+        return Error(result.error);
+      }
+      if (result.value != 1)
+        break;
+      ++bytes_read;
+      if (ch == '\n')
+        break;
+    }
+
+    auto read_span = buf.first(bytes_read);
+    if (result.value == 1 && !read_span.empty() && read_span.back() != '\n') {
----------------
kaladron wrote:

I'm a bit happier with the defence in depth versus some later refactoring, and it looks like it should amount to a register read at this point.

https://github.com/llvm/llvm-project/pull/214720


More information about the libc-commits mailing list