Add custom fill value to std.outbuffer.OutBuffer class

Extend the fill, alignSize, align{2,4} methods of `std.outbuffer.OutBuffer` to specify value to write
when filling (up to an alignment).

For flash device images it is desirable to use 0xff as the fill value,
because 0xff is the value of the unprogrammed flash memory cell. Padding
with 0 requires to programm the flash cell from 0xff to 0x00, which
increases wear and tear on the flash memory device. Usually there is some
larger block at the end if the flash memory image, which must be padded
up to the size of the flash device (usuallay a power of two). Instead
of padding with 0x00 the PR allows to fill with 0xff instead.

There might also be other use-cases, where it might be reasonable to fill
the alignment gaps with some other value than 0x00, e.g. when debugging
and viewing output data in a hex editor. It is easier to spot gaps, when
the padded spaces contain a custom value like 0x55 or 0xaa.

A new fill method was added, which allows filling with a user-defined value
instead of the 0 as in the previous implementation.
This commit is contained in:
Carsten Schlote 2022-04-29 10:23:42 +02:00
parent 707eb37656
commit f434dc3cae

View file

@ -173,21 +173,40 @@ class OutBuffer
}
/****************************************
* Append nbytes of 0 to the internal buffer.
* Append nbytes of val to the internal buffer.
* Params:
* nbytes = Number of bytes to fill.
* val = Value to fill, defaults to 0.
*/
void fill0(size_t nbytes)
void fill(size_t nbytes, ubyte val = 0)
{
reserve(nbytes);
data[offset .. offset + nbytes] = 0;
data[offset .. offset + nbytes] = val;
offset += nbytes;
}
/****************************************
* Append nbytes of 0 to the internal buffer.
* Param:
* nbytes - number of bytes to fill.
*/
void fill0(size_t nbytes)
{
fill(nbytes);
}
/**********************************
* 0-fill to align on power of 2 boundary.
* Append bytes until the buffer aligns on a power of 2 boundary.
*
* By default fills with 0 bytes.
*
* Params:
* alignsize = Alignment value. Must be power of 2.
* val = Value to fill, defaults to 0.
*/
void alignSize(size_t alignsize)
void alignSize(size_t alignsize, ubyte val = 0)
in
{
assert(alignsize && (alignsize & (alignsize - 1)) == 0);
@ -200,7 +219,35 @@ class OutBuffer
{
auto nbytes = offset & (alignsize - 1);
if (nbytes)
fill0(alignsize - nbytes);
fill(alignsize - nbytes, val);
}
///
@safe unittest
{
OutBuffer buf = new OutBuffer();
buf.write(cast(ubyte)1);
buf.align2();
assert(buf.toBytes() == "\x01\x00");
buf.write(cast(ubyte)2);
buf.align4();
assert(buf.toBytes() == "\x01\x00\x02\x00");
buf.write(cast(ubyte)3);
buf.alignSize(8);
assert(buf.toBytes() == "\x01\x00\x02\x00\x03\x00\x00\x00");
}
/// ditto
@safe unittest
{
OutBuffer buf = new OutBuffer();
buf.write(cast(ubyte)1);
buf.align2(0x55);
assert(buf.toBytes() == "\x01\x55");
buf.write(cast(ubyte)2);
buf.align4(0x55);
assert(buf.toBytes() == "\x01\x55\x02\x55");
buf.write(cast(ubyte)3);
buf.alignSize(8, 0x55);
assert(buf.toBytes() == "\x01\x55\x02\x55\x03\x55\x55\x55");
}
/// Clear the data in the buffer
@ -211,23 +258,27 @@ class OutBuffer
/****************************************
* Optimize common special case alignSize(2)
* Params:
* val = Value to fill, defaults to 0.
*/
void align2()
void align2(ubyte val = 0)
{
if (offset & 1)
write(cast(byte) 0);
write(cast(byte) val);
}
/****************************************
* Optimize common special case alignSize(4)
* Params:
* val = Value to fill, defaults to 0.
*/
void align4()
void align4(ubyte val = 0)
{
if (offset & 3)
{ auto nbytes = (4 - offset) & 3;
fill0(nbytes);
fill(nbytes, val);
}
}