/* * Mojito Distributed Hash Table (Mojito DHT) * Copyright (C) 2006-2007 LimeWire LLC * * 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ package org.limewire.mojito.util; import java.io.UnsupportedEncodingException; /** * Miscellaneous utilities for Arrays. */ public final class ArrayUtils { private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private static final String[] BIN = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" }; private ArrayUtils() {} /** * Returns data as a HEX String. */ public static String toHexString(byte[] data) { return toHexString(data, 0, data.length, -1); } /** * Returns data as a HEX String and inserts new lines * every wrapAtColumn. */ public static String toHexString(byte[] data, int wrapAtColumn) { return toHexString(data, 0, data.length, wrapAtColumn); } /** * Returns data as a hex encoded String. */ public static String toHexString(byte[] data, int offset, int length) { return toHexString(data, offset, length, -1); } /** * Returns data as a hex encoded String. */ public static String toHexString(byte[] data, int offset, int length, int wrapAtColumn) { int end = offset+length; if (offset < 0 || length < 0 || end > data.length) { throw new IllegalArgumentException("offset=" + offset + ", length=" + length); } StringBuilder buffer = new StringBuilder(length * 2); int column = 0; for(int i = offset; i < end; i++) { if (wrapAtColumn > 0 && column > wrapAtColumn) { buffer.append("\n"); column = 0; } buffer.append(HEX[(data[i] >> 4) & 0xF]).append(HEX[data[i] & 0xF]); column += 2; } return buffer.toString(); } /** * Returns data as BIN String. */ public static String toBinString(byte[] data) { return toBinString(data, 0, data.length, -1); } /** * Returns data as BIN String and inserts new lines * every wrapAtColumn. */ public static String toBinString(byte[] data, int wrapAtColumn) { return toBinString(data, 0, data.length, wrapAtColumn); } /** * Returns data as a binary encoded String. */ public static String toBinString(byte[] data, int offset, int length) { return toBinString(data, offset, length, -1); } /** * Returns data as a binary encoded String. */ public static String toBinString(byte[] data, int offset, int length, int wrapAtColumn) { int end = offset+length; if (offset < 0 || length < 0 || end > data.length) { throw new IllegalArgumentException("offset=" + offset + ", length=" + length); } StringBuilder buffer = new StringBuilder(length * 8); int column = 0; for(int i = offset; i < end; i++) { if (wrapAtColumn > 0 && column >= wrapAtColumn) { buffer.append("\n"); column = 0; } buffer.append(BIN[(data[i] >> 4) & 0xF]).append(BIN[data[i] & 0xF]).append(" "); column += 9; } if (buffer.length() > 0) { buffer.setLength(buffer.length()-1); } return buffer.toString(); } /** * Converts a HEX String to a byte value. */ public static byte[] parseHexString(String data) { if (data.length() % 2 != 0) { data = "0" + data; } byte[] buffer = new byte[data.length()/2]; for(int i = 0, j = 0; i < buffer.length; i++) { int hi = parseHexChar(data.charAt(j++)); int lo = parseHexChar(data.charAt(j++)); buffer[i] = (byte)(((hi & 0xF) << 4) | (lo & 0xF)); } return buffer; } private static int parseHexChar(char c) { switch(c) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; case 'a': return 10; case 'A': return 10; case 'b': return 11; case 'B': return 11; case 'c': return 12; case 'C': return 12; case 'd': return 13; case 'D': return 13; case 'e': return 14; case 'E': return 14; case 'f': return 15; case 'F': return 15; default: throw new NumberFormatException("Unknown digit: " + c); } } /** * A helper method to convert a 4 character ASCII String * into an integer. */ public static int toInteger(String ascii) { if (ascii == null) { throw new NullPointerException("String is null"); } char[] chars = ascii.toCharArray(); if (chars.length != 4) { throw new IllegalArgumentException("String must be 4 characters long"); } int id = 0; for(char c : chars) { id = (id << 8) | (c & 0xFF); } return id; } /** * A helper method to convert each of vendorId's 4 bytes * into an ASCII character and to return them as String. */ public static String toString(int num) { try { byte[] name = new byte[]{ (byte)((num >> 24) & 0xFF), (byte)((num >> 16) & 0xFF), (byte)((num >> 8) & 0xFF), (byte)((num ) & 0xFF) }; return new String(name, "ISO-8859-1"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } }