1 module dkh.container.stackpayload; 2 3 /** 4 Stack Payload 5 6 If you don't need dark speed, you should use dkh.container.stack 7 */ 8 struct StackPayload(T, size_t MINCAP = 4) if (MINCAP >= 1) { 9 import core.exception : RangeError; 10 11 private T* _data; 12 private uint len, cap; 13 14 @property bool empty() const { return len == 0; } 15 @property size_t length() const { return len; } 16 alias opDollar = length; 17 18 /** 19 Data Slice 20 Warning: Return value points same place with stackpayload 21 */ 22 inout(T)[] data() inout { return (_data) ? _data[0..len] : null; } 23 24 ref inout(T) opIndex(size_t i) inout { 25 version(assert) if (len <= i) throw new RangeError(); 26 return _data[i]; 27 } /// 28 ref inout(T) front() inout { return this[0]; } /// 29 ref inout(T) back() inout { return this[$-1]; } /// 30 31 void reserve(size_t newCap) { 32 import core.memory : GC; 33 import core.stdc..string : memcpy; 34 import std.conv : to; 35 if (newCap <= cap) return; 36 void* newData = GC.malloc(newCap * T.sizeof); 37 cap = newCap.to!uint; 38 if (len) memcpy(newData, _data, len * T.sizeof); 39 _data = cast(T*)(newData); 40 } /// 41 void free() { 42 import core.memory : GC; 43 GC.free(_data); 44 } /// 45 /// This method don't release memory 46 void clear() { 47 len = 0; 48 } 49 50 void insertBack(T item) { 51 import std.algorithm : max; 52 if (len == cap) reserve(max(cap * 2, MINCAP)); 53 _data[len++] = item; 54 } /// 55 alias opOpAssign(string op : "~") = insertBack; /// ditto 56 void removeBack() { 57 assert(!empty, "StackPayload.removeBack: Stack is empty"); 58 len--; 59 } /// 60 } 61 62 unittest { 63 import std.algorithm : equal; 64 auto u = StackPayload!int(); 65 u ~= 4; u ~= 5; 66 assert(equal(u.data, [4, 5])); 67 }