Skip to content

Commit

Permalink
Merge pull request #12 from vibe-d/fixedappender_bufferoverflowmode
Browse files Browse the repository at this point in the history
Add BufferOverflowMode for FixedAppender
  • Loading branch information
s-ludwig authored Apr 2, 2024
2 parents 2f07fa6 + 9be7953 commit e26da4d
Showing 1 changed file with 60 additions and 1 deletion.
61 changes: 60 additions & 1 deletion source/vibe/container/internal/appender.d
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ unittest {
}


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

void put(E el)
{
static if (OM == BufferOverflowMode.exception) {
if (m_fill >= m_data.length)
throw new Exception("Writing past end of FixedAppender");
} else static if (OM == BufferOverflowMode.ignore) {
if (m_fill >= m_data.length)
return;
}

m_data[m_fill++] = el;
}

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

void put(ArrayType arr)
{
static if (OM == BufferOverflowMode.exception) {
if (m_fill + arr.length > m_data.length) {
put(arr[0 .. m_data.length - m_fill]);
throw new Exception("Writing past end of FixedAppender");
}
} else static if (OM == BufferOverflowMode.ignore) {
if (m_fill + arr.length > m_data.length) {
put(arr[0 .. m_data.length - m_fill]);
return;
}
}

m_data[m_fill .. m_fill+arr.length] = arr[];
m_fill += arr.length;
}
Expand All @@ -271,3 +291,42 @@ unittest {
app.put("ar");
assert(app.data == "foobar");
}

unittest {
import std.exception : assertThrown;
import std.format : formattedWrite;

FixedAppender!(string, 8) fa1;
fa1.formattedWrite("foo: %s", 42);
assert(fa1.data == "foo: 42");

FixedAppender!(string, 6, BufferOverflowMode.exception) fa2;
fa2.formattedWrite("foo: %s", 1);
assert(fa2.data == "foo: 1");
fa2.clear();
assertThrown(fa2.formattedWrite("foo: %s", 42));
assert(fa2.data == "foo: 4");
assertThrown(fa2.put('\a'));
assertThrown(fa2.put("bc"));
assert(fa2.data == "foo: 4");

FixedAppender!(string, 6, BufferOverflowMode.ignore) fa3;
fa3.formattedWrite("foo: %s", 1);
assert(fa3.data == "foo: 1");
fa3.clear();
fa3.formattedWrite("foo: %s", 42);
assert(fa2.data == "foo: 4");
fa3.put('\a');
fa3.put("bc");
assert(fa3.data == "foo: 4");
}


/** Determines how to handle buffer overflows in `FixedAppender`.
*/
enum BufferOverflowMode {
none, /// Results in an ArrayBoundsError and terminates the application
exception, /// Throws an exception
ignore /// Skips any extraneous bytes written
}

0 comments on commit e26da4d

Please sign in to comment.