DataBuffer

encapsulates using a local array as a temporary buffer. It is initialized with the local array that should be large enough for most uses. If the need exceeds the size, DataBuffer will resize it using malloc() and friends.

DataBuffer is an OutputRange.

Since DataBuffer potentially stores elements of type T in malloc'd memory, those elements are not scanned when the GC collects. This can cause memory corruption. Do not use DataBuffer when elements of type T point to the GC heap.

Constructors

this
this(T[] buf)

Initialize with buf to use as scratch buffer space.

Members

Aliases

opDollar
alias opDollar = length
Undocumented in source.

Functions

free
void free()

Releases any memory used. This will invalidate any references returned by the [] operator. A destructor is not used, because that would make it not POD (Plain Old Data) and it could not be placed in registers.

opIndex
T opIndex(size_t i)
opSlice
T[] opSlice(size_t lower, size_t upper)
inout(T[]) opSlice()

Retrieve a slice into the result.

put
void put(T c)

Append element c to the buffer. This member function makes DataBuffer an OutputRange.

put
void put(CT[] s)

Append array s to the buffer.

Properties

length
size_t length [@property getter]
length
size_t length [@property setter]

Used to shrink the length of the buffer, typically to 0 so the buffer can be reused. Cannot be used to extend the length of the buffer.

Examples

import core.stdc.stdio;
import DataBuffer.databuffer;
void main()
{
    char[2] buf = void;
    auto textbuf = DataBuffer!char(buf);
    scope(exit) textbuf.free(); // necessary for cleanup

    // Put characters and strings into textbuf, verify they got there
    textbuf.put('a');
    textbuf.put('x');
    textbuf.put("abc");
    assert(textbuf.length == 5);
    assert(textbuf[1..3] == "xa");
    assert(textbuf[3] == 'b');

    // Can shrink it
    textbuf.length = 3;
    assert(textbuf[0..textbuf.length] == "axa");
    assert(textbuf[textbuf.length - 1] == 'a');
    assert(textbuf[1..3] == "xa");

    textbuf.put('z');
    assert(textbuf[] == "axaz");

    // Can shrink it to 0 size, and reuse same memory
    textbuf.length = 0;
}

It is invalid to access DataBuffer's contents when DataBuffer goes out of scope. Hence, copying the contents are necessary to keep them around:

import fluent.databuffer;
string cat(string s1, string s2)
{
    char[10] tmpbuf = void;
    auto textbuf = DataBuffer!char(tmpbuf);
    scope(exit) textbuf.free();
    textbuf.put(s1);
    textbuf.put(s2);
    textbuf.put("even more");
    return textbuf[].idup;
}

DataBuffer is intended for high performance usages in @system and @trusted code. If used incorrectly, memory leaks and corruption can result. Be sure to use scope(exit) textbuf.free(); for proper cleanup, and do not refer to a DataBuffer instance's contents after DataBuffer.free() has been called.

The realloc parameter defaults to C's realloc(). Another can be supplied to override it.

DataBuffer instances may be copied, as in:

textbuf = doSomething(textbuf, args);

which can be very efficent, but these must be regarded as a move rather than a copy. Additionally, the code between passing and returning the instance must not throw exceptions, otherwise when DataBuffer.free() is called, memory may get corrupted.

Meta