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 }