HexUtils.java 9.9 KB

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