Joedb 10.2.0
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 int extra_bytes = first_byte >> 5;
115 T result = first_byte & 0x1f;
116 while (--extra_bytes >= 0)
117 result = T((result << 8) | read<uint8_t>());
118 return result;
119 }
120
121 template<typename T> T read_strong_type()
122 {
123 return T(compact_read<typename underlying_type<T>::type>());
124 }
125
127 {
129 }
130
132 {
133 return Record_Id(read_strong_type<Record_Id>() - 1);
134 }
135
136 void write_string(const std::string &s);
137 std::string read_string();
138 std::string safe_read_string(int64_t max_size);
139
140 void write_blob(Blob blob)
141 {
142 compact_write<int64_t>(blob.get_position());
143 compact_write<int64_t>(blob.get_size());
144 }
145
147 {
148 const int64_t position = compact_read<int64_t>();
149 const int64_t size = compact_read<int64_t>();
150 return Blob(position, size);
151 }
152
153 //////////////////////////////////////////////////////////////////////////
154 void write_data(const char *data, size_t n)
155 //////////////////////////////////////////////////////////////////////////
156 {
157 JOEDB_DEBUG_ASSERT(!buffer_has_read_data());
158
159 if (n <= buffer.extra_size)
160 {
161 std::memcpy(buffer.data + buffer.index, data, n);
162 buffer.index += n;
163 check_write_buffer();
164 }
165 else
166 {
167 const size_t remaining = buffer.size + buffer.extra_size - buffer.index;
168
169 if (n < remaining)
170 {
171 std::memcpy(buffer.data + buffer.index, data, n);
172 buffer.index += n;
173 check_write_buffer();
174 }
175 else
176 {
177 flush();
178 File_Iterator::write(data, n);
179 }
180 }
181 }
182
183 //////////////////////////////////////////////////////////////////////////
184 size_t read_data(char *data, const size_t n)
185 //////////////////////////////////////////////////////////////////////////
186 {
187 JOEDB_DEBUG_ASSERT(!buffer_has_write_data());
188 JOEDB_DEBUG_ASSERT(buffer.index <= read_buffer_size);
189
190 if (buffer.index + n <= read_buffer_size)
191 {
192 std::memcpy(data, buffer.data + buffer.index, n);
193 buffer.index += n;
194 return n;
195 }
196 else
197 {
198 size_t n0 = read_buffer_size - buffer.index;
199 std::memcpy(data, buffer.data + buffer.index, n0);
200 buffer.index += n0;
201
202 if (n <= buffer.size)
203 {
204 read_buffer();
205
206 while (n0 < n && buffer.index < read_buffer_size)
207 data[n0++] = buffer.data[buffer.index++];
208 }
209
210 while (n0 < n)
211 {
212 const size_t actually_read = File_Iterator::read(data + n0, n - n0);
213 if (actually_read == 0)
214 {
216 break;
217 }
218 n0 += actually_read;
219 }
220
221 return n0;
222 }
223 }
224
225 //////////////////////////////////////////////////////////////////////////
226 void ignore(const int64_t n)
227 //////////////////////////////////////////////////////////////////////////
228 {
229 if (buffer.index + n <= read_buffer_size)
230 buffer.index += n;
231 else
233 }
234
235 ~File_Buffer();
236 };
237}
238
239#endif
static void reading_past_end_of_file()
int64_t get_position() const noexcept
Definition Blob.h:29
int64_t get_size() const noexcept
Definition Blob.h:30
T compact_read()
Definition Buffer.h:71
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 compact_write(T x)
Definition File_Buffer.h:99
void set_position(int64_t position)
Record_Id read_reference()
void write_string(const std::string &s)
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