home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / modules / edtplug / classes / netscape / plugin / composer / io / SlidingBuffer.java < prev    next >
Encoding:
Java Source  |  1998-04-08  |  10.6 KB  |  368 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * $Header: /m/pub/ns/modules/edtplug/classes/netscape/plugin/composer/io/SlidingBuffer.java,v 3.1 1998/03/28 03:33:50 ltabb Exp $
  21.  *
  22.  * $Log: SlidingBuffer.java,v $
  23.  * Revision 3.1  1998/03/28 03:33:50  ltabb
  24.  * bump rev to 3.1
  25.  *
  26.  * Revision 1.1  1998/03/28 02:39:09  ltabb
  27.  * Free the lizard
  28.  *
  29.  * Revision 2.1  1998/03/11 23:56:37  anthonyd
  30.  * Bump revision number to 2
  31.  *
  32.  * Revision 1.5  1998/03/06 04:19:44  jwz
  33.  * added NPL and copyright
  34.  *
  35.  * Revision 1.4  1998/02/16 22:11:51  anthonyd
  36.  * Sanitized Files.
  37.  *
  38.  * Revision 1.3  1996/12/18 02:32:54  palevich
  39.  * Version 13.
  40.  *
  41.  * Revision 1.2  1996/12/07 04:30:04  palevich
  42.  * Updated composer plugin API
  43.  *
  44.  * Revision 1.1  1996/11/20 03:19:21  palevich
  45.  * Added Kipp's tokenizer.
  46.  *
  47.  * Revision 1.1  1996/10/28 18:31:03  kipp
  48.  * I fixed some problems in lexical analysis by writing SlidingBuffer.java and
  49.  * then switching the LexicalStream to use it instead of the LookAheadUnicodeInputStream
  50.  * class (which doesn't quite work).
  51.  *
  52.  */
  53. package netscape.plugin.composer.io;
  54.  
  55. import java.io.*;
  56.  
  57. /**
  58.  * A sliding buffer that moves over a Reader. The buffer
  59.  * is designed to support lexical analyzers.
  60.  */
  61. class SlidingBuffer extends Reader {
  62.   static final int DEFAULT_BUFFER_LENGTH = 4096;
  63.  
  64.   // The underlying input stream
  65.   protected Reader in;
  66.  
  67.   // The data buffer. buf[offset] is the next character to read.
  68.   // end is the offset of the last piece of data in the buffer, plus one
  69.   // end - offset is the number of characters in the buffer
  70.   protected char buffer[];
  71.   protected int offset;
  72.   protected int end;
  73.  
  74.   public SlidingBuffer(Reader in) {
  75.     this.in = in;
  76.     buffer = new char[DEFAULT_BUFFER_LENGTH];
  77.   }
  78.  
  79.   public SlidingBuffer(Reader in, int buflen) {
  80.     this.in = in;
  81.     if (buflen < DEFAULT_BUFFER_LENGTH) buflen = DEFAULT_BUFFER_LENGTH;
  82.     buffer = new char[buflen];
  83.   }
  84.  
  85.   /**
  86.    * Reads a character of data. This method will block if no input is
  87.    * available.
  88.    * @return    the byte read, or -1 if the end of the
  89.    *        stream is reached.
  90.    * @exception IOException If an I/O error has occurred.
  91.    */
  92.   public int read() throws IOException {
  93.     int amount = end - offset;
  94.     if (amount == 0) {
  95.       if (!fill()) return -1;
  96.     }
  97.     char c = buffer[offset++];
  98.     return c;
  99.   }
  100.  
  101.   /**
  102.    * Reads into an array of characters.  This method will
  103.    * block until some input is available.
  104.    * @param c   the buffer into which the data is read
  105.    * @return  the actual number of characters read, -1 is
  106.    *        returned when the end of the stream is reached.
  107.    * @exception IOException If an I/O error has occurred.
  108.    */
  109.   public int read(char c[]) throws IOException {
  110.     int amount = end - offset;
  111.     if (amount == 0) {
  112.       if (!fill()) return -1;
  113.     }
  114.     amount = end - offset;
  115.     if (amount > c.length) amount = c.length;
  116.     System.arraycopy(buffer, offset, c, 0, amount);
  117.     offset += amount;
  118.     return amount;
  119.   }
  120.  
  121.   /**
  122.    * Reads into an array of characters.  This method will
  123.    * block until some input is available.
  124.    * @param c   the buffer into which the data is read
  125.    * @param off the start offset of the data
  126.    * @param len the maximum number of bytes read
  127.    * @return  the actual number of characters read, -1 is
  128.    *        returned when the end of the stream is reached.
  129.    * @exception IOException If an I/O error has occurred.
  130.    */
  131.   public int read(char c[], int off, int len) throws IOException {
  132.     int amount = end - offset;
  133.     if (amount == 0) {
  134.       if (!fill()) return -1;
  135.     }
  136.     amount = end - offset;
  137.     if (amount > len) amount = len;
  138.     System.arraycopy(buffer, offset, c, off, amount);
  139.     offset += amount;
  140.     return amount;
  141.   }
  142.  
  143.   /**
  144.    * Skips n bytes of input.
  145.    * @param n the number of characters to be skipped
  146.    * @return    the actual number of characters skipped.
  147.    * @exception IOException If an I/O error has occurred.
  148.    */
  149.   public long skip(long n) throws IOException {
  150.     int amount = end - offset;
  151.     if (amount >= n) {
  152.       offset += n;
  153.       return n;
  154.     }
  155.     offset = 0;
  156.     end = 0;
  157.     return amount + in.skip(n - amount);
  158.   }
  159.  
  160.   ///**
  161.   // * Returns the number of characters that can be read
  162.   // * without blocking.
  163.   // * @return the number of available characters.
  164.   // */
  165.   //public int available() throws IOException {
  166.   //  return (end - offset) + in.available();
  167.   //}
  168.  
  169.   /************************************************************************/
  170.  
  171.   public int peek() throws IOException {
  172.     int amount = end - offset;
  173.     if (amount == 0) {
  174.       if (!fill()) return -1;
  175.     }
  176.     int c = buffer[offset];
  177.     return c;
  178.   }
  179.  
  180.   /**
  181.    * Unread some characters. This will throw an IOException if the count
  182.    * being unread is larger than the amount of previously read data
  183.    * in the buffer.
  184.    */
  185.   public void unread(int count) throws IOException {
  186.     if (offset < count) {
  187.       throw new IOException("invalid unread; offset=" + offset
  188.                 + " count=" + count);
  189.     }
  190.     offset -= count;
  191.   }
  192.  
  193.   /**
  194.    * Look ahead one character. Return true if the next character matches
  195.    * (and consume the character), otherwise return false and leave the
  196.    * input stream unaffected.
  197.    */
  198.   public boolean lookAhead(char c) throws IOException {
  199.     int amount = end - offset;
  200.     if (amount == 0) {
  201.       if (!fill()) return false;
  202.     }
  203.     if (buffer[offset] == c) {
  204.       offset++;
  205.       return true;
  206.     }
  207.     return false;
  208.   }
  209.  
  210.   /**
  211.    * Look ahead for a string of characters. Each character in the string
  212.    * must match exactly otherwise false is returned (and the input stream
  213.    * is left unaffected).
  214.    */
  215.   public boolean lookAhead(String s) throws IOException {
  216.     return lookAhead(s, false);
  217.   }
  218.  
  219.   /**
  220.    * Look ahead for a string of characters allowing for case to not
  221.    * matter.
  222.    */
  223.   public boolean lookAhead(String s, boolean ignoreCase) throws IOException {
  224.     int slen = s.length();
  225.     int amount = end - offset;
  226.     if (amount < slen) {
  227.       if (!fillForCapacity(slen)) return false;
  228.     }
  229.     for (int i = 0; i < slen; i++) {
  230.       char c1 = buffer[offset+i];
  231.       char c2 = s.charAt(i);
  232.       if (ignoreCase) {
  233.     c1 = Character.toLowerCase(c1);
  234.     c2 = Character.toLowerCase(c2);
  235.       }
  236.       if (c1 != c2) {
  237.     return false;
  238.       }
  239.     }
  240.     offset += slen;
  241.     return true;
  242.   }
  243.  
  244.   /**
  245.    * Eat up any whitespace in the buffer. White space is defined as space,
  246.    * tab, return, newline, form feed. If any was eaten up return
  247.    * true, otherwise return false.
  248.    */
  249.   /* XXX we can add an interface to specify a bitmap that defines
  250.      which characters we want to treat as whitespace... */
  251.   public boolean eatWhiteSpace() throws IOException {
  252.     boolean eaten = false;
  253.     for (;;) {
  254.       for (int i = offset; i < end; i++) {
  255.     char c = buffer[i];
  256.     if ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n') ||
  257.         (c == '\f')) {
  258.       eaten = true;
  259.       continue;
  260.     }
  261.     offset = i;
  262.     return eaten;
  263.       }
  264.       if (!fill()) break;
  265.     }
  266.     return eaten;
  267.   }
  268.  
  269.   /**
  270.    * Eat up one newline if present in the buffer. If a newline
  271.    * was eaten up return true otherwise false. This will handle
  272.    * mac (\r), unix (\n) and windows (\r\n) style of newlines
  273.    * transparently.
  274.    */
  275.   public boolean eatNewline() throws IOException {
  276.     boolean eaten = false;
  277.     int amount = end - offset;
  278.     if (amount < 2) {
  279.       if (!fillForCapacity(2)) {
  280.     // Couldn't get two characters
  281.     if (end - offset == 0) {
  282.       return false;
  283.     }
  284.     if ((buffer[offset] == '\r') || (buffer[offset] == '\n')) {
  285.       offset++;
  286.       return true;
  287.     }
  288.     return false;
  289.       }
  290.     }
  291.     if (buffer[offset] == '\r') {
  292.       offset++;
  293.       eaten = true;
  294.     }
  295.     if (buffer[offset] == '\n') {
  296.       eaten = true;
  297.       offset++;
  298.     }
  299.     return eaten;
  300.   }
  301.  
  302.   /************************************************************************/
  303.  
  304.   protected boolean fill() throws IOException {
  305.     if (end - offset != 0) {
  306.       throw new IOException("fill of non-empty buffer");
  307.     }
  308.     offset = 0;
  309.     end = in.read(buffer, 0, buffer.length);
  310.     if (end < 0) {
  311.       end = 0;
  312.       return false;
  313.     }
  314.     return true;
  315.   }
  316.  
  317.   /**
  318.    * Fill the buffer, keeping whatever is unread in the buffer and
  319.    * ensuring that "capacity" characters of total filled buffer
  320.    * space is available. Return false if the final amount of data
  321.    * in the buffer is less than capacity, otherwise return true.
  322.    */
  323.   protected boolean fillForCapacity(int capacity) throws IOException {
  324.     int amount = end - offset;
  325.     if (amount >= capacity) {
  326.       // The buffer already holds enough data to satisfy capacity
  327.       return true;
  328.     }
  329.  
  330.     // The buffer needs more data. See if the buffer itself must be
  331.     // enlarged to statisfy capacity.
  332.     if (capacity >= buffer.length) {
  333.       // Grow the buffer to hold enough space
  334.       int newBufLen = buffer.length * 2;
  335.       if (newBufLen < capacity) newBufLen = capacity;
  336.       char newbuf[] = new char[newBufLen];
  337.       System.arraycopy(buffer, offset, newbuf, 0, amount);
  338.       offset = 0;
  339.       end = amount;
  340.       buffer = newbuf;
  341.     } else {
  342.       if (amount != 0) {
  343.     // Slide the data that is currently present in the buffer down
  344.     // to the start of the buffer
  345.     System.arraycopy(buffer, offset, buffer, 0, amount);
  346.     offset = 0;
  347.     end = amount;
  348.       }
  349.     }
  350.  
  351.     // Fill up the remainder of the buffer
  352.     int mustRead = capacity - amount;
  353.     int nb = in.read(buffer, offset, buffer.length - offset);
  354.     if (nb < mustRead) {
  355.       if (nb > 0) {
  356.     end += nb;
  357.       }
  358.       return false;
  359.     }
  360.     end += nb;
  361.     return true;
  362.   }
  363.  
  364.   public void close() throws IOException {
  365.     in.close();
  366.   }
  367. }
  368.