001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Nikolay A. Kuznetsov
020: * @version $Revision: 1.15.2.2 $
021: */package java.util.regex;
022:
023: import java.util.Arrays;
024:
025: import org.apache.harmony.regex.internal.nls.Messages;
026:
027: /**
028: * Match result implementation
029: * Note: probably it might make sense to combine this class with Matcher.
030: *
031: * @author Nikolay A. Kuznetsov
032: * @version $Revision: 1.15.2.2 $
033: */
034: class MatchResultImpl implements MatchResult {
035:
036: private int[] groupBounds = null;
037:
038: private int[] consumers = null;
039:
040: private int[] compQuantCounters = null;
041:
042: private CharSequence string = null;
043:
044: private int groupCount = 0;
045:
046: private boolean valid = false;
047:
048: private int leftBound;
049:
050: private int rightBound;
051:
052: int startIndex;
053:
054: private boolean transparentBounds = false;
055:
056: private boolean anchoringBounds = false;
057:
058: boolean hitEnd = false;
059:
060: boolean requireEnd = false;
061:
062: int previousMatch = -1;
063:
064: private int mode;
065:
066: MatchResultImpl(CharSequence string, int leftBound, int rightBound,
067: int groupCount, int compQuantCount, int consumersCount) {
068: this .groupCount = ++groupCount;
069: this .groupBounds = new int[groupCount * 2];
070:
071: this .consumers = new int[consumersCount];
072: Arrays.fill(consumers, -1);
073:
074: if (compQuantCount > 0)
075: this .compQuantCounters = new int[compQuantCount];
076: Arrays.fill(groupBounds, -1);
077: reset(string, leftBound, rightBound);
078: }
079:
080: MatchResult cloneImpl() {
081: MatchResultImpl res = new MatchResultImpl(this .string,
082: this .leftBound, this .rightBound, this .groupCount - 1,
083: 0, 0);
084:
085: res.valid = valid;
086: if (valid) {
087: System.arraycopy(groupBounds, 0, res.groupBounds, 0,
088: this .groupBounds.length);
089: }
090: return res;
091: }
092:
093: public void setConsumed(int counter, int value) {
094: this .consumers[counter] = value;
095: }
096:
097: public int getConsumed(int counter) {
098: return this .consumers[counter];
099: }
100:
101: public int end() {
102: return end(0);
103: }
104:
105: public int end(int group) {
106: checkGroup(group);
107: return groupBounds[group * 2 + 1];
108: }
109:
110: void setStart(int group, int offset) {
111: groupBounds[group * 2] = offset;
112: }
113:
114: void setEnd(int group, int offset) {
115: groupBounds[group * 2 + 1] = offset;
116: }
117:
118: int getStart(int group) {
119: return groupBounds[group * 2];
120: }
121:
122: int getEnd(int group) {
123: return groupBounds[group * 2 + 1];
124: }
125:
126: public String group() {
127: return group(0);
128: }
129:
130: public String group(int group) {
131: if (start(group) < 0)
132: return null;
133: return string.subSequence(start(group), end(group)).toString();
134: }
135:
136: String getGroupNoCheck(int group) {
137: int st = getStart(group);
138: int end = getEnd(group);
139: if ((end | st | (end - st)) < 0 || end > string.length())
140: return null;
141:
142: return string.subSequence(st, end).toString();
143: }
144:
145: public int groupCount() {
146: return groupCount - 1;
147: }
148:
149: public int start() {
150: return start(0);
151: }
152:
153: public int start(int group) {
154: checkGroup(group);
155: return groupBounds[group * 2];
156: }
157:
158: /*
159: * This method being called after any successful match; For now it's being
160: * used to check zero group for empty match;
161: */
162: public void finalizeMatch() {
163: if (this .groupBounds[0] == -1) {
164: this .groupBounds[0] = this .startIndex;
165: this .groupBounds[1] = this .startIndex;
166: }
167:
168: previousMatch = end();
169: }
170:
171: public int getEnterCounter(int setCounter) {
172: return compQuantCounters[setCounter];
173: }
174:
175: public void setEnterCounter(int setCounter, int value) {
176: compQuantCounters[setCounter] = value;
177: }
178:
179: private void checkGroup(int group) {
180: if (!valid) {
181: throw new IllegalStateException(Messages
182: .getString("regex.05")); //$NON-NLS-1$
183: }
184:
185: if (group < 0 || group > groupCount) {
186: throw new IndexOutOfBoundsException(Messages.getString(
187: "regex.06", group)); //$NON-NLS-1$
188: }
189: }
190:
191: void updateGroup(int index, int srtOffset, int endOffset) {
192: checkGroup(index);
193: groupBounds[index * 2] = srtOffset;
194: groupBounds[index * 2 + 1] = endOffset;
195: }
196:
197: protected void setValid() {
198: this .valid = true;
199: }
200:
201: protected boolean isValid() {
202: return this .valid;
203: }
204:
205: protected void reset(CharSequence newSequence, int leftBound,
206: int rightBound) {
207: valid = false;
208: mode = Matcher.MODE_MATCH;
209: Arrays.fill(groupBounds, -1);
210: Arrays.fill(consumers, -1);
211:
212: if (newSequence != null)
213: this .string = newSequence;
214: if (leftBound >= 0)
215: this .setBounds(leftBound, rightBound);
216: this .startIndex = this .leftBound;
217: }
218:
219: protected void reset() {
220: reset(null, -1, -1);
221: }
222:
223: private void setBounds(int leftBound, int rightBound) {
224: this .leftBound = leftBound;
225: this .rightBound = rightBound;
226: }
227:
228: protected void setStartIndex(int startIndex) {
229: this .startIndex = startIndex;
230: previousMatch = previousMatch >= 0 ? previousMatch : startIndex;
231: }
232:
233: public int getLeftBound() {
234: return this .leftBound;
235: }
236:
237: public int getRightBound() {
238: return this .rightBound;
239: }
240:
241: protected void setMode(int mode) {
242: this .mode = mode;
243: }
244:
245: protected int mode() {
246: return mode;
247: }
248:
249: protected void useAnchoringBounds(boolean value) {
250: this .anchoringBounds = value;
251: }
252:
253: protected boolean hasAnchoringBounds() {
254: return this .anchoringBounds;
255: }
256:
257: protected void useTransparentBounds(boolean value) {
258: this .transparentBounds = value;
259: }
260:
261: protected boolean hasTransparentBounds() {
262: return this .transparentBounds;
263: }
264:
265: int getPreviousMatchEnd() {
266: return previousMatch;
267: }
268: }
|