Files
gzz-mirror/Java/media/Stream.java
2026-09-14 20:19:29 -04:00

290 lines
7.6 KiB
Java

/*
Stream.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
import java.util.*;
/** Some routines to handle plain text streams.
*/
public class Stream {
public static final String rcsid = "$Id: Stream.java,v 1.9 2000/12/04 13:01:10 tjl Exp $";
public static boolean dbg = false;
static final void p(String s) { if(dbg) System.out.println(s); }
static final void pa(String s) { System.out.println(s); }
static public boolean move(ZZCursor curs, String dim, int nchars) {
return move(curs, dim, nchars, 1);
}
/** Move by an offset in a stream string.
* The last position of the stream is actually one beyond
* the last character.
* @param curs The cursor to move
* @param dim The dimension the stream is along
* @param nchars The number of characters to move. May be
* positive or negative.
* @param lookingDir The direction you want to look from
* the cursor. Matters when the cursor
* is at the edge of two cells and
* positive here means to put it into the
* beginning of the next cell and negative
* to the end of the preceding cell.
* @return false if operation goes past beginning or end.
*/
static public boolean move(ZZCursor curs, String dim, int nchars,
int lookingDir) {
int o = curs.getOffs() + nchars;
ZZCell nc = curs.get();
if(nc == null)
throw new ZZError("Moving stream cursor!");
while(nc != null && o < 0) {
nc = nc.s(dim, -1);
if(nc != null)
o += nc.getText().length();
}
ZZCell prev = null;
while(nc != null && o > nc.getText().length() -
(lookingDir > 0 ? 1 : 0)) {
o -= nc.getText().length();
prev = nc;
nc = nc.s(dim);
}
if(nc == null) {
if(o != 0)
return false;
else {
nc = prev;
o = nc.getText().length();
}
}
if(o < 0)
throw new ZZError("WHAT? WHAT? WHAT? Neg offset in move");
curs.set(nc); curs.setOffs(o);
return true;
}
/** Find a position along a stream with the given string.
* Currently relatively inefficient, unless the cells are relatively
* long.
*/
static public boolean find(ZZCursor from, String dim, int dir,
boolean includeThis, String text) {
// First, see if there is a match inside the current cell,
// done carefully.
ZZCell c = from.get();
int offs = from.getOffs();
p("Find: "+c+" "+offs+" "+dim+" "+dir+" "+includeThis+" '"+text+"'");
String txt = c.getText();
char first = text.charAt(0);
if(!includeThis) offs += dir;
if(dir > 0) {
while(c != null) {
while((offs = txt.indexOf(first, offs)) >= 0) {
if(isMatch(c, offs, text, dim, from))
return true;
offs ++;
}
c = c.s(dim, dir);
if(c != null) {
txt = c.getText();
offs = 0;
}
}
} else {
while(c != null) {
p("Findnegloop: "+c);
while((offs = txt.lastIndexOf(first, offs)) >= 0) {
p("Findnegloop: try "+ offs);
if(isMatch(c, offs, text, dim, from))
return true;
offs --;
}
c = c.s(dim, dir);
if(c != null) {
txt = c.getText();
offs = txt.length()-1;
}
}
}
p("Not found!");
// Then, we're looking at whole cells the rest of the way.
return false;
}
/** Check to see whether the text in the stream is equal to this text.
*/
static public boolean isMatch(ZZCell c, int offs, String text, String dim) {
return isMatch(c, offs, text, dim, null);
}
/** Check whether the match is correct and set the cursor if it is.
*/
static boolean isMatch(ZZCell c, int offs, String text,
String dim, ZZCursor from)
{
p("Match: "+c+" "+offs+" '"+text+"' "+dim);
p("Matching csubstr: '"+c.getText().substring(offs)+"'");
ZZCell origc = c;
int origoffs = offs;
while(c != null) {
String ct = c.getText().substring(offs);
if(ct.length() >= text.length()) {
if(ct.substring(0, text.length()).equals(text)) {
if(from != null) {
from.set(origc);
from.setOffs(origoffs);
}
p("TRUE!");
return true;
} else return false;
}
if(!text.substring(0, ct.length()).equals(ct)) return false;
text = text.substring(ct.length());
c = c.s(dim);
offs = 0;
}
return false;
}
static public String getString(ZZCursor curs, String dim, int n) {
ZZCell c = curs.get();
int offs = curs.getOffs();
StringBuffer res = new StringBuffer();
while(n > 0) {
String txt = c.getText();
if(offs > 0) txt = txt.substring(offs);
if(n <= txt.length()) {
res.append(txt.substring(0, n));
return res.toString();
}
res.append(txt);
n -= txt.length();
offs = 0;
c = c.s(dim);
if(c == null) return null;
}
return null;
}
/** A class for moving along the stream, collecting characters.
* Part of the interface might be abstracted to an interface like
* java.text.CharacterIterator, but in a slightly more restricted subset.
* <p>
* This class considers the end of the stream the location when it
* can't return any characters any more + 1.
*/
static public class Iterator {
final ZZCursorVirtual c;
final String dim;
Iterator(ZZCursorVirtual c, String dim) { this.c = c; this.dim = dim; }
public void set(ZZCursor c) { this.c.set(c); }
/** Get the current iterator position.
* @return The current position. The position should not be modified.
*/
public ZZCursor get() { return c; }
public boolean move(int nsteps) {
if(!Stream.move(c, dim, nsteps)) return false;
if(c.get().s(dim) == null)
// XXX Is this right?
if(c.get().getText().length() <= c.getOffs())
return false;
return true;
}
public boolean move(int nsteps, int lookingDir) {
if(!Stream.move(c, dim, nsteps, lookingDir)) return false;
if(c.get().s(dim) == null)
if(c.get().getText().length() <= c.getOffs())
return false;
return true;
}
public void start() {
c.set(c.get().h(dim));
c.setOffs(0);
}
public void end() {
ZZCell cl = c.get().h(dim, 1);
c.set(cl);
c.setOffs(cl.getText().length());
}
public void end(int dir) {
if(dir < 0) start(); else end();
}
public boolean find(int dir, boolean includeThis, String text) {
return Stream.find(c, dim, dir, includeThis, text);
}
/** Get the current character.
* Returns -1 for the end-of-stream.
*/
public char getChar() {
return getChar(0);
}
public char getChar(int offs) {
ZZCursorVirtual c1 = new ZZCursorVirtual(c);
// Move even if zero, to get the right
// directional position.
if(!Stream.move(c1, dim, offs, 1)) return (char)-1;
String str = c1.get().getText();
if(c1.getOffs() >= str.length()) return (char)-1;
return str.charAt(c1.getOffs());
}
public String getString(int n, int dir) {
// SLOW!!!!
ZZCursorVirtual c1 = new ZZCursorVirtual(c);
if(dir < 0) {
if(!Stream.move(c1, dim, -n)) return null;
}
return Stream.getString(c1, dim, n);
}
}
static public Iterator getIterator(ZZCursor c, String dim) {
return new Iterator(new ZZCursorVirtual(c), dim);
}
}