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