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

192 lines
4.7 KiB
Java

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