1 module mutils.container.sorted_vector;
2 
3 import std.algorithm : sort;
4 import std.experimental.allocator;
5 import std.experimental.allocator.mallocator;
6 import std.functional : binaryFun;
7 
8 import mutils.container.vector;
9 
10 /***
11  * Vector which keeps data sorted
12  */
13 struct SortedVector(T, alias less = "a < b") {
14 	alias cmpFunction = binaryFun!less;
15 	Vector!T vec;
16 
17 	bool empty() {
18 		return (vec.used == 0);
19 	}
20 
21 	size_t length() {
22 		return vec.used;
23 	}
24 
25 	void reset() {
26 		vec.used = 0;
27 	}
28 
29 	void clear() {
30 		vec.clear();
31 	}
32 
33 	size_t add(T t) {
34 		foreach (i, el; vec[]) {
35 			if (cmpFunction(t, el)) {
36 				vec.add(t, i);
37 				return i;
38 			}
39 		}
40 		size_t addPos = vec.length;
41 		vec.add(t, addPos);
42 		return addPos;
43 	}
44 
45 	void add(T[] t) {
46 		T[8] tmpMemory;
47 		Vector!T tmp;
48 		T[] slice;
49 
50 		if (t.length <= 8) {
51 			tmpMemory[0 .. t.length] = t;
52 			slice = tmpMemory[0 .. t.length];
53 		} else {
54 			tmp.add(t);
55 			slice = tmp[];
56 		}
57 		sort!(cmpFunction)(slice);
58 		vec.reserve(vec.length + t.length);
59 		size_t lastInsertIndex = vec.length;
60 		foreach_reverse (elNum, elToAdd; slice) {
61 			size_t posToInsert = lastInsertIndex;
62 			foreach_reverse (i, el; vec.array[0 .. lastInsertIndex]) {
63 				if (cmpFunction(elToAdd, el)) {
64 					posToInsert = i;
65 				}
66 			}
67 			foreach_reverse (i; posToInsert .. lastInsertIndex) {
68 				vec.array[elNum + i + 1] = vec.array[i];
69 			}
70 			vec.array[posToInsert + elNum] = elToAdd;
71 			lastInsertIndex = posToInsert;
72 		}
73 
74 		vec.used += t.length;
75 		tmp.removeAll();
76 	}
77 
78 	void remove(size_t elemNum) {
79 		vec.removeStable(elemNum);
80 	}
81 
82 	void opOpAssign(string op)(T obj) {
83 		static assert(op == "~");
84 		add(obj);
85 	}
86 
87 	void opOpAssign(string op)(T[] obj) {
88 		static assert(op == "~");
89 		add(obj);
90 	}
91 
92 	ref T opIndex(size_t elemNum) {
93 		return vec.array[elemNum];
94 	}
95 
96 	auto opSlice() {
97 		return vec.array[0 .. vec.used];
98 	}
99 
100 	T[] opSlice(size_t x, size_t y) {
101 		return vec.array[x .. y];
102 	}
103 
104 	size_t opDollar() {
105 		return vec.used;
106 	}
107 }
108 
109 // Helper to avoid GC
110 private T[n] s(T, size_t n)(auto ref T[n] array) pure nothrow @nogc @safe {
111 	return array;
112 }
113 
114 unittest {
115 	SortedVector!int vector;
116 	assert(vector.add(5) == 0);
117 	assert(vector.add(3) == 0);
118 	assert(vector.add(6) == 2);
119 	assert(vector[] == [3, 5, 6].s);
120 
121 	vector.add([2, 4, 7].s);
122 	assert(vector[] == [2, 3, 4, 5, 6, 7].s);
123 	vector.add(vector[]);
124 	vector.add(vector[]);
125 	assert(vector[] == [2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7].s);
126 }