1 /* 2 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 Authors: Adam Búš 4 */ 5 module btl.vector.storage; 6 7 8 9 10 package template Storage(T, size_t N, bool allowHeap){ 11 12 struct Storage{ 13 public alias Inline = InlineStorage!(T, N); 14 15 public alias Heap = HeapStorage!(T, allowHeap); 16 17 public enum size_t minimalCapacity = Inline.capacity; 18 19 public enum size_t maximalCapacity = allowHeap ? size_t.max : N; 20 21 public size_t length; 22 23 union{ 24 static if(N > 0){ 25 private Inline _inline; 26 private Heap _heap; 27 } 28 else{ 29 private Heap _heap; 30 private Inline _inline; 31 } 32 } 33 34 pragma(inline, true){ 35 public static size_t heapCapacity(size_t new_capacity)pure nothrow @safe @nogc{ 36 new_capacity |= heapFlag; 37 assert(new_capacity > minimalCapacity); 38 assert(new_capacity <= maximalCapacity); 39 40 return new_capacity; 41 } 42 43 public void reset()pure nothrow @trusted @nogc{ 44 this.length = 0; 45 46 47 static if(N){ 48 this._inline.reset(); 49 } 50 else static if(allowHeap){ 51 this._heap.capacity = 0; 52 this._heap.ptr = null; 53 54 } 55 } 56 57 public @property ref inout(Inline) inline()inout pure nothrow @trusted @nogc{ 58 return this._inline; 59 } 60 61 public @property ref inout(Heap) heap()inout pure nothrow @trusted @nogc{ 62 return this._heap; 63 } 64 public @property void heap(Heap h)pure nothrow @trusted @nogc{ 65 static if(allowHeap){ 66 assert(this.length <= h.capacity); 67 this._heap.capacity = h.capacity; 68 assert(this.external); 69 this._heap.ptr = h.ptr; 70 } 71 else{ 72 assert(0, "no impl"); 73 } 74 } 75 76 public @property size_t capacity()scope const pure nothrow @safe @nogc{ 77 return this.external 78 ? this.heap.capacity 79 : this.inline.capacity; 80 } 81 82 public @property inout(T)* ptr()scope inout pure nothrow @trusted @nogc{ 83 return this.external 84 ? this.heap.ptr 85 : this.inline.ptr; 86 } 87 88 public @property inout(T)[] elements()scope inout pure nothrow @trusted @nogc{ 89 return this.external 90 ? this.heap.elements(this.length) 91 : this.inline.elements(this.length); 92 } 93 94 public @property inout(T)[] allocatedElements()inout return pure nothrow @trusted @nogc{ 95 return this.external 96 ? this.heap.allocatedElements() 97 : this.inline.allocatedElements(); 98 } 99 100 public @property bool external()const scope pure nothrow @trusted @nogc{ 101 static if(allowHeap && N) 102 return (this._inline.flag & heapFlag); 103 else 104 return allowHeap; 105 } 106 public @property void external(bool x)scope pure nothrow @trusted @nogc{ 107 static if(allowHeap && N) 108 this._inline.flag = x ? heapFlag : 0; 109 else 110 assert(0, "no impl"); 111 } 112 113 public @property bool small()const pure nothrow @trusted @nogc{ 114 static if(allowHeap){ 115 static if(N == 0) 116 return (this._heap.capacity == 0); 117 else 118 return !this.external; 119 } 120 else 121 return true; 122 } 123 } 124 125 } 126 127 enum ubyte heapFlag = allowHeap 128 ? 0x1 //heap capacity must be odd 129 : 0; 130 } 131 132 private struct InlineStorage(T, size_t N){ 133 public enum size_t capacity = N; //max(N, 2); 134 135 static if(N){ 136 public align(T.alignof)ubyte flag = 0; 137 public void[capacity * T.sizeof] storage; 138 } 139 else{ 140 public enum ubyte flag = 0; 141 public enum void[] storage = null; 142 } 143 144 145 pragma(inline, true){ 146 public void reset()pure nothrow @safe @nogc{ 147 static if(N) 148 this.flag = 0; 149 } 150 151 public @property inout(T)* ptr()inout pure nothrow @system @nogc{ 152 return cast(inout(T)*)storage.ptr; 153 } 154 155 public @property inout(void)[] data()inout pure nothrow @system @nogc{ 156 return storage[]; 157 } 158 159 public @property inout(T)[] elements(size_t length)inout pure nothrow @system @nogc{ 160 assert(length <= capacity); 161 return ptr[0 .. length]; 162 } 163 164 public @property inout(T)[] allocatedElements()inout pure nothrow @system @nogc{ 165 return ptr[0 .. capacity]; 166 } 167 } 168 } 169 170 private struct HeapStorage(T, bool allowHeap){ 171 172 static if(allowHeap){ 173 public size_t capacity; 174 public T* ptr; 175 } 176 else{ 177 public @property size_t capacity()const pure nothrow @safe @nogc{return 0;} 178 public @property void capacity(size_t)pure nothrow @safe @nogc{assert(0, "no impl");} 179 180 public @property inout(T)* ptr()inout pure nothrow @safe @nogc{return null;} 181 public @property void ptr(T*)pure nothrow @safe @nogc{assert(0, "no impl");} 182 } 183 184 pragma(inline, true){ 185 186 public @property inout(void)[] data()inout pure nothrow @trusted @nogc{ 187 return (cast(inout void*)ptr)[0 .. capacity * T.sizeof]; 188 } 189 190 public @property inout(T)[] elements(size_t length)inout pure nothrow @system @nogc{ 191 assert(length <= capacity); 192 return ptr[0 .. length]; 193 } 194 195 public @property inout(T)[] allocatedElements()inout pure nothrow @system @nogc{ 196 return ptr[0 .. capacity]; 197 } 198 } 199 }