1 /**
2 Copyright: Copyright (c) 2016-2017 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.container.buffer;
7 
8 import std.experimental.allocator.gc_allocator;
9 alias allocator = GCAllocator.instance;
10 
11 T nextPOT(T)(T x) {
12 	--x;
13 	x |= x >> 1;
14 	x |= x >> 2;
15 	x |= x >> 4;
16 	static if (T.sizeof >= 16) x |= x >>  8;
17 	static if (T.sizeof >= 32) x |= x >> 16;
18 	static if (T.sizeof >= 64) x |= x >> 32;
19 	++x;
20 
21 	return x;
22 }
23 
24 struct Buffer(T)
25 {
26 	T[] buf;
27 	private size_t length;
28 
29 	void put(T[] items ...)
30 	{
31 		reserve(items.length);
32 		buf[length..length+items.length] = items;
33 		length += items.length;
34 	}
35 
36 	void put(R)(R itemRange)
37 	{
38 		foreach(item; itemRange)
39 			put(item);
40 	}
41 
42 	void stealthPut(T item)
43 	{
44 		reserve(1);
45 		buf[length] = item;
46 	}
47 
48 	T[] data() {
49 		return buf[0..length];
50 	}
51 
52 	void clear() nothrow {
53 		length = 0;
54 	}
55 
56 	size_t capacity() @property {
57 		return buf.length - length;
58 	}
59 
60 	void reserve(size_t items)
61 	{
62 		if (buf.length - length < items)
63 		{
64 			size_t newCapacity = nextPOT(buf.length + items);
65 			void[] tmp = buf;
66 			allocator.reallocate(tmp, newCapacity*T.sizeof);
67 			buf = cast(T[])tmp;
68 		}
69 	}
70 }