TEC
A lightweight C++ library enabling safe, efficient execution in multithreaded and concurrent systems.
Loading...
Searching...
No Matches
tec_memfile.hpp
Go to the documentation of this file.
1// Time-stamp: <Last changed 2026-02-12 01:52:18 by magnolia>
2/*----------------------------------------------------------------------
3------------------------------------------------------------------------
4Copyright (c) 2020-2026 The Emacs Cat (https://github.com/olddeuteronomy/tec).
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17------------------------------------------------------------------------
18----------------------------------------------------------------------*/
26#pragma once
27
28#include <cstddef>
29#include <cstdio>
30#include <string>
31#include <sstream>
32
33#include <memory.h>
34
35#include "tec/tec_def.hpp" // IWYU pragma: keep
36#include "tec/tec_trace.hpp"
37
38
39namespace tec {
40
41
50class MemFile {
51public:
52 struct _Char2 {
53 char c0;
54 char c1;
55 };
56
89 inline static constexpr _Char2 to_hex_chars(unsigned char ch) noexcept {
90 constexpr char table[] = "0123456789ABCDEF";
91 if (0x20 < ch && ch < 0x7F) {
92 return {' ', static_cast<char>(ch)};
93 } else {
94 return {table[ch >> 4], table[ch & 0x0F]};
95 }
96 }
97
98public:
99
103 static constexpr size_t kDefaultBlockSize{BUFSIZ};
104
105private:
106
108 std::string buffer_;
109
111 size_t blk_size_;
112
114 long pos_;
115
116private:
117
119 size_t calc_required_capacity(long pos, size_t len) const {
120 return buffer_.capacity()
121 + blk_size_
122 + ((pos + len) / blk_size_) * blk_size_;
123 }
124
125public:
136 : buffer_(kDefaultBlockSize, 0)
137 , blk_size_{kDefaultBlockSize}
138 , pos_{0}
139 {
140 buffer_.resize(0);
141 }
142
152 explicit MemFile(size_t block_size)
153 : buffer_(block_size, 0)
154 , blk_size_{block_size}
155 , pos_{0}
156 {
157 buffer_.resize(0);
158 }
159
168 explicit MemFile(const std::string& s)
169 : buffer_(kDefaultBlockSize, 0)
170 , blk_size_{kDefaultBlockSize}
171 , pos_{0}
172 {
173 buffer_.resize(0);
174 write(s.data(), s.size());
175 }
176
186 MemFile(const void* src, size_t len)
187 : buffer_(kDefaultBlockSize, 0)
188 , blk_size_{kDefaultBlockSize}
189 , pos_{0}
190 {
191 buffer_.resize(0);
192 write(src, len);
193 }
194
195 virtual ~MemFile() = default;
196
197
206 void copy_from(const MemFile& src) {
207 rewind();
208 write(src.data(), src.size());
209 }
210
221 void move_from(MemFile&& src, size_t size_to_shrink=0) {
222 blk_size_ = src.blk_size_;
223 pos_ = src.pos_;
224 buffer_ = std::move(src.buffer_);
225 if (size_to_shrink > 0 && size_to_shrink < size()) {
226 buffer_.resize(size_to_shrink);
227 }
228 }
229
235 const std::string& str() const noexcept {
236 return buffer_;
237 }
238
247 const void* data() const {
248 // To prevent silly GCC warning?
249 return &buffer_.at(0);
250 }
251
260 void* data() {
261 // To prevent silly GCC warning?
262 return &buffer_.at(0);
263 }
264
273 const char* ptr(long pos) const {
274 return buffer_.data() + pos;
275 }
276
285 char* ptr(long pos) {
286 return buffer_.data() + pos;
287 }
288
293 constexpr size_t block_size() const noexcept {
294 return blk_size_;
295 }
296
304 size_t size() const noexcept {
305 return buffer_.size();
306 }
307
312 size_t capacity() const noexcept {
313 return buffer_.capacity();
314 }
315
320 constexpr long tell() const noexcept {
321 return pos_;
322 }
323
327 constexpr void rewind() noexcept {
328 pos_ = 0;
329 }
330
343 long seek(long offset, int whence) {
344 long origin = (whence == SEEK_CUR ? pos_ : (whence == SEEK_END ? size() : 0));
345 size_t new_pos = origin + offset;
346 if( new_pos < 0) {
347 return -1;
348 }
349 if( new_pos > size() ) {
350 return -2;
351 }
352 pos_ = new_pos;
353 return pos_;
354 }
355
356 void resize(size_t len) {
357 size_t new_size = pos_ + len;
358 if (new_size > size()) {
359 if (new_size > buffer_.capacity()) {
360 TEC_ENTER("MemFile:resize");
361 size_t new_cap = calc_required_capacity(pos_, new_size);
362 TEC_TRACE("Cap: {}->{}, Size: {}->{}",
363 buffer_.capacity(), new_cap,
364 size(), new_size);
365 buffer_.reserve(new_cap);
366 }
367 buffer_.resize(new_size);
368 }
369 }
370
382 size_t write(const void* src, size_t len) {
383 if( len == 0 ) {
384 return 0;
385 }
386 if (pos_ + len > size()) {
387 resize(len);
388 }
389 ::memcpy(buffer_.data() + pos_, src, len);
390 pos_ += len;
391 return len;
392 }
393
404 size_t read(void* dst, size_t len) {
405 if( len == 0 ) {
406 return 0;
407 }
408 if( pos_ + len > size() ) {
409 // Reading out of bound.
410 return 0;
411 }
412 if (buffer_.empty()) {
413 return 0;
414 }
415 ::memcpy(dst, buffer_.data() + pos_, len);
416 pos_ += len;
417 return len;
418 }
419
420
456 std::string as_hex() const {
457 std::ostringstream os;
458 if (size() > 0) {
459 for (unsigned char c: buffer_) {
460 auto ch = to_hex_chars(c);
461 os << ch.c0 << ch.c1;
462
463 }
464 }
465 return os.str();
466 }
467
468};
469
470
472using Blob = MemFile;
473
476
477
478} // namespace tec
A byte buffer class with stream-like read/write semantics.
Definition tec_memfile.hpp:50
size_t write(const void *src, size_t len)
Writes data into the buffer at the current position.
Definition tec_memfile.hpp:382
long seek(long offset, int whence)
Moves the read/write position relative to a reference point.
Definition tec_memfile.hpp:343
const char * ptr(long pos) const
Returns a const pointer to a specific position in the buffer.
Definition tec_memfile.hpp:273
void * data()
Returns a mutable pointer to the buffer's data.
Definition tec_memfile.hpp:260
char * ptr(long pos)
Returns a mutable pointer to a specific position in the buffer.
Definition tec_memfile.hpp:285
static constexpr _Char2 to_hex_chars(unsigned char ch) noexcept
Converts a byte to a 2-character representation suitable for hex dumps.
Definition tec_memfile.hpp:89
const void * data() const
Returns a const pointer to the buffer's data.
Definition tec_memfile.hpp:247
constexpr void rewind() noexcept
Resets the read/write position to the beginning of the buffer.
Definition tec_memfile.hpp:327
size_t capacity() const noexcept
Returns the current capacity of the underlying storage.
Definition tec_memfile.hpp:312
constexpr size_t block_size() const noexcept
Returns the block size used for buffer expansion.
Definition tec_memfile.hpp:293
MemFile(const void *src, size_t len)
Constructs a MemFile from a raw memory buffer.
Definition tec_memfile.hpp:186
size_t read(void *dst, size_t len)
Reads data from the buffer starting at the current position.
Definition tec_memfile.hpp:404
MemFile(size_t block_size)
Constructs a MemFile with a specified block size for preallocation.
Definition tec_memfile.hpp:152
constexpr long tell() const noexcept
Returns the current read/write position.
Definition tec_memfile.hpp:320
void move_from(MemFile &&src, size_t size_to_shrink=0)
Moves data from another MemFile instance.
Definition tec_memfile.hpp:221
std::string as_hex() const
Returns a human-readable hex+ASCII dump string.
Definition tec_memfile.hpp:456
size_t size() const noexcept
Returns the logical size of the data in the buffer.
Definition tec_memfile.hpp:304
MemFile(const std::string &s)
Constructs a MemFile from a std::string.
Definition tec_memfile.hpp:168
const std::string & str() const noexcept
Returns a const reference to the internal string buffer.
Definition tec_memfile.hpp:235
void copy_from(const MemFile &src)
Copies data from another MemFile instance.
Definition tec_memfile.hpp:206
MemFile()
Constructs a buffer with the specified block size.
Definition tec_memfile.hpp:135
static constexpr size_t kDefaultBlockSize
Default block size for buffer expansion, matches BUFSIZ from <stdio.h>. Usually 8192 bytes.
Definition tec_memfile.hpp:103
#define TEC_ENTER(name)
Logs an entry message for a named context (e.g., function).
Definition tec_trace.hpp:211
#define TEC_TRACE(...)
Logs a formatted trace message.
Definition tec_trace.hpp:222
Definition tec_memfile.hpp:52
Common definitions and utilities for the tec namespace.
Provides a thread-safe tracing utility for debugging in the tec namespace.