// Copyright 2001-2004, FreeHEP.
package org.freehep.postscript;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;
/**
* Objects for PostScript Processor, as defined in 3.3 Data Types and Objects
*
* @author Mark Donszelmann
* @version $Id: PSString.java 10178 2006-12-08 09:03:07Z duns $
*/
public class PSString extends PSComposite implements PSTokenizable, PSDataSource, PSDataTarget, Comparable {
private char[] value;
private int start = 0;
private int length = 0;
private ByteInputStream in = null;
private Scanner scanner = null;
private ByteOutputStream out = null;
private DSC dsc = null;
protected PSString(char[] chars, int index, int count, DSC dsc) {
super("string", true);
value = chars;
start = index;
length = count;
this.dsc = dsc;
}
public PSString(String string) {
this(string, new DSC());
}
public PSString(String string, DSC dsc) {
this(string.length());
string.getChars(0, string.length(), value, 0);
this.dsc = dsc;
}
public PSString(int n) {
this(new char[n]);
}
public PSString(char[] chars) {
this(chars, 0, chars.length, new DSC());
}
public InputStream getInputStream() {
if (in == null) {
in = new ByteInputStream();
}
return in;
}
public DSC getDSC() {
return dsc;
}
public int read() throws IOException {
if (in == null) {
in = new ByteInputStream();
}
return in.read();
}
public void reset() throws IOException {
if (in == null) {
in = new ByteInputStream();
}
in.reset();
}
public OutputStream getOutputStream() {
if (out == null) {
out = new ByteOutputStream();
}
return out;
}
public void write(int b, boolean secure) throws IOException {
if (!secure) throw new IOException();
if (out == null) {
out = new ByteOutputStream();
}
out.write(b);
}
public PSObject token(boolean packingMode, NameLookup lookup) throws IOException, SyntaxException, NameNotFoundException {
getScanner();
return scanner.nextToken(packingMode, lookup);
}
public boolean execute(OperandStack os) {
if (isLiteral()) {
os.push(this.clone());
return true;
}
try {
getScanner();
} catch (IOException e) {
error(os, new IOError());
}
return Dispatcher.dispatch(os, this);
}
public String getType() {
return "stringtype";
}
public int size() {
return length;
}
public char get(int i) {
return value[start+i];
}
public void set(int i, byte b) {
set(i, (char)b);
}
public void set(int i, int b) {
set(i, (char)b);
}
public void set(int i, char c) {
value[start+i] = c;
}
public PSString set(String s) {
byte[] b = s.getBytes();
for (int i=0; i<b.length; i++) {
set(i, b[i]);
}
return subString(0, b.length);
}
public PSString subString(int index, int count) {
if ((index < 0) || (index+count) > length) {
return null;
}
return new PSString(value, index, count, dsc);
}
public PSString subString(int index) {
return subString(index, length-index);
}
public int indexOf(PSString s) {
String string = getValue();
String seek = s.getValue();
return string.indexOf(seek);
}
public int compareTo(Object o) {
String s1 = getValue();
String s2 = ((PSString)o).getValue();
return s1.compareTo(s2);
}
public int hashCode() {
return getValue().hashCode();
}
public boolean equals(Object o) {
if (o instanceof PSString) {
return getValue().equals(((PSString)o).getValue());
} else if (o instanceof PSName) {
return getValue().equals(((PSName)o).getValue());
}
return false;
}
public Object clone() {
return new PSString(value, start, length, dsc);
}
public PSObject copy() {
return new PSString(new String(value, start, length), dsc);
}
public String cvs() {
return getValue();
}
public String toString() {
return "("+getValue()+")";
}
public String getValue() {
return new String(value, start, length);
}
private void getScanner() throws IOException {
if (scanner == null) {
if (in == null) {
in = new ByteInputStream();
}
scanner = new Scanner(in, dsc);
}
}
class ByteInputStream extends PushbackInputStream {
private int initStart;
private int initLength;
public ByteInputStream() {
super(null, 1);
initStart = start;
initLength = length;
}
// make bytes available one at a time
public int available() throws IOException {
return (length > 0) ? 1 : 0;
}
public void close() throws IOException {
}
public synchronized void mark(int readLimit) {
}
public boolean markSupported() {
return false;
}
public int read() throws IOException {
if (length > 0) {
int b = value[start] & 0xFF;
start++;
length--;
return b;
}
return -1;
}
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
public int read(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
return 1;
}
public synchronized void reset() throws IOException {
start = initStart;
length = initLength;
}
public long skip(long n) throws IOException {
if (n <= length) {
start += n;
length -= n;
return n;
}
return -1;
}
public void unread(int b) throws IOException {
if (start > 0) {
start--;
length++;
}
}
public void unread(byte[] b) throws IOException {
unread(b, 0, b.length);
}
public void unread(byte[] b, int off, int len) throws IOException {
if (len > start) {
throw new IOException();
}
start -= len;
length += len;
}
}
class ByteOutputStream extends OutputStream {
public ByteOutputStream() {
super();
}
public void write(int b) throws IOException {
if (length >= value.length) throw new IOException();
value[length] = (char)(b & 0x00FF);
length++;
}
}
}