1 module dparse.stack_buffer; 2 3 import std.traits; 4 5 //version = debug_stack_allocator; 6 7 struct StackBuffer 8 { 9 bool put(T)(T t) 10 { 11 import std.experimental.allocator.mallocator : Mallocator; 12 13 static if (is(T == class) || isPointer!T) 14 if (t is null) 15 return false; 16 17 if (_length == 0) 18 arr = stackSpace[]; 19 20 static if (is(T == class)) 21 static assert(T.sizeof == size_t.sizeof); 22 23 if (arr.ptr != stackSpace.ptr) 24 { 25 if (_length + T.sizeof > arr.length) 26 { 27 size_t newLength = arr.length << 1; 28 while (_length + T.sizeof > newLength) 29 newLength <<= 1; 30 Mallocator.instance.reallocate(arr, newLength); 31 version (debug_stack_allocator) 32 (cast(ubyte[]) arr)[_length .. $] = 0; 33 } 34 } 35 else if (_length + T.sizeof > stackSpace.length) 36 { 37 size_t newLength = stackSpace.length << 1; 38 while (_length + T.sizeof > newLength) 39 newLength <<= 1; 40 arr = Mallocator.instance.allocate(newLength); 41 version (debug_stack_allocator) 42 (cast(ubyte[]) arr)[] = 0; 43 arr[0 .. stackSpace.length] = stackSpace[]; 44 } 45 arr[_length .. _length + T.sizeof] = (cast(void*) &t)[0 .. T.sizeof]; 46 _length += T.sizeof; 47 return true; 48 } 49 50 ~this() 51 { 52 import std.experimental.allocator.mallocator:Mallocator; 53 54 version (debug_stack_allocator) 55 (cast(ubyte[]) arr)[] = 0; 56 if (arr.ptr !is stackSpace.ptr) 57 Mallocator.instance.deallocate(arr); 58 } 59 60 void[] opSlice() 61 { 62 return arr[0 .. _length]; 63 } 64 65 @disable this(this); 66 67 uint length() const pure nothrow @nogc @safe @property 68 { 69 return _length; 70 } 71 72 alias opDollar = length; 73 74 auto opIndex(size_t i) 75 { 76 return arr[i]; 77 } 78 79 private: 80 81 void[8 * 16] stackSpace; 82 void[] arr; 83 uint _length; 84 } 85 86 unittest 87 { 88 StackBuffer sb; 89 ubyte[80] u; 90 sb.put(u); 91 assert(sb.length == 80); 92 static struct S 93 { 94 void[100] u; 95 } 96 97 S s; 98 sb.put(s); 99 }