/** * @throws IllegalArgumentException if variable-length value does not terminate * after 5 bytes have been read * @throws IOException if {@link DataInput} throws {@link IOException} * @see #readSignedVarLong(DataInput) */ public static int readSignedVarInt(DataInput in) throws IOException { int raw = readUnsignedVarInt(in); // This undoes the trick in writeSignedVarInt() int temp = (((raw << 31) >> 31) ^ raw) >> 1; // This extra step lets us deal with the largest signed values by treating // negative results from read unsigned methods as like unsigned values. // Must re-flip the top bit if the original read value had it set. return temp ^ (raw & (1 << 31)); }
/** * @see #writeSignedVarLong(long, DataOutput) */ public static void writeSignedVarInt(int value, DataOutput out) throws IOException { // Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types writeUnsignedVarInt((value << 1) ^ (value >> 31), out); }
/** * Encodes a value using the variable-length encoding from * <a href="http://code.google.com/apis/protocolbuffers/docs/encoding.html"> * Google Protocol Buffers</a>. It uses zig-zag encoding to efficiently * encode signed values. If values are known to be nonnegative, * {@link #writeUnsignedVarLong(long, DataOutput)} should be used. * * @param value value to encode * @param out to write bytes to * @throws IOException if {@link DataOutput} throws {@link IOException} */ public static void writeSignedVarLong(long value, DataOutput out) throws IOException { // Great trick from http://code.google.com/apis/protocolbuffers/docs/encoding.html#types writeUnsignedVarLong((value << 1) ^ (value >> 63), out); }
/** * @param in to read bytes from * @return decode value * @throws IOException if {@link DataInput} throws {@link IOException} * @throws IllegalArgumentException if variable-length value does not terminate * after 9 bytes have been read * @see #writeSignedVarLong(long, DataOutput) */ public static long readSignedVarLong(DataInput in) throws IOException { long raw = readUnsignedVarLong(in); // This undoes the trick in writeSignedVarLong() long temp = (((raw << 63) >> 63) ^ raw) >> 1; // This extra step lets us deal with the largest signed values by treating // negative results from read unsigned methods as like unsigned values // Must re-flip the top bit if the original read value had it set. return temp ^ (raw & (1L << 63)); }