001: /**
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */package com.tc.util;
005:
006: import com.tc.bytes.TCByteBuffer;
007: import com.tc.exception.TCRuntimeException;
008:
009: import java.io.UnsupportedEncodingException;
010:
011: /**
012: * Data conversion algorithms and whatnot can be found in java.io.DataInput and java.io.DataOutput. Contains methods for
013: * converting from one kind of thing to another.
014: *
015: * @author orion
016: */
017: public class Conversion {
018:
019: public static final long MIN_UINT = 0;
020: public static final long MAX_UINT = 4294967295L; // 2^32 - 1
021:
022: private static int makeInt(byte b3, byte b2, byte b1, byte b0) {
023: return ((((b3 & 0xff) << 24) | ((b2 & 0xff) << 16)
024: | ((b1 & 0xff) << 8) | ((b0 & 0xff) << 0)));
025: }
026:
027: public static byte setFlag(byte flags, int offset, boolean value) {
028: if (value) {
029: return (byte) (flags | offset);
030: } else {
031: return (byte) (flags & ~offset);
032: }
033: }
034:
035: public static boolean getFlag(byte flags, int offset) {
036: return (flags & offset) == offset;
037: }
038:
039: /**
040: * Helper method to convert a byte to an unsigned int. Use me when you want to treat a java byte as unsigned
041: */
042: public static short byte2uint(byte b) {
043: return (short) (b & 0xFF);
044: }
045:
046: public static long bytes2uint(byte b[]) {
047: return bytes2uint(b, 0, b.length);
048: }
049:
050: public static long bytes2uint(byte b[], int length) {
051: return bytes2uint(b, 0, length);
052: }
053:
054: /**
055: * Helper method to convert 1-4 bytes (big-endiand) into an unsigned int (max: 2^32 -1)
056: */
057: public static long bytes2uint(byte b[], int offset, int length) {
058: if ((length < 1) || (length > 4)) {
059: throw new IllegalArgumentException(
060: "invalid byte array length: " + length);
061: }
062:
063: if ((b.length - offset) < length) {
064: throw new IllegalArgumentException(
065: "not enough data available for length " + length
066: + " starting at offset " + offset
067: + " in a byte array of length " + b.length);
068: }
069:
070: long rv = 0;
071:
072: switch (length) {
073: case 1: {
074: return byte2uint(b[offset]);
075: }
076: case 2: {
077: rv += ((long) byte2uint(b[0 + offset])) << 8;
078: rv += byte2uint(b[1 + offset]);
079: return rv;
080: }
081: case 3: {
082: rv += ((long) byte2uint(b[0 + offset])) << 16;
083: rv += ((long) byte2uint(b[1 + offset])) << 8;
084: rv += byte2uint(b[2 + offset]);
085: return rv;
086: }
087: case 4: {
088: rv += ((long) byte2uint(b[0 + offset])) << 24;
089: rv += ((long) byte2uint(b[1 + offset])) << 16;
090: rv += ((long) byte2uint(b[2 + offset])) << 8;
091: rv += byte2uint(b[3 + offset]);
092: return rv;
093: }
094: default: {
095: throw new RuntimeException("internal error");
096: }
097: }
098: }
099:
100: /**
101: * Helper method to write a 4 byte unsigned integer value into a given byte array at a given offset
102: *
103: * @param l the unsigned int value to write
104: * @param dest the byte array to write the uint into
105: * @param index starting offset into the destination byte array
106: */
107: public static void writeUint(long l, byte[] dest, int index) {
108: if ((l > MAX_UINT) || (l < 0)) {
109: throw new IllegalArgumentException(
110: "unsigned integer value invalid: " + l);
111: }
112:
113: int pos = index;
114:
115: dest[pos++] = (byte) ((l >>> 24) & 0x000000FF);
116: dest[pos++] = (byte) ((l >>> 16) & 0x000000FF);
117: dest[pos++] = (byte) ((l >>> 8) & 0x000000FF);
118: dest[pos++] = (byte) (l & 0x000000FF);
119:
120: return;
121: }
122:
123: /**
124: * Helper method to write a 4 byte java (signed) integer value into a given byte array at a given offset
125: *
126: * @param l the signed int value to write
127: * @param dest the byte array to write the uint into
128: * @param index starting offset into the destination byte array
129: */
130: public static void writeInt(int i, byte[] dest, int index) {
131: dest[index] = (byte) ((i >>> 24) & 0x000000FF);
132: dest[index + 1] = (byte) ((i >>> 16) & 0x000000FF);
133: dest[index + 2] = (byte) ((i >>> 8) & 0x000000FF);
134: dest[index + 3] = (byte) ((i >>> 0) & 0x000000FF);
135:
136: return;
137: }
138:
139: /**
140: * Helper method to convert an unsigned short to 2 bytes (big-endian)
141: */
142: public static byte[] ushort2bytes(int i) {
143: if ((i > 0xFFFF) || (i < 0)) {
144: throw new IllegalArgumentException("invalid short value: "
145: + i);
146: }
147:
148: byte[] rv = new byte[2];
149:
150: rv[0] = (byte) ((i >>> 8) & 0x000000FF);
151: rv[1] = (byte) ((i >>> 0) & 0x000000FF);
152:
153: return rv;
154: }
155:
156: /**
157: * Helper method to convert an unsigned integer to 4 bytes (big-endian)
158: */
159: public static byte[] uint2bytes(long l) {
160: if ((l > MAX_UINT) || (l < 0)) {
161: throw new IllegalArgumentException(
162: "unsigned integer value out of range: " + l);
163: }
164:
165: byte[] rv = new byte[4];
166:
167: rv[0] = (byte) ((l >>> 24) & 0x000000FF);
168: rv[1] = (byte) ((l >>> 16) & 0x000000FF);
169: rv[2] = (byte) ((l >>> 8) & 0x000000FF);
170: rv[3] = (byte) ((l >>> 0) & 0x000000FF);
171:
172: return rv;
173: }
174:
175: /**
176: * Helper method to convert a string to bytes in a safe way.
177: */
178: public static String bytes2String(byte[] bytes) {
179: try {
180: return new String(bytes, "UTF-8");
181: } catch (UnsupportedEncodingException e) {
182: throw new TCRuntimeException(e);
183: }
184: }
185:
186: /**
187: * Helper method to convert a string to bytes in a safe way.
188: */
189: public static byte[] string2Bytes(String string) {
190: try {
191: return (string == null) ? new byte[0] : string
192: .getBytes("UTF-8");
193: } catch (UnsupportedEncodingException e) {
194: throw new TCRuntimeException(e);
195: }
196: }
197:
198: public static boolean bytes2Boolean(byte[] bytes) {
199: return (bytes[0] != 0 ? true : false);
200: }
201:
202: public static byte[] boolean2Bytes(boolean v) {
203: byte[] rv = new byte[1];
204:
205: rv[0] = v ? (byte) 1 : (byte) 0;
206: return rv;
207: }
208:
209: public static byte[] byte2Bytes(byte v) {
210: return new byte[] { v };
211: }
212:
213: public static char bytes2Char(byte[] bytes) {
214: return (char) ((bytes[0] << 8) | (bytes[1] & 0xff));
215: }
216:
217: public static byte[] char2Bytes(char v) {
218: return new byte[] { (byte) (0xff & (v >> 8)), (byte) (0xff & v) };
219: }
220:
221: public static double bytes2Double(byte[] bytes) {
222: return Double.longBitsToDouble(Conversion.bytes2Long(bytes));
223: }
224:
225: public static byte[] double2Bytes(double l) {
226: return Conversion.long2Bytes(Double.doubleToLongBits(l));
227: }
228:
229: public static float bytes2Float(byte[] bytes) {
230: return Float.intBitsToFloat(Conversion.bytes2Int(bytes));
231: }
232:
233: public static byte[] float2Bytes(float l) {
234: return Conversion.int2Bytes(Float.floatToIntBits(l));
235: }
236:
237: public static int bytes2Int(byte[] bytes, int offset) {
238: return makeInt(bytes[offset], bytes[offset + 1],
239: bytes[offset + 2], bytes[offset + 3]);
240: }
241:
242: public static int bytes2Int(byte[] bytes) {
243: return makeInt(bytes[0], bytes[1], bytes[2], bytes[3]);
244: }
245:
246: public static byte[] int2Bytes(int v) {
247: byte[] rv = new byte[4];
248:
249: rv[0] = (byte) ((v >>> 24) & 0xFF);
250: rv[1] = (byte) ((v >>> 16) & 0xFF);
251: rv[2] = (byte) ((v >>> 8) & 0xFF);
252: rv[3] = (byte) ((v >>> 0) & 0xFF);
253:
254: return rv;
255: }
256:
257: public static long bytes2Long(byte[] bytes) {
258: return bytes2Long(bytes, 0);
259: }
260:
261: public static long bytes2Long(byte[] bytes, int offset) {
262:
263: return (((long) bytes[offset] << 56)
264: + ((long) (bytes[offset + 1] & 0xFF) << 48)
265: + ((long) (bytes[offset + 2] & 0xFF) << 40)
266: + ((long) (bytes[offset + 3] & 0xFF) << 32)
267: + ((long) (bytes[offset + 4] & 0xFF) << 24)
268: + ((bytes[offset + 5] & 0xFF) << 16)
269: + ((bytes[offset + 6] & 0xFF) << 8) + ((bytes[offset + 7] & 0xFF) << 0));
270: }
271:
272: public static byte[] long2Bytes(long l) {
273: byte[] rv = new byte[8];
274: writeLong(l, rv, 0);
275: return rv;
276: }
277:
278: public static void writeLong(long l, byte[] rv, int offset) {
279:
280: rv[offset] = (byte) (l >>> 56);
281: rv[offset + 1] = (byte) (l >>> 48);
282: rv[offset + 2] = (byte) (l >>> 40);
283: rv[offset + 3] = (byte) (l >>> 32);
284: rv[offset + 4] = (byte) (l >>> 24);
285: rv[offset + 5] = (byte) (l >>> 16);
286: rv[offset + 6] = (byte) (l >>> 8);
287: rv[offset + 7] = (byte) (l >>> 0);
288:
289: }
290:
291: public static short bytes2Short(byte[] bytes) {
292: short rv = (short) (((bytes[0] & 0xFF) << 8) + ((bytes[1] & 0xFF) << 0));
293: return rv;
294: }
295:
296: public static byte[] short2Bytes(short v) {
297: byte[] rv = new byte[2];
298:
299: rv[0] = (byte) ((v >>> 8) & 0xFF);
300: rv[1] = (byte) ((v >>> 0) & 0xFF);
301:
302: return rv;
303: }
304:
305: public static boolean byte2Boolean(byte b) {
306: return b != 0;
307: }
308:
309: /**
310: * @param value
311: */
312: public static byte boolean2Byte(boolean value) {
313: return (value) ? (byte) 1 : (byte) 0;
314: }
315:
316: /**
317: * Equivalent to calling <code>bytesToHex(b, 0, b.length)</code>.
318: */
319: public static String bytesToHex(byte[] b) {
320: return bytesToHex(b, 0, b.length);
321: }
322:
323: /**
324: * Converts a single byte to a hex string representation, can be decoded with Byte.parseByte().
325: *
326: * @param b the byte to encode
327: * @return a
328: */
329: public static String bytesToHex(byte[] b, int index, int length) {
330: StringBuffer buf = new StringBuffer();
331: byte leading, trailing;
332: for (int pos = index; pos >= 0 && pos < index + length
333: && pos < b.length; ++pos) {
334: leading = (byte) ((b[pos] >>> 4) & 0x0f);
335: trailing = (byte) (b[pos] & 0x0f);
336: buf
337: .append((0 <= leading) && (leading <= 9) ? (char) ('0' + leading)
338: : (char) ('A' + (leading - 10)));
339: buf
340: .append((0 <= trailing) && (trailing <= 9) ? (char) ('0' + trailing)
341: : (char) ('A' + (trailing - 10)));
342: }
343: return buf.toString();
344: }
345:
346: /**
347: * @param hexString
348: * @return an array of bytes, decoded from the hex-encoded string, if <code>hexString</code> is <code>null</code>
349: * or the length is not a multiple of two then <code>null</code> is returned.
350: */
351: public static byte[] hexToBytes(String hexString) {
352: if (hexString == null || hexString.length() % 2 != 0) {
353: return null;
354: }
355: int length = hexString.length();
356: byte rv[] = new byte[length / 2];
357: int x, y;
358: for (x = 0, y = 0; x < length; x += 2, ++y) {
359: rv[y] = Byte.parseByte(hexString.substring(x, x + 2), 16);
360: }
361: return rv;
362: }
363:
364: public static String buffer2String(int length, TCByteBuffer buffer) {
365: byte[] bytes = new byte[length];
366: buffer.get(bytes);
367: return Conversion.bytes2String(bytes);
368: }
369: }
|