1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 1999-2004 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *     http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.regexp.internal;
  22 
  23 import java.io.Reader;
  24 import java.io.IOException;
  25 
  26 /**
  27  * Encapsulates java.io.Reader as CharacterIterator
  28  *
  29  * @author <a href="mailto:ales.novak@netbeans.com">Ales Novak</a>
  30  */
  31 public final class ReaderCharacterIterator implements CharacterIterator
  32 {
  33     /** Underlying reader */
  34     private final Reader reader;
  35 
  36     /** Buffer of read chars */
  37     private final StringBuffer buff;
  38 
  39     /** read end? */
  40     private boolean closed;
  41 
  42     /** @param reader a Reader, which is parsed */
  43     public ReaderCharacterIterator(Reader reader)
  44     {
  45         this.reader = reader;
  46         this.buff = new StringBuffer(512);
  47         this.closed = false;
  48     }
  49 
  50     /** @return a substring */
  51     public String substring(int beginIndex, int endIndex)
  52     {
  53         try
  54         {
  55             ensure(endIndex);
  56             return buff.toString().substring(beginIndex, endIndex);
  57         }
  58         catch (IOException e)
  59         {
  60             throw new StringIndexOutOfBoundsException(e.getMessage());
  61         }
  62     }
  63 
  64     /** @return a substring */
  65     public String substring(int beginIndex)
  66     {
  67         try
  68         {
  69             readAll();
  70             return buff.toString().substring(beginIndex);
  71         }
  72         catch (IOException e)
  73         {
  74             throw new StringIndexOutOfBoundsException(e.getMessage());
  75         }
  76     }
  77 
  78     /** @return a character at the specified position. */
  79     public char charAt(int pos)
  80     {
  81         try
  82         {
  83             ensure(pos);
  84             return buff.charAt(pos);
  85         }
  86         catch (IOException e)
  87         {
  88             throw new StringIndexOutOfBoundsException(e.getMessage());
  89         }
  90     }
  91 
  92     /** @return <tt>true</tt> iff if the specified index is after the end of the character stream */
  93     public boolean isEnd(int pos)
  94     {
  95         if (buff.length() > pos)
  96         {
  97             return false;
  98         }
  99         else
 100         {
 101             try
 102             {
 103                 ensure(pos);
 104                 return (buff.length() <= pos);
 105             }
 106             catch (IOException e)
 107             {
 108                 throw new StringIndexOutOfBoundsException(e.getMessage());
 109             }
 110         }
 111     }
 112 
 113     /** Reads n characters from the stream and appends them to the buffer */
 114     private int read(int n) throws IOException
 115     {
 116         if (closed)
 117         {
 118             return 0;
 119         }
 120 
 121         char[] c = new char[n];
 122         int count = 0;
 123         int read = 0;
 124 
 125         do
 126         {
 127             read = reader.read(c);
 128             if (read < 0) // EOF
 129             {
 130                 closed = true;
 131                 break;
 132             }
 133             count += read;
 134             buff.append(c, 0, read);
 135         }
 136         while (count < n);
 137 
 138         return count;
 139     }
 140 
 141     /** Reads rest of the stream. */
 142     private void readAll() throws IOException
 143     {
 144         while(! closed)
 145         {
 146             read(1000);
 147         }
 148     }
 149 
 150     /** Reads chars up to the idx */
 151     private void ensure(int idx) throws IOException
 152     {
 153         if (closed)
 154         {
 155             return;
 156         }
 157 
 158         if (idx < buff.length())
 159         {
 160             return;
 161         }
 162         read(idx + 1 - buff.length());
 163     }
 164 }