1 module simplefixedsizearray; 2 3 struct SFA(T,size_t Size = 32) { 4 static assert(Size > 0); 5 import std.traits : CopyTypeQualifiers, hasElaborateDestructor, hasMember; 6 7 size_t length; 8 ubyte[T.sizeof * Size] store; 9 10 ~this() { 11 static if(hasElaborateDestructor!T) { 12 this.removeAll(); 13 } 14 } 15 16 struct SFARange(S,U) { 17 S* ptr; 18 size_t low; 19 size_t high; 20 21 @property bool empty() const pure @safe nothrow @nogc { 22 return this.low >= this.high; 23 } 24 25 pragma(inline, true) 26 @property size_t length() pure @safe nothrow @nogc { 27 return cast(size_t)(this.high - this.low); 28 } 29 30 @property ref U front() { 31 return (*this.ptr)[this.low]; 32 } 33 34 @property ref U back() { 35 return (*this.ptr)[this.high]; 36 } 37 38 ref T opIndex(const size_t idx) { 39 return (*this.fsa)[this.low + idx]; 40 } 41 42 void popFront() pure @safe nothrow @nogc { 43 ++this.low; 44 } 45 46 void popBack() pure @safe nothrow @nogc { 47 --this.high; 48 } 49 50 @property typeof(this) save() pure @safe nothrow @nogc { 51 return this; 52 } 53 } 54 55 SFARange!(typeof(this), CopyTypeQualifiers!(S,T)) opSlice(this S)(size_t low, size_t high) { 56 assert(low <= high); 57 assert(low <= this.length); 58 return typeof(return)(&this, low, high); 59 } 60 61 @property bool empty() const @safe @nogc nothrow { 62 return this.length == 0U; 63 } 64 65 @property bool hasCapacity() const @safe @nogc nothrow { 66 return (this.length * T.sizeof) < this.store.length; 67 } 68 69 void insertBack(T t) { 70 assert(this.length + 1 <= Size); 71 *(cast(T*)(&this.store[cast(size_t)(this.length * T.sizeof)])) = t; 72 ++length; 73 } 74 75 ref CopyTypeQualifiers!(S,T) opIndex(this S)(size_t idx) { 76 idx *= T.sizeof; 77 assert(idx < this.store.length); 78 return *(cast(T*)&(this.store[idx])); 79 } 80 81 @property ref CopyTypeQualifiers!(S,T) front(this S)() { 82 assert(!this.empty); 83 return *(cast(T*)(&this.store[0U])); 84 } 85 86 @property ref CopyTypeQualifiers!(S,T) back(this S)() { 87 import std.stdio; 88 assert(!this.empty); 89 return *(cast(T*)(&this.store[(this.length * T.sizeof) - T.sizeof])); 90 } 91 92 void removeAll() { 93 while(!this.empty) { 94 this.removeBack(); 95 } 96 } 97 98 void removeBack() { 99 assert(!this.empty); 100 101 static if(hasElaborateDestructor!T) { 102 static if(hasMember!(T, "__dtor")) { 103 this.back().__dtor(); 104 } else static if(hasMember!(T, "__xdtor")) { 105 this.back().__xdtor(); 106 } else { 107 static assert(false); 108 } 109 } 110 111 --this.length; 112 } 113 114 void remove(size_t idx) { 115 assert(idx < this.length); 116 static if(hasElaborateDestructor!T) { 117 static if(hasMember!(T, "__dtor")) { 118 this[idx].__dtor(); 119 } else static if(hasMember!(T, "__xdtor")) { 120 this[idx].__xdtor(); 121 } else { 122 static assert(false); 123 } 124 } 125 126 for(size_t i = idx * T.sizeof; i < ((this.length - 1U) * T.sizeof); ++i) { 127 this.store[i] = this.store[i + T.sizeof]; 128 } 129 130 --this.length; 131 } 132 } 133 134 unittest { 135 SFA!(int) a; 136 } 137 138 unittest { 139 SFA!(int) a; 140 assert(a.hasCapacity); 141 a.insertBack(10); 142 assert(a[0] == 10); 143 assert(a.front == 10); 144 assert(a.back == 10); 145 a.removeBack(); 146 assert(a.empty); 147 } 148 149 unittest { 150 struct Foo { 151 size_t value; 152 alias value this; 153 154 ~this() { 155 } 156 } 157 158 void test(size_t Size, T)() { 159 SFA!(T, Size) a; 160 assert(a.empty); 161 foreach(it; 0 .. Size) { 162 assert(a.hasCapacity); 163 a.insertBack(T(it)); 164 assert(a.length == it + 1); 165 assert(a.front == 0); 166 assert(a.back == it); 167 168 foreach(jt; 0 .. it + 1) { 169 assert(a[jt] == jt); 170 } 171 172 auto r = a[0 .. a.length - 1]; 173 assert(r.front == 0); 174 assert(r.back == it); 175 } 176 assert(!a.hasCapacity); 177 } 178 179 static foreach(tSize; [1,2,3,4,5,10,11,32,63,64]) { 180 test!(tSize, size_t)(); 181 test!(tSize, Foo)(); 182 } 183 } 184 185 unittest { 186 import std.stdio; 187 SFA!(int) a; 188 foreach(it; [0,1,2,3,4,5,6,7,8,9]) { 189 a.insertBack(it); 190 } 191 192 a.remove(5); 193 194 foreach(idx, it; [0,1,2,3,4,6,7,8,9]) { 195 assert(a[idx] == it); 196 } 197 } 198 199 unittest { 200 SFA!int a; 201 a.insertBack(1337); 202 a.remove(0); 203 assert(a.empty); 204 }