/* Copyright (C) 1998, 1999  Cygnus Solutions

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */
 
package java.io;

/**
 * @author Warren Levy <warrenl@cygnus.com>
 * @date October 19, 1998.  
 */
/* 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
 */
 
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;

  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();

      // 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();

      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();

      /* 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;
    }
  }

  public boolean ready() // TODO12: throws IOException
  {
    // TODO12: The JCL specifically says this returns true even if the
    // reader has been closed, whereas the online 1.2 doc specifically
    // says to throw an IOException if closed.
    return true;
  }

  public void reset() throws IOException
  {
    synchronized (lock)
    {
      if (buf == null)
        throw new IOException();

      pos = markedPos;
    }
  }

  public long skip(long n) throws IOException
  {
    synchronized (lock)
    {
      if (buf == null)
        throw new IOException();

      // 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;
    }
  }
}
