A gutted, @nogc version of Appender.

This commit is contained in:
Ferdinand Majerech 2014-07-25 16:51:56 +02:00
parent cac40a6a85
commit 5f27ab26c7

View file

@ -63,3 +63,127 @@ body
assert(!atStart, "Nothing to parse in parse()"); assert(!atStart, "Nothing to parse in parse()");
return v; return v;
} }
/// Convenience function that returns an $(D AppenderNoGCFixed!A) using with $(D array)
/// for storage.
AppenderNoGCFixed!(E[]) appenderNoGC(A : E[], E)(A array)
{
return AppenderNoGCFixed!(E[])(array);
}
/// A gutted, NoGC version of std.array.appender.
///
/// Works on a fixed-size buffer.
struct AppenderNoGCFixed(A : T[], T)
{
import std.array;
import std.traits;
private struct Data
{
size_t capacity;
Unqual!T[] arr;
bool canExtend = false;
}
private Data _data;
@nogc:
/// Construct an appender that will work with given buffer.
///
/// Data written to the appender will overwrite the buffer from the start.
this(T[] arr) @trusted pure nothrow
{
// initialize to a given array.
_data.arr = cast(Unqual!T[])arr[0 .. 0]; //trusted
if (__ctfe)
return;
_data.capacity = arr.length;
}
/**
* Returns the capacity of the array (the maximum number of elements the
* managed array can accommodate before triggering a reallocation). If any
* appending will reallocate, $(D capacity) returns $(D 0).
*/
@property size_t capacity() const @safe pure nothrow
{
return _data.capacity;
}
/**
* Returns the managed array.
*/
@property inout(T)[] data() inout @trusted pure nothrow
{
/* @trusted operation:
* casting Unqual!T[] to inout(T)[]
*/
return cast(typeof(return))(_data.arr);
}
// ensure we can add nelems elements, resizing as necessary
private void ensureAddable(size_t nelems) @safe pure nothrow
{
assert(_data.capacity >= _data.arr.length + nelems,
"AppenderFixed ran out of space");
}
/**
* Appends one item to the managed array.
*/
void put(U)(U item) if (is(Unqual!U == T))
{
ensureAddable(1);
immutable len = _data.arr.length;
auto bigDataFun() @trusted nothrow { return _data.arr.ptr[0 .. len + 1];}
auto bigData = bigDataFun();
emplaceRef!T(bigData[len], item);
//We do this at the end, in case of exceptions
_data.arr = bigData;
}
void put(U)(U[] items) if (is(Unqual!U == T))
{
// make sure we have enough space, then add the items
ensureAddable(items.length);
immutable len = _data.arr.length;
immutable newlen = len + items.length;
auto bigDataFun() @trusted nothrow { return _data.arr.ptr[0 .. newlen];}
auto bigData = bigDataFun();
alias UT = Unqual!T;
bigData[len .. newlen] = items[];
//We do this at the end, in case of exceptions
_data.arr = bigData;
}
// only allow overwriting data on non-immutable and non-const data
static if (isMutable!T)
{
/**
* Clears the managed array. This allows the elements of the array to be reused
* for appending.
*
* Note that clear is disabled for immutable or const element types, due to the
* possibility that $(D AppenderNoGCFixed) might overwrite immutable data.
*/
void clear() @safe pure nothrow
{
_data.arr = ()@trusted{ return _data.arr.ptr[0 .. 0]; }();
}
}
else
{
/// Clear is not available for const/immutable data.
@disable void clear();
}
}