1 /**
2  * Tree Map
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 containers.treemap;
9 
10 /**
11  * A key→value mapping where the keys are guaranteed to be sorted.
12  * Params:
13  *     K = the key type
14  *     V = the value type
15  *     less = the key comparison function to use
16  *     supportGC = true to support storing GC-allocated objects, false otherwise
17  *     cacheLineSize = the size of the internal nodes in bytes
18  */
19 struct TreeMap(K, V, alias less = "a < b", bool supportGC = true,
20 	size_t cacheLineSize = 64)
21 {
22 
23 	this(this) @disable;
24 
25 	/// Supports $(B treeMap[key] = value;) syntax.
26 	void opIndexAssign(V value, K key)
27 	{
28 		auto tme = TreeMapElement(key, value);
29 		tree.insert(tme);
30 	}
31 
32 	/// Supports $(B treeMap[key]) syntax.
33 	V opIndex(K key) const
34 	{
35 		auto tme = TreeMapElement(key);
36 		return tree.equalRange(tme).front.value;
37 	}
38 
39 	/**
40 	 * Removes the key→value mapping for the given key.
41 	 * Params: key = the key to remove
42 	 * Returns: true if the key existed in the map
43 	 */
44 	bool remove(K key)
45 	{
46 		auto tme = TreeMapElement(key);
47 		return tree.remove(tme);
48 	}
49 
50 	/// Returns: true if the mapping contains the given key
51 	bool containsKey(K key)
52 	{
53 		auto tme = TreeMapElement(key);
54 		return tree.contains(tme);
55 	}
56 
57 	/// Returns: true if the mapping is empty
58 	bool empty() const pure nothrow @property @safe @nogc
59 	{
60 		return tree.empty;
61 	}
62 
63 	/// Returns: the number of key→value pairs in the map
64 	size_t length() const pure nothrow @property @safe @nogc
65 	{
66 		return tree.length;
67 	}
68 
69 	/// Supports $(B foreach(k, v; treeMap)) syntax.
70 	int opApply(int delegate(ref K, ref V) loopBody)
71 	{
72 		int result;
73 		foreach (ref tme; tree[])
74 		{
75 			result = loopBody(tme.key, tme.value);
76 			if (result)
77 				break;
78 		}
79 		return result;
80 	}
81 
82 private:
83 
84 	import containers.ttree : TTree;
85 
86 	static struct TreeMapElement
87 	{
88 		K key;
89 		V value;
90 		int opCmp(ref const TreeMapElement other) const
91 		{
92 			import std.functional : binaryFun;
93 			return binaryFun!less(key, other.key);
94 		}
95 	}
96 	TTree!(TreeMapElement, false, "a.opCmp(b) > 0", supportGC, cacheLineSize) tree;
97 }
98 
99 unittest
100 {
101 	TreeMap!(string, string) tm;
102 	tm["test1"] = "hello";
103 	tm["test2"] = "world";
104 	tm.remove("test1");
105 	tm.remove("test2");
106 }