1 /** Helpers used by containers. 2 */ 3 module nxt.container.common; 4 5 /** Growth strategy. 6 */ 7 enum GrowthStrategy { 8 grow_2, // 2.0 9 grow_3over2, // 1.5 10 } 11 12 /** Reserve room for `extra` more elements in `x`. 13 */ 14 size_t reserveWithGrowth(GrowthStrategy gs, T)(ref T x, size_t extra) 15 if (is(typeof(T.init.capacity) : size_t) && 16 is(typeof(x.reserve(size_t.init)) == size_t)) 17 { 18 const newCapacity = x.capacity + extra; 19 static if (gs == GrowthStrategy.grow_2) 20 return x.reserve(newCapacity); 21 else static if (gs == GrowthStrategy.grow_3over2) 22 return x.reserve(newCapacity); 23 else 24 static assert(0, "Unknown growth strategy " ~ gs.stringof); 25 } 26 27 @safe pure nothrow unittest { 28 int[] x; 29 x.reserve(2); 30 x.reserveWithGrowth!(GrowthStrategy.grow_2)(1); 31 assert(x.capacity >= 3); 32 } 33 34 /** Try to pop first occurrence of `needle` in `haystack` (if any). 35 Returns: `true` iff pop was made, `false` otherwise. 36 */ 37 bool popFirstMaybe(alias pred = "a == b", C, E)(ref C haystack, in E needle) 38 if (__traits(hasMember, C, "length") && 39 __traits(hasMember, C, "popAt")) 40 // TODO: activate this restriction 41 // if (hasSlicing!C && 42 // is(ElementType!C == E.init)) 43 { 44 import std.functional : binaryFun; 45 // doesn't work for uncopyable element types: import std.algorithm.searching : countUntil; 46 size_t offset = 0; 47 foreach (const ref e; haystack[]) 48 { 49 if (binaryFun!pred(e, needle)) 50 break; 51 offset += 1; 52 } 53 if (offset != haystack.length) 54 { 55 haystack.popAt(offset); 56 return true; 57 } 58 return false; 59 } 60 61 /** Remove element at index `index` in `r`. 62 * 63 * TODO: reuse in array*.d 64 * TODO: better name removeAt 65 */ 66 void shiftToFrontAt(T)(T[] r, size_t index) @trusted 67 { 68 assert(index + 1 <= r.length); 69 70 // TODO: use this instead: 71 // immutable si = index + 1; // source index 72 // immutable ti = index; // target index 73 // immutable restLength = this.length - (index + 1); 74 // moveEmplaceAll(_store.ptr[si .. si + restLength], 75 // _store.ptr[ti .. ti + restLength]); 76 77 // for each element index that needs to be moved 78 foreach (immutable i; 0 .. r.length - (index + 1)) 79 { 80 immutable si = index + i + 1; // source index 81 immutable ti = index + i; // target index 82 import core.lifetime : moveEmplace; 83 moveEmplace(r.ptr[si], // TODO: remove `move` when compiler does it for us 84 r.ptr[ti]); 85 } 86 } 87 88 @safe pure nothrow @nogc unittest 89 { 90 int[4] x = [11, 12, 13, 14]; 91 x[].shiftToFrontAt(1); 92 assert(x == [11, 13, 14, 14]); 93 }