OpenXLSX 1.9.1
Loading...
Searching...
No Matches
XLStringArena.hpp
Go to the documentation of this file.
1#ifndef OPENXLSX_XLSTRINGARENA_HPP
2#define OPENXLSX_XLSTRINGARENA_HPP
3
4#include <algorithm>
5#include <cstdint>
6#include <memory>
7#include <string_view>
8#include <vector>
9
10namespace OpenXLSX
11{
12
23 {
24 public:
25 // Default block size: 4 MB accommodates many short strings without fragmentation.
26 explicit XLStringArena(size_t blockSize = 4 * 1024 * 1024) : m_blockSize(blockSize), m_currentOffset(blockSize) {}
27
28 // Disable copy — string_view pointers would dangle after a copy
29 XLStringArena(const XLStringArena&) = delete;
31
32 XLStringArena(XLStringArena&&) noexcept = default;
33 XLStringArena& operator=(XLStringArena&&) noexcept = default;
34
40 [[nodiscard]] std::string_view store(std::string_view str)
41 {
42 if (str.empty()) {
43 static constexpr char emptyStr[] = "";
44 return {emptyStr, 0};
45 }
46
47 const size_t needed = str.size() + 1; // +1 for null terminator
48
49 if (m_currentOffset + needed > blockCapacity()) {
50 // Try to reuse a free block, otherwise allocate a new one
51 const size_t allocSize = std::max(m_blockSize, needed);
52 if (!m_freeBlocks.empty() && m_freeBlocks.back().capacity >= allocSize) {
53 m_activeBlocks.push_back(std::move(m_freeBlocks.back()));
54 m_freeBlocks.pop_back();
55 }
56 else {
57 m_activeBlocks.push_back({std::make_unique<char[]>(allocSize), allocSize});
58 }
59 m_currentOffset = 0;
60 }
61
62 char* dest = m_activeBlocks.back().data.get() + m_currentOffset;
63 std::copy(str.begin(), str.end(), dest);
64 dest[str.size()] = '\0';
65
66 m_currentOffset += needed;
67 return {dest, str.size()};
68 }
69
76 void clear() noexcept
77 {
78 for (auto& blk : m_activeBlocks) m_freeBlocks.push_back(std::move(blk));
79 m_activeBlocks.clear();
80 m_currentOffset = m_blockSize; // force new-block allocation on next store
81 }
82
86 void reset() noexcept
87 {
88 m_activeBlocks.clear();
89 m_freeBlocks.clear();
90 m_currentOffset = m_blockSize;
91 }
92
96 [[nodiscard]] size_t capacity() const noexcept
97 {
98 size_t total = 0;
99 for (const auto& blk : m_activeBlocks) total += blk.capacity;
100 return total;
101 }
102
106 [[nodiscard]] size_t used() const noexcept { return m_currentOffset; }
107
108 private:
109 struct Block
110 {
111 std::unique_ptr<char[]> data;
112 size_t capacity{0};
113 };
114
115 [[nodiscard]] size_t blockCapacity() const noexcept { return m_activeBlocks.empty() ? 0 : m_activeBlocks.back().capacity; }
116
117 size_t m_blockSize; // target size for new blocks
118 size_t m_currentOffset; // write position within the current active block
119 std::vector<Block> m_activeBlocks; // currently in-use blocks
120 std::vector<Block> m_freeBlocks; // recycled blocks awaiting reuse
121 };
122
123} // namespace OpenXLSX
124
125#endif // OPENXLSX_XLSTRINGARENA_HPP
String memory pool (Arena Allocator) with block recycling.
Definition XLStringArena.hpp:23
std::string_view store(std::string_view str)
Store a string in the arena and return a non-owning view.
Definition XLStringArena.hpp:40
XLStringArena(size_t blockSize=4 *1024 *1024)
Definition XLStringArena.hpp:26
void reset() noexcept
Release all memory (active + free blocks). Use at shutdown.
Definition XLStringArena.hpp:86
XLStringArena & operator=(const XLStringArena &)=delete
size_t capacity() const noexcept
Total bytes allocated (active blocks only).
Definition XLStringArena.hpp:96
XLStringArena(const XLStringArena &)=delete
size_t used() const noexcept
Bytes used in the current active block.
Definition XLStringArena.hpp:106
void clear() noexcept
Recycle all blocks for reuse without freeing heap memory.
Definition XLStringArena.hpp:76
XLStringArena(XLStringArena &&) noexcept=default
Definition IZipArchive.hpp:18
Definition XLCellIterator.hpp:121