/*
* Copyright (C) 2009 JavaRosa
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.openrosa.client.jr.core.util.externalizable;
import java.io.IOException;
import org.openrosa.client.java.io.DataInputStream;
import org.openrosa.client.java.io.DataOutputStream;
public class ExtWrapIntEncodingSmall extends ExtWrapIntEncoding {
public static final int DEFAULT_BIAS = 1;
/* max magnitude of negative number encodable in one byte; allowed range [0,254]
* increasing this steals from the max positive range
* ex.: BIAS = 0 -> [0,254] will fit in one byte; all other values will overflow
* BIAS = 30 -> [-30,224]
* BIAS = 254 -> [-254,0]
*/
public int bias;
/* serialization */
public ExtWrapIntEncodingSmall (long l) {
this(l, DEFAULT_BIAS);
}
public ExtWrapIntEncodingSmall (long l, int bias) {
val = new Long(l);
this.bias = bias;
}
/* deserialization */
public ExtWrapIntEncodingSmall () {
this(null, DEFAULT_BIAS);
}
//need the garbage param or else it conflicts with (long) constructor
public ExtWrapIntEncodingSmall (Object ignore, int bias) {
this.bias = bias;
}
public ExternalizableWrapper clone(Object val) {
return new ExtWrapIntEncodingSmall(ExtUtil.toLong(val), bias);
}
public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOException {
byte b = in.readByte();
long l;
if (b == (byte)0xff) {
l = in.readInt();
} else {
l = (b < 0 ? b + 256 : b) - bias;
}
val = new Long(l);
}
/**
* serialize a numeric value, only using as many bytes as needed. splits up the value into
* chunks of 7 bits, using as many chunks as needed to unambiguously represent the value. each
* chunk is serialized as a single byte, where the most-significant bit is set to 1 to indicate
* there are more bytes to follow, or 0 to indicate the last byte
**/
public void writeExternal(DataOutputStream out) throws IOException {
int n = ExtUtil.toInt(((Long)val).longValue());
if (n >= -bias && n < 255 - bias) {
n += bias;
out.writeByte((byte)(n >= 128 ? n - 256 : n));
} else {
out.writeByte(0xff);
out.writeInt(n);
}
}
public void metaReadExternal(DataInputStream in, PrototypeFactory pf) throws IOException {
bias = in.readUnsignedByte();
}
public void metaWriteExternal(DataOutputStream out) throws IOException {
out.writeByte((byte)bias);
}
}