KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > oro > text > awk > AwkMatcher


1 package org.apache.oro.text.awk;
2
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2000 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgment may appear in the software itself,
26  * if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation", "Jakarta-Oro"
29  * must not be used to endorse or promote products derived from this
30  * software without prior written permission. For written
31  * permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache"
34  * or "Jakarta-Oro", nor may "Apache" or "Jakarta-Oro" appear in their
35  * name, without prior written permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  *
56  * Portions of this software are based upon software originally written
57  * by Daniel F. Savarese. We appreciate his contributions.
58  */

59
60 import java.io.*;
61
62 import org.apache.oro.text.regex.*;
63
64 /**
65  * The AwkMatcher class is used to match regular expressions
66  * (conforming to the Awk regular expression syntax) generated by
67  * AwkCompiler. AwkMatcher only supports 8-bit ASCII. Any attempt
68  * to match Unicode values greater than 255 will result in undefined
69  * behavior. AwkMatcher finds true leftmost-longest matches, so
70  * you must take care with how you formulate your regular expression
71  * to avoid matching more than you really want.
72  * <p>
73  * It is important for you to remember that AwkMatcher does not save
74  * parenthesized sub-group information. Therefore the number of groups
75  * saved in a MatchResult produced by AwkMatcher will always be 1.
76
77  @author <a HREF="dfs@savarese.org">Daniel F. Savarese</a>
78  @version $Id: AwkMatcher.java,v 1.1.1.1 2000/07/23 23:08:50 jon Exp $
79
80  * @see org.apache.oro.text.regex.PatternMatcher
81  * @see AwkCompiler
82  */

