created mirror

This commit is contained in:
whatever
2026-09-14 20:19:29 -04:00
commit 6764738d92
600 changed files with 87187 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
/*
ContentStore.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.*;
/** An interface for storing contents info in.
* The Objects are supposed to be either String or Span type.
*/
public interface ContentStore {
String rcsid = "$Id: ContentStore.java,v 1.4 2000/09/19 10:32:00 ajk Exp $";
void put(String id1, Object what);
Object get(String id);
}

View File

@@ -0,0 +1,36 @@
/*
ContentStore.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.*;
/** An interface for storing contents info.
* The difference with ContentStore is that this is analogous to
* ZZDimStorer whereas ContentStore is more like ZZDimension.
* The Objects are supposed to be either String or Span type.
*/
public interface ContentStorer {
String rcsid = "$Id: ContentStorer.java,v 1.3 2000/09/19 10:32:00 ajk Exp $";
void putContent(String id, Object what);
}

View File

@@ -0,0 +1,71 @@
/*
CountingStream.java
*
* Copyright (c) 2001, 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.awt.*;
import java.util.*;
import java.io.*;
/** Something Java should have: we conut our position in the stream.
*/
public class CountingStream extends FilterInputStream {
int curPos = 0;
public CountingStream(InputStream is) {
super(is);
}
public int read() throws IOException {
int c = super.read();
curPos++;
return c;
}
public int read(byte b[]) throws IOException {
int n = super.read(b);
if(n < 0) return n;
curPos += n;
return n;
}
public int read(byte b[],
int off,
int len) throws IOException {
int n = super.read(b, off, len);
if(n < 0) return n;
curPos += n;
return n;
}
public long skip(long n) throws IOException {
long ns = super.skip(n);
curPos += ns;
return ns;
}
public int getCount() {
return curPos;
}
}

View File

@@ -0,0 +1,33 @@
/*
DimStore.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.*;
/** An interface for storing dimension info in.
*/
public interface DimStore {
String rcsid = "$Id: DimStore.java,v 1.3 2000/09/19 10:32:00 ajk Exp $";
void put(String id1, String id2);
String get(String id, int dir);
}

View File

@@ -0,0 +1,91 @@
/*
DirStreamSet.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, locking by Antti-Juhani Kaijanaho
*/
package org.gzigzag;
import java.util.*;
import java.io.*;
/** A directory implementation of StreamSet
*/
public class DirStreamSet extends StreamSet {
public static final String rcsid = "$Id: DirStreamSet.java,v 1.5 2000/09/18 14:28:22 tjl Exp $";
File dir;
public InputStream getInputStream(String id) {
try {
File f = new File(dir, id);
if(!f.exists()) return null;
if(!f.canRead()) throw new ZZFatalError("Can't read file");
return new BufferedInputStream(
new FileInputStream(f), 4096);
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZFatalError("File problem");
}
}
public OutputStream getAppendStream(String id) {
try {
File f = new File(dir, id);
return new BufferedOutputStream(
new FileOutputStream(f.getPath(), true));
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZFatalError("File problem");
}
}
public boolean exists(String id) {
File fn = new File(dir, id);
return fn.exists();
}
public Writable getWritable(String id) {
if(id == null || id.equals(""))
throw new ZZError("Can't use writables with null or empty name");
try {
File fn = new File(dir, id);
final RandomAccessFile f = new RandomAccessFile(fn, "rw");
return new FileWritable(f) ;
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError(" "+e);
}
}
public DirStreamSet(File dir0) {
try {
dir = dir0;
if(dir.exists() && !dir.isDirectory()) {
throw new ZZError("MUST BE DIRECTORY!!!! "+dir);
}
if(!dir.exists()) {
dir.mkdirs();
}
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError(" "+e);
}
}
}

View File

@@ -0,0 +1,50 @@
/*
DummyStreamSet.java
*
* Copyright (c) 1999-2001, 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 Benjamin Fallenstein
*/
package org.gzigzag;
import java.awt.*;
import java.applet.*;
import java.io.*;
import java.util.*;
/** A dummy stream set for ZZ spaces.
* Save fails, mostly for applets and testing.
*/
public class DummyStreamSet extends StreamSet {
public InputStream getInputStream(String id) { return null; }
public OutputStream getAppendStream(String id) { return null; }
public boolean exists(String id) { return false; }
Hashtable ws = new Hashtable();
public Writable getWritable(String id) {
Writable res = (Writable)ws.get(id);
if(res == null) {
res = new MemWritable();
ws.put(id, res);
}
return res;
}
}

View File

@@ -0,0 +1,251 @@
/*
FileWritable.java
*
* Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen
*
* 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 & Vesa Parkkinen
*/
package org.gzigzag;
import java.util.*;
import java.io.*;
/** A Writable that is just a file.
*
* Default: caching off..
*/
// Beginning of block:
// long: index of next block
// long: offset in subfile0 to the name.
public class FileWritable implements Writable {
public static final String rcsid =
"$Id: FileWritable.java,v 1.6 2000/09/19 10:32:00 ajk Exp $";
public static final 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); }
public static final int BUF_SIZE = 512;
RandomAccessFile f;
byte[] r_buffer;
byte[] w_buffer;
boolean cache;
boolean dirty;
// read buffer offset
long off;
// write buffer offset
long w_off;
// read bytes in buffer
int r_size;
// bytes written
int written;
/*
* XXX TODO: not quite there yet...
*/
public void write(long offset, byte[] data) {
//p("write");
try {
if( ! cache ){
f.seek(offset);
f.write(data);
return;
}else {
// clear read cache
if ( offset < off + r_size &&
offset + data.length > off ) {
off = 0;
r_size = 0;
}
if ( data.length > BUF_SIZE ){
//p(" > ");
flush();
f.seek(offset);
f.write(data);
return;
}
if ( offset + data.length < w_off ){
//p(" under ");
f.seek(offset);
f.write(data);
//return;
}else if ( offset > w_off + written ){
//p(" over ");
flush();
w_off = offset;
written = data.length;
System.arraycopy( data, 0, w_buffer, 0, written );
dirty = true;
}else if ( offset < w_off && offset + data.length > w_off ){
//p(" partial ");
flush();
f.seek(offset);
f.write(data);
} else if( offset == w_off + written &&
BUF_SIZE - written > data.length ) {
//p(" hit: " + offset);
System.arraycopy( data, 0, w_buffer, written, data.length);
written += data.length;
//p(" written = " + written);
dirty = true;
}else {
//p(" other ");
flush();
f.seek(offset);
f.write(data);
return;
}
}
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError(" "+e);
}
}
public byte[] read(long offset, int n) {
//p("read");
try {
byte[] b = new byte[n];
if( ! cache ){
f.seek(offset);
f.read(b);
return b;
} else {
if( offset < w_off + written &&
offset + n > w_off ) {
flush();
}
if ( offset > off && offset - off + n < r_size ){
System.arraycopy(r_buffer, (int)(offset - off), b, 0, n );
return b;
}
f.seek(offset);
r_size = f.read(r_buffer);
System.arraycopy(r_buffer, 0, b, 0, n );
off = offset;
return b;
}
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError(" read "+offset+" "+n+" "+e);
}
}
public void read(long offset, byte b[], int o, int n) {
//p("read2");
try {
if (! cache ){
f.seek(offset);
f.read(b, o, n);
}else {
if( offset + o < w_off + written &&
offset + o + n > w_off ) {
flush();
}
if ( offset + o> off && offset + o - off + n < r_size ){
System.arraycopy(r_buffer, (int)(offset + o - off),
b, o, n );
}else {
f.seek(offset + o);
r_size = f.read(r_buffer);
System.arraycopy(r_buffer, 0, b, o, n );
off = offset + o;
}
}
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError(" read " +e);
}
}
public long length() {
try {
return f.length();
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError(" "+e);
}
}
public void flush() {
if ( ! cache ) return;
if( ! dirty || written == 0) return;
try{
f.seek(w_off);
f.write(w_buffer, 0, written);
dirty = false;
//p("FLUSH " + written);
written = 0;
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError(" "+e);
}
}
public FileWritable(RandomAccessFile f) {
/*
* set this to true, if you want to test caching
*/
this(f, false);
}
public FileWritable(RandomAccessFile f, boolean b) {
//p("FW: create");
this.f = f;
cache = b;
if ( cache ){
r_buffer = new byte[BUF_SIZE];
w_buffer = new byte[BUF_SIZE];
}else{
r_buffer = null;
}
dirty = false;
r_size = 0;
}
}

