comparison src/org/tmatesoft/hg/internal/BatchRangeHelper.java @ 520:1ee452f31187

Experimental support for inverse direction history walking. Refactored/streamlined cancellation in HgLogCommand and down the stack
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 21 Dec 2012 21:20:26 +0100
parents
children
comparison
equal deleted inserted replaced
519:934037edbea0 520:1ee452f31187
1 /*
2 * Copyright (c) 2012 TMate Software Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * For information on how to redistribute this software under
14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com
16 */
17 package org.tmatesoft.hg.internal;
18
19 import java.util.Arrays;
20 import java.util.NoSuchElementException;
21
22 /**
23 * Helper to break given range [start..end] (inclusive bounds) to series of ranges,
24 * all but last are of batchSize length, and the last one is at most of batchSize+batchSizeTolerance length.
25 *
26 * Range is [{@link #start()rangeStart}..{@link #end() rangeEnd}], where rangeStart is less or equal to rangeEnd.
27 *
28 * When reverse range iteration is requested, original range is iterated from end to start, but the subranges
29 * boundaries are in natural order. i.e. for 0..100, 10 first subrange would be [91..100], not [100..91]. This
30 * helps clients of this class to get [start()..end()] in natural order regardless of iteration direction.
31 *
32 * Note, this class (and its treatment of inclusive boundaries) is designed solely for use with methods that navigate
33 * revlogs and take (start,end) pair of inclusive range.
34 *
35 * @author Artem Tikhomirov
36 * @author TMate Software Ltd.
37 */
38 public class BatchRangeHelper {
39
40 private final int rangeCount;
41 private final int rangeDelta;
42 private final int nextValueDelta;
43 private final int firstBoundary, lastBoundary;
44 private int rangeIndex, rangeValue, rangeStart, rangeEnd;
45
46 public BatchRangeHelper(int start, int end, int batchSize, boolean reverse) {
47 this(start, end, batchSize, batchSize/5, reverse);
48 }
49
50 public BatchRangeHelper(int start, int end, int batchSize, int batchSizeTolerance, boolean reverse) {
51 assert end >= start;
52 assert start >= 0;
53 assert batchSize > 0;
54 assert batchSizeTolerance >= 0;
55 final int totalElements = end-start+1;
56 int batchRangeCount = totalElements / batchSize;
57 // batchRangeCount == 0, totalElements > 0 => need at least 1 range
58 if (batchRangeCount == 0 || batchRangeCount*batchSize+batchSizeTolerance < totalElements) {
59 batchRangeCount++;
60 }
61 rangeCount = batchRangeCount;
62 rangeDelta = batchSize-1; // ranges are inclusive, and always grow naturally.
63 nextValueDelta = reverse ? -batchSize : batchSize;
64 firstBoundary = reverse ? end-rangeDelta : start;
65 lastBoundary = reverse ? start : end;
66 reset();
67 }
68
69 public boolean hasNext() {
70 return rangeIndex < rangeCount;
71 }
72
73 public void next() {
74 if (!hasNext()) {
75 throw new NoSuchElementException();
76 }
77 rangeStart = rangeValue;
78 rangeEnd = rangeValue + rangeDelta;
79 rangeValue += nextValueDelta;
80 if (++rangeIndex >= rangeCount) {
81 if (nextValueDelta < 0) {
82 // reverse iteration, lastBoundary represents start
83 rangeStart = lastBoundary;
84 } else {
85 // lastBoundary represents end
86 rangeEnd = lastBoundary;
87 }
88 }
89 }
90
91 public int start() {
92 return rangeStart;
93 }
94
95 public int end() {
96 return rangeEnd;
97 }
98
99 public BatchRangeHelper reset() {
100 rangeValue = firstBoundary;
101 rangeIndex = 0;
102 return this;
103 }
104
105 public int[] toArray() {
106 int[] rv = new int[rangeCount*2];
107 reset();
108 int i = 0;
109 while (hasNext()) {
110 next();
111 rv[i++] = start();
112 rv[i++] = end();
113 }
114 reset();
115 return rv;
116 }
117
118 public static void main(String[] args) {
119 System.out.println("With remainder within tolerance");
120 System.out.println(Arrays.toString(new BatchRangeHelper(0, 102, 10, 4, false).toArray()));
121 System.out.println(Arrays.toString(new BatchRangeHelper(0, 102, 10, 4, true).toArray()));
122 System.out.println("With remainder out of tolerance");
123 System.out.println(Arrays.toString(new BatchRangeHelper(0, 102, 10, 2, false).toArray()));
124 System.out.println(Arrays.toString(new BatchRangeHelper(0, 102, 10, 2, true).toArray()));
125 System.out.println("Range smaller than batch");
126 System.out.println(Arrays.toString(new BatchRangeHelper(1, 9, 10, false).toArray()));
127 System.out.println(Arrays.toString(new BatchRangeHelper(1, 9, 10, true).toArray()));
128 System.out.println("Range smaller than batch and smaller than tolerance");
129 System.out.println(Arrays.toString(new BatchRangeHelper(1, 9, 10, 20, false).toArray()));
130 System.out.println(Arrays.toString(new BatchRangeHelper(1, 9, 10, 20, true).toArray()));
131 System.out.println("Zero tolerance");
132 System.out.println(Arrays.toString(new BatchRangeHelper(0, 100, 10, 0, false).toArray()));
133 System.out.println(Arrays.toString(new BatchRangeHelper(0, 100, 10, 0, true).toArray()));
134 System.out.println("Right to boundary");
135 System.out.println(Arrays.toString(new BatchRangeHelper(1, 100, 10, false).toArray()));
136 System.out.println(Arrays.toString(new BatchRangeHelper(1, 100, 10, true).toArray()));
137 }
138 }