1 | /* | |
2 | * Copyright 2004 by Paulo Soares. | |
3 | * | |
4 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
5 | * (the "License"); you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
7 | * | |
8 | * Software distributed under the License is distributed on an "AS IS" basis, | |
9 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
10 | * for the specific language governing rights and limitations under the License. | |
11 | * | |
12 | * The Original Code is 'iText, a free JAVA-PDF library'. | |
13 | * | |
14 | * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by | |
15 | * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. | |
16 | * All Rights Reserved. | |
17 | * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer | |
18 | * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. | |
19 | * | |
20 | * Contributor(s): all the names of the contributors are added in the source code | |
21 | * where applicable. | |
22 | * | |
23 | * Alternatively, the contents of this file may be used under the terms of the | |
24 | * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the | |
25 | * provisions of LGPL are applicable instead of those above. If you wish to | |
26 | * allow use of your version of this file only under the terms of the LGPL | |
27 | * License and not to allow others to use your version of this file under | |
28 | * the MPL, indicate your decision by deleting the provisions above and | |
29 | * replace them with the notice and other provisions required by the LGPL. | |
30 | * If you do not delete the provisions above, a recipient may use your version | |
31 | * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. | |
32 | * | |
33 | * This library is free software; you can redistribute it and/or modify it | |
34 | * under the terms of the MPL as stated above or under the terms of the GNU | |
35 | * Library General Public License as published by the Free Software Foundation; | |
36 | * either version 2 of the License, or any later version. | |
37 | * | |
38 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
39 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
40 | * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more | |
41 | * details. | |
42 | * | |
43 | * If you didn't download this code from the following link, you should check if | |
44 | * you aren't using an obsolete version: | |
45 | * http://www.lowagie.com/iText/ | |
46 | */ | |
47 | package com.lowagie.text.pdf; | |
48 | ||
49 | import java.util.LinkedList; | |
50 | import java.util.List; | |
51 | import java.util.ListIterator; | |
52 | ||
53 | /** | |
54 | * This class expands a string into a list of numbers. The main use is to select a | |
55 | * range of pages. | |
56 | * <p> | |
57 | * The general syntax is:<br> | |
58 | * [!][o][odd][e][even]start-end | |
59 | * <p> | |
60 | * You can have multiple ranges separated by commas ','. The '!' modifier removes the | |
61 | * range from what is already selected. The range changes are incremental, that is, | |
62 | * numbers are added or deleted as the range appears. The start or the end, but not both, can be omitted. | |
63 | */ | |
64 | public class SequenceList { | |
65 | protected static final int COMMA = 1; | |
66 | protected static final int MINUS = 2; | |
67 | protected static final int NOT = 3; | |
68 | protected static final int TEXT = 4; | |
69 | protected static final int NUMBER = 5; | |
70 | protected static final int END = 6; | |
71 | protected static final char EOT = '\uffff'; | |
72 | ||
73 | private static final int FIRST = 0; | |
74 | private static final int DIGIT = 1; | |
75 | private static final int OTHER = 2; | |
76 | private static final int DIGIT2 = 3; | |
77 | private static final String NOT_OTHER = "-,!0123456789"; | |
78 | ||
79 | protected char[] text; | |
80 | protected int ptr; | |
81 | protected int number; | |
82 | protected String other; | |
83 | ||
84 | protected int low; | |
85 | protected int high; | |
86 | protected boolean odd; | |
87 | protected boolean even; | |
88 | protected boolean inverse; | |
89 | ||
90 | protected SequenceList(String range) { | |
91 | ptr = 0; | |
92 | text = range.toCharArray(); | |
93 | } | |
94 | | |
95 | protected char nextChar() { | |
96 | while (true) { | |
97 |
2
1. nextChar : changed conditional boundary → NO_COVERAGE 2. nextChar : negated conditional → NO_COVERAGE |
if (ptr >= text.length) |
98 |
1
1. nextChar : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return EOT; |
99 |
1
1. nextChar : Replaced integer addition with subtraction → NO_COVERAGE |
char c = text[ptr++]; |
100 |
2
1. nextChar : changed conditional boundary → NO_COVERAGE 2. nextChar : negated conditional → NO_COVERAGE |
if (c > ' ') |
101 |
1
1. nextChar : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return c; |
102 | } | |
103 | } | |
104 | | |
105 | protected void putBack() { | |
106 |
1
1. putBack : Replaced integer subtraction with addition → NO_COVERAGE |
--ptr; |
107 |
2
1. putBack : changed conditional boundary → NO_COVERAGE 2. putBack : negated conditional → NO_COVERAGE |
if (ptr < 0) |
108 | ptr = 0; | |
109 | } | |
110 | | |
111 | protected int getType() { | |
112 | StringBuilder buf = new StringBuilder(); | |
113 | int state = FIRST; | |
114 | while (true) { | |
115 | char c = nextChar(); | |
116 |
1
1. getType : negated conditional → NO_COVERAGE |
if (c == EOT) { |
117 |
1
1. getType : negated conditional → NO_COVERAGE |
if (state == DIGIT) { |
118 | number = Integer.parseInt(other = buf.toString()); | |
119 |
1
1. getType : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return NUMBER; |
120 | } | |
121 |
1
1. getType : negated conditional → NO_COVERAGE |
else if (state == OTHER) { |
122 | other = buf.toString().toLowerCase(); | |
123 |
1
1. getType : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return TEXT; |
124 | } | |
125 |
1
1. getType : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return END; |
126 | } | |
127 | switch (state) { | |
128 | case FIRST: | |
129 | switch (c) { | |
130 | case '!': | |
131 |
1
1. getType : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return NOT; |
132 | case '-': | |
133 |
1
1. getType : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return MINUS; |
134 | case ',': | |
135 |
1
1. getType : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return COMMA; |
136 | } | |
137 | buf.append(c); | |
138 |
4
1. getType : changed conditional boundary → NO_COVERAGE 2. getType : changed conditional boundary → NO_COVERAGE 3. getType : negated conditional → NO_COVERAGE 4. getType : negated conditional → NO_COVERAGE |
if (c >= '0' && c <= '9') |
139 | state = DIGIT; | |
140 | else | |
141 | state = OTHER; | |
142 | break; | |
143 | case DIGIT: | |
144 |
4
1. getType : changed conditional boundary → NO_COVERAGE 2. getType : changed conditional boundary → NO_COVERAGE 3. getType : negated conditional → NO_COVERAGE 4. getType : negated conditional → NO_COVERAGE |
if (c >= '0' && c <= '9') |
145 | buf.append(c); | |
146 | else { | |
147 |
1
1. getType : removed call to com/lowagie/text/pdf/SequenceList::putBack → NO_COVERAGE |
putBack(); |
148 | number = Integer.parseInt(other = buf.toString()); | |
149 |
1
1. getType : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return NUMBER; |
150 | } | |
151 | break; | |
152 | case OTHER: | |
153 |
2
1. getType : changed conditional boundary → NO_COVERAGE 2. getType : negated conditional → NO_COVERAGE |
if (NOT_OTHER.indexOf(c) < 0) |
154 | buf.append(c); | |
155 | else { | |
156 |
1
1. getType : removed call to com/lowagie/text/pdf/SequenceList::putBack → NO_COVERAGE |
putBack(); |
157 | other = buf.toString().toLowerCase(); | |
158 |
1
1. getType : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return TEXT; |
159 | } | |
160 | break; | |
161 | } | |
162 | } | |
163 | } | |
164 | | |
165 | private void otherProc() { | |
166 |
2
1. otherProc : negated conditional → NO_COVERAGE 2. otherProc : negated conditional → NO_COVERAGE |
if (other.equals("odd") || other.equals("o")) { |
167 | odd = true; | |
168 | even = false; | |
169 | } | |
170 |
2
1. otherProc : negated conditional → NO_COVERAGE 2. otherProc : negated conditional → NO_COVERAGE |
else if (other.equals("even") || other.equals("e")) { |
171 | odd = false; | |
172 | even = true; | |
173 | } | |
174 | } | |
175 | | |
176 | protected boolean getAttributes() { | |
177 | low = -1; | |
178 | high = -1; | |
179 | odd = even = inverse = false; | |
180 | int state = OTHER; | |
181 | while (true) { | |
182 | int type = getType(); | |
183 |
2
1. getAttributes : negated conditional → NO_COVERAGE 2. getAttributes : negated conditional → NO_COVERAGE |
if (type == END || type == COMMA) { |
184 |
1
1. getAttributes : negated conditional → NO_COVERAGE |
if (state == DIGIT) |
185 | high = low; | |
186 |
2
1. getAttributes : negated conditional → NO_COVERAGE 2. getAttributes : replaced return of integer sized value with (x == 0 ? 1 : 0) → NO_COVERAGE |
return (type == END); |
187 | } | |
188 | switch (state) { | |
189 | case OTHER: | |
190 | switch (type) { | |
191 | case NOT: | |
192 | inverse = true; | |
193 | break; | |
194 | case MINUS: | |
195 | state = DIGIT2; | |
196 | break; | |
197 | default: | |
198 |
1
1. getAttributes : negated conditional → NO_COVERAGE |
if (type == NUMBER) { |
199 | low = number; | |
200 | state = DIGIT; | |
201 | } | |
202 | else | |
203 |
1
1. getAttributes : removed call to com/lowagie/text/pdf/SequenceList::otherProc → NO_COVERAGE |
otherProc(); |
204 | break; | |
205 | } | |
206 | break; | |
207 | case DIGIT: | |
208 | switch (type) { | |
209 | case NOT: | |
210 | inverse = true; | |
211 | state = OTHER; | |
212 | high = low; | |
213 | break; | |
214 | case MINUS: | |
215 | state = DIGIT2; | |
216 | break; | |
217 | default: | |
218 | high = low; | |
219 | state = OTHER; | |
220 |
1
1. getAttributes : removed call to com/lowagie/text/pdf/SequenceList::otherProc → NO_COVERAGE |
otherProc(); |
221 | break; | |
222 | } | |
223 | break; | |
224 | case DIGIT2: | |
225 | switch (type) { | |
226 | case NOT: | |
227 | inverse = true; | |
228 | state = OTHER; | |
229 | break; | |
230 | case MINUS: | |
231 | break; | |
232 | case NUMBER: | |
233 | high = number; | |
234 | state = OTHER; | |
235 | break; | |
236 | default: | |
237 | state = OTHER; | |
238 |
1
1. getAttributes : removed call to com/lowagie/text/pdf/SequenceList::otherProc → NO_COVERAGE |
otherProc(); |
239 | break; | |
240 | } | |
241 | break; | |
242 | } | |
243 | } | |
244 | } | |
245 | | |
246 | /** | |
247 | * Generates a list of numbers from a string. | |
248 | * @param ranges the comma separated ranges | |
249 | * @param maxNumber the maximum number in the range | |
250 | * @return a list with the numbers as <CODE>Integer</CODE> | |
251 | */ | |
252 | public static List expand(String ranges, int maxNumber) { | |
253 | SequenceList parse = new SequenceList(ranges); | |
254 | LinkedList list = new LinkedList(); | |
255 | boolean sair = false; | |
256 |
1
1. expand : negated conditional → NO_COVERAGE |
while (!sair) { |
257 | sair = parse.getAttributes(); | |
258 |
4
1. expand : negated conditional → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE 4. expand : negated conditional → NO_COVERAGE |
if (parse.low == -1 && parse.high == -1 && !parse.even && !parse.odd) |
259 | continue; | |
260 |
2
1. expand : changed conditional boundary → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE |
if (parse.low < 1) |
261 | parse.low = 1; | |
262 |
4
1. expand : changed conditional boundary → NO_COVERAGE 2. expand : changed conditional boundary → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE 4. expand : negated conditional → NO_COVERAGE |
if (parse.high < 1 || parse.high > maxNumber) |
263 | parse.high = maxNumber; | |
264 |
2
1. expand : changed conditional boundary → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE |
if (parse.low > maxNumber) |
265 | parse.low = maxNumber; | |
266 | | |
267 | //System.out.println("low="+parse.low+",high="+parse.high+",odd="+parse.odd+",even="+parse.even+",inverse="+parse.inverse); | |
268 | int inc = 1; | |
269 |
1
1. expand : negated conditional → NO_COVERAGE |
if (parse.inverse) { |
270 |
2
1. expand : changed conditional boundary → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE |
if (parse.low > parse.high) { |
271 | int t = parse.low; | |
272 | parse.low = parse.high; | |
273 | parse.high = t; | |
274 | } | |
275 |
1
1. expand : negated conditional → NO_COVERAGE |
for (ListIterator it = list.listIterator(); it.hasNext();) { |
276 | int n = (Integer) it.next(); | |
277 |
3
1. expand : Replaced bitwise AND with OR → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE |
if (parse.even && (n & 1) == 1) |
278 | continue; | |
279 |
3
1. expand : Replaced bitwise AND with OR → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE |
if (parse.odd && (n & 1) == 0) |
280 | continue; | |
281 |
4
1. expand : changed conditional boundary → NO_COVERAGE 2. expand : changed conditional boundary → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE 4. expand : negated conditional → NO_COVERAGE |
if (n >= parse.low && n <= parse.high) |
282 |
1
1. expand : removed call to java/util/ListIterator::remove → NO_COVERAGE |
it.remove(); |
283 | } | |
284 | } | |
285 | else { | |
286 |
2
1. expand : changed conditional boundary → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE |
if (parse.low > parse.high) { |
287 | inc = -1; | |
288 |
2
1. expand : negated conditional → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE |
if (parse.odd || parse.even) { |
289 |
1
1. expand : Changed increment from -1 to 1 → NO_COVERAGE |
--inc; |
290 |
1
1. expand : negated conditional → NO_COVERAGE |
if (parse.even) |
291 |
1
1. expand : Replaced bitwise AND with OR → NO_COVERAGE |
parse.low &= ~1; |
292 | else | |
293 |
3
1. expand : Replaced bitwise AND with OR → NO_COVERAGE 2. expand : Replaced integer subtraction with addition → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE |
parse.low -= ((parse.low & 1) == 1 ? 0 : 1); |
294 | } | |
295 |
3
1. expand : changed conditional boundary → NO_COVERAGE 2. expand : Replaced integer addition with subtraction → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE |
for (int k = parse.low; k >= parse.high; k += inc) |
296 | list.add(k); | |
297 | } | |
298 | else { | |
299 |
2
1. expand : negated conditional → NO_COVERAGE 2. expand : negated conditional → NO_COVERAGE |
if (parse.odd || parse.even) { |
300 |
1
1. expand : Changed increment from 1 to -1 → NO_COVERAGE |
++inc; |
301 |
1
1. expand : negated conditional → NO_COVERAGE |
if (parse.odd) |
302 |
1
1. expand : Replaced bitwise OR with AND → NO_COVERAGE |
parse.low |= 1; |
303 | else | |
304 |
3
1. expand : Replaced bitwise AND with OR → NO_COVERAGE 2. expand : Replaced integer addition with subtraction → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE |
parse.low += ((parse.low & 1) == 1 ? 1 : 0); |
305 | } | |
306 |
3
1. expand : changed conditional boundary → NO_COVERAGE 2. expand : Replaced integer addition with subtraction → NO_COVERAGE 3. expand : negated conditional → NO_COVERAGE |
for (int k = parse.low; k <= parse.high; k += inc) { |
307 | list.add(k); | |
308 | } | |
309 | } | |
310 | } | |
311 | // for (int k = 0; k < list.size(); ++k) | |
312 | // System.out.print(((Integer)list.get(k)).intValue() + ","); | |
313 | // System.out.println(); | |
314 | } | |
315 |
1
1. expand : mutated return of Object value for com/lowagie/text/pdf/SequenceList::expand to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return list; |
316 | } | |
317 | } | |
Mutations | ||
97 |
1.1 2.2 |
|
98 |
1.1 |
|
99 |
1.1 |
|
100 |
1.1 2.2 |
|
101 |
1.1 |
|
106 |
1.1 |
|
107 |
1.1 2.2 |
|
116 |
1.1 |
|
117 |
1.1 |
|
119 |
1.1 |
|
121 |
1.1 |
|
123 |
1.1 |
|
125 |
1.1 |
|
131 |
1.1 |
|
133 |
1.1 |
|
135 |
1.1 |
|
138 |
1.1 2.2 3.3 4.4 |
|
144 |
1.1 2.2 3.3 4.4 |
|
147 |
1.1 |
|
149 |
1.1 |
|
153 |
1.1 2.2 |
|
156 |
1.1 |
|
158 |
1.1 |
|
166 |
1.1 2.2 |
|
170 |
1.1 2.2 |
|
183 |
1.1 2.2 |
|
184 |
1.1 |
|
186 |
1.1 2.2 |
|
198 |
1.1 |
|
203 |
1.1 |
|
220 |
1.1 |
|
238 |
1.1 |
|
256 |
1.1 |
|
258 |
1.1 2.2 3.3 4.4 |
|
260 |
1.1 2.2 |
|
262 |
1.1 2.2 3.3 4.4 |
|
264 |
1.1 2.2 |
|
269 |
1.1 |
|
270 |
1.1 2.2 |
|
275 |
1.1 |
|
277 |
1.1 2.2 3.3 |
|
279 |
1.1 2.2 3.3 |
|
281 |
1.1 2.2 3.3 4.4 |
|
282 |
1.1 |
|
286 |
1.1 2.2 |
|
288 |
1.1 2.2 |
|
289 |
1.1 |
|
290 |
1.1 |
|
291 |
1.1 |
|
293 |
1.1 2.2 3.3 |
|
295 |
1.1 2.2 3.3 |
|
299 |
1.1 2.2 |
|
300 |
1.1 |
|
301 |
1.1 |
|
302 |
1.1 |
|
304 |
1.1 2.2 3.3 |
|
306 |
1.1 2.2 3.3 |
|
315 |
1.1 |