Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/print/attribute/SetOfIntegerSyntax.java
38918 views
1
/*
2
* Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
27
package javax.print.attribute;
28
29
import java.io.Serializable;
30
import java.util.Vector;
31
32
/**
33
* Class SetOfIntegerSyntax is an abstract base class providing the common
34
* implementation of all attributes whose value is a set of nonnegative
35
* integers. This includes attributes whose value is a single range of integers
36
* and attributes whose value is a set of ranges of integers.
37
* <P>
38
* You can construct an instance of SetOfIntegerSyntax by giving it in "string
39
* form." The string consists of zero or more comma-separated integer groups.
40
* Each integer group consists of either one integer, two integers separated by
41
* a hyphen (<CODE>-</CODE>), or two integers separated by a colon
42
* (<CODE>:</CODE>). Each integer consists of one or more decimal digits
43
* (<CODE>0</CODE> through <CODE>9</CODE>). Whitespace characters cannot
44
* appear within an integer but are otherwise ignored. For example:
45
* <CODE>""</CODE>, <CODE>"1"</CODE>, <CODE>"5-10"</CODE>, <CODE>"1:2,
46
* 4"</CODE>.
47
* <P>
48
* You can also construct an instance of SetOfIntegerSyntax by giving it in
49
* "array form." Array form consists of an array of zero or more integer groups
50
* where each integer group is a length-1 or length-2 array of
51
* <CODE>int</CODE>s; for example, <CODE>int[0][]</CODE>,
52
* <CODE>int[][]{{1}}</CODE>, <CODE>int[][]{{5,10}}</CODE>,
53
* <CODE>int[][]{{1,2},{4}}</CODE>.
54
* <P>
55
* In both string form and array form, each successive integer group gives a
56
* range of integers to be included in the set. The first integer in each group
57
* gives the lower bound of the range; the second integer in each group gives
58
* the upper bound of the range; if there is only one integer in the group, the
59
* upper bound is the same as the lower bound. If the upper bound is less than
60
* the lower bound, it denotes a null range (no values). If the upper bound is
61
* equal to the lower bound, it denotes a range consisting of a single value. If
62
* the upper bound is greater than the lower bound, it denotes a range
63
* consisting of more than one value. The ranges may appear in any order and are
64
* allowed to overlap. The union of all the ranges gives the set's contents.
65
* Once a SetOfIntegerSyntax instance is constructed, its value is immutable.
66
* <P>
67
* The SetOfIntegerSyntax object's value is actually stored in "<I>canonical</I>
68
* array form." This is the same as array form, except there are no null ranges;
69
* the members of the set are represented in as few ranges as possible (i.e.,
70
* overlapping ranges are coalesced); the ranges appear in ascending order; and
71
* each range is always represented as a length-two array of <CODE>int</CODE>s
72
* in the form {lower bound, upper bound}. An empty set is represented as a
73
* zero-length array.
74
* <P>
75
* Class SetOfIntegerSyntax has operations to return the set's members in
76
* canonical array form, to test whether a given integer is a member of the
77
* set, and to iterate through the members of the set.
78
* <P>
79
*
80
* @author David Mendenhall
81
* @author Alan Kaminsky
82
*/
83
public abstract class SetOfIntegerSyntax implements Serializable, Cloneable {
84
85
private static final long serialVersionUID = 3666874174847632203L;
86
87
/**
88
* This set's members in canonical array form.
89
* @serial
90
*/
91
private int[][] members;
92
93
94
/**
95
* Construct a new set-of-integer attribute with the given members in
96
* string form.
97
*
98
* @param members Set members in string form. If null, an empty set is
99
* constructed.
100
*
101
* @exception IllegalArgumentException
102
* (Unchecked exception) Thrown if <CODE>members</CODE> does not
103
* obey the proper syntax.
104
*/
105
protected SetOfIntegerSyntax(String members) {
106
this.members = parse (members);
107
}
108
109
/**
110
* Parse the given string, returning canonical array form.
111
*/
112
private static int[][] parse(String members) {
113
// Create vector to hold int[] elements, each element being one range
114
// parsed out of members.
115
Vector theRanges = new Vector();
116
117
// Run state machine over members.
118
int n = (members == null ? 0 : members.length());
119
int i = 0;
120
int state = 0;
121
int lb = 0;
122
int ub = 0;
123
char c;
124
int digit;
125
while (i < n) {
126
c = members.charAt(i ++);
127
switch (state) {
128
129
case 0: // Before first integer in first group
130
if (Character.isWhitespace(c)) {
131
state = 0;
132
}
133
else if ((digit = Character.digit(c, 10)) != -1) {
134
lb = digit;
135
state = 1;
136
} else {
137
throw new IllegalArgumentException();
138
}
139
break;
140
141
case 1: // In first integer in a group
142
if (Character.isWhitespace(c)){
143
state = 2;
144
} else if ((digit = Character.digit(c, 10)) != -1) {
145
lb = 10 * lb + digit;
146
state = 1;
147
} else if (c == '-' || c == ':') {
148
state = 3;
149
} else if (c == ',') {
150
accumulate (theRanges, lb, lb);
151
state = 6;
152
} else {
153
throw new IllegalArgumentException();
154
}
155
break;
156
157
case 2: // After first integer in a group
158
if (Character.isWhitespace(c)) {
159
state = 2;
160
}
161
else if (c == '-' || c == ':') {
162
state = 3;
163
}
164
else if (c == ',') {
165
accumulate(theRanges, lb, lb);
166
state = 6;
167
} else {
168
throw new IllegalArgumentException();
169
}
170
break;
171
172
case 3: // Before second integer in a group
173
if (Character.isWhitespace(c)) {
174
state = 3;
175
} else if ((digit = Character.digit(c, 10)) != -1) {
176
ub = digit;
177
state = 4;
178
} else {
179
throw new IllegalArgumentException();
180
}
181
break;
182
183
case 4: // In second integer in a group
184
if (Character.isWhitespace(c)) {
185
state = 5;
186
} else if ((digit = Character.digit(c, 10)) != -1) {
187
ub = 10 * ub + digit;
188
state = 4;
189
} else if (c == ',') {
190
accumulate(theRanges, lb, ub);
191
state = 6;
192
} else {
193
throw new IllegalArgumentException();
194
}
195
break;
196
197
case 5: // After second integer in a group
198
if (Character.isWhitespace(c)) {
199
state = 5;
200
} else if (c == ',') {
201
accumulate(theRanges, lb, ub);
202
state = 6;
203
} else {
204
throw new IllegalArgumentException();
205
}
206
break;
207
208
case 6: // Before first integer in second or later group
209
if (Character.isWhitespace(c)) {
210
state = 6;
211
} else if ((digit = Character.digit(c, 10)) != -1) {
212
lb = digit;
213
state = 1;
214
} else {
215
throw new IllegalArgumentException();
216
}
217
break;
218
}
219
}
220
221
// Finish off the state machine.
222
switch (state) {
223
case 0: // Before first integer in first group
224
break;
225
case 1: // In first integer in a group
226
case 2: // After first integer in a group
227
accumulate(theRanges, lb, lb);
228
break;
229
case 4: // In second integer in a group
230
case 5: // After second integer in a group
231
accumulate(theRanges, lb, ub);
232
break;
233
case 3: // Before second integer in a group
234
case 6: // Before first integer in second or later group
235
throw new IllegalArgumentException();
236
}
237
238
// Return canonical array form.
239
return canonicalArrayForm (theRanges);
240
}
241
242
/**
243
* Accumulate the given range (lb .. ub) into the canonical array form
244
* into the given vector of int[] objects.
245
*/
246
private static void accumulate(Vector ranges, int lb,int ub) {
247
// Make sure range is non-null.
248
if (lb <= ub) {
249
// Stick range at the back of the vector.
250
ranges.add(new int[] {lb, ub});
251
252
// Work towards the front of the vector to integrate the new range
253
// with the existing ranges.
254
for (int j = ranges.size()-2; j >= 0; -- j) {
255
// Get lower and upper bounds of the two ranges being compared.
256
int[] rangea = (int[]) ranges.elementAt (j);
257
int lba = rangea[0];
258
int uba = rangea[1];
259
int[] rangeb = (int[]) ranges.elementAt (j+1);
260
int lbb = rangeb[0];
261
int ubb = rangeb[1];
262
263
/* If the two ranges overlap or are adjacent, coalesce them.
264
* The two ranges overlap if the larger lower bound is less
265
* than or equal to the smaller upper bound. The two ranges
266
* are adjacent if the larger lower bound is one greater
267
* than the smaller upper bound.
268
*/
269
if (Math.max(lba, lbb) - Math.min(uba, ubb) <= 1) {
270
// The coalesced range is from the smaller lower bound to
271
// the larger upper bound.
272
ranges.setElementAt(new int[]
273
{Math.min(lba, lbb),
274
Math.max(uba, ubb)}, j);
275
ranges.remove (j+1);
276
} else if (lba > lbb) {
277
278
/* If the two ranges don't overlap and aren't adjacent but
279
* are out of order, swap them.
280
*/
281
ranges.setElementAt (rangeb, j);
282
ranges.setElementAt (rangea, j+1);
283
} else {
284
/* If the two ranges don't overlap and aren't adjacent and
285
* aren't out of order, we're done early.
286
*/
287
break;
288
}
289
}
290
}
291
}
292
293
/**
294
* Convert the given vector of int[] objects to canonical array form.
295
*/
296
private static int[][] canonicalArrayForm(Vector ranges) {
297
return (int[][]) ranges.toArray (new int[ranges.size()][]);
298
}
299
300
/**
301
* Construct a new set-of-integer attribute with the given members in
302
* array form.
303
*
304
* @param members Set members in array form. If null, an empty set is
305
* constructed.
306
*
307
* @exception NullPointerException
308
* (Unchecked exception) Thrown if any element of
309
* <CODE>members</CODE> is null.
310
* @exception IllegalArgumentException
311
* (Unchecked exception) Thrown if any element of
312
* <CODE>members</CODE> is not a length-one or length-two array or if
313
* any non-null range in <CODE>members</CODE> has a lower bound less
314
* than zero.
315
*/
316
protected SetOfIntegerSyntax(int[][] members) {
317
this.members = parse (members);
318
}
319
320
/**
321
* Parse the given array form, returning canonical array form.
322
*/
323
private static int[][] parse(int[][] members) {
324
// Create vector to hold int[] elements, each element being one range
325
// parsed out of members.
326
Vector ranges = new Vector();
327
328
// Process all integer groups in members.
329
int n = (members == null ? 0 : members.length);
330
for (int i = 0; i < n; ++ i) {
331
// Get lower and upper bounds of the range.
332
int lb, ub;
333
if (members[i].length == 1) {
334
lb = ub = members[i][0];
335
} else if (members[i].length == 2) {
336
lb = members[i][0];
337
ub = members[i][1];
338
} else {
339
throw new IllegalArgumentException();
340
}
341
342
// Verify valid bounds.
343
if (lb <= ub && lb < 0) {
344
throw new IllegalArgumentException();
345
}
346
347
// Accumulate the range.
348
accumulate(ranges, lb, ub);
349
}
350
351
// Return canonical array form.
352
return canonicalArrayForm (ranges);
353
}
354
355
/**
356
* Construct a new set-of-integer attribute containing a single integer.
357
*
358
* @param member Set member.
359
*
360
* @exception IllegalArgumentException
361
* (Unchecked exception) Thrown if <CODE>member</CODE> is less than
362
* zero.
363
*/
364
protected SetOfIntegerSyntax(int member) {
365
if (member < 0) {
366
throw new IllegalArgumentException();
367
}
368
members = new int[][] {{member, member}};
369
}
370
371
/**
372
* Construct a new set-of-integer attribute containing a single range of
373
* integers. If the lower bound is greater than the upper bound (a null
374
* range), an empty set is constructed.
375
*
376
* @param lowerBound Lower bound of the range.
377
* @param upperBound Upper bound of the range.
378
*
379
* @exception IllegalArgumentException
380
* (Unchecked exception) Thrown if the range is non-null and
381
* <CODE>lowerBound</CODE> is less than zero.
382
*/
383
protected SetOfIntegerSyntax(int lowerBound, int upperBound) {
384
if (lowerBound <= upperBound && lowerBound < 0) {
385
throw new IllegalArgumentException();
386
}
387
members = lowerBound <=upperBound ?
388
new int[][] {{lowerBound, upperBound}} :
389
new int[0][];
390
}
391
392
393
/**
394
* Obtain this set-of-integer attribute's members in canonical array form.
395
* The returned array is "safe;" the client may alter it without affecting
396
* this set-of-integer attribute.
397
*
398
* @return This set-of-integer attribute's members in canonical array form.
399
*/
400
public int[][] getMembers() {
401
int n = members.length;
402
int[][] result = new int[n][];
403
for (int i = 0; i < n; ++ i) {
404
result[i] = new int[] {members[i][0], members[i][1]};
405
}
406
return result;
407
}
408
409
/**
410
* Determine if this set-of-integer attribute contains the given value.
411
*
412
* @param x Integer value.
413
*
414
* @return True if this set-of-integer attribute contains the value
415
* <CODE>x</CODE>, false otherwise.
416
*/
417
public boolean contains(int x) {
418
// Do a linear search to find the range that contains x, if any.
419
int n = members.length;
420
for (int i = 0; i < n; ++ i) {
421
if (x < members[i][0]) {
422
return false;
423
} else if (x <= members[i][1]) {
424
return true;
425
}
426
}
427
return false;
428
}
429
430
/**
431
* Determine if this set-of-integer attribute contains the given integer
432
* attribute's value.
433
*
434
* @param attribute Integer attribute.
435
*
436
* @return True if this set-of-integer attribute contains
437
* <CODE>theAttribute</CODE>'s value, false otherwise.
438
*/
439
public boolean contains(IntegerSyntax attribute) {
440
return contains (attribute.getValue());
441
}
442
443
/**
444
* Determine the smallest integer in this set-of-integer attribute that is
445
* greater than the given value. If there are no integers in this
446
* set-of-integer attribute greater than the given value, <CODE>-1</CODE> is
447
* returned. (Since a set-of-integer attribute can only contain nonnegative
448
* values, <CODE>-1</CODE> will never appear in the set.) You can use the
449
* <CODE>next()</CODE> method to iterate through the integer values in a
450
* set-of-integer attribute in ascending order, like this:
451
* <PRE>
452
* SetOfIntegerSyntax attribute = . . .;
453
* int i = -1;
454
* while ((i = attribute.next (i)) != -1)
455
* {
456
* foo (i);
457
* }
458
* </PRE>
459
*
460
* @param x Integer value.
461
*
462
* @return The smallest integer in this set-of-integer attribute that is
463
* greater than <CODE>x</CODE>, or <CODE>-1</CODE> if no integer in
464
* this set-of-integer attribute is greater than <CODE>x</CODE>.
465
*/
466
public int next(int x) {
467
// Do a linear search to find the range that contains x, if any.
468
int n = members.length;
469
for (int i = 0; i < n; ++ i) {
470
if (x < members[i][0]) {
471
return members[i][0];
472
} else if (x < members[i][1]) {
473
return x + 1;
474
}
475
}
476
return -1;
477
}
478
479
/**
480
* Returns whether this set-of-integer attribute is equivalent to the passed
481
* in object. To be equivalent, all of the following conditions must be
482
* true:
483
* <OL TYPE=1>
484
* <LI>
485
* <CODE>object</CODE> is not null.
486
* <LI>
487
* <CODE>object</CODE> is an instance of class SetOfIntegerSyntax.
488
* <LI>
489
* This set-of-integer attribute's members and <CODE>object</CODE>'s
490
* members are the same.
491
* </OL>
492
*
493
* @param object Object to compare to.
494
*
495
* @return True if <CODE>object</CODE> is equivalent to this
496
* set-of-integer attribute, false otherwise.
497
*/
498
public boolean equals(Object object) {
499
if (object != null && object instanceof SetOfIntegerSyntax) {
500
int[][] myMembers = this.members;
501
int[][] otherMembers = ((SetOfIntegerSyntax) object).members;
502
int m = myMembers.length;
503
int n = otherMembers.length;
504
if (m == n) {
505
for (int i = 0; i < m; ++ i) {
506
if (myMembers[i][0] != otherMembers[i][0] ||
507
myMembers[i][1] != otherMembers[i][1]) {
508
return false;
509
}
510
}
511
return true;
512
} else {
513
return false;
514
}
515
} else {
516
return false;
517
}
518
}
519
520
/**
521
* Returns a hash code value for this set-of-integer attribute. The hash
522
* code is the sum of the lower and upper bounds of the ranges in the
523
* canonical array form, or 0 for an empty set.
524
*/
525
public int hashCode() {
526
int result = 0;
527
int n = members.length;
528
for (int i = 0; i < n; ++ i) {
529
result += members[i][0] + members[i][1];
530
}
531
return result;
532
}
533
534
/**
535
* Returns a string value corresponding to this set-of-integer attribute.
536
* The string value is a zero-length string if this set is empty. Otherwise,
537
* the string value is a comma-separated list of the ranges in the canonical
538
* array form, where each range is represented as <CODE>"<I>i</I>"</CODE> if
539
* the lower bound equals the upper bound or
540
* <CODE>"<I>i</I>-<I>j</I>"</CODE> otherwise.
541
*/
542
public String toString() {
543
StringBuffer result = new StringBuffer();
544
int n = members.length;
545
for (int i = 0; i < n; i++) {
546
if (i > 0) {
547
result.append (',');
548
}
549
result.append (members[i][0]);
550
if (members[i][0] != members[i][1]) {
551
result.append ('-');
552
result.append (members[i][1]);
553
}
554
}
555
return result.toString();
556
}
557
558
}
559
560