/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
*******************************************************************************
* (C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved *
* *
* The original version of this source code and documentation is copyrighted *
* and owned by IBM, These materials are provided under terms of a License *
* Agreement between IBM and Sun. This technology is protected by multiple *
* US and International patents. This notice and attribution to IBM may not *
* to removed. *
*******************************************************************************
*/
/**
* A mutable set of Unicode characters and multicharacter strings. Objects of this class
* represent <em>character classes</em> used in regular expressions.
* A character specifies a subset of Unicode code points. Legal
* code points are U+0000 to U+10FFFF, inclusive.
*
* <p>The UnicodeSet class is not designed to be subclassed.
*
* <p><code>UnicodeSet</code> supports two APIs. The first is the
* <em>operand</em> API that allows the caller to modify the value of
* a <code>UnicodeSet</code> object. It conforms to Java 2's
* <code>java.util.Set</code> interface, although
* <code>UnicodeSet</code> does not actually implement that
* interface. All methods of <code>Set</code> are supported, with the
* modification that they take a character range or single character
* instead of an <code>Object</code>, and they take a
* <code>UnicodeSet</code> instead of a <code>Collection</code>. The
* operand API may be thought of in terms of boolean logic: a boolean
* OR is implemented by <code>add</code>, a boolean AND is implemented
* by <code>retain</code>, a boolean XOR is implemented by
* <code>complement</code> taking an argument, and a boolean NOT is
* implemented by <code>complement</code> with no argument. In terms
* of traditional set theory function names, <code>add</code> is a
* union, <code>retain</code> is an intersection, <code>remove</code>
* is an asymmetric difference, and <code>complement</code> with no
* argument is a set complement with respect to the superset range
* <code>MIN_VALUE-MAX_VALUE</code>
*
* <p>The second API is the
* <code>applyPattern()</code>/<code>toPattern()</code> API from the
* <code>java.text.Format</code>-derived classes. Unlike the
* methods that add characters, add categories, and control the logic
* of the set, the method <code>applyPattern()</code> sets all
* attributes of a <code>UnicodeSet</code> at once, based on a
* string pattern.
*
* <p><b>Pattern syntax</b></p>
*
* Patterns are accepted by the constructors and the
* <code>applyPattern()</code> methods and returned by the
* <code>toPattern()</code> method. These patterns follow a syntax
* similar to that employed by version 8 regular expression character
* classes. Here are some simple examples:
*
* <blockquote>
* <table>
* <tr align="top">
* <td nowrap valign="top" align="left"><code>[]</code></td>
* <td valign="top">No characters</td>
* </tr><tr align="top">
* <td nowrap valign="top" align="left"><code>[a]</code></td>
* <td valign="top">The character 'a'</td>
* </tr><tr align="top">
* <td nowrap valign="top" align="left"><code>[ae]</code></td>
* <td valign="top">The characters 'a' and 'e'</td>
* </tr>
* <tr>
* <td nowrap valign="top" align="left"><code>[a-e]</code></td>
* <td valign="top">The characters 'a' through 'e' inclusive, in Unicode code
* point order</td>
* </tr>
* <tr>
* <td nowrap valign="top" align="left"><code>[\\u4E01]</code></td>
* <td valign="top">The character U+4E01</td>
* </tr>
* <tr>
* <td nowrap valign="top" align="left"><code>[a{ab}{ac}]</code></td>
* <td valign="top">The character 'a' and the multicharacter strings "ab" and
* "ac"</td>
* </tr>
* <tr>
* <td nowrap valign="top" align="left"><code>[\p{Lu}]</code></td>
* <td valign="top">All characters in the general category Uppercase Letter</td>
* </tr>
* </table>
* </blockquote>
*
* Any character may be preceded by a backslash in order to remove any special
* meaning. White space characters, as defined by UCharacterProperty.isRuleWhiteSpace(), are
* ignored, unless they are escaped.
*
* <p>Property patterns specify a set of characters having a certain
* property as defined by the Unicode standard. Both the POSIX-like
* "[:Lu:]" and the Perl-like syntax "\p{Lu}" are recognized. For a
* complete list of supported property patterns, see the User's Guide
* for UnicodeSet at
* <a href="http://www.icu-project.org/userguide/unicodeSet.html">
* Actual determination of property data is defined by the underlying
* Unicode database as implemented by UCharacter.
*
* <p>Patterns specify individual characters, ranges of characters, and
* Unicode property sets. When elements are concatenated, they
* specify their union. To complement a set, place a '^' immediately
* after the opening '['. Property patterns are inverted by modifying
* their delimiters; "[:^foo]" and "\P{foo}". In any other location,
* '^' has no special meaning.
*
* <p>Ranges are indicated by placing two a '-' between two
* characters, as in "a-z". This specifies the range of all
* characters from the left to the right, in Unicode order. If the
* left character is greater than or equal to the
* right character it is a syntax error. If a '-' occurs as the first
* character after the opening '[' or '[^', or if it occurs as the
* last character before the closing ']', then it is taken as a
* literal. Thus "[a\\-b]", "[-ab]", and "[ab-]" all indicate the same
* set of three characters, 'a', 'b', and '-'.
*
* <p>Sets may be intersected using the '&' operator or the asymmetric
* set difference may be taken using the '-' operator, for example,
* "[[:L:]&[\\u0000-\\u0FFF]]" indicates the set of all Unicode letters
* with values less than 4096. Operators ('&' and '|') have equal
* precedence and bind left-to-right. Thus
* "[[:L:]-[a-z]-[\\u0100-\\u01FF]]" is equivalent to
* "[[[:L:]-[a-z]]-[\\u0100-\\u01FF]]". This only really matters for
* difference; intersection is commutative.
*
* <table>
* <tr valign=top><td nowrap><code>[a]</code><td>The set containing 'a'
* <tr valign=top><td nowrap><code>[a-z]</code><td>The set containing 'a'
* through 'z' and all letters in between, in Unicode order
* <tr valign=top><td nowrap><code>[^a-z]</code><td>The set containing
* all characters but 'a' through 'z',
* that is, U+0000 through 'a'-1 and 'z'+1 through U+10FFFF
* <tr valign=top><td nowrap><code>[[<em>pat1</em>][<em>pat2</em>]]</code>
* <td>The union of sets specified by <em>pat1</em> and <em>pat2</em>
* <tr valign=top><td nowrap><code>[[<em>pat1</em>]&[<em>pat2</em>]]</code>
* <td>The intersection of sets specified by <em>pat1</em> and <em>pat2</em>
* <tr valign=top><td nowrap><code>[[<em>pat1</em>]-[<em>pat2</em>]]</code>
* <td>The asymmetric difference of sets specified by <em>pat1</em> and
* <em>pat2</em>
* <tr valign=top><td nowrap><code>[:Lu:] or \p{Lu}</code>
* <td>The set of characters having the specified
* Unicode property; in
* this case, Unicode uppercase letters
* <tr valign=top><td nowrap><code>[:^Lu:] or \P{Lu}</code>
* <td>The set of characters <em>not</em> having the given
* Unicode property
* </table>
*
* <p><b>Warning</b>: you cannot add an empty string ("") to a UnicodeSet.</p>
*
* <p><b>Formal syntax</b></p>
*
* <blockquote>
* <table>
* <tr align="top">
* <td nowrap valign="top" align="right"><code>pattern := </code></td>
* <td valign="top"><code>('[' '^'? item* ']') |
* property</code></td>
* </tr>
* <tr align="top">
* <td nowrap valign="top" align="right"><code>item := </code></td>
* <td valign="top"><code>char | (char '-' char) | pattern-expr<br>
* </code></td>
* </tr>
* <tr align="top">
* <td nowrap valign="top" align="right"><code>pattern-expr := </code></td>
* <td valign="top"><code>pattern | pattern-expr pattern |
* pattern-expr op pattern<br>
* </code></td>
* </tr>
* <tr align="top">
* <td nowrap valign="top" align="right"><code>op := </code></td>
* <td valign="top"><code>'&' | '-'<br>
* </code></td>
* </tr>
* <tr align="top">
* <td nowrap valign="top" align="right"><code>special := </code></td>
* <td valign="top"><code>'[' | ']' | '-'<br>
* </code></td>
* </tr>
* <tr align="top">
* <td nowrap valign="top" align="right"><code>char := </code></td>
* <td valign="top"><em>any character that is not</em><code> special<br>
* | ('\\' </code><em>any character</em><code>)<br>
* | ('\u' hex hex hex hex)<br>
* </code></td>
* </tr>
* <tr align="top">
* <td nowrap valign="top" align="right"><code>hex := </code></td>
* <td valign="top"><em>any character for which
* </em><code>Character.digit(c, 16)</code><em>
* returns a non-negative result</em></td>
* </tr>
* <tr>
* <td nowrap valign="top" align="right"><code>property := </code></td>
* <td valign="top"><em>a Unicode property set pattern</td>
* </tr>
* </table>
* <br>
* <table border="1">
* <tr>
* <td>Legend: <table>
* <tr>
* <td nowrap valign="top"><code>a := b</code></td>
* <td width="20" valign="top"> </td>
* <td valign="top"><code>a</code> may be replaced by <code>b</code> </td>
* </tr>
* <tr>
* <td nowrap valign="top"><code>a?</code></td>
* <td valign="top"></td>
* <td valign="top">zero or one instance of <code>a</code><br>
* </td>
* </tr>
* <tr>
* <td nowrap valign="top"><code>a*</code></td>
* <td valign="top"></td>
* <td valign="top">one or more instances of <code>a</code><br>
* </td>
* </tr>
* <tr>
* <td nowrap valign="top"><code>a | b</code></td>
* <td valign="top"></td>
* <td valign="top">either <code>a</code> or <code>b</code><br>
* </td>
* </tr>
* <tr>
* <td nowrap valign="top"><code>'a'</code></td>
* <td valign="top"></td>
* <td valign="top">the literal string between the quotes </td>
* </tr>
* </table>
* </td>
* </tr>
* </table>
* </blockquote>
* <p>To iterate over contents of UnicodeSet, use UnicodeSetIterator class.
*
* @author Alan Liu
* @stable ICU 2.0
* @see UnicodeSetIterator
*/
// 110000 for codepoints
/**
* Minimum value that can be stored in a UnicodeSet.
* @stable ICU 2.0
*/
/**
* Maximum value that can be stored in a UnicodeSet.
* @stable ICU 2.0
*/
// NOTE: normally the field should be of type SortedSet; but that is missing a public clone!!
// is not private so that UnicodeSetIterator can get access
/**
* The pattern representation of this set. This may not be the
* most economical pattern. It is the pattern supplied to
* applyPattern(), with variables substituted and whitespace
* removed. For sets constructed without applyPattern(), or
* modified using the non-pattern API, this string will be null,
* indicating that toPattern() must generate a pattern
* representation from the inversion list.
*/
/**
* A set of all characters _except_ the second through last characters of
* certain ranges. These ranges are ranges of characters whose
* properties are all exactly alike, e.g. CJK Ideographs from
* U+4E00 to U+9FA5.
*/
//----------------------------------------------------------------
// Public API
//----------------------------------------------------------------
/**
* Constructs an empty set.
* @stable ICU 2.0
*/
public UnicodeSet() {
}
/**
* Constructs a set containing the given range. If <code>end >
* start</code> then an empty set is created.
*
* @param start first character, inclusive, of range
* @param end last character, inclusive, of range
* @stable ICU 2.0
*/
this();
}
/**
* Constructs a set from the given pattern. See the class description
* for the syntax of the pattern language. Whitespace is ignored.
* @param pattern a string specifying what characters are in the set
* @exception java.lang.IllegalArgumentException if the pattern contains
* a syntax error.
* @stable ICU 2.0
*/
this();
}
/**
* Make this object represent the same set as <code>other</code>.
* @param other a <code>UnicodeSet</code> whose value will be
* copied to this object
* @stable ICU 2.0
*/
return this;
}
/**
* Modifies this set to represent the set specified by the given pattern.
* See the class description for the syntax of the pattern language.
* Whitespace is ignored.
* @param pattern a string specifying what characters are in the set
* @exception java.lang.IllegalArgumentException if the pattern
* contains a syntax error.
* @stable ICU 2.0
*/
}
/**
* Append the <code>toPattern()</code> representation of a
* string to the given <code>StringBuffer</code>.
*/
}
}
/**
* Append the <code>toPattern()</code> representation of a
* character to the given <code>StringBuffer</code>.
*/
// Use hex escape notation (<backslash>uxxxx or <backslash>Uxxxxxxxx) for anything
// unprintable
return;
}
}
// Okay to let ':' pass through
switch (c) {
case '[': // SET_OPEN:
case ']': // SET_CLOSE:
case '-': // HYPHEN:
case '^': // COMPLEMENT:
case '&': // INTERSECTION:
case '\\': //BACKSLASH:
case '{':
case '}':
case '$':
case ':':
break;
default:
// Escape whitespace
if (UCharacterProperty.isRuleWhiteSpace(c)) {
}
break;
}
}
/**
* Append a string representation of this set to result. This will be
* a cleaned version of the string passed to applyPattern(), if there
* is one. Otherwise it will be generated.
*/
boolean escapeUnprintable) {
int i;
int backslashCount = 0;
i += UTF16.getCharCount(c);
// If the unprintable character is preceded by an odd
// number of backslashes, then it has been escaped.
// Before unescaping it, we delete the final
// backslash.
}
backslashCount = 0;
} else {
if (c == '\\') {
} else {
backslashCount = 0;
}
}
}
return result;
}
}
/**
* Generate and append a string representation of this set to result.
* This does not use this.pat, the cleaned up copy of the string
* passed to applyPattern().
* @param includeStrings if false, doesn't include the strings.
* @stable ICU 3.8
*/
boolean escapeUnprintable, boolean includeStrings) {
int count = getRangeCount();
// If the set contains at least 2 intervals and includes both
// MIN_VALUE and MAX_VALUE, then the inverse representation will
// be more economical.
if (count > 1 &&
// Emit the inverse
for (int i = 1; i < count; ++i) {
}
}
}
}
// Default; emit the ranges as pairs
else {
for (int i = 0; i < count; ++i) {
int start = getRangeStart(i);
int end = getRangeEnd(i);
}
}
}
}
}
}
}
// for internal use, after checkFrozen has been called
}
}
}
return this;
}
/**
* Adds the specified character to this set if it is not already
* present. If this set already contains the specified character,
* the call leaves this set unchanged.
* @stable ICU 2.0
*/
return add_unchecked(c);
}
// for internal use only, after checkFrozen has been called
}
// find smallest i such that c < list[i]
// if odd, then it is IN the set
// if even, then it is OUT of the set
int i = findCodePoint(c);
// already in set?
if ((i & 1) != 0) return this;
// HIGH is 0x110000
// assert(list[len-1] == HIGH);
// empty = [HIGH]
// [start_0, limit_0, start_1, limit_1, HIGH]
// [..., start_k-1, limit_k-1, start_k, limit_k, ..., HIGH]
// ^
// list[i]
// i == 0 means c is before the first range
if (c == list[i]-1) {
// c is before start of next range
list[i] = c;
// if we touched the HIGH mark, then add a new one
if (c == MAX_VALUE) {
}
// collapse adjacent ranges
// [..., start_k-1, c, c, limit_k, ..., HIGH]
// ^
// list[i]
len -= 2;
}
}
// c is after end of prior range
list[i-1]++;
// no need to chcek for collapse here
}
else {
// At this point we know the new char is not adjacent to
// any existing ranges, and it is not 10FFFF.
// [..., start_k-1, limit_k-1, start_k, limit_k, ..., HIGH]
// ^
// list[i]
// [..., start_k-1, limit_k-1, c, c+1, start_k, limit_k, ..., HIGH]
// ^
// list[i]
// Don't use ensureCapacity() to save on copying.
// NOTE: This has no measurable impact on performance,
// but it might help in some usage patterns.
} else {
}
list[i] = c;
len += 2;
}
return this;
}
/**
* Adds the specified multicharacter to this set if it is not already
* present. If this set already contains the multicharacter,
* the call leaves this set unchanged.
* Thus "ch" => {"ch"}
* <br><b>Warning: you cannot add an empty string ("") to a UnicodeSet.</b>
* @param s the source string
* @return this object, for chaining
* @stable ICU 2.0
*/
int cp = getSingleCP(s);
if (cp < 0) {
} else {
}
return this;
}
/**
* @return a code point IF the string consists of a single one.
* otherwise returns -1.
* @param string to test
*/
if (s.length() < 1) {
throw new IllegalArgumentException("Can't use zero-length strings in UnicodeSet");
}
// at this point, len = 2
return cp;
}
return -1;
}
/**
* Complements the specified range in this set. Any character in
* the range will be removed if it is in this set, or will be
* added if it is not in this set. If <code>end > start</code>
* then an empty range is complemented, leaving the set unchanged.
*
* @param start first character, inclusive, of range to be removed
* from this set.
* @param end last character, inclusive, of range to be removed
* from this set.
* @stable ICU 2.0
*/
}
}
}
return this;
}
/**
* This is equivalent to
* <code>complement(MIN_VALUE, MAX_VALUE)</code>.
* @stable ICU 2.0
*/
--len;
} else {
++len;
}
return this;
}
/**
* Returns true if this set contains the given character.
* @param c character to be checked for containment
* @return true if the test condition is met
* @stable ICU 2.0
*/
public boolean contains(int c) {
}
/*
// Set i to the index of the start item greater than ch
// We know we will terminate without length test!
int i = -1;
while (true) {
if (c < list[++i]) break;
}
*/
int i = findCodePoint(c);
return ((i & 1) != 0); // return true if odd
}
/**
* Returns the smallest value i such that c < list[i]. Caller
* must ensure that c is a legal value or this method will enter
* an infinite loop. This method performs a binary search.
* @param c a character in the range MIN_VALUE..MAX_VALUE
* inclusive
* @return the smallest integer i in the range 0..len-1,
* inclusive, such that c < list[i]
*/
private final int findCodePoint(int c) {
/* Examples:
findCodePoint(c)
set list[] c=0 1 3 4 7 8
=== ============== ===========
[] [110000] 0 0 0 0 0 0
[\u0000-\u0003] [0, 4, 110000] 1 1 1 2 2 2
[\u0004-\u0007] [4, 8, 110000] 0 0 0 1 1 2
[:all:] [0, 110000] 1 1 1 1 1 1
*/
// Return the smallest i such that c < list[i]. Assume
// list[len - 1] == HIGH and that c is legal (0..HIGH-1).
// High runner test. c is often after the last range, so an
// initial check for this condition pays off.
int lo = 0;
// invariant: c >= list[lo]
// invariant: c < list[hi]
for (;;) {
if (c < list[i]) {
hi = i;
} else {
lo = i;
}
}
}
/**
* Adds all of the elements in the specified set to this set if
* they're not already present. This operation effectively
* modifies this set so that its value is the <i>union</i> of the two
* sets. The behavior of this operation is unspecified if the specified
* collection is modified while the operation is in progress.
*
* @param c set whose elements are to be added to this set.
* @stable ICU 2.0
*/
return this;
}
/**
* Retains only the elements in this set that are contained in the
* specified set. In other words, removes from this set all of
* its elements that are not contained in the specified set. This
* operation effectively modifies this set so that its value is
* the <i>intersection</i> of the two sets.
*
* @param c set that defines which elements this set will retain.
* @stable ICU 2.0
*/
return this;
}
/**
* Removes from this set all of its elements that are contained in the
* specified set. This operation effectively modifies this
* set so that its value is the <i>asymmetric set difference</i> of
* the two sets.
*
* @param c set that defines which elements will be removed from
* this set.
* @stable ICU 2.0
*/
return this;
}
/**
* Removes all of the elements from this set. This set will be
* empty after this call returns.
* @stable ICU 2.0
*/
len = 1;
return this;
}
/**
* Iteration method that returns the number of ranges contained in
* this set.
* @see #getRangeStart
* @see #getRangeEnd
* @stable ICU 2.0
*/
public int getRangeCount() {
return len/2;
}
/**
* Iteration method that returns the first character in the
* specified range of this set.
* @exception ArrayIndexOutOfBoundsException if index is outside
* the range <code>0..getRangeCount()-1</code>
* @see #getRangeCount
* @see #getRangeEnd
* @stable ICU 2.0
*/
}
/**
* Iteration method that returns the last character in the
* specified range of this set.
* @exception ArrayIndexOutOfBoundsException if index is outside
* the range <code>0..getRangeCount()-1</code>
* @see #getRangeStart
* @see #getRangeEnd
* @stable ICU 2.0
*/
}
//----------------------------------------------------------------
// Implementation: Pattern parsing
//----------------------------------------------------------------
/**
* Parses the given pattern, starting at the given position. The character
* at pattern.charAt(pos.getIndex()) must be '[', or the parse fails.
* Parsing continues until the corresponding closing ']'. If a syntax error
* is encountered between the opening and closing brace, the parse fails.
* Upon return from a successful parse, the ParsePosition is updated to
* point to the character following the closing ']', and an inversion
* list for the parsed pattern is returned. This method
* calls itself recursively to parse embedded subpatterns.
*
* @param pattern the string containing the pattern to be parsed. The
* portion of the string from pos.getIndex(), which must be a '[', to the
* corresponding closing ']', is parsed.
* @param pos upon entry, the position at which to being parsing. The
* character at pattern.charAt(pos.getIndex()) must be a '['. Upon return
* from a successful parse, pos.getIndex() is either the character after the
* closing ']' of the parsed pattern, or pattern.length() if the closing ']'
* is the last character of the pattern string.
* @return an inversion list for the parsed substring
* of <code>pattern</code>
* @exception java.lang.IllegalArgumentException if the parse fails.
*/
int options) {
// Need to build the pattern in a temporary string because
// _applyPattern calls add() etc., which set pat to empty.
if (parsePositionWasNull) {
}
if (chars.inVariable()) {
}
if (parsePositionWasNull) {
// Skip over trailing whitespace
}
"\" failed at " + i);
}
}
return this;
}
/**
* Parse the pattern from the given RuleCharacterIterator. The
* iterator is advanced over the parsed pattern.
* @param chars iterator over the pattern characters. Upon return
* it will be advanced to the first character after the parsed
* pattern, or the end of the iteration if all characters are
* parsed.
* @param symbols symbol table to use to parse and dereference
* variables, or null if none.
* @param rebuiltPat the pattern that was parsed, rebuilt or
* copied from the input pattern, as appropriate.
* @param options a bit mask of zero or more of the following:
* IGNORE_SPACE, CASE.
*/
// Syntax characters: [ ] ^ - & { }
// Recognized special forms for chars, sets: c-c s-s s&s
}
boolean usePat = false;
// mode: 0=before [, 1=between [...], 2=after ]
// lastItem: 0=none, 1=char, 2=set
char op = 0;
boolean invert = false;
clear();
if (false) {
// Debugging assertion
throw new IllegalArgumentException();
}
}
int c = 0;
boolean literal = false;
// -------- Check for property pattern
// setMode: 0=none, 1=unicodeset, 2=propertypat, 3=preparsed
int setMode = 0;
setMode = 2;
}
// -------- Parse '[' of opening delimiter OR nested set.
// If there is a nested set, use `setMode' to define how
// the set should be parsed. If the '[' is part of the
// opening delimiter for this pattern, parse special
// strings "[", "[^", "[-", and "[^-". Check for stand-in
// characters representing a nested set in the symbol
// table.
else {
// Prepare to backup if necessary
if (c == '[' && !literal) {
if (mode == 1) {
setMode = 1;
} else {
// Handle opening '[' delimiter
mode = 1;
if (c == '^' && !literal) {
invert = true;
}
// Fall through to handle special leading '-';
// otherwise restart loop for nested [], \p{}, etc.
if (c == '-') {
literal = true;
// Fall through to handle literal '-' below
} else {
continue;
}
}
if (m != null) {
try {
nested = (UnicodeSet) m;
setMode = 3;
} catch (ClassCastException e) {
}
}
}
}
// -------- Handle a nested set. This either is inline in
// the pattern or represented by a stand-in that has
// previously been parsed and was looked up in the symbol
// table.
if (setMode != 0) {
if (lastItem == 1) {
if (op != 0) {
}
}
}
}
switch (setMode) {
case 1:
break;
case 2:
break;
case 3: // `nested' already parsed
break;
}
usePat = true;
if (mode == 0) {
// Entire pattern is a category; leave parse loop
mode = 2;
break;
}
switch (op) {
case '-':
break;
case '&':
break;
case 0:
break;
}
op = 0;
lastItem = 2;
continue;
}
if (mode == 0) {
}
// -------- Parse special (syntax) characters. If the
// current character is not special, or if it is escaped,
// then fall through and handle it below.
if (!literal) {
switch (c) {
case ']':
if (lastItem == 1) {
}
// Treat final trailing '-' as a literal
if (op == '-') {
} else if (op == '&') {
}
mode = 2;
continue;
case '-':
if (op == 0) {
if (lastItem != 0) {
op = (char) c;
continue;
} else {
// Treat final trailing '-' as a literal
add_unchecked(c, c);
if (c == ']' && !literal) {
mode = 2;
continue;
}
}
}
case '&':
op = (char) c;
continue;
}
case '^':
case '{':
if (op != 0) {
}
if (lastItem == 1) {
}
lastItem = 0;
buf = new StringBuffer();
} else {
}
boolean ok = false;
if (c == '}' && !literal) {
ok = true;
break;
}
}
}
// We have new string. Add it to set and continue;
// we don't need to drop through to the further
// processing
continue;
case SymbolTable.SYMBOL_REF:
// symbols nosymbols
// [a-$] error error (ambiguous)
// [a$] anchor anchor
// [a-$x] var "x"* literal '$'
// [a-$.] error literal '$'
// *We won't get here in the case of var "x"
c = SymbolTable.SYMBOL_REF;
break; // literal '$'
}
if (lastItem == 1) {
}
usePat = true;
mode = 2;
continue;
}
default:
break;
}
}
// -------- Parse literal characters. This includes both
// escaped chars ("\u4E01") and non-syntax characters
// ("a").
switch (lastItem) {
case 0:
lastItem = 1;
lastChar = c;
break;
case 1:
if (op == '-') {
if (lastChar >= c) {
// Don't allow redundant (a-a) or empty (b-a) ranges;
// these are most likely typos.
}
add_unchecked(lastChar, c);
_appendToPat(patBuf, c, false);
} else {
lastChar = c;
}
break;
case 2:
if (op != 0) {
}
lastChar = c;
lastItem = 1;
break;
}
}
if (mode != 2) {
}
if (invert) {
complement();
}
// Use the rebuilt pattern (pat) only if necessary. Prefer the
// generated pattern.
if (usePat) {
} else {
_generatePattern(rebuiltPat, false, true);
}
}
'"');
}
//----------------------------------------------------------------
// Implementation: Utility methods
//----------------------------------------------------------------
}
}
/**
* Assumes start <= end.
*/
} else {
}
return rangeList;
}
//----------------------------------------------------------------
// Implementation: Fundamental operations
//----------------------------------------------------------------
// polarity = 0, 3 is normal: x xor y
// polarity = 1, 2: x xor ~y == x === y
int i = 0, j = 0, k = 0;
int a = list[i++];
int b;
b = LOW;
++j;
b = other[j];
}
} else {
b = other[j++];
}
// simplest of all the routines
// sort the values, discarding identicals!
while (true) {
if (a < b) {
buffer[k++] = a;
a = list[i++];
} else if (b < a) {
buffer[k++] = b;
b = other[j++];
} else if (a != HIGH) { // at this point, a == b
// discard both values!
a = list[i++];
b = other[j++];
} else { // DONE!
len = k;
break;
}
}
// swap list and buffer
return this;
}
// polarity = 0 is normal: x union y
// polarity = 2: x union ~y
// polarity = 1: ~x union y
// polarity = 3: ~x union ~y
int i = 0, j = 0, k = 0;
int a = list[i++];
int b = other[j++];
// change from xor is that we have to check overlapping pairs
// polarity bit 1 means a is second, bit 2 means b is.
main:
while (true) {
switch (polarity) {
case 0: // both first; take lower if unequal
if (a < b) { // take a
// Back up over overlapping ranges in buffer[]
// Pick latter end value in buffer[] vs. list[]
} else {
// No overlap
buffer[k++] = a;
a = list[i];
}
polarity ^= 1;
} else if (b < a) { // take b
} else {
buffer[k++] = b;
b = other[j];
}
j++;
polarity ^= 2;
} else { // a == b, take a, drop b
// This is symmetrical; it doesn't matter if
// we backtrack with a or b. - liu
} else {
// No overlap
buffer[k++] = a;
a = list[i];
}
i++;
polarity ^= 1;
}
break;
case 3: // both second; take higher if unequal, and drop other
if (b <= a) { // take a
buffer[k++] = a;
} else { // take b
buffer[k++] = b;
}
break;
case 1: // a second, b first; if b < a, overlap
if (a < b) { // no overlap, take a
} else if (b < a) { // OVERLAP, drop b
} else { // a == b, drop both!
}
break;
case 2: // a first, b second; if a < b, overlap
if (b < a) { // no overlap, take b
} else if (a < b) { // OVERLAP, drop a
} else { // a == b, drop both!
}
break;
}
}
len = k;
// swap list and buffer
return this;
}
// polarity = 0 is normal: x intersect y
// polarity = 2: x intersect ~y == set-minus
// polarity = 1: ~x intersect y
// polarity = 3: ~x intersect ~y
int i = 0, j = 0, k = 0;
int a = list[i++];
int b = other[j++];
// change from xor is that we have to check overlapping pairs
// polarity bit 1 means a is second, bit 2 means b is.
main:
while (true) {
switch (polarity) {
case 0: // both first; drop the smaller
if (a < b) { // drop a
} else if (b < a) { // drop b
} else { // a == b, take one, drop other
}
break;
case 3: // both second; take lower if unequal
if (a < b) { // take a
} else if (b < a) { // take b
} else { // a == b, take one, drop other
}
break;
case 1: // a second, b first;
if (a < b) { // NO OVERLAP, drop a
} else if (b < a) { // OVERLAP, take b
} else { // a == b, drop both!
}
break;
case 2: // a first, b second; if a < b, overlap
if (b < a) { // no overlap, drop b
} else if (a < b) { // OVERLAP, take a
} else { // a == b, drop both!
}
break;
}
}
len = k;
// swap list and buffer
return this;
}
private static final int max(int a, int b) {
return (a > b) ? a : b;
}
//----------------------------------------------------------------
// Generic filter-based scanning code
//----------------------------------------------------------------
private static interface Filter {
}
// VersionInfo for unassigned characters
// Reference comparison ok; VersionInfo caches and reuses
// unique objects.
return v != NO_VERSION &&
}
}
if (INCLUSIONS == null) {
}
switch(src) {
break;
default:
}
}
return INCLUSIONS[src];
}
/**
* Generic filter-based scanning code for UCD property UnicodeSets.
*/
// Walk through all Unicode characters, noting the start
// and end of each range for which filter.contain(c) is
// true. Add each range to a set.
//
// To improve performance, use the INCLUSIONS set, which
// encodes information about character ranges that are known
// to have identical properties, such as the CJK Ideographs
// from U+4E00 to U+9FA5. INCLUSIONS contains all characters
// except the first characters of such ranges.
//
// TODO Where possible, instead of scanning over code points,
// use internal property data to initialize UnicodeSets for
// those properties. Scanning code points is slow.
clear();
int startHasProperty = -1;
for (int j=0; j<limitRange; ++j) {
// get current range
// for all the code points in the range, process
// only add to the unicodeset on inflection points --
// where the hasProperty value changes to false
if (startHasProperty < 0) {
}
} else if (startHasProperty >= 0) {
startHasProperty = -1;
}
}
}
if (startHasProperty >= 0) {
}
return this;
}
/**
* Remove leading and trailing rule white space and compress
* internal rule white space to a single space character.
*
* @see UCharacterProperty#isRuleWhiteSpace
*/
continue;
}
}
}
}
}
/**
* Modifies this set to contain those code points which have the
* given value for the given property. Prior contents of this
* set are lost.
* @param propertyAlias
* @param valueAlias
* @param symbols if not null, then symbols are first called to see if a property
* is available. If true, then everything else is skipped.
* @return this set
* @stable ICU 3.2
*/
// Must munge name, since
// VersionInfo.getInstance() does not do
// 'loose' matching.
return this;
}
}
}
/**
* Return true if the given iterator appears to point at a
* property pattern. Regardless of the result, return with the
* iterator unchanged.
* @param chars iterator over the pattern characters. Upon return
* it will be unchanged.
* @param iterOpts RuleCharacterIterator options
*/
int iterOpts) {
boolean result = false;
if (c == '[' || c == '\\') {
(d == 'N' || d == 'p' || d == 'P');
}
return result;
}
/**
* Parse the given property pattern at the given parse position.
* @param symbols TODO
*/
// On entry, ppos should point to one of the following locations:
// Minimum length is 5 characters, e.g. \p{L}
return null;
}
boolean posix = false; // true for [:pat:], false for \p{pat} \P{pat} \N{pat}
boolean isName = false; // true for \N{pat}, o/w false
boolean invert = false;
// Look for an opening [:, [:^, \p, or \P
posix = true;
++pos;
invert = true;
}
invert = (c == 'P');
isName = (c == 'N');
// Syntax error; "\p" or "\P" not followed by "{"
return null;
}
} else {
// Open delimiter not seen
return null;
}
// Look for the matching close delimiter, either :] or }
if (close < 0) {
// Syntax error; close delimiter missing
return null;
}
// Look for an '=' sign. If this is present, we will parse a
// medium \p{gc=Cf} or long \p{GeneralCategory=Format}
// pattern.
}
else {
// Handle case where no '=' is seen, and \N{}
valueName = "";
// Handle \N{name}
if (isName) {
// This is a little inefficient since it means we have to
// parse "na" back to UProperty.NAME even though we already
// know it's UProperty.NAME. If we refactor the API to
// support args of (int, String) then we can remove
// "na" and make this a little more efficient.
propName = "na";
}
}
if (invert) {
complement();
}
// Move to the limit position after the close delimiter
return this;
}
/**
* Parse a property pattern.
* @param chars iterator over the pattern characters. Upon return
* it will be advanced to the first character after the parsed
* pattern, or the end of the iteration if all characters are
* parsed.
* @param rebuiltPat the pattern that was parsed, rebuilt or
* copied from the input pattern, as appropriate.
* @param symbols TODO
*/
}
}
//----------------------------------------------------------------
// Case folding API
//----------------------------------------------------------------
/**
* Bitmask for constructor and applyPattern() indicating that
* white space should be ignored. If set, ignore characters for
* which UCharacterProperty.isRuleWhiteSpace() returns true,
* unless they are quoted or escaped. This may be ORed together
* with other selectors.
* @stable ICU 3.8
*/
}