1 module auxil.cursor; 2 3 import std.math : isNaN; 4 5 struct Cursor 6 { 7 alias Type = int; 8 /// defines direction of traversing 9 enum Order : bool { backward, forward, } 10 11 // sum of all previous elements 12 // it can have only fixed set of values so it is called `fixed` 13 Type fixedPosition; 14 // the value we should iterate over given sequence and 15 // can be any value 16 private Type _destination; 17 // the start position 18 Type init_value; 19 Type last_value; 20 Type current_value; 21 22 this(Type v) @safe @nogc 23 { 24 reset(v); 25 } 26 27 void reset(Type v = 0) @safe @nogc 28 { 29 fixedPosition = 0; 30 _destination = 0; 31 init_value = v; 32 last_value = 0; 33 current_value = 0; 34 } 35 36 void scroll(Type value) @safe @nogc 37 { 38 assert(value >= 0); 39 _destination = fixedPosition + value; 40 } 41 42 auto phase() @safe @nogc const 43 { 44 return _destination - fixedPosition; 45 } 46 47 // used if the sequence has ended before 48 // the destination was achieved 49 // because the current position is 50 // the position of the next elements, i.e. 51 // non-existing element because the sequence 52 // has ended 53 // 54 // the reason is that there is no way to get know 55 // if the current element is the last one 56 auto fixUp() @safe @nogc 57 { 58 // if processing was not completed it 59 // means the fixed position belongs to the next 60 // element after the last one so correct this 61 if (!_complete) 62 fixedPosition -= last_value; 63 } 64 65 private bool _complete; 66 bool complete() @safe @nogc { return _complete; } 67 68 void begin(Type v) @safe @nogc 69 { 70 current_value = v; 71 debug { 72 import std; 73 writeln(current_value); 74 } 75 } 76 77 void next(Type v) @safe @nogc 78 { 79 if (fixedPosition + v > _destination) 80 { 81 _complete = true; 82 } 83 else 84 { 85 last_value = v; 86 fixedPosition += last_value; 87 } 88 } 89 90 void toString(Writer)(ref Writer w) @safe 91 { 92 import std.algorithm : copy; 93 import std.conv : text; 94 typeof(this).stringof.copy(w); 95 w.put('('); 96 static foreach(i; 0..this.tupleof.length) 97 {{ 98 enum name = __traits(identifier, this.tupleof[i]); 99 text(name, " : ", this.tupleof[i], ", ").copy(w); 100 }} 101 w.put(')'); 102 } 103 104 package auto calcPosition(Order order)() @safe @nogc 105 { 106 static if (order == Cursor.Order.forward) 107 return init_value + fixedPosition; 108 else 109 return init_value - fixedPosition - current_value; 110 } 111 }