A gutted, @nogc version of Appender.
This commit is contained in:
parent
cac40a6a85
commit
5f27ab26c7
|
@ -63,3 +63,127 @@ body
|
|||
assert(!atStart, "Nothing to parse in parse()");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue