Line data Source code
1 : // Copyright 2023 The terCAD team. All rights reserved. 2 : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file. 3 : 4 : import 'dart:collection'; 5 : 6 : abstract interface class InterfaceIterator<T extends num, K, M> { 7 : void reset(); 8 : int get length; 9 : bool get isFirst; 10 : bool get isFinished; 11 : bool get isEmpty; 12 : M? get next; 13 : void jumpTo(T key); 14 : Iterable<M?> loop(); 15 : List<M> chunk(int length); 16 : List<M> getTill(T boundary); 17 : List<M> toList(); 18 : } 19 : 20 : class IteratorController<T extends num, K, M> implements InterfaceIterator<T, K, M> { 21 : SplayTreeMap<T, K> data; 22 : T? boundary; 23 : Function? filter; 24 4 : late List<T> keys = data.keys.toList(); 25 : int pointer = 0; 26 : // ignore: prefer_final_fields 27 : int _pointer = 0; 28 : Function transform; 29 : 30 1 : IteratorController(this.data, {required this.transform, this.boundary, this.filter}); 31 : 32 0 : @override 33 0 : int get length => data.length; 34 : 35 0 : @override 36 0 : void reset() => pointer = 0; 37 : 38 0 : @override 39 0 : bool get isEmpty => data.isEmpty; 40 : 41 0 : @override 42 0 : bool get isFirst => _pointer == pointer; 43 : 44 1 : @override 45 4 : bool get isFinished => keys.length == pointer; 46 : 47 1 : @override 48 : void jumpTo(T key) { 49 2 : final nextKey = data.firstKeyAfter(key); 50 3 : pointer = nextKey != null ? keys.indexOf(nextKey) : keys.length - 1; 51 : } 52 : 53 1 : @override 54 : Iterable<M?> loop() sync* { 55 4 : while (pointer < keys.length) { 56 4 : final index = keys.elementAt(pointer++); 57 3 : if (boundary != null && boundary! < index) { 58 : break; 59 : } 60 4 : M? value = transform(data[index] ?? ''); 61 3 : if (filter?.call(value) == true) { 62 : continue; 63 : } 64 : yield value; 65 : } 66 : } 67 : 68 1 : @override 69 : M? get next { 70 2 : final iterator = loop().iterator; 71 2 : return iterator.moveNext() ? iterator.current as M : null; 72 : } 73 : 74 1 : @override 75 : List<M> chunk(int length) { 76 3 : final result = List.generate(length, (_) => next); 77 2 : result.removeWhere((e) => e == null); 78 1 : return result.cast<M>(); 79 : } 80 : 81 0 : @override 82 0 : List<M> toList() => [...loop()].cast(); 83 : 84 0 : @override 85 : List<M> getTill(T boundary) { 86 0 : final result = <M>[]; 87 0 : while (!isFinished && boundary > keys[pointer]) { 88 0 : final value = next; 89 0 : if (boundary <= keys[pointer - 1]) { 90 0 : pointer--; 91 : break; 92 : } 93 : if (value == null) { 94 : break; 95 : } 96 0 : result.add(value); 97 : } 98 : return result; 99 : } 100 : } 101 : 102 : class IteratorReverseController<T extends num, K, M> extends IteratorController<T, K, M> { 103 1 : IteratorReverseController(super.data, {required super.transform, super.boundary, super.filter}) { 104 5 : pointer = data.keys.length - 1; 105 2 : _pointer = pointer; 106 : } 107 : 108 1 : @override 109 2 : bool get isFinished => pointer < 0; 110 : 111 0 : @override 112 0 : void reset() => data.keys.length - 1; 113 : 114 1 : @override 115 : void jumpTo(T key) { 116 2 : final nextKey = data.lastKeyBefore(key); 117 3 : pointer = nextKey != null ? keys.indexOf(nextKey) : 0; 118 : } 119 : 120 1 : @override 121 : Iterable<M?> loop() sync* { 122 2 : while (pointer >= 0) { 123 4 : final index = keys.elementAt(pointer--); 124 3 : if (boundary != null && boundary! > index) { 125 : break; 126 : } 127 4 : M? value = transform(data[index] ?? ''); 128 2 : if (filter?.call(value) == true) { 129 : continue; 130 : } 131 : yield value; 132 : } 133 : } 134 : 135 0 : @override 136 : List<M> getTill(T boundary) { 137 0 : final result = <M>[]; 138 0 : while (!isFinished && boundary < keys[pointer]) { 139 0 : final value = next; 140 0 : if (boundary >= keys[pointer + 1]) { 141 0 : pointer++; 142 : break; 143 : } 144 : if (value == null) { 145 : break; 146 : } 147 0 : result.add(value); 148 : } 149 : return result; 150 : } 151 : }