@@ -208,7 +208,7 @@ unittest {
208
208
}
209
209
210
210
211
- struct FixedAppender (ArrayType : E[], size_t NELEM , E) {
211
+ struct FixedAppender (ArrayType : E[], size_t NELEM , BufferOverflowMode OM = BufferOverflowMode.none, E) {
212
212
alias ElemType = Unqual! E;
213
213
private {
214
214
ElemType[NELEM ] m_data;
@@ -222,6 +222,14 @@ struct FixedAppender(ArrayType : E[], size_t NELEM, E) {
222
222
223
223
void put (E el)
224
224
{
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
+
225
233
m_data[m_fill++ ] = el;
226
234
}
227
235
@@ -253,6 +261,18 @@ struct FixedAppender(ArrayType : E[], size_t NELEM, E) {
253
261
254
262
void put (ArrayType arr)
255
263
{
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
+
256
276
m_data[m_fill .. m_fill+ arr.length] = arr[];
257
277
m_fill += arr.length;
258
278
}
@@ -271,3 +291,42 @@ unittest {
271
291
app.put(" ar" );
272
292
assert (app.data == " foobar" );
273
293
}
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