/* StringReader.java -- permits a String to be read as a character input stream
   Copyright (C) 1998, 1999, 2000, 2003  Free Software Foundation

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.io;

/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
 * "The Java Language Specification", ISBN 0-201-63451-1
 * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
 * Status:  Believed complete and correct
 */

/**
 * This class permits a <code>String</code> to be read as a character 
 * input stream.
 * <p>
 * The mark/reset functionality in this class behaves differently than
 * normal.  If no mark has been set, then calling the <code>reset()</code>
 * method rewinds the read pointer to the beginning of the <code>String</code>.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Warren Levy (warrenl@cygnus.com)
 * @date October 19, 1998.  
 */
public class StringReader extends Reader
{
  /* A String provided by the creator of the stream. */
  private String buf;

  /* Position of the next char in buf to be read. */
  private int pos;

  /* The currently marked position in the stream. */
  private int markedPos;

  /* The index in buf one greater than the last valid character. */
  private int count;

  /**
   * Create a new <code>StringReader</code> that will read chars from the 
   * passed in <code>String</code>.  This stream will read from the beginning 
   * to the end of the <code>String</code>.
   *
   * @param buffer The <code>String</code> this stream will read from.
   */
  public StringReader(String buffer)
  {
    super();
    buf = buffer;

    count = buffer.length();
    markedPos = pos = 0;
  }

  public void close()
  {
    synchronized (lock)
    {
      buf = null;
    }
  }

  public void mark(int readAheadLimit) throws IOException
  {
    synchronized (lock)
    {
      if (buf == null)
        throw new IOException("Stream closed");

      // readAheadLimit is ignored per Java Class Lib. book, p. 1692.
      markedPos = pos;
    }
  }

  public boolean markSupported()
  {
    return true;
  }

  public int read() throws IOException
  {
    synchronized (lock)
    {
      if (buf == null)
        throw new IOException("Stream closed");

      if (pos < count)
        return ((int) buf.charAt(pos++)) & 0xFFFF;
      return -1;
    }
  }

  public int read(char[] b, int off, int len) throws IOException
  {
    synchronized (lock)
    {
      if (buf == null)
        throw new IOException("Stream closed");

      /* Don't need to check pos value, arraycopy will check it. */
      if (off < 0 || len < 0 || off + len > b.length)
        throw new ArrayIndexOutOfBoundsException();

      if (pos >= count)
        return -1;

      int lastChar = Math.min(count, pos + len);
      buf.getChars(pos, lastChar, b, off);
      int numChars = lastChar - pos;
      pos = lastChar;
      return numChars;
    }
  }

  /**
   * This method determines if the stream is ready to be read.  This class
   * is always ready to read and so always returns <code>true</code>, unless
   * close() has previously been called in which case an IOException is
   * thrown.
   *
   * @return <code>true</code> to indicate that this object is ready to be read.
   * @exception IOException If the stream is closed.
   */
  public boolean ready() throws IOException
  {
    if (buf == null)
      throw new IOException("Stream closed");

    return true;
  }

  /**
   * Sets the read position in the stream to the previously
   * marked position or to 0 (i.e., the beginning of the stream) if the mark
   * has not already been set.
   */
  public void reset() throws IOException
  {
    synchronized (lock)
    {
      if (buf == null)
        throw new IOException("Stream closed");

      pos = markedPos;
    }
  }

  /**
    * This method attempts to skip the requested number of chars in the
    * input stream.  It does this by advancing the <code>pos</code> value by 
    * the specified number of chars.  It this would exceed the length of the
    * buffer, then only enough chars are skipped to position the stream at
    * the end of the buffer.  The actual number of chars skipped is returned.
    *
    * @param n The requested number of chars to skip
    *
    * @return The actual number of chars skipped.
    */
  public long skip(long n) throws IOException
  {
    synchronized (lock)
    {
      if (buf == null)
        throw new IOException("Stream closed");

      // Even though the var numChars is a long, in reality it can never
      // be larger than an int since the result of subtracting 2 positive
      // ints will always fit in an int.  Since we have to return a long
      // anyway, numChars might as well just be a long.
      long numChars = Math.min((long) (count - pos), n < 0 ? 0L : n);
      pos += numChars;
      return numChars;
    }
  }
}

