1 module mutils.container.vector_allocator;
2 
3 import std.experimental.allocator;
4 import std.traits;
5 
6 /**
7  * Vector backed by given allocator
8  **/
9 struct VectorAllocator(T, Allocator){
10 	static if(hasStaticMember!(Allocator,"instance")){
11 		alias allocator=Allocator.instance;
12 	}else{
13 		Allocator allocator;
14 	}
15 
16 	
17 	T[] array;
18 public:
19 
20 	this(size_t numElements){
21 		assert(numElements>0);
22 		setLenght(numElements);
23 	}
24 
25 	void clear(){
26 		removeAll();
27 	}
28 
29 	void removeAll(){
30 		if(array !is null){
31 			freeData(cast(void[])array);
32 		}
33 		array=T[].init;
34 	}
35 
36 	bool empty(){
37 		return (array.length==0);
38 	}
39 
40 	size_t length(){
41 		return array.length;
42 	}	
43 
44 	void reset(){
45 		clear();
46 	}
47 
48 	void setLenght(size_t newNumOfElements){
49 		if( array is null){
50 			array=allocator.makeArray!(T)(newNumOfElements);
51 		}else{
52 			if(array.length<newNumOfElements){
53 				allocator.expandArray(array, newNumOfElements-array.length);
54 			}else if(array.length>newNumOfElements){
55 				allocator.shrinkArray(array, array.length-newNumOfElements);
56 			}
57 		}
58 	}
59 
60 	void freeData(void[] data){
61 		allocator.dispose(array);
62 	}
63 
64 	void add( T  t ) {
65 		setLenght(array.length+1);
66 		array[$-1]=t;
67 	}
68 
69 	void add( T[]  t ) {
70 		size_t sizeBefore=array.length;
71 		setLenght(array.length+t.length);
72 		foreach(i;0..t.length){
73 			array[sizeBefore+i]=t[i];
74 		}
75 	}
76 
77 	
78 	void remove(size_t elemNum){
79 		array[elemNum]=array[$-1];
80 		setLenght(array.length-1);
81 	}
82 
83 	void removeElement(T elem){
84 		foreach(i,ref el;array){
85 			if(el==elem){
86 				remove(i);
87 				return;
88 			}
89 		}
90 	}
91 
92 	T opIndex(size_t elemNum){
93 		return array[elemNum];
94 	}
95 
96 	auto opSlice(){
97 		return array;
98 	}
99 
100 	T[] opSlice(size_t x, size_t y){
101 		return array[x..y];
102 	}
103 
104 	size_t opDollar(){
105 		return array.length;
106 	}
107 
108 	void opOpAssign(string op)(T obj){
109 		static assert(op=="~");
110 		add(obj);
111 	}
112 
113 	void opOpAssign(string op)(T[] obj){
114 		static assert(op=="~");
115 		add(obj);
116 	}
117 
118 	void opIndexAssign(T obj,size_t elemNum){
119 		array[elemNum]=obj;
120 
121 	}
122 	
123 }
124 unittest{
125 	import std.experimental.allocator.mallocator;
126 	VectorAllocator!(int, Mallocator) vec;
127 	assert(vec.empty);
128 	vec.add(0);
129 	vec.add(1);
130 	vec.add(2);
131 	vec.add(3);
132 	vec.add(4);
133 	vec.add(5);
134 	assert(vec.length==6);
135 	assert(vec[3]==3);
136 	assert(vec[5]==5);
137 	assert(vec[]==[0,1,2,3,4,5]);
138 	assert(!vec.empty);
139 	vec.remove(3);
140 	assert(vec.length==5);
141 	assert(vec[]==[0,1,2,5,4]);//unstable remove
142 }