Added support for streaming arrays of streamables; extracted the efficient
streamable serialization code from PolyStreamableList and made it generally available; modified the StreamableArrayList to support heterogenous lists (because they don't have much more overhead than homogenous lists now) which allows us to remove PolyStreamableList entirely. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1140 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: StreamableUtil.java,v 1.1 2001/12/03 23:48:38 mdb Exp $
|
||||
// $Id: StreamableUtil.java,v 1.2 2002/03/20 22:58:26 mdb Exp $
|
||||
|
||||
package com.threerings.presents.io;
|
||||
|
||||
@@ -7,6 +7,11 @@ import java.io.IOException;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import com.samskivert.io.NestableIOException;
|
||||
import com.samskivert.util.ListUtil;
|
||||
|
||||
/**
|
||||
* Utility functions useful for {@link Streamable} implementations.
|
||||
*/
|
||||
@@ -67,4 +72,118 @@ public class StreamableUtil
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the supplied streamable array to the data output stream. The
|
||||
* array cannot be null, but can be of zero length.
|
||||
*/
|
||||
public static void writeStreamables (
|
||||
DataOutputStream out, Streamable[] values)
|
||||
throws IOException
|
||||
{
|
||||
// create a list used to map class names to class ids
|
||||
Object[] cnames = new Object[DEFAULT_SIZE];
|
||||
|
||||
// seed it with the component type of the array (which we write
|
||||
// out first so that we can recreate the array on the other side)
|
||||
String cname = values.getClass().getComponentType().getName();
|
||||
cnames[0] = cname;
|
||||
out.writeUTF(cname);
|
||||
|
||||
// write out the size of the list
|
||||
int size = (values == null) ? 0 : values.length;
|
||||
out.writeInt(size);
|
||||
|
||||
// write out each of the list elements
|
||||
short nextIdx = 1;
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
// get the next streamable to write out
|
||||
Streamable s = values[ii];
|
||||
|
||||
// look up the class id
|
||||
cname = s.getClass().getName();
|
||||
short cidx = (short)ListUtil.indexOfEqual(cnames, cname);
|
||||
if (cidx == -1) {
|
||||
// store this class name to class id mapping
|
||||
cidx = nextIdx++;
|
||||
cnames = ListUtil.add(cnames, cidx, cname);
|
||||
|
||||
// write out the class id and class name
|
||||
out.writeShort(cidx);
|
||||
out.writeUTF(cname);
|
||||
|
||||
} else {
|
||||
// we need only write out the class id
|
||||
out.writeShort(cidx);
|
||||
}
|
||||
|
||||
// write out the object itself
|
||||
s.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an array of streamables from the data input stream that was
|
||||
* previously written via {@link #writeStreamables}.
|
||||
*/
|
||||
public static Streamable[] readStreamables (DataInputStream in)
|
||||
throws IOException
|
||||
{
|
||||
// read in the component type and array size
|
||||
String ctype = in.readUTF();
|
||||
int size = in.readInt();
|
||||
Streamable[] values = null;
|
||||
|
||||
// create the target array
|
||||
try {
|
||||
values = (Streamable[])
|
||||
Array.newInstance(Class.forName(ctype), size);
|
||||
} catch (Exception e) {
|
||||
String errmsg = "Unable to instantiate streamable array " +
|
||||
"[ctype=" + ctype + "]";
|
||||
throw new NestableIOException(errmsg, e);
|
||||
}
|
||||
|
||||
// create a list used to map class ids to class names
|
||||
Object[] cnames = new Object[DEFAULT_SIZE];
|
||||
// seed our class names with the component type
|
||||
cnames[0] = ctype;
|
||||
|
||||
// read in each of the list elements
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
// read the class id number
|
||||
short cidx = in.readShort();
|
||||
|
||||
// look up the class name
|
||||
String cname = (cidx > cnames.length - 1) ? null :
|
||||
(String)cnames[cidx];
|
||||
if (cname == null) {
|
||||
// store this class id to class name mapping
|
||||
cname = in.readUTF();
|
||||
cnames = ListUtil.add(cnames, cidx, cname);
|
||||
}
|
||||
|
||||
try {
|
||||
// instantiate the streamable object
|
||||
Class clazz = Class.forName(cname);
|
||||
Streamable s = (Streamable)clazz.newInstance();
|
||||
// read in the object itself
|
||||
s.readFrom(in);
|
||||
// and add it to the list
|
||||
values[ii] = s;
|
||||
|
||||
} catch (Exception e) {
|
||||
String errmsg = "Error instantiating streamable array " +
|
||||
"element [ctype=" + ctype + ", index=" + ii +
|
||||
", etype=" + cname + "]";
|
||||
throw new NestableIOException(errmsg, e);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/** The default size of the class name lists used when serializing or
|
||||
* unserializing the list. */
|
||||
protected static final int DEFAULT_SIZE = 8;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user