View File

@@ -0,0 +1,39 @@
/*
Flushable.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.*;
/** An interface for things that can be flushed.
* Mostly for determining if e.g. a ZZSpace needs flushing.
*/
public interface Flushable {
String rcsid = "$Id: Flushable.java,v 1.3 2000/09/19 10:32:00 ajk Exp $";
/** Flush the contents not yet flushed to disk.
*/
void flush();
/** Whether this object is in fact in a cache-keeping mode.
*/
boolean isCaching();
}

191
Java/storage/GZZ0.java Normal file
View File

@@ -0,0 +1,191 @@
/*
GZZ0.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.io.*;
/** An implementation of the GZZ0 file format.
*/
public class GZZ0 {
String rcsid = "$Id: GZZ0.java,v 1.7 2001/03/01 13:53:53 ajk Exp $";
public static boolean dbg = false;
final static void p(String s) { if(dbg) System.out.println(s); }
final static void pa(String s) { System.out.println(s); }
final int magic = 0x475a5a30; // "GZZ0"
final int version = 0;
final byte rTime = 116;
public interface Runner {
/** Returns the GZZ0 content type of this runner.
*/
int getContentType();
/** Returns the GZZ0 content version of this runner.
*/
int getContentVersion();
/** Read a run.
*/
void readRun(InputStream is);
/** Start writing.
*/
void startWrite(OutputStream os);
/** Finish writing.
*/
void endWrite();
}
StreamSet ss;
String id;
public GZZ0(StreamSet ss, String id) {
this.ss = ss; this.id = id;
}
/** Read the latest dataset into the given runner.
* @param r The runner into which to give the runs
* @param maxtimestamp The maximum timestamp whose changes to include.
* @return The latest timestamp read.
*/
public int read(Runner r, int maxtimestamp) {
InputStream is = ss.getInputStream(id);
CountingStream counts = null;
if(dbg) {
is = counts = new CountingStream(is);
}
DataInputStream dis = new DataInputStream(is);
// Read header
try {
int i = dis.readInt();
if(i != magic)
throw new ZZFatalError("Invalid file format! Doesn't begin with GZZ0 magic");
i = dis.readInt();
if(i != version)
throw new ZZFatalError("Invalid file version! Not "+version);
i = dis.readInt();
if(i != r.getContentType())
throw new ZZFatalError("Wrong content type!");
i = dis.readInt();
if(i != r.getContentVersion())
throw new ZZFatalError("Wrong content version!");
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Reading file");
}
// Read body.
int lastTime = -1;
boolean eofOk = true;
byte[] byt = new byte[4096];
try {
while(true) {
eofOk = true;
byte rectype = dis.readByte();
eofOk = false;
if(rectype != rTime)
throw new ZZFatalError("Invalid timestamp record! " + id + " " +
(counts != null ? counts.getCount() : -1));
lastTime = dis.readInt();
int nbytes = dis.readInt();
if(maxtimestamp > 0 && lastTime > maxtimestamp) {
dis.close();
return lastTime;
}
if(nbytes > byt.length)
byt = new byte[nbytes];
dis.readFully(byt, 0, nbytes);
ByteArrayInputStream bis =
new ByteArrayInputStream(byt, 0, nbytes);
r.readRun(bis);
}
} catch(EOFException e) {
if(!eofOk)
throw new ZZFatalError("Unexpected eof in simpledimfile");
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Reading file");
}
return lastTime;
}
ByteArrayOutputStream outputStream;
DataOutputStream dos;
Runner runner;
int timestamp;
/** Write the changes back.
* XXX Should check runner's type...
*/
public void startWrite(int timestamp, Runner r) {
outputStream = new ByteArrayOutputStream();
this.timestamp = timestamp;
this.runner = r;
runner.startWrite(new DataOutputStream(outputStream));
}
/** Finish writing. */
public void endWrite(boolean forceStamp) {
boolean ex = ss.exists(id);
runner.endWrite();
try {
OutputStream os = ss.getAppendStream(id);
dos = new DataOutputStream(os);
if(!ex) {
// Write header.
dos.writeInt(magic);
dos.writeInt(version);
dos.writeInt(runner.getContentType());
dos.writeInt(runner.getContentVersion());
dos.flush();
}
byte[] byt = outputStream.toByteArray();
if(byt.length == 0 && !forceStamp) {
pa("Not writing "+id);
return;
}
pa("Writing "+id+" "+byt.length);
dos.writeByte(rTime);
dos.writeInt(timestamp);
dos.writeInt(byt.length);
dos.write(byt);
dos.flush();
dos = null;
outputStream = null;
runner = null;
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Writing file");
}
}
}

