1 module mutils.view2d;
2 
3 import std.traits: ForeachType;
4 
5 struct View2D(Slice){
6 	alias T=ForeachType!Slice;
7 	Slice slice;
8 	size_t columnsNum=1;
9 	
10 	
11 	Slice opIndex(size_t y){
12 		return slice[y*columnsNum..(y+1)*columnsNum];
13 	}
14 
15 	ref T opIndex(size_t y, size_t x){
16 		assert(x<columnsNum);
17 		return slice[y*columnsNum+x];
18 	}
19 
20 	Slice opIndex(size_t y, size_t[2] x){
21 		assert(x[0]<=x[1]);
22 		assert(x[1]<=columnsNum);
23 		size_t start=y*columnsNum;
24 		return slice[start+x[0]..start+x[1]];
25 	}
26 
27 	size_t[2] opSlice(size_t dim)(size_t start, size_t end){
28 		return [start, end];
29 	}
30 
31 	size_t opDollar(size_t dim )() { 
32 		static assert(dim<2);
33 		static if(dim==0){
34 			return columnsNum; 
35 		}else{
36 			return cast(size_t)(slice.length/columnsNum);
37 		}
38 	}
39 
40 	// foreach support
41 	int opApply(scope int delegate(Slice) dg){ 
42 		int result;
43 		foreach(y;0..cast(size_t)(slice.length/columnsNum)){			
44 			result=dg(opIndex(y));
45 			if (result)
46 				break;	
47 		}		
48 		
49 		return result;
50 	}
51 
52 	// foreach support
53 	int opApply(scope int delegate(size_t, Slice) dg){ 
54 		int result;
55 		foreach(y;0..cast(size_t)(slice.length/columnsNum)){			
56 			result=dg(y, opIndex(y));
57 			if (result)
58 				break;	
59 		}		
60 		
61 		return result;
62 	}
63 }
64 
65 unittest{
66 	int[9] arr=[0,1,2,3,4,5,6,7,8];
67 	View2D!(int[]) view;
68 	view.slice=arr[];
69 	view.columnsNum=3;
70 	
71 	// opIndex[y]
72 	assert(view[0]==[0,1,2]);
73 	assert(view[1]==[3,4,5]);
74 	assert(view[2]==[6,7,8]);
75 	
76 	// opIndex[y, x]
77 	assert(view[0,0]==0);
78 	assert(view[0,1]==1);
79 	assert(view[0,2]==2);
80 	assert(view[1,0]==3);
81 	assert(view[1,1]==4);
82 	assert(view[1,2]==5);
83 	assert(view[2,0]==6);
84 	assert(view[2,1]==7);
85 	assert(view[2,2]==8);
86 	// opIndex[y,x1..x2]
87 	assert(view[0,1..$]==[1,2]);
88 	// opDollar
89 	assert(view[$-1]==[6,7,8]);
90 	assert(view[$-1,$-2]==7);
91 	// Foreach
92 	foreach(row; view){}
93 	foreach(i, row; view){
94 		assert(row==[i*3+0, i*3+1, i*3+2]);
95 	}
96 	// Assigment
97 	view[2,2]=123;
98 	assert(view[2,2]==123);
99 }