Joedb 10.4.6
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
filebuf.cpp
Go to the documentation of this file.
3
4#include <cstring>
5
6namespace joedb
7{
8 ////////////////////////////////////////////////////////////////////////////
9 void filebuf::syncg()
10 ////////////////////////////////////////////////////////////////////////////
11 {
12 in_pos += gptr() - eback();
13 setg(buffer.data(), buffer.data(), buffer.data());
14 }
15
16 ////////////////////////////////////////////////////////////////////////////
17 void filebuf::syncp()
18 ////////////////////////////////////////////////////////////////////////////
19 {
20 const ptrdiff_t n = pptr() - pbase();
21 if (n)
22 {
23 file.pwrite(buffer.data(), n, out_pos);
24 out_pos += n;
25 setp(buffer.data(), buffer.data() + buffer.size());
26 }
27 }
28
29 ////////////////////////////////////////////////////////////////////////////
30 filebuf::pos_type filebuf::seekoff
31 ////////////////////////////////////////////////////////////////////////////
32 (
33 off_type off,
34 std::ios_base::seekdir dir,
35 std::ios_base::openmode which
36 )
37 {
38 pos_type base = -1;
39
40 if (dir == std::ios_base::beg)
41 base = 0;
42 else if (dir == std::ios_base::cur)
43 {
44 base = bool(which & std::ios_base::in)
45 ? in_pos + gptr() - eback()
46 : out_pos + pptr() - pbase();
47 }
48 else if (dir == std::ios_base::end)
49 {
50 syncp();
51 base = file.get_size();
52 }
53
54 if (base < 0)
55 return pos_type(off_type(-1));
56 else
57 return seekpos(base + off, which);
58 }
59
60 ////////////////////////////////////////////////////////////////////////////
61 filebuf::pos_type filebuf::seekpos
62 ////////////////////////////////////////////////////////////////////////////
63 (
64 pos_type pos,
65 std::ios_base::openmode which
66 )
67 {
68 sync();
69
70 if (which & std::ios_base::in)
71 in_pos = pos;
72
73 if (which & std::ios_base::out)
74 out_pos = pos;
75
76 return pos;
77 }
78
79 ////////////////////////////////////////////////////////////////////////////
81 ////////////////////////////////////////////////////////////////////////////
82 {
83 syncg();
84 syncp();
85 return 0;
86 }
87
88 ////////////////////////////////////////////////////////////////////////////
89 std::streamsize filebuf::showmanyc()
90 ////////////////////////////////////////////////////////////////////////////
91 {
92 const int64_t size = file.get_size();
93 if (size < 0)
94 return 0;
95 return size - (in_pos + gptr() - eback());
96 }
97
98 ////////////////////////////////////////////////////////////////////////////
99 filebuf::int_type filebuf::underflow()
100 ////////////////////////////////////////////////////////////////////////////
101 {
102 if (gptr() == egptr())
103 {
104 in_pos += gptr() - eback();
105 const size_t size = file.pread(buffer.data(), buffer.size(), in_pos);
106 setg(buffer.data(), buffer.data(), buffer.data() + size);
107 if (size == 0)
108 return traits_type::eof();
109 }
110
111 return traits_type::to_int_type(*gptr());
112 }
113
114 ////////////////////////////////////////////////////////////////////////////
115 std::streamsize filebuf::xsgetn(char_type* s, std::streamsize count)
116 ////////////////////////////////////////////////////////////////////////////
117 {
118 std::streamsize result = 0;
119
120 {
121 const std::streamsize available = egptr() - gptr();
122 const std::streamsize n = std::min(available, count);
123 std::memcpy(s, gptr(), n);
124 gbump(int(n));
125 result += n;
126 s += n;
127 count -= n;
128 }
129
130 if (count > 0)
131 {
132 syncg();
133
134 do
135 {
136 const std::streamsize n = std::streamsize(file.pread(s, count, in_pos));
137 if (n > 0)
138 {
139 in_pos += n;
140 result += n;
141 s += n;
142 count -= n;
143 }
144 else
145 break;
146 }
147 while (count > 0);
148 }
149
150 return result;
151 }
152
153 ////////////////////////////////////////////////////////////////////////////
154 std::streamsize filebuf::xsputn(const char_type* s, std::streamsize count)
155 ////////////////////////////////////////////////////////////////////////////
156 {
157 const ptrdiff_t available = epptr() - pptr();
158
159 if (available >= count)
160 {
161 std::memcpy(pptr(), s, count);
162 pbump(int(count));
163 }
164 else
165 {
166 syncp();
167 file.pwrite(s, count, out_pos);
168 out_pos += count;
169 }
170
171 return count;
172 }
173
174 ////////////////////////////////////////////////////////////////////////////
175 filebuf::int_type filebuf::overflow(int_type ch)
176 ////////////////////////////////////////////////////////////////////////////
177 {
178 if (pptr() >= epptr())
179 syncp();
180
181 if (!traits_type::eq_int_type(ch, traits_type::eof()))
182 {
183 *pptr() = traits_type::to_char_type(ch);
184 pbump(1);
185 }
186
187 return traits_type::not_eof(ch);
188 }
189
190 ////////////////////////////////////////////////////////////////////////////
191 filebuf::int_type filebuf::pbackfail(int_type c)
192 ////////////////////////////////////////////////////////////////////////////
193 {
194 if (gptr() == eback() && in_pos > 0)
195 {
196 const pos_type previous_position = in_pos - off_type(1);
197 if (file.pread(buffer.data(), 1, previous_position) == 1)
198 {
199 in_pos = previous_position;
200 setg(buffer.data(), buffer.data() + 1, buffer.data() + 1);
201 }
202 }
203
204 if (gptr() > eback())
205 {
206 gbump(-1);
207 if (!traits_type::eq_int_type(c, traits_type::eof()))
208 {
209 const char cc = traits_type::to_char_type(c);
210 if (*gptr() != cc)
211 {
212 *gptr() = cc;
213 file.pwrite(gptr(), 1, in_pos + gptr() - eback());
214 }
215 }
216 return traits_type::to_int_type(*gptr());
217 }
218
219 return traits_type::eof();
220 }
221
222 ////////////////////////////////////////////////////////////////////////////
224 ////////////////////////////////////////////////////////////////////////////
225 {
226 in_pos = 0;
227 setg(buffer.data(), buffer.data(), buffer.data());
228
229 out_pos = 0;
230 setp(buffer.data(), buffer.data() + buffer.size());
231 }
232
233 ////////////////////////////////////////////////////////////////////////////
235 ////////////////////////////////////////////////////////////////////////////
236 {
237 if (pptr() > pbase())
238 {
239 Destructor_Logger::warning("filebuf: flushing buffer");
240 try {syncp();} catch (...) {}
241 }
242 }
243}
virtual int64_t get_size() const
Get the size of the file, or -1 if it is unknown.
virtual void pwrite(const char *data, size_t size, int64_t offset)
Write a range of bytes. Extend file size if necessary.
virtual size_t pread(char *data, size_t size, int64_t offset) const
Read a range of bytes.
static void warning(beman::cstring_view message) noexcept
int sync() override
Definition filebuf.cpp:80
pos_type seekpos(pos_type pos, std::ios_base::openmode which) override
Definition filebuf.cpp:63
pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) override
Definition filebuf.cpp:32
std::streamsize showmanyc() override
Definition filebuf.cpp:89
filebuf(Abstract_File &file)
Definition filebuf.cpp:223
~filebuf() override
Definition filebuf.cpp:234
int_type pbackfail(int_type c) override
Definition filebuf.cpp:191
int_type overflow(int_type ch) override
Definition filebuf.cpp:175
std::streamsize xsputn(const char_type *s, std::streamsize count) override
Definition filebuf.cpp:154
int_type underflow() override
Definition filebuf.cpp:99
std::streamsize xsgetn(char_type *s, std::streamsize count) override
Definition filebuf.cpp:115