View File

@@ -0,0 +1,76 @@
/*
MemWritable.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 Benjamin Fallenstein
*/
package org.gzigzag;
import java.util.*;
/** A writable that stores its contents in memory.
* Used to make scrolls work in applets. Not necessarily very efficient;
* however, I don't think that's so much of an issue in applets, where we
* won't save a lot of data anyway.
*/
public class MemWritable implements Writable {
String rcsid = "$Id: MemWritable.java,v 1.1 2000/12/26 22:48:37 bfallenstein Exp $";
/** The size of the chunks in which memory is allocated. */
final int CHUNK = 500;
/** The data. */
byte[] d = new byte[CHUNK];
/** The length of the data actually used.
* len-1 is the highest index of any data ever written.
*/
int len = 0;
public void extend() {
byte[] nu = new byte[d.length + CHUNK];
System.arraycopy(d, 0, nu, 0, len);
d = nu;
}
public void write(long offset0, byte[] data) {
int offset = (int)offset0;
int n = data.length;
while(offset + n >= d.length) extend();
System.arraycopy(data, 0, d, offset, n);
if(offset + n > len) len = offset + n;
}
public byte[] read(long offset0, int n) {
byte[] res = new byte[n];
read(offset0, res, 0, n);
return res;
}
public void read(long offset0, byte b[], int off, int n){
System.out.println("MemWritable.read "+d.length+" "+len+" params "+
offset0+" "+b.length+" "+off+" "+n);
int offset = (int)offset0;
while(offset + n >= d.length) extend();
System.arraycopy(d, offset, b, off, n);
}
public long length() {
return len;
}
public void flush() {}
}

232
Java/storage/Recs.pl Normal file
View File

