[libc-commits] [libc] [libc] Support dynamically-grown lines in FlatFileDatabase (PR #223811)
Alexey Samsonov via libc-commits
libc-commits at lists.llvm.org
Tue Sep 15 15:50:25 PDT 2026
================
@@ -0,0 +1,104 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Growable byte buffer with explicit lifetime management.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_PWD_DYNAMIC_BUFFER_H
+#define LLVM_LIBC_SRC___SUPPORT_PWD_DYNAMIC_BUFFER_H
+
+#include "hdr/func/free.h"
+#include "hdr/func/realloc.h"
+#include "hdr/types/size_t.h"
+#include "src/__support/CPP/limits.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/CPP/type_traits/is_trivially_destructible.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace pwd {
+
+// A heap-backed, growable byte buffer for the flat-file database engine.
+//
+// This type is trivially destructible by design, so an instance can be a
+// constant-initialised process global. The owner releases the storage
+// explicitly when done.
+class DynamicBuffer {
+ static constexpr size_t INITIAL_CAPACITY = 256;
+
+ char *ptr = nullptr;
+ size_t cap = 0;
+
+public:
+ LIBC_INLINE constexpr DynamicBuffer() = default;
+
+ DynamicBuffer(const DynamicBuffer &) = delete;
+ DynamicBuffer &operator=(const DynamicBuffer &) = delete;
+
+ // Grows the buffer to hold at least new_capacity bytes, preserving the
+ // existing contents. Capacity doubles so that repeated growth stays linear
+ // in the number of bytes read. Returns false if allocation failed, in which
+ // case the buffer is left untouched.
+ [[nodiscard]] LIBC_INLINE bool reserve(size_t new_capacity) {
+ if (new_capacity <= cap)
+ return true;
+
+ size_t next = cap == 0 ? INITIAL_CAPACITY : cap;
+ while (next < new_capacity) {
+ if (next > cpp::numeric_limits<size_t>::max() / 2)
+ return false;
+ next *= 2;
+ }
+
+ void *new_ptr = ::realloc(ptr, next);
+ if (new_ptr == nullptr)
+ return false;
+
+ ptr = static_cast<char *>(new_ptr);
+ cap = next;
+ return true;
+ }
+
+ // Doubles the current capacity, or allocates the initial capacity when the
+ // buffer is empty. Returns false if allocation failed.
+ [[nodiscard]] LIBC_INLINE bool grow() {
+ if (cap == cpp::numeric_limits<size_t>::max())
+ return false;
+ return reserve(cap == 0 ? INITIAL_CAPACITY : cap + 1);
+ }
+
+ // Frees the storage and returns the buffer to its empty state. Safe to call
+ // more than once.
+ LIBC_INLINE void release() {
+ ::free(ptr);
+ ptr = nullptr;
+ cap = 0;
+ }
+
+ [[nodiscard]] LIBC_INLINE cpp::span<char> span() { return {ptr, cap}; }
----------------
vonosmas wrote:
This is also technically const method, though it returns a mutable span.
https://github.com/llvm/llvm-project/pull/223811
More information about the libc-commits
mailing list