1 /** 2 * Tools for building up arrays without using the GC. 3 * Copyright: © 2014 Economic Modeling Specialists, Intl. 4 * Authors: Brian Schott 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt Boost, License 1.0) 6 */ 7 8 module memory.appender; 9 10 /** 11 * Allocator-backed array appender. 12 */ 13 struct Appender(T, A, size_t initialSize = 10) 14 { 15 public: 16 17 @disable this(); 18 19 /** 20 * Params: 21 * allocator = the allocator to use 22 */ 23 this()(auto ref A allocator) 24 { 25 this.allocator = allocator; 26 mem = cast(T[]) allocator.allocate(initialSize * T.sizeof); 27 assert (mem.length == initialSize); 28 } 29 30 /** 31 * Returns: all of the items 32 */ 33 T[] opSlice() 34 { 35 return mem[0 .. next]; 36 } 37 38 alias put = append; 39 40 /** 41 * Appends an item. 42 */ 43 void append(T item) @trusted 44 { 45 if (next >= mem.length) 46 { 47 next = mem.length; 48 immutable newSize = T.sizeof * (mem.length << 1); 49 void[] original = cast(void[]) mem; 50 assert (original.ptr is mem.ptr); 51 assert (mem); 52 assert (original); 53 assert (original.length == mem.length * T.sizeof); 54 bool success = allocator.reallocate(original, newSize); 55 assert (success); 56 mem = cast(T[]) original; 57 assert (mem.ptr == original.ptr); 58 } 59 assert (next < mem.length); 60 mem[next++] = item; 61 } 62 63 void append(inout(T)[] items) @trusted 64 { 65 foreach (ref i; items) 66 append(i); 67 } 68 69 void reset() 70 { 71 next = 0; 72 } 73 74 T[] mem; 75 76 private: 77 import memory.allocators; 78 size_t next; 79 80 A allocator; 81 } 82 83 unittest 84 { 85 import std.allocator; 86 auto a = Appender!(int, shared Mallocator, 64)(Mallocator.it); 87 foreach (i; 0 .. 20) 88 a.append(i); 89 assert (a[].length == 20); 90 Mallocator.it.deallocate(a.mem); 91 }