Skip to content

Commit e26da4d

Browse files
authored
Merge pull request #12 from vibe-d/fixedappender_bufferoverflowmode
Add BufferOverflowMode for FixedAppender
2 parents 2f07fa6 + 9be7953 commit e26da4d

File tree

1 file changed

+60
-1
lines changed

1 file changed

+60
-1
lines changed

source/vibe/container/internal/appender.d

+60-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ unittest {
208208
}
209209

210210

211-
struct FixedAppender(ArrayType : E[], size_t NELEM, E) {
211+
struct FixedAppender(ArrayType : E[], size_t NELEM, BufferOverflowMode OM = BufferOverflowMode.none, E) {
212212
alias ElemType = Unqual!E;
213213
private {
214214
ElemType[NELEM] m_data;
@@ -222,6 +222,14 @@ struct FixedAppender(ArrayType : E[], size_t NELEM, E) {
222222

223223
void put(E el)
224224
{
225+
static if (OM == BufferOverflowMode.exception) {
226+
if (m_fill >= m_data.length)
227+
throw new Exception("Writing past end of FixedAppender");
228+
} else static if (OM == BufferOverflowMode.ignore) {
229+
if (m_fill >= m_data.length)
230+
return;
231+
}
232+
225233
m_data[m_fill++] = el;
226234
}
227235

@@ -253,6 +261,18 @@ struct FixedAppender(ArrayType : E[], size_t NELEM, E) {
253261

254262
void put(ArrayType arr)
255263
{
264+
static if (OM == BufferOverflowMode.exception) {
265+
if (m_fill + arr.length > m_data.length) {
266+
put(arr[0 .. m_data.length - m_fill]);
267+
throw new Exception("Writing past end of FixedAppender");
268+
}
269+
} else static if (OM == BufferOverflowMode.ignore) {
270+
if (m_fill + arr.length > m_data.length) {
271+
put(arr[0 .. m_data.length - m_fill]);
272+
return;
273+
}
274+
}
275+
256276
m_data[m_fill .. m_fill+arr.length] = arr[];
257277
m_fill += arr.length;
258278
}
@@ -271,3 +291,42 @@ unittest {
271291
app.put("ar");
272292
assert(app.data == "foobar");
273293
}
294+
295+
unittest {
296+
import std.exception : assertThrown;
297+
import std.format : formattedWrite;
298+
299+
FixedAppender!(string, 8) fa1;
300+
fa1.formattedWrite("foo: %s", 42);
301+
assert(fa1.data == "foo: 42");
302+
303+
FixedAppender!(string, 6, BufferOverflowMode.exception) fa2;
304+
fa2.formattedWrite("foo: %s", 1);
305+
assert(fa2.data == "foo: 1");
306+
fa2.clear();
307+
assertThrown(fa2.formattedWrite("foo: %s", 42));
308+
assert(fa2.data == "foo: 4");
309+
assertThrown(fa2.put('\a'));
310+
assertThrown(fa2.put("bc"));
311+
assert(fa2.data == "foo: 4");
312+
313+
FixedAppender!(string, 6, BufferOverflowMode.ignore) fa3;
314+
fa3.formattedWrite("foo: %s", 1);
315+
assert(fa3.data == "foo: 1");
316+
fa3.clear();
317+
fa3.formattedWrite("foo: %s", 42);
318+
assert(fa2.data == "foo: 4");
319+
fa3.put('\a');
320+
fa3.put("bc");
321+
assert(fa3.data == "foo: 4");
322+
}
323+
324+
325+
/** Determines how to handle buffer overflows in `FixedAppender`.
326+
*/
327+
enum BufferOverflowMode {
328+
none, /// Results in an ArrayBoundsError and terminates the application
329+
exception, /// Throws an exception
330+
ignore /// Skips any extraneous bytes written
331+
}
332+

0 commit comments

Comments
 (0)