83 public final class AwkMatcher implements PatternMatcher {
84   private int __lastMatchedBufferOffset;
85   private AwkMatchResult __lastMatchResult = null;
86   private AwkStreamInput __scratchBuffer, __streamSearchBuffer;
87   private AwkPattern __awkPattern;
88   private int __offsets[] = new int[2];
89
90   public AwkMatcher() {
91     __scratchBuffer = new AwkStreamInput();
92     __scratchBuffer._endOfStreamReached = true;
93   }
94
95   /**
96    * Determines if a prefix of a string (represented as a char[])
97    * matches a given pattern, starting from a given offset into the string.
98    * If a prefix of the string matches the pattern, a MatchResult instance
99    * representing the match is made accesible via
100    * {@link #getMatch()}.
101    * <p>
102    * This method is useful for certain common token identification tasks
103    * that are made more difficult without this functionality.
104    * <p>
105    * @param input The char[] to test for a prefix match.
106    * @param pattern The Pattern to be matched.
107    * @param offset The offset at which to start searching for the prefix.
108    * @return True if input matches pattern, false otherwise.
109    */

110   // I reimplemented this method in terms of streammatchesPrefix
111
// to reduce the code size. This is not very elegant and
112
// reduces performance by a small degree.
113
public boolean matchesPrefix(char[] input, Pattern pattern, int offset){
114     int result = -1;
115
116     __awkPattern = (AwkPattern)pattern;
117
118     __scratchBuffer._buffer = input;
119     __scratchBuffer._bufferSize = input.length;
120     __scratchBuffer._bufferOffset = 0;
121     __scratchBuffer._endOfStreamReached = true;
122     __streamSearchBuffer = __scratchBuffer;
123     __offsets[0] = offset;
124     try {
125       result = __streamMatchPrefix();
126     } catch(IOException e){
127       // Don't do anything because we're not doing any I/O
128
result = -1;
129     }
130
131     if(result < 0) {
132       __lastMatchResult = null;
133       return false;
134     }
135
136     __lastMatchResult =
137       new AwkMatchResult(new String JavaDoc(input, 0, result), offset);
138
139     return true;
140   }
141
142
143   /**
144    * Determines if a prefix of a string (represented as a char[])
145    * matches a given pattern.
146    * If a prefix of the string matches the pattern, a MatchResult instance
147    * representing the match is made accesible via
148    * {@link #getMatch()}.
149    * <p>
150    * This method is useful for certain common token identification tasks
151    * that are made more difficult without this functionality.
152    * <p>
153    * @param input The char[] to test for a prefix match.
154    * @param pattern The Pattern to be matched.
155    * @return True if input matches pattern, false otherwise.
156    */

157   public boolean matchesPrefix(char[] input, Pattern pattern){
158     return matchesPrefix(input, pattern, 0);
159   }
160
161
162   /**
163    * Determines if a prefix of a string matches a given pattern.
164    * If a prefix of the string matches the pattern, a MatchResult instance
165    * representing the match is made accesible via
166    * {@link #getMatch()}.
167    * <p>
168    * This method is useful for certain common token identification tasks
169    * that are made more difficult without this functionality.
170    * <p>
171    * @param input The String to test for a prefix match.
172    * @param pattern The Pattern to be matched.
173    * @return True if input matches pattern, false otherwise.
174    */

175   public boolean matchesPrefix(String JavaDoc input, Pattern pattern) {
176     return matchesPrefix(input.toCharArray(), pattern, 0);
177   }
178
179
180   /**
181    * Determines if a prefix of a PatternMatcherInput instance
182    * matches a given pattern. If there is a match, a MatchResult instance
183    * representing the match is made accesible via
184    * {@link #getMatch()}. Unlike the
185    * {@link #contains(PatternMatcherInput, Pattern)}
186    * method, the current offset of the PatternMatcherInput argument
187    * is not updated. You should remember that the region starting
188    * from the begin offset of the PatternMatcherInput will be
189    * tested for a prefix match.
190    * <p>
191    * This method is useful for certain common token identification tasks
192    * that are made more difficult without this functionality.
193    * <p>
194    * @param input The PatternMatcherInput to test for a prefix match.
195    * @param pattern The Pattern to be matched.
196    * @return True if input matches pattern, false otherwise.
197    */

198   public boolean matchesPrefix(PatternMatcherInput input, Pattern pattern){
199     int result = -1;
200
201     __awkPattern = (AwkPattern)pattern;
202     __scratchBuffer._buffer = input.getBuffer();
203     __scratchBuffer._bufferOffset = 0;
204     __offsets[0] = input.getCurrentOffset();
205
206     __scratchBuffer._bufferSize = input.length();
207     __scratchBuffer._endOfStreamReached = true;
208     __streamSearchBuffer = __scratchBuffer;
209     try {
210       result = __streamMatchPrefix();
211     } catch(IOException e) {
212       // Don't do anything because we're not doing any I/O
213
result = -1;
214     }
215
216     if(result < 0) {
217       __lastMatchResult = null;
218       return false;
219     }
220
221     __lastMatchResult =
222       new AwkMatchResult(new String JavaDoc(__scratchBuffer._buffer, __offsets[0],
223                     result), __offsets[0]);
224
225     return true;
226   }
227
228
229
230   /**
231    * Determines if a string (represented as a char[]) exactly
232    * matches a given pattern. If
233    * there is an exact match, a MatchResult instance
234    * representing the match is made accesible via
235    * {@link #getMatch()}. The pattern must be
236    * an AwkPattern instance, otherwise a ClassCastException will
237    * be thrown. You are not required to, and indeed should NOT try to
238    * (for performance reasons), catch a ClassCastException because it
239    * will never be thrown as long as you use an AwkPattern as the pattern
240    * parameter.
241    * <p>
242    * @param input The char[] to test for an exact match.
243    * @param pattern The AwkPattern to be matched.
244    * @return True if input matches pattern, false otherwise.
245    * @exception ClassCastException If a Pattern instance other than an
246    * AwkPattern is passed as the pattern parameter.
247    */

248   public boolean matches(char[] input, Pattern pattern) {
249     int result = -1;
250
251     __awkPattern = (AwkPattern)pattern;
252     __scratchBuffer._buffer = input;
253     __scratchBuffer._bufferSize = input.length;
254     __scratchBuffer._bufferOffset = 0;
255     __scratchBuffer._endOfStreamReached = true;
256     __streamSearchBuffer = __scratchBuffer;
257     __offsets[0] = 0;
258     try {
259       result = __streamMatchPrefix();
260     } catch(IOException e){
261       // Don't do anything because we're not doing any I/O
262
result = -1;
263     }
264
265     if(result != input.length) {
266       __lastMatchResult = null;
267       return false;
268     }
269
270     __lastMatchResult =
271       new AwkMatchResult(new String JavaDoc(input, 0, result), 0);
272
273     return true;
274   }
275
276
277
278
279   /**
280    * Determines if a string exactly matches a given pattern. If
281    * there is an exact match, a MatchResult instance
282    * representing the match is made accesible via
283    * {@link #getMatch()}. The pattern must be
284    * a AwkPattern instance, otherwise a ClassCastException will
285    * be thrown. You are not required to, and indeed should NOT try to
286    * (for performance reasons), catch a ClassCastException because it
287    * will never be thrown as long as you use an AwkPattern as the pattern
288    * parameter.
289    * <p>
290    * @param input The String to test for an exact match.
291    * @param pattern The AwkPattern to be matched.
292    * @return True if input matches pattern, false otherwise.
293    * @exception ClassCastException If a Pattern instance other than an
294    * AwkPattern is passed as the pattern parameter.
295    */

296   public boolean matches(String JavaDoc input, Pattern pattern){
297     return matches(input.toCharArray(), pattern);
298   }
299
300
301   /**
302    * Determines if the contents of a PatternMatcherInput instance
303    * exactly matches a given pattern. If
304    * there is an exact match, a MatchResult instance
305    * representing the match is made accesible via
306    * {@link #getMatch()}. Unlike the
307    * {@link #contains(PatternMatcherInput, Pattern)}
308    * method, the current offset of the PatternMatcherInput argument
309    * is not updated. You should remember that the region between
310    * the begin and end offsets of the PatternMatcherInput will be
311    * tested for an exact match.
312    * <p>
313    * The pattern must be an AwkPattern instance, otherwise a
314    * ClassCastException will be thrown. You are not required to, and
315    * indeed should NOT try to (for performance reasons), catch a
316    * ClassCastException because it will never be thrown as long as you use
317    * an AwkPattern as the pattern parameter.
318    * <p>
319    * @param input The PatternMatcherInput to test for a match.
320    * @param pattern The AwkPattern to be matched.
321    * @return True if input matches pattern, false otherwise.
322    * @exception ClassCastException If a Pattern instance other than an
323    * AwkPattern is passed as the pattern parameter.
324    */

325   public boolean matches(PatternMatcherInput input, Pattern pattern){
326     int result = -1;
327
328     __awkPattern = (AwkPattern)pattern;
329     __scratchBuffer._buffer = input.getBuffer();
330     __scratchBuffer._bufferSize = input.length();
331     __scratchBuffer._bufferOffset = 0;
332     __offsets[0] = input.getBeginOffset();
333     __scratchBuffer._endOfStreamReached = true;
334     __streamSearchBuffer = __scratchBuffer;
335     try {
336       result = __streamMatchPrefix();
337     } catch(IOException e){
338       // Don't do anything because we're not doing any I/O
339
result = -1;
340     }
341
342     if(result != __scratchBuffer._bufferSize) {
343       __lastMatchResult = null;
344       return false;
345     }
346
347     __lastMatchResult =
348       new AwkMatchResult(new String JavaDoc(__scratchBuffer._buffer, __offsets[0],
349                  __scratchBuffer._bufferSize), __offsets[0]);
350
351     return true;
352   }
353
354
355
356   /**
357    * Determines if a string (represented as a char[]) contains a pattern.
358    * If the pattern is
359    * matched by some substring of the input, a MatchResult instance
360    * representing the <b> first </b> such match is made acessible via
361    * {@link #getMatch()}. If you want to access
362    * subsequent matches you should either use a PatternMatcherInput object
363    * or use the offset information in the MatchResult to create a substring
364    * representing the remaining input. Using the MatchResult offset
365    * information is the recommended method of obtaining the parts of the
366    * string preceeding the match and following the match.
367    * <p>
368    * The pattern must be an AwkPattern instance, otherwise a
369    * ClassCastException will be thrown. You are not required to, and
370    * indeed should NOT try to (for performance reasons), catch a
371    * ClassCastException because it will never be thrown as long as you use
372    * an AwkPattern as the pattern parameter.
373    * <p>
374    * @param input The char[] to test for a match.
375    * @param pattern The AwkPattern to be matched.
376    * @return True if the input contains a pattern match, false otherwise.
377    * @exception ClassCastException If a Pattern instance other than an
378    * AwkPattern is passed as the pattern parameter.
379    */

380   public boolean contains(char[] input, Pattern pattern) {
381     __awkPattern = (AwkPattern)pattern;
382
383     // Begin anchor requires match occur at beginning of input
384
if(__awkPattern._hasBeginAnchor && !__awkPattern._fastMap[input[0]]){
385       __lastMatchResult = null;
386       return false;
387     }
388
389     __scratchBuffer._buffer = input;
390     __scratchBuffer._bufferSize = input.length;
391     __scratchBuffer._bufferOffset = 0;
392     __scratchBuffer._endOfStreamReached = true;
393     __streamSearchBuffer = __scratchBuffer;
394     __lastMatchedBufferOffset = 0;
395     try {
396       _search();
397     } catch(IOException e) {
398       // do nothing
399
}
400     return (__lastMatchResult != null);
401   }
402
403
404   /**
405    * Determines if a string contains a pattern. If the pattern is
406    * matched by some substring of the input, a MatchResult instance
407    * representing the <b> first </b> such match is made acessible via
408    * {@link #getMatch()}. If you want to access
409    * subsequent matches you should either use a PatternMatcherInput object
410    * or use the offset information in the MatchResult to create a substring
411    * representing the remaining input. Using the MatchResult offset
412    * information is the recommended method of obtaining the parts of the
413    * string preceeding the match and following the match.
414    * <p>
415    * The pattern must be an AwkPattern instance, otherwise a
416    * ClassCastException will be thrown. You are not required to, and
417    * indeed should NOT try to (for performance reasons), catch a
418    * ClassCastException because it will never be thrown as long as you use
419    * an AwkPattern as the pattern parameter.
420    * <p>
421    * @param input The String to test for a match.
422    * @param pattern The AwkPattern to be matched.
423    * @return True if the input contains a pattern match, false otherwise.
424    * @exception ClassCastException If a Pattern instance other than an
425    * AwkPattern is passed as the pattern parameter.
426    */

427   public boolean contains(String JavaDoc input, Pattern pattern){
428     return contains(input.toCharArray(), pattern);
429   }
430
431
432
433   /**
434    * Determines if the contents of a PatternMatcherInput, starting from the
435    * current offset of the input contains a pattern.
436    * If a pattern match is found, a MatchResult
437    * instance representing the <b>first</b> such match is made acessible via
438    * {@link #getMatch()}. The current offset of the
439    * PatternMatcherInput is set to the offset corresponding to the end
440    * of the match, so that a subsequent call to this method will continue
441    * searching where the last call left off. You should remember that the
442    * region between the begin and end offsets of the PatternMatcherInput are
443    * considered the input to be searched, and that the current offset
444    * of the PatternMatcherInput reflects where a search will start from.
445    * Matches extending beyond the end offset of the PatternMatcherInput
446    * will not be matched. In other words, a match must occur entirely
447    * between the begin and end offsets of the input. See
448    * {@link org.apache.oro.text.regex.PatternMatcherInput PatternMatcherInput}
449    * for more details.
450    * <p>
451    * As a side effect, if a match is found, the PatternMatcherInput match
452    * offset information is updated. See the PatternMatcherInput
453    * {@link org.apache.oro.text.regex.PatternMatcherInput#setMatchOffsets
454    * setMatchOffsets(int, int)} method for more details.
455    * <p>
456    * The pattern must be an AwkPattern instance, otherwise a
457    * ClassCastException will be thrown. You are not required to, and
458    * indeed should NOT try to (for performance reasons), catch a
459    * ClassCastException because it will never be thrown as long as you use
460    * an AwkPattern as the pattern parameter.
461    * <p>
462    * This method is usually used in a loop as follows:
463    * <blockquote><pre>
464    * PatternMatcher matcher;
465    * PatternCompiler compiler;
466    * Pattern pattern;
467    * PatternMatcherInput input;
468    * MatchResult result;
469    *
470    * compiler = new AwkCompiler();
471    * matcher = new AwkMatcher();
472    *
473    * try {
474    * pattern = compiler.compile(somePatternString);
475    * } catch(MalformedPatternException e) {
476    * System.err.println("Bad pattern.");
477    * System.err.println(e.getMessage());
478    * return;
479    * }
480    *
481    * input = new PatternMatcherInput(someStringInput);
482    *
483    * while(matcher.contains(input, pattern)) {
484    * result = matcher.getMatch();
485    * // Perform whatever processing on the result you want.
486    * }
487    *
488    * </pre></blockquote>
489    * <p>
490    * @param input The PatternMatcherInput to test for a match.
491    * @param pattern The Pattern to be matched.
492    * @return True if the input contains a pattern match, false otherwise.
493    * @exception ClassCastException If a Pattern instance other than an
494    * AwkPattern is passed as the pattern parameter.
495    */

496   public boolean contains(PatternMatcherInput input, Pattern pattern) {
497     __awkPattern = (AwkPattern)pattern;
498     __scratchBuffer._buffer = input.getBuffer();
499     __scratchBuffer._bufferOffset = 0;
500     __lastMatchedBufferOffset = input.getCurrentOffset();
501
502     // Begin anchor requires match occur at beginning of input
503
// No need to adjust current offset if no match found.
504
if(__awkPattern._hasBeginAnchor) {
505       int begin;
506
507       begin = input.getBeginOffset();
508       if(begin != __lastMatchedBufferOffset ||
509      !__awkPattern._fastMap[__scratchBuffer._buffer[begin]]) {
510     __lastMatchResult = null;
511     return false;
512       }
513     }
514
515     __scratchBuffer._bufferSize = input.length();
516     __scratchBuffer._endOfStreamReached = true;
517     __streamSearchBuffer = __scratchBuffer;
518     try {
519       _search();
520     } catch(IOException e) {
521       // do nothing
522
}
523     input.setCurrentOffset(__lastMatchedBufferOffset);
524
525     if(__lastMatchResult == null)
526       return false;
527
528     input.setMatchOffsets(__lastMatchResult.beginOffset(0),
529               __lastMatchResult.endOffset(0));
530
531     return true;
532   }
533
534
535   /**
536    * Determines if the contents of an AwkStreamInput, starting from the
537    * current offset of the input contains a pattern.
538    * If a pattern match is found, a MatchResult
539    * instance representing the <b>first</b> such match is made acessible via
540    * {@link #getMatch()}. The current offset of the
541    * input stream is advanced to the end offset corresponding to the end
542    * of the match. Consequently a subsequent call to this method will continue
543    * searching where the last call left off.
544    * See {@link AwkStreamInput} for more details.
545    * <p>
546    * Note, patterns matching the null string do NOT match at end of input
547    * stream. This is different from the behavior you get from the other
548    * contains() methods.
549    * <p>
550    * The pattern must be an AwkPattern instance, otherwise a
551    * ClassCastException will be thrown. You are not required to, and
552    * indeed should NOT try to (for performance reasons), catch a
553    * ClassCastException because it will never be thrown as long as you use
554    * an AwkPattern as the pattern parameter.
555    * <p>
556    * This method is usually used in a loop as follows:
557    * <blockquote><pre>
558    * PatternMatcher matcher;
559    * PatternCompiler compiler;
560    * Pattern pattern;
561    * AwkStreamInput input;
562    * MatchResult result;
563    *
564    * compiler = new AwkCompiler();
565    * matcher = new AwkMatcher();
566    *
567    * try {
568    * pattern = compiler.compile(somePatternString);
569    * } catch(MalformedPatternException e) {
570    * System.err.println("Bad pattern.");
571    * System.err.println(e.getMessage());
572    * return;
573    * }
574    *
575    * input = new AwkStreamInput(
576    * new BufferedInputStream(new FileInputStream(someFileName)));
577    *
578    * while(matcher.contains(input, pattern)) {
579    * result = matcher.getMatch();
580    * // Perform whatever processing on the result you want.
581    * }
582    *
583    * </pre></blockquote>
584    * <p>
585    * @param input The PatternStreamInput to test for a match.
586    * @param pattern The Pattern to be matched.
587    * @return True if the input contains a pattern match, false otherwise.
588    * @exception ClassCastException If a Pattern instance other than an
589    * AwkPattern is passed as the pattern parameter.
590    */

591   public boolean contains(AwkStreamInput input, Pattern pattern)
592        throws IOException
593   {
594     __awkPattern = (AwkPattern)pattern;
595
596     // Begin anchor requires match occur at beginning of input
597
if(__awkPattern._hasBeginAnchor) {
598       // Do read here instead of in _search() so we can test first char
599
if(input._bufferOffset == 0) {
600     if(input.read() && !__awkPattern._fastMap[input._buffer[0]]) {
601       __lastMatchResult = null;
602       return false;
603     }
604       } else {
605     __lastMatchResult = null;
606     return false;
607       }
608     }
609
610     __lastMatchedBufferOffset = input._currentOffset;
611     __streamSearchBuffer = input;
612     _search();
613     input._currentOffset = __lastMatchedBufferOffset;
614     return (__lastMatchResult != null);
615   }
616
617
618   private int __streamMatchPrefix() throws IOException {
619     int token, current = AwkPattern._START_STATE, lastState, transition;
620     int offset, initialOffset;
621     int lastMatchedOffset = -1;
622     int[] tstateArray;
623
624     offset = initialOffset = __offsets[0];
625   test:
626     while(offset < __streamSearchBuffer._bufferSize) {
627       token = __streamSearchBuffer._buffer[offset++];
628
629       if(current < __awkPattern._numStates) {
630     lastState = current;
631     tstateArray = __awkPattern._getStateArray(current);
632     current = tstateArray[token];
633
634     if(current == 0){
635       __awkPattern._createNewState(lastState, token, tstateArray);
636       current = tstateArray[token];
637     }
638     if(current == AwkPattern._INVALID_STATE){
639       break test;
640     }
641     else if(__awkPattern._endStates.get(current)){
642       lastMatchedOffset = offset;
643     }
644     if(offset == __streamSearchBuffer._bufferSize){
645       offset = __streamSearchBuffer._reallocate(initialOffset);
646
647       // If we're at the end of the stream, don't reset values
648
if(offset != __streamSearchBuffer._bufferSize){
649         if(lastMatchedOffset != -1)
650           lastMatchedOffset-=initialOffset;
651         initialOffset = 0;
652       }
653
654     }
655       }
656       else
657     break;
658     }
659
660     __offsets[0] = initialOffset;
661     __offsets[1] = lastMatchedOffset - 1;
662
663     if(lastMatchedOffset == -1 && __awkPattern._matchesNullString)
664       return 0;
665
666     // End anchor requires match occur at end of input
667
if(__awkPattern._hasEndAnchor &&
668        (!__streamSearchBuffer._endOfStreamReached ||
669     lastMatchedOffset < __streamSearchBuffer._bufferSize))
670       return -1;
671
672     return (lastMatchedOffset - initialOffset);
673   }
674
675
676
677    void _search() throws IOException {
678     char[] currentLine;
679     int position, tokensMatched;
680     String JavaDoc currentString;
681
682     __lastMatchResult = null;
683
684     while(true){
685       if(__lastMatchedBufferOffset >= __streamSearchBuffer._bufferSize){
686     if(__streamSearchBuffer._endOfStreamReached){
687       // Get rid of reference now that it should no longer be used.
688
__streamSearchBuffer = null;
689       return;
690     } else {
691       if(!__streamSearchBuffer.read())
692         return;
693       __lastMatchedBufferOffset = 0;
694     }
695       }
696
697       for(position=__lastMatchedBufferOffset;
698       position < __streamSearchBuffer._bufferSize;
699       position = __offsets[0] + 1) {
700
701     __offsets[0] = position;
702     if(__awkPattern._fastMap[__streamSearchBuffer._buffer[position]] &&
703        (tokensMatched = __streamMatchPrefix()) > -1) {
704
705       __lastMatchResult = new AwkMatchResult(
706       new String JavaDoc(__streamSearchBuffer._buffer, __offsets[0],
707              tokensMatched),
708       __offsets[0] + __streamSearchBuffer._bufferOffset);
709
710       __lastMatchedBufferOffset =
711         (tokensMatched > 0 ? __offsets[1] + 1 : __offsets[0] + 1);
712
713       return;
714     } else if(__awkPattern._matchesNullString) {
715       __lastMatchResult = new AwkMatchResult(new String JavaDoc(),
716               position + __streamSearchBuffer._bufferOffset);
717
718       __lastMatchedBufferOffset = position + 1;
719
720       return;
721     }
722       }
723
724       __lastMatchedBufferOffset = position;
725     }
726   }
727
728
729   /**
730    * Fetches the last match found by a call to a matches() or contains()
731    * method.
732    * <p>
733    * @return A MatchResult instance containing the pattern match found
734    * by the last call to any one of the matches() or contains()
735    * methods. If no match was found by the last call, returns
736    * null.
737    */

738   public MatchResult getMatch() { return __lastMatchResult; }
739
740 }
741
Popular Tags