@@ -0,0 +1,232 @@
#
# $Id: Recs.pl,v 1.8 2001/03/06 13:44:39 ajk Exp $
#
# Generate Recs.java for record types for file formats.
#
# Java Serializable is CLOSE but not quite close enough to what we need
# (e.g. it would write out the "offset" field)
# AND we want a standard binary format.
$file = $ARGV[0];
$file = "Recs.pl" if ($file eq "");
open F, ">$file" or die "Can't open file $file";
$rcsid = '$Id: Recs.pl,v 1.8 2001/03/06 13:44:39 ajk Exp $';
print F <<END;
/*
Recs.java
*
* GENERATED USING Recs.pl - DO NOT MODIFY THE JAVA CODE:
* YOUR CHANGES WILL BE OVERWRITTEN. MODIFY THE GENERATING
* PERL CODE IN Recs.pl instead.
*
* 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.*;
import java.io.*;
/** A generated class that defines a number of binary record
* types.
*/
public class Recs {
static final void p(String s) { System.out.println(s); }
static short getMagic(long offset) {
return (short)(23415 ^ (offset % 30411));
}
public static class InvalidMagic extends ZZError {
public InvalidMagic(String s) { super(s); }
}
static Record readRecord(long offs, DataInputStream s) {
try {
short mag = s.readShort();
if(mag != getMagic(offs))
throw new InvalidMagic("Invalid record magic!"+offs+" "+mag+" "+getMagic(offs)+" ");
short typ = s.readShort();
Record r = createRecord(typ);
// p("Before rd:\\n "+r);
r.read_data(offs, s);
// p("After rd:\\n "+r);
return r;
// if(getTypeNo() != typ)
// throw new ZZError("Invalid record type!");
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError("IO ERROR!");
}
}
static ByteArrayOutputStream bos = new ByteArrayOutputStream();
static DataOutputStream os = new DataOutputStream(bos);
static void writeRecord(Record r, Writable w) {
bos.reset();
writeRecord(r, os);
w.write(r.offset, bos.toByteArray());
}
static void writeRecord(Record r, DataOutputStream s) {
r.write(s);
}
static public abstract class Record {
long offset;
public long getOffset() { return offset; }
public int length() { return 4; } // magic + type
public abstract short getTypeNo();
public void write_data(DataOutputStream s) throws IOException {
// Unsymmetric: read back in readRecord
s.writeShort(getMagic(offset));
s.writeShort(getTypeNo());
}
public void read_data(long offs, DataInputStream s)
throws IOException {
offset = offs;
// Skip 4 bytes, as those were read by readRecord already.
}
public String toString() {
return " Offset: "+offset+"\\n";
}
public void write(DataOutputStream s) {
try {
write_data(s);
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError("IOERRROR");
}
}
public void read(long offs, DataInputStream s) {
try {
read_data(offs, s);
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError("IOERRROR");
}
}
}
END
my $rettype;
@recs = (
[ TreeRecord, Record, "int hash; int prevwhash", 42],
[ ConnRecord, TreeRecord, "String cell; short othoffs", 43],
[ ContentRecord, TreeRecord, "String cell; boolean span; String content",
44],
[ HdrRecord, Record, "short nbits; int mask; long lasthash; long end;
long id", 45],
[ HashRecord, Record, "short nbits", 46],
[ RootRecord, Record, "long nextCell", 47],
);
for(@recs) {
$rettype .= "if(typ == $_->[3]) return new $_->[0](); \n";
my @f = map { [split ' '] } split ';', $_->[2];
my $len = join '+',
" super.length() ",
map {
$_->[0] eq "long" and 8
or $_->[0] eq "int" and 4
or $_->[0] eq "short" and 2
or $_->[0] eq "boolean" and 1
or $_->[0] eq "String" and
" (2 + $_->[1].getBytes(\"UTF8\").length) "
or die "Invalid type $_->[0]"
} @f;
my $write = join '',
map {
$_->[0] eq "String" and
"{
byte[] bt = $_->[1].getBytes(\"UTF8\");
s.writeShort(bt.length);
s.write(bt, 0, bt.length);
}
"
# or $_->[0] eq "bool" and "s.writeBoolean($_->[1]);"
or "s.write".(ucfirst $_->[0])."($_->[1]);";
} @f;
my $read = join '',
map {
$_->[0] eq "String" and
"{
short l = s.readShort();
byte[] bt = new byte[l];
int n = s.read(bt);
if(n!=l) throw new ZZError(\"NOT ENOUGH DATA\");
$_->[1] = new String(bt, \"UTF8\");
}
"
# or $_->[0] eq "bool" and "$_->[1] = s.readBoolean();"
or "$_->[1] = s.read".(ucfirst $_->[0])."();";
} @f;
my $tostring = join '',
map {
qq( + " $_->[1]: "+$_->[1]+"\\n" )
} @f;
print F <<END
static public class $_->[0] extends $_->[1] {
$_->[2];
public int length() {
try {
return $len;
} catch(Exception e) {
ZZLogger.exc(e);
throw new ZZError("ARGH");
}
}
public short getTypeNo() { return $_->[3]; }
public void write_data(DataOutputStream s) throws IOException {
super.write_data(s);
$write
}
public void read_data(long offs, DataInputStream s)
throws IOException {
super.read_data(offs, s);
$read
}
public String toString() {
return "$_->[0]:\\n"
$tostring
+ super.toString();
}
}
END
}
print F qq[
static public Record createRecord(int typ) {
$rettype
throw new ZZError("Invalid record type "+typ);
}
}
];

View File

@@ -0,0 +1,129 @@
/*
SimpleContentFile.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.*;
import java.io.*;
/** A simple content file format.
* The format consists of records: s(cell)(string), S(cell)(span),
* t(time4). Currently spans are stored in their stringized format
* but this may be changed later.
* <p>
* The record types are defined by the ASCII values of the above characters.
* <p>
* Note the similarity with SimpleDimFile.
*/
public class SimpleContentFile implements ContentStorer, GZZ0.Runner {
public static final String rcsid = "$Id: SimpleContentFile.java,v 1.6 2000/09/19 10:32:00 ajk Exp $";
final byte rString = 115;
final byte rSpan = 83;
ContentStorer sto;
public void startRead(ContentStorer sto) {
this.sto = sto;
}
public void endRead() {
sto = null;
}
public int getContentType() {
return 43;
}
public int getContentVersion() {
return 0;
}
public void readRun(InputStream is) {
DataInputStream dis = new DataInputStream(is);
boolean eofOk = true;
try {
while(true) {
eofOk = true;
byte rectype = dis.readByte();
eofOk = false;
switch(rectype) {
case rString: {
String id = dis.readUTF();
String ct = dis.readUTF();
sto.putContent(id, ct); }
break;
case rSpan: {
String id = dis.readUTF();
String cts = dis.readUTF();
Span sp = Span.parse(cts);
sto.putContent(id, sp); }
break;
default:
throw new ZZFatalError("Invalid record");
}
}
} catch(EOFException e) {
if(!eofOk)
throw new ZZError("Unexpected eof in simpledimfile");
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Reading file");
}
}
DataOutputStream dos;
public void putContent(String id, Object ct) {
if(ct == null)
throw new ZZFatalError("Tried to store null content!");
try {
if(ct instanceof String) {
dos.writeByte(rString);
dos.writeUTF(id);
dos.writeUTF((String)ct);
} else if(ct instanceof Span) {
dos.writeByte(rSpan);
dos.writeUTF(id);
dos.writeUTF(((Span)ct).toString());
} else {
throw new ZZFatalError("Can't put odd object: "+ct);
}
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Reading file");
}
}
public void startWrite(OutputStream dos) {
this.dos = new DataOutputStream(dos);
}
public void endWrite() {
try {
dos.flush();
dos = null;
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Reading file");
}
}
}

View File

@@ -0,0 +1,137 @@
/*
SimpleDimFile.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.*;
import java.io.*;
/** A simple dimension file format.
* The format consists of records: c(cell)(cell), d+(cell), d-(cell),
* Later to be extended with h(cell) which defines the
* given cell to be the headcell of its rank.
* <p>
* The record types are defined by the ASCII values of the above characters.
* <p>
*/
public class SimpleDimFile implements ZZDimStorer, GZZ0.Runner{
public static final String rcsid = "$Id: SimpleDimFile.java,v 1.6 2000/09/19 10:32:00 ajk Exp $";
final byte rConn = 99;
final byte rDisc = 100;
final byte rPlus = 43;
final byte rMinus = 45;
ZZDimStorer sto;
public void startRead(ZZDimStorer sto) {
this.sto = sto;
}
public void endRead() {
sto = null;
}
public int getContentType() {
return 42;
}
public int getContentVersion() {
return 0;
}
public void readRun(InputStream is) {
DataInputStream dis = new DataInputStream(is);
boolean eofOk = true;
try {
while(true) {
eofOk = true;
byte rectype = dis.readByte();
eofOk = false;
switch(rectype) {
case rConn:
String id1 = dis.readUTF();
String id2 = dis.readUTF();
sto.storeConnect(id1, id2);
break;
case rDisc:
byte bdir = dis.readByte();
int dir;
if(bdir == rPlus)
dir = 1;
else if(bdir == rMinus)
dir = -1;
else
throw new ZZFatalError("Invalid directon");
String id = dis.readUTF();
sto.storeDisconnect(id, dir);
break;
default:
throw new ZZFatalError("Invalid record");
}
}
} catch(EOFException e) {
if(!eofOk)
throw new ZZFatalError("Unexpected eof in simpledimfile");
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Reading file");
}
}
DataOutputStream dos;
public void storeConnect(String a, String b) {
try {
dos.writeByte(rConn);
dos.writeUTF(a);
dos.writeUTF(b);
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Writing file");
}
}
public void storeDisconnect(String a, int dir) {
try {
dos.writeByte(rDisc);
dos.writeByte(dir > 0 ? rPlus : rMinus);
dos.writeUTF(a);
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Writing file");
}
}
public void startWrite(OutputStream dos) {
this.dos = new DataOutputStream(dos);
}
public void endWrite() {
try {
dos.flush();
dos = null;
} catch(IOException e) {
ZZLogger.exc(e);
throw new ZZFatalError("Reading file");
}
}
}

87
Java/storage/Sliced.java Normal file
View File

@@ -0,0 +1,87 @@
/*
Sliced.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.*;
class FEIHFSEHFSHFSMEKFMESKUFMSEF { }
/** EXPERIMENTAL, NOT FUNCTIONAL: A dimension created by splicing
* together several other
* dimensions. Inter-dimension connections are stored locally and
* in preflets.
* <p>
* This class extends ZZLocalDimension, which is used for caching
* accesses.
* <p>
* What makes things easier here is that the slice definition guarantees
* that all ranks that do not come from s.0 remain untouched. All alterations
* are insertions of ranks from the other slices
* in the middle of ranks from s.0 (of course, removing preflets and the like)
*/
/*
public class Sliced extends ZZDimension {
public static final String rcsid = "$Id: Sliced.java,v 1.8 2000/11/07 23:07:34 tjl Exp $";
ZZDimension[] slices;
ZZSlicedDimSpace sds;
Sliced(ZZSlicedDimSpace ss, ZZDimension[] s) {
sds = ss;
slices = s;
}
public String s(String c, int steps, ZZObs o) {
String oid = sds.getOrigID(c);
int sli = sds.getSliceID(c);
ZZDimension slice = slices[sli];
String ores = slice.s(oid, steps, o);
if(ores==null) return null;
return sds.getConvID(sli, ores);
}
public String h(String c, int dir, ZZObs o) {
String oid = sds.getOrigID(c);
int sli = sds.getSliceID(c);
ZZDimension slice = slices[sli];
String ores = slice.h(oid, dir, o);
if(ores==null) return null;
return sds.getConvID(sli, ores);
}
public void connect(String c, String d) {
int ci = sds.getSliceID(c);
int di = sds.getSliceID(d);
// Silently fail
if(sds.getSliceID(c) != sds.getSliceID(d))
return;
String cor = sds.getOrigID(c);
String dor = sds.getOrigID(d);
slices[ci].connect(cor, dor);
}
public void disconnect(String c, int dir) {
String oid = sds.getOrigID(c);
int sli = sds.getSliceID(c);
slices[sli].disconnect(oid, dir);
}
}
*/

View File

@@ -0,0 +1,149 @@
/*
SlicedCursor.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 org.gzigzag.*;
import java.util.*;
/** A dimension for the sliced space cursor.
*/
class KUHELFMSKUFHSUKFMSEF { }
/*
public class SlicedCursor extends Sliced {
public static final String rcsid = "$Id: SlicedCursor.java,v 1.7 2000/11/07 23:07:34 tjl Exp $";
static boolean dbg = true;
static final void p(String s) { if(dbg) System.out.println(s); }
String prefletdim;
// Need several mappings:
// Our cells to preflet cells in s0.
Hashtable our2prefs = new Hashtable();
// Preflet cells to our cells.
Hashtable pref2ours = new Hashtable();
SlicedCursor(ZZSlicedDimSpace ss, ZZDimension[] s,
String prefletdim) {
super(ss, s);
this.prefletdim = prefletdim;
ZZCell pr = sds.slices[0].getHomeCell();
while((pr = pr.s(prefletdim, 1)) != null) {
loadPref(pr);
}
}
// This cell is from the subspace.
void loadPref(ZZCell c) {
String t = c.getText();
String i = sds.getConvID(0, c.getID());
our2prefs.put(t, i);
pref2ours.put(i, t);
}
public String s(String c, int steps, ZZObs o) {
// Do one by one
// VERY unoptimized.
String orig = c;
if(o != null) triggers.addObs(orig, o);
int origsteps = steps;
if(steps > 0) {
while(--steps >= 0) {
String n = getOneStepPos(c, o);
if(n==null) return null;
if(o != null) triggers.addObs(n, o);
c=n;
}
} else {
while(++steps <= 0) {
String n = getOneStepNeg(c, o);
if(n==null) return null;
if(o != null) triggers.addObs(n, o);
c=n;
}
}
p("Cursor getsteps: "+orig+" "+steps+" "+c);
return c;
}
String getOneStepNeg(String c, ZZObs o) {
// First, if there is a real connection
String s = super.s(c, -1, o);
if(s == null) return null;
// Then, this might be a preflet.
// Then, if it's in either hashtable
String p = (String)pref2ours.get(s);
if(p != null)
return p;
return s;
}
String getOneStepPos(String c, ZZObs o) {
String s = (String)our2prefs.get(c);
if(s != null) {
s = super.s(s, 1, o);
// But if there's nothing, don't.
if(s != null) return s;
}
// It was not *that* special case. Now,
s = super.s(c, 1, o);
return s;
}
public void insert(String c, int dir, String d) {
throw new ZZError("No direct insert along d.cursor allowed!");
}
public void connect(String c, String d) {
int ci = sds.getSliceID(c);
int di = sds.getSliceID(d);
if(ci == di) {
slices[ci].connect(sds.getOrigID(c), sds.getOrigID(d));
return;
}
if(di != 0)
throw new ZZError("SlicedStpr: can't use non-slice0 cursors");
String pref = (String)our2prefs.get(c);
if(pref == null) {
// No preflet, have to create our own.
ZZCell pr = sds.slices[0].getHomeCell().N(prefletdim, 1);
pr.setText(c);
loadPref(pr);
pref = pr.getID();
}
slices[0].connect(sds.getOrigID(pref), sds.getOrigID(d));
triggers.chg(c);
triggers.chg(d);
}
public void disconnect(String c, int dir) {
if(dir < 0) {
slices[0].disconnect(sds.getOrigID(c), -1);
} else {
throw new ZZError("Can't disconnect poswards in slicedcursor");
}
}
}
*/

View File

@@ -0,0 +1,59 @@
/*
SlicedHomes.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 org.gzigzag.*;
import java.util.*;
/** A simple class to connect the sliced home cells together.
* There must be a way to move between the spaces, right?
*/
class EKUEHFKUEHFMEUFHMSEFS { }
/*
public class SlicedHomes extends ZZRODimension {
public static final String rcsid = "$Id: SlicedHomes.java,v 1.7 2000/11/07 23:07:34 tjl Exp $";
ZZSlicedDimSpace ss;
Hashtable homeinds = new Hashtable();
SlicedHomes(ZZSlicedDimSpace ss) {
this.ss = ss;
for(int i=0; i<ss.slices.length; i++) {
homeinds.put(
ss.getConvID(i, ss.slices[i].getHomeCellID()),
new Integer(i));
}
}
public String s(String c, int steps, ZZObs o) {
Integer ind = (Integer)homeinds.get(c);
if(ind == null) return null;
int i = ind.intValue() + steps;
if(i < 0 || i >= ss.slices.length)
return null;
return ss.getConvID(i, ss.slices[i].getHomeCellID());
}
}
*/

View File

@@ -0,0 +1,50 @@
/*
SlicedSame.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 org.gzigzag.*;
import java.util.*;
/** A simple dimension to connect cells with the same ID in sliced
* spaces together.
*/
class ELIJSEFIEHSFSHFSEF { }
/*
public class SlicedSame extends ZZRODimension {
ZZSlicedDimSpace ss;
SlicedSame(ZZSlicedDimSpace ss) {
this.ss = ss;
}
public String s(String c, int steps, ZZObs o) {
int si = ss.getSliceID(c);
String s = ss.getOrigID(c);
si += steps;
if(si < 1 || si >= ss.slices.length)
return null;
if(ss.slices[si].getCellByID(s) == null) return null;
return ss.getConvID(si, s);
}
}
*/

View File

@@ -0,0 +1,63 @@
/*
StreamSet.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.io.*;
/** A multi-file or multi-stream.
* Used for reading and writing multiple, named streams.
* They may be stored as a directory or as a single file, interleaved.
* Make sure you call close() after done with a stream.
*/
public abstract class StreamSet {
String rcsid = "$Id: StreamSet.java,v 1.5 2000/09/18 14:28:22 tjl Exp $";
/** Obtain the inputstream associated with the given id.
* @return The input stream, or null if it doesn't exist.
*/
public abstract InputStream getInputStream(String id);
/** Obtain an OutputStream for appending to the given id's stream.
*/
public abstract OutputStream getAppendStream(String id);
/** Whether a stream exists.
*/
public abstract boolean exists(String id);
/** Obtain a writable for a given id.
* This is so that string scrolls can work for now - they should
* be changed to use the usual routines.
*/
public abstract Writable getWritable(String id);
/** Obtain a streamset for the given file.
* NOT IMPLEMENTED. Should return either directory or single-file
* stream set.
*/
static public StreamSet get(File f) {
return null;
}
}

View File

@@ -0,0 +1,37 @@
/*
Writable.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.*;
/** A part of a multi-file or other nearly append-only storage.
*/
public interface Writable {
String rcsid = "$Id: Writable.java,v 1.5 2000/09/19 10:32:01 ajk Exp $";
void write(long offset, byte[] data);
byte[] read(long offset, int n);
void read(long offset, byte b[], int off, int len);
long length();
void flush();
}

View File

@@ -0,0 +1,122 @@
/*
ZZCacheContentStore.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.*;
/** A locally cached content storage, which tracks text changes.
*/
public class ZZCacheContentStore implements ContentStore,
ContentStorer {
public static final String rcsid = "$Id: ZZCacheContentStore.java,v 1.7 2000/09/19 10:32:01 ajk Exp $";
public static boolean dbg = false;
final static void p(String s) { if(dbg) System.out.println(s); }
final static void pa(String s) { System.out.println(s); }
UndoList undo;
public void setUndoList(UndoList l) { undo = l; }
ZZCacheDimSpace ds;
public void setSpace(ZZCacheDimSpace s) { ds = s; }
/** The current contents. */
Hashtable c = new Hashtable();
/** The earlier connection on each cell's poswards or negwards
* direction at commit time.
* This list is created at commit time by reversing all operations
* so we can then compare these values and the current values to
* see which have changed.
* Hmm.. do we really even need comm?
*/
Hashtable com;
static final Object nolla = new Object();
synchronized public void startCommit() {
com = new Hashtable();
}
synchronized public void endCommit(ContentStorer sto) {
for(Enumeration e = com.keys();
e.hasMoreElements();) {
String id = (String)e.nextElement();
Object chgfrom = com.get(id);
Object chgto = c.get(id);
if(chgfrom == nolla) chgfrom = null;
if(chgfrom == chgto ||
(chgfrom != null && chgfrom.equals(chgto)))
continue;
sto.putContent(id, chgto);
}
com = null;
}
/** The abstracted operation of connecting two cells.
* Parameters: cell1 cell2.
* The cells are explicitly assumed to be not connected before
* this.
*/
protected class ChangeContent implements UndoList.Op {
public void undo(Object[] list, int nth) {
String id = (String)list[nth+1];
Object before = list[nth+2];
Object after = list[nth+3];
if(before == null)
c.remove(id);
else
c.put(id, before);
ds.invalidateText(id);
}
public void redo(Object[] list, int nth) {
String id = (String)list[nth+1];
Object before = list[nth+2];
Object after = list[nth+3];
c.put(id, after);
ds.invalidateText(id);
}
public void commit(Object[] list, int nth) {
String id = (String)list[nth+1];
Object before = list[nth+2];
Object after = list[nth+3];
if(before == null)
com.put(id, nolla);
else
com.put(id,before);
}
}
protected ChangeContent mychange = new ChangeContent();
public Object get(String id) {
return c.get(id);
}
public void put(String id, Object o) {
undo.add(mychange, id, c.get(id), o);
p("SetText: "+id+" '"+o+"'");
c.put(id, o);
}
public void putContent(String id, Object o) {
c.put(id, o);
}
}

View File

@@ -0,0 +1,249 @@
/*
ZZCacheDimSpace.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.*;
import java.io.*;
import java.lang.reflect.*;
/** A dimspace that uses a StreamSet to be persistent.
* XXX Triggers to undo events?!?!? Existing ZZCells deleted??
*/
public class ZZCacheDimSpace extends ZZDimSpace {
public static final String rcsid = "$Id: ZZCacheDimSpace.java,v 1.28 2001/03/08 13:54:20 ajk Exp $";
protected int maxtimestamp;
StreamSet strs;
// XXX Stamps!
UndoList ul = new UndoList(2935);
ZZCacheContentStore ct = new ZZCacheContentStore();
Hashtable scrolls = new Hashtable();
int timestamp = 1;
synchronized public int stamp() { return ul.stamp(); }
synchronized public void undo() { ul.undo(); }
synchronized public void redo() { ul.redo(); }
synchronized public int commit() {
if (readonly) return timestamp;
p("COMMIT!");
// Put in time of last save. Not used anywhere yet.
ct.put("savetime", ""+System.currentTimeMillis());
for(Enumeration e = dims.keys();
e.hasMoreElements(); ) {
String dname = (String)e.nextElement();
ZZDimension d = (ZZDimension)dims.get(dname);
if(d instanceof ZZCacheDimension) {
ZZCacheDimension cd = (ZZCacheDimension)d;
cd.startCommit();
}
}
ct.startCommit();
ul.commit();
int stmp = ++timestamp;
SimpleDimFile outf = new SimpleDimFile();
for(Enumeration e = dims.keys();
e.hasMoreElements(); ) {
String dname = (String)e.nextElement();
ZZDimension d = (ZZDimension)dims.get(dname);
if(d instanceof ZZCacheDimension) {
ZZCacheDimension cd = (ZZCacheDimension)d;
GZZ0 writ = new GZZ0(strs, dname);
writ.startWrite(stmp, outf);
cd.endCommit(outf);
writ.endWrite(false);
}
}
SimpleContentFile coutf = new SimpleContentFile();
GZZ0 cwrit = new GZZ0(strs, "CONTENT");
cwrit.startWrite(stmp, coutf);
ct.endCommit(coutf);
cwrit.endWrite(true);
for (Enumeration e = spaceParts.keys(); e.hasMoreElements();) {
String s = (String)e.nextElement();
ZZSpacePart sp = (ZZSpacePart)spaceParts.get(s);
sp.postCommitHook();
}
return stmp;
}
public ZZCacheDimSpace(StreamSet w) {
this(w, -1);
}
public ZZCacheDimSpace(ZZCacheDimSpace cds, int tstamp) {
this(cds.strs, tstamp);
}
public ZZCacheDimSpace(StreamSet w, int tstamp) {
this(w, tstamp, (tstamp != -1));
}
public ZZCacheDimSpace(StreamSet w, int tstamp, boolean readonly) {
super(readonly);
strs = w;
ct.setUndoList(ul);
ct.setSpace(this);
maxtimestamp = tstamp;
if(strs.exists("CONTENT")) {
SimpleContentFile cinf = new SimpleContentFile();
GZZ0 crea = new GZZ0(strs, "CONTENT");
cinf.startRead(ct);
timestamp = crea.read(cinf, tstamp);
cinf.endRead();
} else {
// The id of the next free cell must be stored in the space,
// this is a kludge.
ct.put("nextfreeid", nextID);
// The home cell is called HOME
ct.put("1", "HOME");
}
nextID = (String)ct.get("nextfreeid");
spaceParts.put("bintree", new BinaryTreePart(this, "bintree"));
spaceParts.put("imptree", new ImpliedTreePart(this, "imptree"));
spaceParts.put("imptree2", new ImpliedTreePart2(this, "imptree2"));
spaceParts.put("doubler", new DoubleStepPart(this, "doubler"));
spaceParts.put("version", new VersionPart(this, "version"));
spaceParts.put("gentreetest", new GenTreePart(this, "gentreetest",
new GenTreeTestModel()));
try {
spaceParts.put("nile1str", new GenTreePart(this, "nile1str",
(GenTreePartModel)
Class.forName("org.gzigzag.module.Nile1GenTreeModel").
newInstance()));
} catch(Exception e) {
p("Nile module not found - this is not fatal unless you know what nile is. Don't worry.");
}
try {
Class ztp = Class.forName("org.zaubertrank.ZaubertrankPart");
Class zzsp = Class.forName("org.gzigzag.ZZSpace");
Constructor ztpc = ztp.getConstructor(new Class[] {
zzsp, "".getClass() });
ZZSpacePart sp = (ZZSpacePart)
ztpc.newInstance(new Object[] { this, "zaubertrank" });
spaceParts.put("zaubertrank", sp);
} catch (ClassNotFoundException e) {
// ignore: that Zaubertrank stack trace is annoying
} catch(Throwable t) {
ZZLogger.exc(t);
// the zaubertrank isn't compiled by standard, so don't tell
}
}
protected void setNextID(String s) {
super.setNextID(s);
ct.put("nextfreeid", nextID);
}
protected Span getSpan(String id) {
Object o = ct.get(id);
if(!(o instanceof Span))
return null;
return (Span)o;
}
protected String getText(String id) {
Object o = ct.get(id);
if(o==null) return "";
if(o instanceof Span)
o = ((Span)o).getString(getHomeCell());
return (String)o;
}
protected void setText(String id, Object cont) {
if (readonly) throw new ZZError("readonly space");
ct.put(id, cont);
}
protected ZZDimension createDimension(String s) {
if(!validDim(s)) return null;
if(s.indexOf(':') != -1) return createPartDimension(s);
ZZDimension d;
if(s.equals("d.cellcreation")) {
d = new IDDimension();
} else {
ZZCacheDimension dim = new ZZCacheDimension(readonly);
dim.setUndoList(ul);
InputStream is = strs.getInputStream(s);
if(strs.exists(s)) {
SimpleDimFile inf = new SimpleDimFile();
inf.startRead(dim);
GZZ0 rea = new GZZ0(strs, s);
rea.read(inf, maxtimestamp);
inf.endRead();
}
d = dim;
}
d.setSpace(this);
return d;
}
public String getIDOrNull() {
Object o = ct.get("spaceid");
if (!(o instanceof String)) {
return null;
}
return (String)o;
}
public void setID(String id) {
if (readonly) throw new ZZError("readonly space");
ct.put("spaceid", id);
}
public StringScroll getStringScroll() {
return getStringScroll("text");
}
public StringScroll getStringScroll(String name) {
StringScroll scr;
if((scr = (StringScroll)scrolls.get(name)) == null) {
Writable wr = strs.getWritable("STRSCR_"+name);
scr = new StringScroll(name, wr, readonly);
// XXX ???
Scroll.register(name, scr);
scrolls.put(name, scr);
}
return scr;
}
}

View File

@@ -0,0 +1,281 @@
/*
ZZCacheDimension.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.*;
/** Dimension-centric implementation of a locally
* cached dimension.
* This class may be used as a cache to
* a dimension stored on disk, and includes facilities for tracking
* the changes.
* XXX Look into replacing hashtable with a more memory-saving constructions?
* <p>
* This, uglily, shares some code with ZZLocalDimension but making
* this an inheritance relationship would have been difficult, and
* the point is to keep ZZLocalDimension a truly simple basic
* example implementation of a dimension.
* <p>
* The mechanism for the undolist is quite interesting:
* we save each connect / disconnect operation with the two cells,
* so we know the inverse of each operation.
* We can then, at commit time, build a hash table by taking the first
* operation and seeing if it cancels an earlier operation (undolist does
* commits in reverse order) and if it does, we do nothing.
* This allows the user to move the cursor without wasting storage on all
* positions.
* Interestingly, although we store all connections bidirectionally as
* connect/disconnect pairs in the undolist, we cannot save them like that
* after compression: they must be saved as single-sided disconnects and
* pair connects.
*/
public class ZZCacheDimension extends ZZDimension implements ZZDimStorer {
public static final String rcsid = "$Id: ZZCacheDimension.java,v 1.11 2001/02/23 08:33:37 ajk Exp $";
public static final boolean dbg = true;
final static void p(String s) { if(dbg) System.out.println(s); }
final static void pa(String s) { System.out.println(s); }
UndoList undo;
public void setUndoList(UndoList l) { undo = l; }
protected boolean readonly;
public ZZCacheDimension() { this(false); }
public ZZCacheDimension(boolean readonly) {
this.readonly = readonly;
}
/** Connections to the positive direction. */
Hashtable cp = new Hashtable();
/** Connections to the negative direction. */
Hashtable cm = new Hashtable();
/** The earlier connection on each cell's poswards or negwards
* direction at commit time.
* This list is created at commit time by reversing all operations
* so we can then compare these values and the current values to
* see which have changed.
* Hmm.. do we really even need comm?
*/
Hashtable comp;
Hashtable comm;
/** A null marker for the hashtables. */
static final Object nolla = new Object();
synchronized public void startCommit() {
if (readonly) throw new ZZError("readonly dimension");
comp = new Hashtable();
comm = new Hashtable();
}
synchronized public void endCommit(ZZDimStorer sto) {
if (readonly) throw new ZZError("readonly dimension");
for(Enumeration e = comp.keys();
e.hasMoreElements();) {
String id = (String)e.nextElement();
Object oidto = comp.get(id);
String idto = (oidto == nolla ? null : (String)oidto);
String idwasto = (String)cp.get(id);
// If it's the same, then nevermind.
if(idto == idwasto || (
idto != null && idto.equals(idwasto)))
continue;
if(idwasto != null)
sto.storeConnect(id, idwasto);
else
sto.storeDisconnect(id, 1);
}
for(Enumeration e = comm.keys();
e.hasMoreElements();) {
String id = (String)e.nextElement();
Object oidto = comm.get(id);
String idto = (oidto == nolla ? null : (String)oidto);
String idwasto = (String)cm.get(id);
// If it's the same, then nevermind.
if(idto == idwasto || (
idto != null && idto.equals(idwasto)))
continue;
if(idwasto == null)
sto.storeDisconnect(id, -1);
// Not here: we only call connect once.
// else
// sto.connect(id, -1, idto);
}
comp = null;
comm = null;
}
ZZCellHandle ch(Object o) {
if(o instanceof ZZCellHandle) return (ZZCellHandle)o;
return (ZZCellHandle)space.getCellByID((String)o);
}
String cid(Object o) {
if(o instanceof ZZCellHandle) return ((ZZCellHandle)o).id;
return (String)o;
}
/** The abstracted operation of connecting two cells.
* Parameters: cell1 cell2.
* The cells are explicitly assumed to be not connected before
* this.
*/
protected class Connect implements UndoList.Op {
public void undo(Object[] list, int nth) {
String c1 = (String)list[nth+1];
String c2 = (String)list[nth+2];
if(!s((ZZCellHandle)space.getCellByID(c1), 1, null).id.equals(c2))
throw new ZZError(
"Error when undoing change: disconnect assertion broken");
cp.remove(c1);
cm.remove(c2);
triggers.chg(c1);
triggers.chg(c2);
}
public void redo(Object[] list, int nth) {
String c1 = (String)list[nth+1];
String c2 = (String)list[nth+2];
if(cp.get(c1) != null ||
cm.get(c2) != null)
throw new ZZError(
"Error when redoing change: unconnected assertion broken");
cp.put(c1, c2);
cm.put(c2, c1);
triggers.chg(c1);
triggers.chg(c2);
}
public void commit(Object[] list, int nth) {
String c1 = (String)list[nth+1];
String c2 = (String)list[nth+2];
comp.put(c1, nolla);
comm.put(c2, nolla);
}
}
/** The abstracted operation of disconnecting two cells.
* Parameters: cell1 cell2.
*/
protected class Disconnect implements UndoList.Op {
public void undo(Object[] list, int nth) {
String c1 = (String)list[nth+1];
String c2 = (String)list[nth+2];
// Note we can't use disconnect() since that would make
// new undolist entries.
if(cp.get(c1) != null ||
cm.get(c2) != null)
throw new ZZError(
"Error when undoing change: unconnected assertion broken");
cp.put(c1, c2);
cm.put(c2, c1);
triggers.chg(c1);
triggers.chg(c2);
}
public void redo(Object[] list, int nth) {
String c1 = (String)list[nth+1];
String c2 = (String)list[nth+2];
if(!s((ZZCellHandle)space.getCellByID(c1), 1, null).id.equals(c2))
throw new ZZError(
"Error when redoing change: disconnect assertion broken");
cp.remove(c1);
cm.remove(c2);
triggers.chg(c1);
triggers.chg(c2);
}
public void commit(Object[] list, int nth) {
String c1 = (String)list[nth+1];
String c2 = (String)list[nth+2];
comp.put(c1, c2);
comm.put(c2, c1);
}
}
Connect myconnect = new Connect();
Disconnect mydisconnect = new Disconnect();
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
String s = c.id;
if(o != null) triggers.addObs(s, o);
if(steps>0)
while(steps-- > 0 && s != null) {
s = (String)cp.get(s);
if(o != null && s!=null) triggers.addObs(s, o);
}
else
while(steps++ < 0 && s != null) {
s = (String)cm.get(s);
if(o != null && s!=null) triggers.addObs(s, o);
}
if(s==null) return null;
return (ZZCellHandle)space.getCellByID(s);
}
public void connect(ZZCellHandle c0, ZZCellHandle d0) {
if (readonly) throw new ZZError("readonly dimension");
String c = c0.id;
String d = d0.id;
disconnect(c0, 1);
disconnect(d0, -1);
cp.put(c, d);
cm.put(d, c);
undo.add(myconnect, c, d);
triggers.chg(c);
triggers.chg(d);
}
public void disconnect(ZZCellHandle c0, int dir) {
if (readonly) throw new ZZError("readonly dimension");
String c = c0.id;
String o;
if(dir>0) {
o = (String)cp.get(c);
if(o!=null) {
undo.add(mydisconnect, c, o);
cp.remove(c);
cm.remove(o);
}
} else {
o = (String)cm.get(c);
if(o!=null) {
undo.add(mydisconnect, o, c);
cm.remove(c);
cp.remove(o);
}
}
triggers.chg(c);
if(o!=null) triggers.chg(o);
}
// ZZDimStorer implementation
public void storeConnect(String a, String b) {
cp.put(a, b);
cm.put(b, a);
}
public void storeDisconnect(String a, int dir) {
Hashtable h = (dir > 0 ? cp : cm);
h.remove(a);
}
}

View File

@@ -0,0 +1,47 @@
/*
ZZDimStorer.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.awt.*;
import java.util.*;
import java.io.*;
/** A simple interface between persistent and temporary storage.
* This class is used simply for transmitting information about
* connections.
* <p>
* The speciality of this class is that the operations need not make
* sense atomically: only the end result of several operations counts.
* So if a is connected to b, then connect(b, -, c), disconnect(a, +),
* is perfectly valid.
* All disconnections must be given in both directions; connects
* only once (that's why there's no dir there).
* <p>
* If the above seems unclear, just see how it's used and where
* it's not used: the class that is used for the on-line dims is ZZDimension.
*/
public interface ZZDimStorer {
String rcsid = "$Id: ZZDimStorer.java,v 1.4 2000/09/19 10:32:01 ajk Exp $";
void storeConnect(String a, String b);
void storeDisconnect(String a, int dir);
}