Joedb 10.4.1
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
File_Buffer.h
Go to the documentation of this file.
1#ifndef joedb_File_Buffer_declared
2#define joedb_File_Buffer_declared
3
7#include "joedb/index_types.h"
8
9#include <string>
10
11namespace joedb
12{
13 /// @ingroup journal
15 {
16 private:
17 Buffer<12> buffer;
18
19 size_t read_buffer_size;
20
21 //////////////////////////////////////////////////////////////////////////
22 bool buffer_has_write_data() const noexcept
23 //////////////////////////////////////////////////////////////////////////
24 {
25 return buffer.index > 0 && !read_buffer_size;
26 }
27
28 //////////////////////////////////////////////////////////////////////////
29 bool buffer_has_read_data() const
30 //////////////////////////////////////////////////////////////////////////
31 {
32 return read_buffer_size;
33 }
34
35 //////////////////////////////////////////////////////////////////////////
36 void read_buffer()
37 //////////////////////////////////////////////////////////////////////////
38 {
39 JOEDB_DEBUG_ASSERT(!buffer_has_write_data());
40 JOEDB_DEBUG_ASSERT(buffer.index <= read_buffer_size);
41
42 buffer.index = 0;
43 read_buffer_size = File_Iterator::read(buffer.data, buffer.size);
44 if (read_buffer_size == 0)
46 }
47
48 //////////////////////////////////////////////////////////////////////////
49 void write_buffer()
50 //////////////////////////////////////////////////////////////////////////
51 {
52 JOEDB_DEBUG_ASSERT(!buffer_has_read_data());
53
54 File_Iterator::write(buffer.data, buffer.index);
55 buffer.index = 0;
56 }
57
58 //////////////////////////////////////////////////////////////////////////
59 void check_write_buffer()
60 //////////////////////////////////////////////////////////////////////////
61 {
62 JOEDB_DEBUG_ASSERT(!buffer_has_read_data());
63
64 if (buffer.index >= buffer.size)
65 write_buffer();
66 }
67
68 public:
70 void flush();
71
72 // set_position must be called when switching between write and read
73 void set_position(int64_t position);
74
75 int64_t get_position() const noexcept
76 {
77 return File_Iterator::get_position() - read_buffer_size + buffer.index;
78 }
79
80 //////////////////////////////////////////////////////////////////////////
81 template<typename T> void write(T x)
82 //////////////////////////////////////////////////////////////////////////
83 {
84 static_assert(sizeof(T) <= decltype(buffer)::extra_size);
85 buffer.write<T>(x);
86 check_write_buffer();
87 }
88
89 //////////////////////////////////////////////////////////////////////////
90 template<typename T> T read()
91 //////////////////////////////////////////////////////////////////////////
92 {
93 T result;
94 read_data(reinterpret_cast<char *>(&result), sizeof(result));
95 return result;
96 }
97
98 //////////////////////////////////////////////////////////////////////////
99 template<typename T> void compact_write(T x)
100 //////////////////////////////////////////////////////////////////////////
101 {
102 buffer.compact_write<T>(x);
103 check_write_buffer();
104 }
105
106 //////////////////////////////////////////////////////////////////////////
107 template<typename T> T compact_read()
108 //////////////////////////////////////////////////////////////////////////
109 {
110 if (buffer.index + 8 <= read_buffer_size)
111 return buffer.compact_read<T>();
112
113 const uint8_t first_byte = read<uint8_t>();
114#ifdef JOEDB_DIRTY_WORKAROUND
115 if (first_byte == 0xff)
116 return 0;
117#endif
118 int extra_bytes = first_byte >> 5;
119 T result = first_byte & 0x1f;
120 while (--extra_bytes >= 0)
121 result = T((result << 8) | read<uint8_t>());
122 return result;
123 }
124
125 template<typename T> T read_strong_type()
126 {
127 return T(compact_read<typename underlying_type<T>::type>());
128 }
129
131 {
133 }
134
136 {
137 return Record_Id(read_strong_type<Record_Id>() - 1);
138 }
139
140 void write_string(std::string_view s);
141 std::string read_string();
142 std::string safe_read_string(int64_t max_size);
143
144 void write_blob(Blob blob)
145 {
146 compact_write<int64_t>(blob.get_position());
147 compact_write<int64_t>(blob.get_size());
148 }
149
151 {
152 const int64_t position = compact_read<int64_t>();
153 const int64_t size = compact_read<int64_t>();
154 return Blob(position, size);
155 }
156
157 //////////////////////////////////////////////////////////////////////////
158 void write_data(const char *data, size_t n)
159 //////////////////////////////////////////////////////////////////////////
160 {
161 JOEDB_DEBUG_ASSERT(!buffer_has_read_data());
162
163 if (n <= buffer.extra_size)
164 {
165 std::memcpy(buffer.data + buffer.index, data, n);
166 buffer.index += n;
167 check_write_buffer();
168 }
169 else
170 {
171 const size_t remaining = buffer.size + buffer.extra_size - buffer.index;
172
173 if (n < remaining)
174 {
175 std::memcpy(buffer.data + buffer.index, data, n);
176 buffer.index += n;
177 check_write_buffer();
178 }
179 else
180 {
181 flush();
182 File_Iterator::write(data, n);
183 }
184 }
185 }
186
187 //////////////////////////////////////////////////////////////////////////
188 size_t read_data(char *data, const size_t n)
189 //////////////////////////////////////////////////////////////////////////
190 {
191 JOEDB_DEBUG_ASSERT(!buffer_has_write_data());
192 JOEDB_DEBUG_ASSERT(buffer.index <= read_buffer_size);
193
194 if (buffer.index + n <= read_buffer_size)
195 {
196 std::memcpy(data, buffer.data + buffer.index, n);
197 buffer.index += n;
198 return n;
199 }
200 else
201 {
202 size_t n0 = read_buffer_size - buffer.index;
203 std::memcpy(data, buffer.data + buffer.index, n0);
204 buffer.index += n0;
205
206 if (n <= buffer.size)
207 {
208 read_buffer();
209
210 while (n0 < n && buffer.index < read_buffer_size)
211 data[n0++] = buffer.data[buffer.index++];
212 }
213
214 while (n0 < n)
215 {
216 const size_t actually_read = File_Iterator::read(data + n0, n - n0);
217 if (actually_read == 0)
218 {
220 break;
221 }
222 n0 += actually_read;
223 }
224
225 return n0;
226 }
227 }
228
229 //////////////////////////////////////////////////////////////////////////
230 void ignore(const int64_t n)
231 //////////////////////////////////////////////////////////////////////////
232 {
233 if (buffer.index + n <= read_buffer_size)
234 buffer.index += n;
235 else
237 }
238
239 ~File_Buffer();
240 };
241}
242
243#endif
static void reading_past_end_of_file()
int64_t get_position() const noexcept
Definition Blob.h:30
int64_t get_size() const noexcept
Definition Blob.h:31
T compact_read()
Definition Buffer.h:76
size_t index
Definition Buffer.h:20
void write(T x)
Definition Buffer.h:23
static constexpr size_t extra_size
Definition Buffer.h:17
char data[size+extra_size]
Definition Buffer.h:19
static constexpr size_t size
Definition Buffer.h:15
void compact_write(T x)
Definition Buffer.h:43
void write_reference(Record_Id id)
size_t read_data(char *data, const size_t n)
void write_blob(Blob blob)
std::string safe_read_string(int64_t max_size)
void write_data(const char *data, size_t n)
int64_t get_position() const noexcept
Definition File_Buffer.h:75
void ignore(const int64_t n)
std::string read_string()
void write_string(std::string_view s)
void compact_write(T x)
Definition File_Buffer.h:99
void set_position(int64_t position)
Record_Id read_reference()
int64_t get_position() const noexcept
void write(const char *data, size_t size)
size_t read(char *data, size_t size)
Abstract_File & file
#define JOEDB_DEBUG_ASSERT(x)
assertion tested in debug mode
Definition assert.h:19
constexpr index_t to_underlying(Record_Id id)
Definition index_types.h:59
typename std::underlying_type< T >::type type
Definition index_types.h:51