1 /++ 2 + Authors: Stephan Dilly (@extrawurst), lastname dot firstname at gmail dot com 3 + Copyright: Stephan Dilly 4 + License: MIT 5 +/ 6 module unecht.core.staticRingBuffer; 7 8 @safe @nogc: 9 10 /// @nogc @safe ringbuffer using static memory block 11 struct StaticRingBuffer(size_t size, T) 12 { 13 /// 14 enum StaticSize = size; 15 16 private T[size] data; 17 private size_t spaceUsed; 18 19 /// append operator 20 ref auto opOpAssign(string op)(T v) @trusted nothrow if (op == "~") 21 { 22 if (spaceUsed < StaticSize) 23 { 24 data[spaceUsed++] = v; 25 } 26 else 27 { 28 import core.stdc..string : memmove; 29 30 memmove(data.ptr, data.ptr + 1, (StaticSize - 1) * T.sizeof); 31 data[StaticSize - 1] = v; 32 } 33 34 return this; 35 } 36 37 /// 38 unittest 39 { 40 StaticRingBuffer!(2, int) foo; 41 42 // append operator 43 foo ~= 1; 44 foo ~= 2; 45 46 assert(foo[0] == 1); 47 assert(foo[1] == 2); 48 } 49 50 /// random access operator 51 auto ref opIndex(size_t idx) 52 { 53 static immutable exc = new Exception("idx out of range"); 54 55 if (idx >= spaceUsed) 56 throw exc; 57 58 return data[idx]; 59 } 60 61 /// 62 unittest 63 { 64 StaticRingBuffer!(2, int) foo; 65 66 foo ~= 1; 67 68 assert(foo[0] == 1); 69 70 foo[0] = 2; 71 72 assert(foo[0] == 2); 73 } 74 75 /// current amount of elements used in the buffer 76 @property size_t length() const nothrow 77 { 78 return spaceUsed; 79 } 80 81 /// 82 unittest 83 { 84 StaticRingBuffer!(2, int) foo; 85 86 assert(foo.length == 0); 87 88 foo ~= 1; 89 90 assert(foo.length == 1); 91 92 foo ~= 1; 93 94 assert(foo.length == 2); 95 96 // append but let first element drop out 97 foo ~= 1; 98 99 assert(foo.length == 2); 100 } 101 102 /// 103 @property T* ptr() nothrow 104 { 105 return &data[0]; 106 } 107 } 108 109 /// 110 unittest 111 { 112 StaticRingBuffer!(2, int) foo; 113 assert(foo.length == 0); 114 115 foo ~= 1; 116 117 assert(foo.length == 1); 118 assert(foo[0] == 1); 119 120 foo ~= 2; 121 122 assert(foo.length == 2); 123 assert(foo[0] == 1); 124 assert(foo[1] == 2); 125 126 foo ~= 3; 127 128 assert(foo.length == 2); 129 assert(foo[0] == 2); 130 assert(foo[1] == 3); 131 }