HexUtils.java 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package com.l2jserver.util;
  16. import java.util.Arrays;
  17. /**
  18. * @author FBIagent
  19. */
  20. public class HexUtils
  21. {
  22. // lookup table for hex characters
  23. private static final char[] _NIBBLE_CHAR_LOOKUP =
  24. {
  25. '0',
  26. '1',
  27. '2',
  28. '3',
  29. '4',
  30. '5',
  31. '6',
  32. '7',
  33. '8',
  34. '9',
  35. 'A',
  36. 'B',
  37. 'C',
  38. 'D',
  39. 'E',
  40. 'F'
  41. };
  42. private static final char[] _NEW_LINE_CHARS = System.getProperty("line.separator").toCharArray();
  43. /**
  44. * Method to generate the hexadecimal character presentation of a byte<br>
  45. * This call is equivalent to {@link HexUtils#b2HexChars(byte, char[], int)} with parameters (data, null, 0)
  46. * @param data byte to generate the hexadecimal character presentation from
  47. * @return a new char array with exactly 2 elements
  48. */
  49. public static char[] b2HexChars(final byte data)
  50. {
  51. return b2HexChars(data, null, 0);
  52. }
  53. /**
  54. * Method to generate the hexadecimal character presentation of a byte
  55. * @param data byte to generate the hexadecimal character presentation from
  56. * @param dstHexChars the char array the hexadecimal character presentation should be copied to, if this is null, dstOffset is ignored and a new char array with 2 elements is created
  57. * @param dstOffset offset at which the hexadecimal character presentation is copied to dstHexChars
  58. * @return the char array the hexadecimal character presentation was copied to
  59. */
  60. public static char[] b2HexChars(final byte data, char[] dstHexChars, int dstOffset)
  61. {
  62. if (dstHexChars == null)
  63. {
  64. dstHexChars = new char[2];
  65. dstOffset = 0;
  66. }
  67. // /////////////////////////////
  68. // NIBBLE LOOKUP
  69. dstHexChars[dstOffset] = _NIBBLE_CHAR_LOOKUP[(data & 0xF0) >> 4];
  70. dstHexChars[dstOffset + 1] = _NIBBLE_CHAR_LOOKUP[data & 0x0F];
  71. return dstHexChars;
  72. }
  73. /**
  74. * Method to generate the hexadecimal character presentation of an integer This call is equivalent to {@link HexUtils#int2HexChars(int, char[], int)} with parameters (data, null, 0)
  75. * @param data integer to generate the hexadecimal character presentation from
  76. * @return new char array with 8 elements
  77. */
  78. public static char[] int2HexChars(final int data)
  79. {
  80. return int2HexChars(data, new char[8], 0);
  81. }
  82. /**
  83. * Method to generate the hexadecimal character presentation of an integer
  84. * @param data integer to generate the hexadecimal character presentation from
  85. * @param dstHexChars the char array the hexadecimal character presentation should be copied to, if this is null, dstOffset is ignored and a new char array with 8 elements is created
  86. * @param dstOffset offset at which the hexadecimal character presentation is copied to dstHexChars
  87. * @return the char array the hexadecimal character presentation was copied to
  88. */
  89. public static char[] int2HexChars(final int data, char[] dstHexChars, int dstOffset)
  90. {
  91. if (dstHexChars == null)
  92. {
  93. dstHexChars = new char[8];
  94. dstOffset = 0;
  95. }
  96. b2HexChars((byte) ((data & 0xFF000000) >> 24), dstHexChars, dstOffset);
  97. b2HexChars((byte) ((data & 0x00FF0000) >> 16), dstHexChars, dstOffset + 2);
  98. b2HexChars((byte) ((data & 0x0000FF00) >> 8), dstHexChars, dstOffset + 4);
  99. b2HexChars((byte) (data & 0x000000FF), dstHexChars, dstOffset + 6);
  100. return dstHexChars;
  101. }
  102. /**
  103. * Method to generate the hexadecimal character presentation of a byte array<br>
  104. * This call is equivalent to {@link HexUtils#bArr2HexChars(byte[], int, int, char[], int)} with parameters (data, offset, len, null, 0)
  105. * @param data byte array to generate the hexadecimal character presentation from
  106. * @param offset offset where to start in data array
  107. * @param len number of bytes to generate the hexadecimal character presentation from
  108. * @return a new char array with len*2 elements
  109. */
  110. public static char[] bArr2HexChars(final byte[] data, final int offset, final int len)
  111. {
  112. return bArr2HexChars(data, offset, len, null, 0);
  113. }
  114. /**
  115. * Method to generate the hexadecimal character presentation of a byte array
  116. * @param data byte array to generate the hexadecimal character presentation from
  117. * @param offset offset where to start in data array
  118. * @param len number of bytes to generate the hexadecimal character presentation from
  119. * @param dstHexChars the char array the hexadecimal character presentation should be copied to, if this is null, dstOffset is ignored and a new char array with len*2 elements is created
  120. * @param dstOffset offset at which the hexadecimal character presentation is copied to dstHexChars
  121. * @return the char array the hexadecimal character presentation was copied to
  122. */
  123. public static char[] bArr2HexChars(final byte[] data, final int offset, final int len, char[] dstHexChars, int dstOffset)
  124. {
  125. if (dstHexChars == null)
  126. {
  127. dstHexChars = new char[len * 2];
  128. dstOffset = 0;
  129. }
  130. for (int dataIdx = offset, charsIdx = dstOffset; dataIdx < (len + offset); ++dataIdx, ++charsIdx)
  131. {
  132. // /////////////////////////////
  133. // NIBBLE LOOKUP, we duplicate the code from b2HexChars here, we want to save a few cycles(for charsIdx increment)
  134. dstHexChars[charsIdx] = _NIBBLE_CHAR_LOOKUP[(data[dataIdx] & 0xF0) >> 4];
  135. dstHexChars[++charsIdx] = _NIBBLE_CHAR_LOOKUP[data[dataIdx] & 0x0F];
  136. }
  137. return dstHexChars;
  138. }
  139. public static char[] bArr2AsciiChars(byte[] data, final int offset, final int len)
  140. {
  141. return bArr2AsciiChars(data, offset, len, new char[len], 0);
  142. }
  143. public static char[] bArr2AsciiChars(byte[] data, final int offset, final int len, char[] dstAsciiChars, int dstOffset)
  144. {
  145. if (dstAsciiChars == null)
  146. {
  147. dstAsciiChars = new char[len];
  148. dstOffset = 0;
  149. }
  150. for (int dataIdx = offset, charsIdx = dstOffset; dataIdx < (len + offset); ++dataIdx, ++charsIdx)
  151. {
  152. if ((data[dataIdx] > 0x1f) && (data[dataIdx] < 0x80))
  153. {
  154. dstAsciiChars[charsIdx] = (char) data[dataIdx];
  155. }
  156. else
  157. {
  158. dstAsciiChars[charsIdx] = '.';
  159. }
  160. }
  161. return dstAsciiChars;
  162. }
  163. private static final int _HEX_ED_BPL = 16;
  164. private static final int _HEX_ED_CPB = 2;
  165. /**
  166. * Method to generate the hexadecimal character representation of a byte array like in a hex editor<br>
  167. * Line Format: {OFFSET} {HEXADECIMAL} {ASCII}({NEWLINE})<br>
  168. * {OFFSET} = offset of the first byte in line(8 chars)<br>
  169. * {HEXADECIMAL} = hexadecimal character representation({@link #_HEX_ED_BPL}*2 chars)<br>
  170. * {ASCII} = ascii character presentation({@link #_HEX_ED_BPL} chars)
  171. * @param data byte array to generate the hexadecimal character representation
  172. * @param len the number of bytes to generate the hexadecimal character representation from
  173. * @return byte array which contains the hexadecimal character representation of the given byte array
  174. */
  175. public static char[] bArr2HexEdChars(byte[] data, int len)
  176. {
  177. // {OFFSET} {HEXADECIMAL} {ASCII}{NEWLINE}
  178. final int lineLength = 9 + (_HEX_ED_BPL * _HEX_ED_CPB) + 1 + _HEX_ED_BPL + _NEW_LINE_CHARS.length;
  179. final int lenBplMod = len % _HEX_ED_BPL;
  180. // create text buffer
  181. // 1. don't allocate a full last line if not _HEX_ED_BPL bytes are shown in last line
  182. // 2. no new line at end of buffer
  183. // BUG: when the length is multiple of _HEX_ED_BPL we erase the whole ascii space with this
  184. // char[] textData = new char[lineLength * numLines - (_HEX_ED_BPL - (len % _HEX_ED_BPL)) - _NEW_LINE_CHARS.length];
  185. // FIXED HERE
  186. int numLines;
  187. char[] textData;
  188. if (lenBplMod == 0)
  189. {
  190. numLines = len / _HEX_ED_BPL;
  191. textData = new char[(lineLength * numLines) - _NEW_LINE_CHARS.length];
  192. }
  193. else
  194. {
  195. numLines = (len / _HEX_ED_BPL) + 1;
  196. textData = new char[(lineLength * numLines) - (_HEX_ED_BPL - (lenBplMod)) - _NEW_LINE_CHARS.length];
  197. }
  198. // performance penalty, only doing space filling in the loop is faster
  199. // Arrays.fill(textData, ' ');
  200. int dataOffset;
  201. int dataLen;
  202. int lineStart;
  203. int lineHexDataStart;
  204. int lineAsciiDataStart;
  205. for (int i = 0; i < numLines; ++i)
  206. {
  207. dataOffset = i * _HEX_ED_BPL;
  208. dataLen = Math.min(len - dataOffset, _HEX_ED_BPL);
  209. lineStart = i * lineLength;
  210. lineHexDataStart = lineStart + 9;
  211. lineAsciiDataStart = lineHexDataStart + (_HEX_ED_BPL * _HEX_ED_CPB) + 1;
  212. int2HexChars(dataOffset, textData, lineStart); // the offset of this line
  213. textData[lineHexDataStart - 1] = ' '; // separate
  214. bArr2HexChars(data, dataOffset, dataLen, textData, lineHexDataStart); // the data in hex
  215. bArr2AsciiChars(data, dataOffset, dataLen, textData, lineAsciiDataStart); // the data in ascii
  216. if (i < (numLines - 1))
  217. {
  218. textData[lineAsciiDataStart - 1] = ' '; // separate
  219. System.arraycopy(_NEW_LINE_CHARS, 0, textData, lineAsciiDataStart + _HEX_ED_BPL, _NEW_LINE_CHARS.length); // the new line
  220. }
  221. else if (dataLen < _HEX_ED_BPL)
  222. {
  223. // last line which shows less than _HEX_ED_BPL bytes
  224. int lineHexDataEnd = lineHexDataStart + (dataLen * _HEX_ED_CPB);
  225. Arrays.fill(textData, lineHexDataEnd, lineHexDataEnd + ((_HEX_ED_BPL - dataLen) * _HEX_ED_CPB) + 1, ' '); // spaces, for the last line if there are not _HEX_ED_BPL bytes
  226. }
  227. else
  228. {
  229. // last line which shows _HEX_ED_BPL bytes
  230. textData[lineAsciiDataStart - 1] = ' '; // separate
  231. }
  232. }
  233. return textData;
  234. }
  235. }