/**
* Fortika - Robust Group Communication
* Copyright (C) 2002-2006 Sergio Mena de la Cruz (EPFL) (sergio.mena@epfl.ch)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
// Transportable class for String
package framework.libraries.serialization;
import uka.transport.Transportable;
public class TString implements Transportable{
// Value
private char[] value;
//ORUTTI: the field below must be suppressed or updated upon unmarshalling or deepclone
// Otherwise, the function hashCode may be inconsistent with the function equals
// which result in bugs!
//private int length;
// Constructor
public TString(){
this.value = new char[0];
//this.length = 0;
}
public TString(String string){
this.value = string.toCharArray();
//this.length = this.value.length;
}
public TString(char[] value){
this.value = value;
//this.length = value.length;
}
// Cache the hash code for the string
private int hash; // Default to 0
public int hashCode() {
int h = hash;
int len = value.length;
if (h == 0 && len != 0) {
int off = 0;
char val[] = value;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof TString) {
TString str = (TString)obj;
int n = value.length;
if (n == str.value.length) {
char v1[] = value;
char v2[] = str.value;
int i = 0;
int j = 0;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
public int compareTo(Object obj){
throw new InternalError("TString not implementing compareTo");
}
public String toString(){
return new String(value);
}
/**
* Methods defined by the Transportable interface
*/
// Size of primitive fields
protected static final int _SIZE = uka.transport.BasicIO.SIZEOF_int; //value's length
// Length of char array
transient private int _length;
/** Used by uka.transport.UnmarshalStream to unmarshal the object */
public TString(uka.transport.UnmarshalStream _stream)
throws java.io.IOException, ClassNotFoundException
{
this(_stream, _SIZE);
_stream.accept(_SIZE);
}
protected TString(uka.transport.UnmarshalStream _stream, int _size)
throws java.io.IOException, ClassNotFoundException
{
_stream.request(_size);
byte[] _buffer = _stream.getBuffer();
int _pos = _stream.getPosition();
_length = uka.transport.BasicIO.extractInt(_buffer, _pos);
_pos += uka.transport.BasicIO.SIZEOF_int;
}
/** Method of interface Transportable, it must be declared public.
It is called from within UnmarshalStream after creating the
object and assigning a stream reference to it. */
public void unmarshalReferences(uka.transport.UnmarshalStream _stream)
throws java.io.IOException, ClassNotFoundException
{
//Extracting the char array
int _size = _length * uka.transport.BasicIO.SIZEOF_char;
if(_size > uka.transport.BasicIO.REQUEST_MAX){
//b is too big to be serialized as a primitive field
//value = (char[]) _stream.readObject();
value = new String((byte[]) _stream.readObject()).toCharArray();
// 20070831 Sergio: this change is due to "special" way that
// uka.transport treats array of chars, which limits the legnth
// to REQUEST_MAX_char... too bad :(
} else {
//b is small enough to be serialized as a primitive field
_stream.request(_size);
byte[] _buffer = _stream.getBuffer();
int _pos = _stream.getPosition();
value = new char[_length];
_pos = uka.transport.BasicIO.extract(_buffer, _pos, value);
_stream.accept(_size);
}
}
/** Called directly by uka.transport.MarshalStream */
public void marshal(uka.transport.MarshalStream _stream)
throws java.io.IOException
{
_stream.reserve(_SIZE);
byte[] _buffer = _stream.getBuffer();
int _pos = _stream.getPosition();
marshalPrimitives(_buffer, _pos);
_stream.deliver(_SIZE);
marshalReferences(_stream);
}
protected void marshalPrimitives(byte[] _buffer, int _pos)
throws java.io.IOException
{
_length = value.length;
_pos = uka.transport.BasicIO.insert(_buffer, _pos, _length);
}
protected void marshalReferences(uka.transport.MarshalStream _stream)
throws java.io.IOException
{
//Inserting the char array
int _size = _length * uka.transport.BasicIO.SIZEOF_char;
if(_size > uka.transport.BasicIO.REQUEST_MAX){
//b is too big to be serialized as a primitive field
//_stream.writeObject(value);
_stream.writeObject((new String(value)).getBytes());
// 20070831 Sergio: this change is due to "special" way that
// uka.transport treats array of chars, which limits the legnth
// to REQUEST_MAX_char... too bad :(
} else {
//b is small enough to be serialized as a primitive field
_stream.reserve(_size);
byte[] _buffer = _stream.getBuffer();
int _pos = _stream.getPosition();
_pos = uka.transport.BasicIO.insert(_buffer, _pos, value);
_stream.deliver(_size);
}
}
public final Object deepClone(uka.transport.DeepClone _helper)
throws CloneNotSupportedException
{
Object _copy = clone();
_helper.add(this, _copy);
((TString) _copy).deepCloneReferences(_helper);
return _copy;
}
/** Clone all references to other objects. Use the
DeepClone to resolve cycles */
protected void deepCloneReferences(uka.transport.DeepClone _helper)
throws CloneNotSupportedException
{
//Cloning the char array
this.value = _helper.doDeepClone(this.value);
//char[] value_clone = new char[this.value.length];
//System.arraycopy(this.value, 0, value_clone, 0, this.value.length);
//this.value = value_clone;
}
}