1 module nxt.container.tree;
2 
3 /** N-ary tree that cannot shrink but only grow (in breadth and depth).
4  *
5  * Because of this a region allocator can be used for internal memory
6  * allocation.
7  *
8  * See_Also: http://forum.dlang.org/post/prsxfcmkngfwomygmthi@forum.dlang.org
9  */
10 struct GrowOnlyNaryTree(E) {
11 	alias N = Node!E;
12 
13 	/* @safe pure: */
14 public:
15 
16 	/// Create with region size in bytes.
17 	this(size_t regionSize) @trusted
18 	{
19 		_allocator = Allocator(regionSize);
20 	}
21 
22 	this(in E e, size_t regionSize) @trusted
23 	{
24 		_allocator = Allocator(regionSize);
25 		_root = _allocator.make!N(e);
26 	}
27 
28 	/// Returns: top node.
29 	inout(Node!E)* root() inout return scope
30 	{
31 		return _root;
32 	}
33 
34 private:
35 	N* _root;
36 
37 	import std.experimental.allocator : make, makeArray;
38 	import std.experimental.allocator.building_blocks.region : Region;
39 	import std.experimental.allocator.mallocator : Mallocator;
40 	alias Allocator = Region!Mallocator;
41 
42 	Allocator _allocator;
43 }
44 
45 /*@safe*/ unittest {
46 	struct X { string src; }
47 
48 	const e = X("alpha");
49 	auto tree = GrowOnlyNaryTree!X(e, 1024 * 1024);
50 	assert(tree.root.data == e);
51 
52 	/+ TODO: this should fail to compile with -dip1000 +/
53 	Node!X* dumb() {
54 		auto tree = GrowOnlyNaryTree!X(e, 1024 * 1024);
55 		return tree.root;
56 	}
57 
58 	dumb();
59 }
60 
61 /// Tree node containing `E`.
62 private struct Node(E) {
63 private:
64 	E data;
65 
66 	// allocate with pointers with std.experimental.allocator.makeArray and each
67 	// pointer with std.experimental.allocator.makeArray
68 	Node!E*[] subs;
69 }