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