All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.util.Bits Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 33.0.2.Final
Show newest version
package org.jgroups.util;

import org.jgroups.Global;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Class (similar to java.nio.Bits) containing helper methods to encode variables (e.g. ints, long, List<Address> etc)
 * to memory (byte buffer) or output streams and read variables from memory or input streams.
 * 

* The write methods write a type (e.g. an int or a char) to a buffer ({@link ByteBuffer} or output stream, using * variable-length encoding. If * there are not enough byte in the buffer to write a type, a {@link java.nio.BufferOverflowException} is thrown. * If the variable cannot be written to the output stream, an IOException is thrown. *

* The read methods read a variable-length encoded type from a buffer or input stream. If there are fewer bytes in * the buffer than needed to read the type, a {@link java.nio.BufferUnderflowException} is thrown. If the read fails, * an IOException is thrown. *

* The size() methods return the number of bytes used to encode the given type with variable-length encoding. *

* There are additional helper methods to write/read custom JGroups types, e.g. address lists, Views etc *

* Note that methods to read/write atomic types (char, int etc) should only be used if variable-length encoding is * desired; otherwise {@link DataOutput#writeInt(int)} or {@link ByteBuffer#putInt(int)} should be used instead. *

* At the time of writing this (Feb 2014), most methods have not yet been implemented. * @author Bela Ban * @author Sanne Grinovero * @since 3.5 */ public class Bits { // -------------------- byte ------------------------ // /* public static int readUnsignedByte(ByteBuffer buf) { return 0; } public static int readUnsignedByte(DataInput in) throws IOException { return 0; }*/ // -------------------- char ------------------------ // /** * Writes a char to a ByteBuffer * @param ch the character to be written * @param buf the buffer */ public static void writeChar(char ch, ByteBuffer buf) { } /** * Writes a char to an output stream * @param ch the character to be written * @param out the output stream */ public static void writeChar(char ch, DataOutput out) throws IOException { } /** * Reads a char from a buffer. * @param buf the buffer * @return the character read from the buffer */ public static char readChar(ByteBuffer buf) { return 0; } /** * Reads a char from an input stream * @param in the input stream * @return the character read from the input stream */ public static char readChar(DataInput in) throws IOException { return 0; } /** * Computes the size of a variable-length encoded character * @param ch the character * @return the number of bytes needed to variable-length encode the char */ public static int size(char ch) { return 0; } // -------------------- short ----------------------- // /** * Writes a short to a ByteBuffer * @param num the short to be written * @param buf the buffer */ public static void writeShort(short num, ByteBuffer buf) { } /** * Writes a short to an output stream * @param num the short to be written * @param out the output stream */ public static void writeShort(short num, DataOutput out) throws IOException { } /** * Reads a short from a buffer. * @param buf the buffer * @return the short read from the buffer */ public static short readShort(ByteBuffer buf) { return 0; } /** * Reads a short from an input stream * @param in the input stream * @return the short read from the input stream */ public static short readShort(DataInput in) throws IOException { return 0; } /** * Reads an unsigned short from a buffer. * @param buf the buffer * @return the short read from the buffer */ public static int readUnsignedShort(ByteBuffer buf) { return 0; } /** * Reads an unsigned short from an input stream * @param in the input stream * @return the short read from the input stream */ public static int readUnsignedShort(DataInput in) throws IOException { return 0; } /** * Computes the size of a variable-length encoded short * @param num the short * @return the number of bytes needed to variable-length encode num */ public static int size(short num) { return 0; } public static short makeShort(byte a, byte b) { return (short)((a << 8) | (b & 0xff)); } public static short makeShort(byte a) { return (short) (a & 0xff); } // --------------------- int ------------------------ // /** * Writes an int to a ByteBuffer * @param num the int to be written * @param buf the buffer */ public static void writeInt(int num, ByteBuffer buf) { } /** * Writes an int to an output stream * @param num the int to be written * @param out the output stream */ public static void writeInt(int num, DataOutput out) throws IOException { if(num == 0) { out.write(0); return; } final byte bytes_needed=bytesRequiredFor(num); out.write(bytes_needed); for(int i=0; i < bytes_needed; i++) out.write(getByteAt(num, i)); } /** * Reads an int from a buffer. * @param buf the buffer * @return the int read from the buffer */ public static int readInt(ByteBuffer buf) { return 0; } /** * Reads an int from an input stream * @param in the input stream * @return the int read from the input stream */ public static int readInt(DataInput in) throws IOException { byte len=in.readByte(); if(len == 0) return 0; byte[] buf=new byte[len]; in.readFully(buf, 0, len); return makeInt(buf, 0, len); } /** * Computes the size of a variable-length encoded int * @param num the int * @return the number of bytes needed to variable-length encode num */ public static int size(int num) { return (byte)(num == 0? 1 : bytesRequiredFor(num) +1); } // -------------------- long ------------------------ // /** * Writes a long to a ByteBuffer * @param num the long to be written * @param buf the buffer */ public static void writeLong(long num, ByteBuffer buf) { } /** * Writes a long to out in variable-length encoding. Note that currently variable-length encoding is not * used (a similar mechanism is used); this will be implemented later. * @param num the long * @param out the output stream to write num to * @throws IOException */ public static void writeLong(final long num, final DataOutput out) throws IOException { if(num == 0) { out.write(0); return; } final byte bytes_needed=bytesRequiredFor(num); out.write(bytes_needed); for(int i=0; i < bytes_needed; i++) out.write(getByteAt(num, i)); } /** * Reads a long from a buffer. * @param buf the buffer * @return the long read from the buffer */ public static long readLong(ByteBuffer buf) { return 0; } /** * Reads a variable-length encoded long from an input stream. Note that currently variable-length encoding is not * used (a similar mechanism is used); this will be implemented later. * @param in the input stream * @return the long read from the input stream * @throws IOException */ public static long readLong(DataInput in) throws IOException { byte len=in.readByte(); if(len == 0) return 0; byte[] buf=new byte[len]; in.readFully(buf, 0, len); return makeLong(buf, 0, len); } /** * Computes the size of a variable-length encoded long. Note that this is not currently using * variable-length encoding (will be implemented later). * @param num the long * @return the number of bytes needed to variable-length encode num */ public static int size(long num) { return (byte)(num == 0? 1 : bytesRequiredFor(num) +1); } // ------------------ long seq ---------------------- // /** * Writes 2 sequence numbers (seqnos) in compressed format to buf. * The seqnos are non-negative and hr is guaranteed to be >= hd. *

* Once variable-length encoding has been implemented, this method will probably get dropped as we can simply * write the 2 longs individually. * @param hd the highest delivered seqno. Guaranteed to be a positive number * @param hr the highest received seqno. Guaranteed to be a positive number. Greater than or equal to hd * @param buf the buffer to write to */ public static void writeLongSequence(long hd, long hr, ByteBuffer buf) { } /** * Writes 2 sequence numbers (seqnos) in compressed format to an output stream. * The seqnos are non-negative and hr is guaranteed to be >= hd. *

* Once variable-length encoding has been implemented, this method will probably get dropped as we can simply * write the 2 longs individually. * @param hd the highest delivered seqno. Guaranteed to be a positive number * @param hr the highest received seqno. Guaranteed to be a positive number. Greater than or equal to hd * @param out the output stream to write to */ public static void writeLongSequence(long hd, long hr, DataOutput out) throws IOException { if(hr < hd) throw new IllegalArgumentException("hr (" + hr + ") has to be >= hd (" + hd + ")"); if(hd == 0 && hr == 0) { out.write(0); return; } long delta=hr - hd; // encode highest_delivered followed by delta byte bytes_for_hd=bytesRequiredFor(hd), bytes_for_delta=bytesRequiredFor(delta); byte bytes_needed=encodeLength(bytes_for_hd, bytes_for_delta); out.write(bytes_needed); for(int i=0; i < bytes_for_hd; i++) out.write(getByteAt(hd, i)); for(int i=0; i < bytes_for_delta; i++) out.write(getByteAt(delta, i)); } /** * Reads 2 compressed longs from buf. *

* Once variable-length encoding has been implemented, this method will probably get dropped as we can simply * read the 2 longs individually. * @param buf the buffer to read from * @return an array of 2 longs (hd and hr) */ public static long[] readLongSequence(ByteBuffer buf) { return null; } /** * Reads 2 compressed longs from in. * Reads 2 compressed longs from buf. *

* Once variable-length encoding has been implemented, this method will probably get dropped as we can simply * read the 2 longs individually. * @param in the input stream to read from * @return an array of 2 longs (hd and hr) */ public static long[] readLongSequence(DataInput in) throws IOException { byte len=in.readByte(); if(len == 0) return new long[]{0,0}; byte[] lengths=decodeLength(len); long[] seqnos=new long[2]; byte[] buf=new byte[lengths[0] + lengths[1]]; in.readFully(buf, 0, buf.length); seqnos[0]=makeLong(buf, 0, lengths[0]); seqnos[1]=makeLong(buf, lengths[0], lengths[1]) + seqnos[0]; return seqnos; } public static byte size(long hd, long hr) { if(hd == 0 && hr == 0) return 1; byte num_bytes_for_hd=bytesRequiredFor(hd), num_bytes_for_delta=bytesRequiredFor(hr - hd); return (byte)(num_bytes_for_hd + num_bytes_for_delta + 1); } public static long makeLong(byte[] buf, int offset, int bytes_to_read) { long retval=0; for(int i=0; i < bytes_to_read; i++) { byte b=buf[offset + i]; retval |= ((long)b & 0xff) << (i * 8); } return retval; } public static int makeInt(byte[] buf, int offset, int bytes_to_read) { int retval=0; for(int i=0; i < bytes_to_read; i++) { byte b=buf[offset + i]; retval |= ((int)b & 0xff) << (i * 8); } return retval; } // -------------------- float ----------------------- // /** * Writes a float to a ByteBuffer * @param num the float to be written * @param buf the buffer */ public static void writeFloat(float num, ByteBuffer buf) { } /** * Writes a float to an output stream * @param num the float to be written * @param out the output stream */ public static void writeFloat(float num, DataOutput out) throws IOException { } /** * Reads a a float from a buffer. * @param buf the buffer * @return the float read from the buffer */ public static float readFloat(ByteBuffer buf) { return 0; } /** * Reads a a float from an input stream. * @param in the input stream * @return the float read from the input stream */ public static float readFloat(DataInput in) throws IOException { return 0; } /** * Computes the size of a variable-length encoded float * @param num the float * @return the number of bytes needed to variable-length encode num */ public static int size(float num) { return 0; } // -------------------- double ---------------------- // /** * Writes a double to a ByteBuffer * @param num the double to be written * @param buf the buffer */ public static void writeDouble(double num, ByteBuffer buf) { } /** * Writes a double to an output stream * @param num the double to be written * @param out the output stream */ public static void writeDouble(double num, DataOutput out) throws IOException { } /** * Reads a double from a buffer. * @param buf the buffer * @return the double read from the buffer */ public static double readDouble(ByteBuffer buf) { return 0; } /** * Reads a double from an input stream * @param in the input stream * @return the double read from the input stream */ public static double readDouble(DataInput in) throws IOException { return 0; } /** * Computes the size of a variable-length encoded double * @param num the double * @return the number of bytes needed to variable-length encode num */ public static int size(double num) { return 0; } // -------------------- String ---------------------- // /** * Writes a string to buf. The length of the string is written first, followed by the chars (as single-byte values). * Multi-byte values are truncated: only the lower byte of each multi-byte char is written, similar to * {@link DataOutput#writeChars(String)}. * @param s the string * @param buf the buffer */ public static void writeString(String s, ByteBuffer buf) { } /** * Writes a string to buf. The length of the string is written first, followed by the chars (as single-byte values). * Multi-byte values are truncated: only the lower byte of each multi-byte char is written, similar to * {@link DataOutput#writeChars(String)}. * @param s the string * @param out the output stream */ public static void writeString(String s, DataOutput out) throws IOException { if(s != null) { out.write(1); out.writeUTF(s); } else { out.write(0); } } /** * Reads a string from buf. The length is read first, followed by the chars. Each char is a single byte * @param buf the buffer * @return the string read from buf */ public static String readString(ByteBuffer buf) { return null; } /** * Reads a string from buf. The length is read first, followed by the chars. Each char is a single byte * @param in the input stream * @return the string read from buf */ public static String readString(DataInput in) throws IOException { int b=in.readByte(); if(b == 1) return in.readUTF(); return null; } /** * Measures the number of bytes required to encode a string, taking multibyte characters into account. Measures * strings written by {@link DataOutput#writeUTF(String)}. * @param str the string * @return the number of bytes required for encoding str */ public static int sizeUTF(String str) { int len=str != null? str.length() : 0, utflen=2; if(len == 0) return utflen; for(int i = 0; i < len; i++) { int c=str.charAt(i); if((c >= 0x0001) && (c <= 0x007F)) utflen++; else if (c > 0x07FF) utflen += 3; else utflen += 2; } return utflen; } // ------------------ AsciiString ------------------- // /** * Writes an AsciiString to buf. The length of the string is written first, followed by the chars (as single-byte values). * @param s the string * @param buf the buffer */ public static void writeAsciiString(AsciiString s, ByteBuffer buf) { short length=(short)(s != null? s.length() : -1); buf.putShort(length); if(s != null) buf.put(s.chars()); } /** * Writes an AsciiString to buf. The length of the string is written first, followed by the chars (as single-byte values). * @param s the string * @param out the output stream */ public static void writeAsciiString(AsciiString s, DataOutput out) throws IOException { short length=(short)(s != null? s.length() : -1); out.writeShort(length); if(s != null) out.write(s.chars()); } /** * Reads an AsciiString from buf. The length is read first, followed by the chars. Each char is a single byte * @param buf the buffer * @return the string read from buf */ public static AsciiString readAsciiString(ByteBuffer buf) { short len=buf.getShort(); if(len < 0) return null; AsciiString retval=new AsciiString(len); buf.get(retval.chars()); return retval; } /** * Reads an AsciiString from buf. The length is read first, followed by the chars. Each char is a single byte * @param in the input stream * @return the string read from buf */ public static AsciiString readAsciiString(DataInput in) throws IOException { short len=in.readShort(); if(len < 0) return null; AsciiString retval=new AsciiString(len); in.readFully(retval.chars()); return retval; } /** * Measures the number of bytes required to encode an AsciiSring. * @param str the string * @return the number of bytes required for encoding str */ public static int size(AsciiString str) { return str == null? Global.SHORT_SIZE : Global.SHORT_SIZE + str.length(); } /** * Encodes the number of bytes needed into a single byte. The first number is encoded in the first nibble (the * first 4 bits), the second number in the second nibble * @param len1 The number of bytes needed to store a long. Must be between 0 and 8 * @param len2 The number of bytes needed to store a long. Must be between 0 and 8 * @return The byte storing the 2 numbers len1 and len2 */ protected static byte encodeLength(byte len1, byte len2) { byte retval=len2; retval |= (len1 << 4); return retval; } protected static byte[] decodeLength(byte len) { return new byte[]{(byte)((len & 0xff) >> 4),(byte)(len & ~0xf0)}; // 0xf0 is the first nibble set (11110000) } protected static byte bytesRequiredFor(long number) { if(number >> 56 != 0) return 8; if(number >> 48 != 0) return 7; if(number >> 40 != 0) return 6; if(number >> 32 != 0) return 5; if(number >> 24 != 0) return 4; if(number >> 16 != 0) return 3; if(number >> 8 != 0) return 2; return 1; } protected static byte bytesRequiredFor(int number) { if(number >> 24 != 0) return 4; if(number >> 16 != 0) return 3; if(number >> 8 != 0) return 2; return 1; } static protected byte getByteAt(long num, int index) { return (byte)((num >> (index * 8))); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy