/src/main/java/com/logicartisan/pcap/util/ByteArrays.java

https://bitbucket.org/robeden/pcap4j-optimized · Java · 823 lines · 495 code · 71 blank · 257 comment · 91 complexity · 8a0c42a34e9d2d113f98077209c2aea1 MD5 · raw file

  1. /*_##########################################################################
  2. _##
  3. _## Copyright (C) 2011 Kaito Yamada
  4. _##
  5. _##########################################################################
  6. */
  7. package com.logicartisan.pcap.util;
  8. import static java.nio.ByteOrder.*;
  9. import java.net.Inet4Address;
  10. import java.net.Inet6Address;
  11. import java.net.InetAddress;
  12. import java.net.UnknownHostException;
  13. import java.nio.ByteOrder;
  14. import java.util.regex.Pattern;
  15. /**
  16. * @author Kaito Yamada
  17. * @since pcap4j 0.9.1
  18. */
  19. public final class ByteArrays {
  20. /**
  21. *
  22. */
  23. public static final int BYTE_SIZE_IN_BYTES = 1;
  24. /**
  25. *
  26. */
  27. public static final int SHORT_SIZE_IN_BYTES = 2;
  28. /**
  29. *
  30. */
  31. public static final int INT_SIZE_IN_BYTES = 4;
  32. /**
  33. *
  34. */
  35. public static final int LONG_SIZE_IN_BYTES = 8;
  36. /**
  37. *
  38. */
  39. public static final int INET4_ADDRESS_SIZE_IN_BYTES = 4;
  40. /**
  41. *
  42. */
  43. public static final int INET6_ADDRESS_SIZE_IN_BYTES = 16;
  44. /**
  45. *
  46. */
  47. public static final int BYTE_SIZE_IN_BITS = 8;
  48. private static final Pattern NO_SEPARATOR_HEX_STRING_PATTERN
  49. = Pattern.compile("\\A([0-9a-fA-F][0-9a-fA-F])+\\z");
  50. private ByteArrays() { throw new AssertionError(); }
  51. /**
  52. *
  53. * @param array
  54. * @return a new array containing specified array's elements in reverse order.
  55. */
  56. public static byte[] reverse(byte[] array) {
  57. byte[] rarray = new byte[array.length];
  58. for (int i = 0; i < array.length; i++) {
  59. rarray[i] = array[array.length - i - 1];
  60. }
  61. return rarray;
  62. }
  63. /**
  64. *
  65. * @param array
  66. * @param offset
  67. * @return byte value.
  68. */
  69. public static byte getByte(byte[] array, int offset) {
  70. if (array == null) {
  71. throw new NullPointerException("array may not be null");
  72. }
  73. if (offset < 0 || offset + BYTE_SIZE_IN_BYTES > array.length) {
  74. StringBuilder sb = new StringBuilder(100);
  75. sb.append("array: ").append(toHexString(array, " "))
  76. .append(" offset: ").append(offset);
  77. throw new ArrayIndexOutOfBoundsException(sb.toString());
  78. }
  79. return array[offset];
  80. }
  81. /**
  82. *
  83. * @param value
  84. * @return byte array
  85. */
  86. public static byte[] toByteArray(byte value) {
  87. return new byte[] { value };
  88. }
  89. /**
  90. *
  91. * @param value
  92. * @param separator
  93. * @return hex string
  94. */
  95. public static String toHexString(byte value, String separator) {
  96. return toHexString(toByteArray(value), separator);
  97. }
  98. /**
  99. *
  100. * @param array
  101. * @param offset
  102. * @return short value
  103. */
  104. public static short getShort(byte[] array, int offset) {
  105. return getShort(array, offset, ByteOrder.BIG_ENDIAN);
  106. }
  107. /**
  108. *
  109. * @param array
  110. * @param offset
  111. * @param bo
  112. * @return short value
  113. */
  114. public static short getShort(byte[] array, int offset, ByteOrder bo) {
  115. if (array == null || bo == null) {
  116. StringBuilder sb = new StringBuilder(40);
  117. sb.append("array: ").append(array)
  118. .append(" bo: ").append(bo);
  119. throw new NullPointerException(sb.toString());
  120. }
  121. if (offset < 0 || offset + SHORT_SIZE_IN_BYTES > array.length) {
  122. StringBuilder sb = new StringBuilder(100);
  123. sb.append("array: ").append(toHexString(array, " "))
  124. .append(" offset: ").append(offset)
  125. .append(" bo: ").append(bo);
  126. throw new ArrayIndexOutOfBoundsException(sb.toString());
  127. }
  128. if (bo.equals(LITTLE_ENDIAN)) {
  129. return (short)(
  130. (( array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1))
  131. | ((0xFF & array[offset ]) )
  132. );
  133. }
  134. else {
  135. return (short)(
  136. (( array[offset ]) << (BYTE_SIZE_IN_BITS * 1))
  137. | ((0xFF & array[offset + 1]) )
  138. );
  139. }
  140. }
  141. /**
  142. *
  143. * @param value
  144. * @return byte array
  145. */
  146. public static byte[] toByteArray(short value) {
  147. return toByteArray(value, ByteOrder.BIG_ENDIAN);
  148. }
  149. /**
  150. *
  151. * @param value
  152. * @param bo
  153. * @return byte array
  154. */
  155. public static byte[] toByteArray(short value, ByteOrder bo) {
  156. if (bo.equals(LITTLE_ENDIAN)) {
  157. return new byte[] {
  158. (byte)(value ),
  159. (byte)(value >> BYTE_SIZE_IN_BITS * 1)
  160. };
  161. }
  162. else {
  163. return new byte[] {
  164. (byte)(value >> BYTE_SIZE_IN_BITS * 1),
  165. (byte)(value )
  166. };
  167. }
  168. }
  169. /**
  170. *
  171. * @param value
  172. * @param separator
  173. * @return hex string
  174. */
  175. public static String toHexString(short value, String separator) {
  176. return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
  177. }
  178. /**
  179. *
  180. * @param value
  181. * @param separator
  182. * @param bo
  183. * @return hex string
  184. */
  185. public static String toHexString(short value, String separator, ByteOrder bo) {
  186. return toHexString(toByteArray(value, bo), separator);
  187. }
  188. /**
  189. *
  190. * @param array
  191. * @param offset
  192. * @return int value.
  193. */
  194. public static int getInt(byte[] array, int offset) {
  195. return getInt(array, offset, ByteOrder.BIG_ENDIAN);
  196. }
  197. /**
  198. *
  199. * @param array
  200. * @param offset
  201. * @param bo
  202. * @return int value.
  203. */
  204. public static int getInt(byte[] array, int offset, ByteOrder bo) {
  205. if (array == null || bo == null) {
  206. StringBuilder sb = new StringBuilder(40);
  207. sb.append("array: ").append(array)
  208. .append(" bo: ").append(bo);
  209. throw new NullPointerException(sb.toString());
  210. }
  211. if (offset < 0 || offset + INT_SIZE_IN_BYTES > array.length) {
  212. StringBuilder sb = new StringBuilder(100);
  213. sb.append("array: ").append(toHexString(array, " "))
  214. .append(" offset: ").append(offset)
  215. .append(" bo: ").append(bo);
  216. throw new ArrayIndexOutOfBoundsException(sb.toString());
  217. }
  218. if (bo.equals(LITTLE_ENDIAN)) {
  219. return (int)(
  220. (( array[offset + 3]) << (BYTE_SIZE_IN_BITS * 3))
  221. | ((0xFF & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 2))
  222. | ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1))
  223. | ((0xFF & array[offset ]) )
  224. );
  225. }
  226. else {
  227. return (int)(
  228. (( array[offset ]) << (BYTE_SIZE_IN_BITS * 3))
  229. | ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 2))
  230. | ((0xFF & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 1))
  231. | ((0xFF & array[offset + 3]) )
  232. );
  233. }
  234. }
  235. /**
  236. *
  237. * @param value
  238. * @return byte array
  239. */
  240. public static byte[] toByteArray(int value) {
  241. return toByteArray(value, ByteOrder.BIG_ENDIAN);
  242. }
  243. /**
  244. *
  245. * @param value
  246. * @param bo
  247. * @return byte array
  248. */
  249. public static byte[] toByteArray(int value, ByteOrder bo) {
  250. if (bo.equals(LITTLE_ENDIAN)) {
  251. return new byte[] {
  252. (byte)(value ),
  253. (byte)(value >> BYTE_SIZE_IN_BITS * 1),
  254. (byte)(value >> BYTE_SIZE_IN_BITS * 2),
  255. (byte)(value >> BYTE_SIZE_IN_BITS * 3),
  256. };
  257. }
  258. else {
  259. return new byte[] {
  260. (byte)(value >> BYTE_SIZE_IN_BITS * 3),
  261. (byte)(value >> BYTE_SIZE_IN_BITS * 2),
  262. (byte)(value >> BYTE_SIZE_IN_BITS * 1),
  263. (byte)(value )
  264. };
  265. }
  266. }
  267. /**
  268. *
  269. * @param value
  270. * @param separator
  271. * @return hex string
  272. */
  273. public static String toHexString(int value, String separator) {
  274. return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
  275. }
  276. /**
  277. *
  278. * @param value
  279. * @param separator
  280. * @param bo
  281. * @return hex string
  282. */
  283. public static String toHexString(int value, String separator, ByteOrder bo) {
  284. return toHexString(toByteArray(value, bo), separator);
  285. }
  286. /**
  287. *
  288. * @param array
  289. * @param offset
  290. * @return long value
  291. */
  292. public static long getLong(byte[] array, int offset) {
  293. return getLong(array, offset, ByteOrder.BIG_ENDIAN);
  294. }
  295. /**
  296. *
  297. * @param array
  298. * @param offset
  299. * @param bo
  300. * @return long value
  301. */
  302. public static long getLong(byte[] array, int offset, ByteOrder bo) {
  303. if (array == null || bo == null) {
  304. StringBuilder sb = new StringBuilder(40);
  305. sb.append("array: ").append(array)
  306. .append(" bo: ").append(bo);
  307. throw new NullPointerException(sb.toString());
  308. }
  309. if (offset < 0 || offset + LONG_SIZE_IN_BYTES > array.length) {
  310. StringBuilder sb = new StringBuilder(100);
  311. sb.append("array: ").append(toHexString(array, " "))
  312. .append(" offset: ").append(offset)
  313. .append(" bo: ").append(bo);
  314. throw new ArrayIndexOutOfBoundsException(sb.toString());
  315. }
  316. if (bo.equals(LITTLE_ENDIAN)) {
  317. return (long)(
  318. (( (long)array[offset + 7]) << (BYTE_SIZE_IN_BITS * 7))
  319. | ((0xFFL & (long)array[offset + 6]) << (BYTE_SIZE_IN_BITS * 6))
  320. | ((0xFFL & (long)array[offset + 5]) << (BYTE_SIZE_IN_BITS * 5))
  321. | ((0xFFL & (long)array[offset + 4]) << (BYTE_SIZE_IN_BITS * 4))
  322. | ((0xFFL & (long)array[offset + 3]) << (BYTE_SIZE_IN_BITS * 3))
  323. | ((0xFFL & (long)array[offset + 2]) << (BYTE_SIZE_IN_BITS * 2))
  324. | ((0xFFL & (long)array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1))
  325. | ((0xFFL & (long)array[offset ]) )
  326. );
  327. }
  328. else {
  329. return (long)(
  330. (( (long)array[offset ]) << (BYTE_SIZE_IN_BITS * 7))
  331. | ((0xFFL & (long)array[offset + 1]) << (BYTE_SIZE_IN_BITS * 6))
  332. | ((0xFFL & (long)array[offset + 2]) << (BYTE_SIZE_IN_BITS * 5))
  333. | ((0xFFL & (long)array[offset + 3]) << (BYTE_SIZE_IN_BITS * 4))
  334. | ((0xFFL & (long)array[offset + 4]) << (BYTE_SIZE_IN_BITS * 3))
  335. | ((0xFFL & (long)array[offset + 5]) << (BYTE_SIZE_IN_BITS * 2))
  336. | ((0xFFL & (long)array[offset + 6]) << (BYTE_SIZE_IN_BITS * 1))
  337. | ((0xFFL & (long)array[offset + 7]) )
  338. );
  339. }
  340. }
  341. /**
  342. *
  343. * @param value
  344. * @return byte array
  345. */
  346. public static byte[] toByteArray(long value) {
  347. return toByteArray(value, ByteOrder.BIG_ENDIAN);
  348. }
  349. /**
  350. *
  351. * @param value
  352. * @param bo
  353. * @return byte array
  354. */
  355. public static byte[] toByteArray(long value, ByteOrder bo) {
  356. if (bo.equals(LITTLE_ENDIAN)) {
  357. return new byte[] {
  358. (byte)(value ),
  359. (byte)(value >> BYTE_SIZE_IN_BITS * 1),
  360. (byte)(value >> BYTE_SIZE_IN_BITS * 2),
  361. (byte)(value >> BYTE_SIZE_IN_BITS * 3),
  362. (byte)(value >> BYTE_SIZE_IN_BITS * 4),
  363. (byte)(value >> BYTE_SIZE_IN_BITS * 5),
  364. (byte)(value >> BYTE_SIZE_IN_BITS * 6),
  365. (byte)(value >> BYTE_SIZE_IN_BITS * 7)
  366. };
  367. }
  368. else {
  369. return new byte[] {
  370. (byte)(value >> BYTE_SIZE_IN_BITS * 7),
  371. (byte)(value >> BYTE_SIZE_IN_BITS * 6),
  372. (byte)(value >> BYTE_SIZE_IN_BITS * 5),
  373. (byte)(value >> BYTE_SIZE_IN_BITS * 4),
  374. (byte)(value >> BYTE_SIZE_IN_BITS * 3),
  375. (byte)(value >> BYTE_SIZE_IN_BITS * 2),
  376. (byte)(value >> BYTE_SIZE_IN_BITS * 1),
  377. (byte)(value )
  378. };
  379. }
  380. }
  381. /**
  382. *
  383. * @param value
  384. * @param separator
  385. * @return hex string
  386. */
  387. public static String toHexString(long value, String separator) {
  388. return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
  389. }
  390. /**
  391. *
  392. * @param value
  393. * @param separator
  394. * @param bo
  395. * @return hex string
  396. */
  397. public static String toHexString(long value, String separator, ByteOrder bo) {
  398. return toHexString(toByteArray(value, bo), separator);
  399. }
  400. /**
  401. *
  402. * @param array
  403. * @param offset
  404. * @return a new MacAddress object.
  405. */
  406. public static MacAddress getMacAddress(byte[] array, int offset) {
  407. return getMacAddress(array, offset, ByteOrder.BIG_ENDIAN);
  408. }
  409. /**
  410. *
  411. * @param array
  412. * @param offset
  413. * @param bo
  414. * @return a new MacAddress object.
  415. */
  416. public static MacAddress getMacAddress(
  417. byte[] array, int offset, ByteOrder bo
  418. ) {
  419. if (array == null || bo == null) {
  420. StringBuilder sb = new StringBuilder(40);
  421. sb.append("array: ").append(array)
  422. .append(" bo: ").append(bo);
  423. throw new NullPointerException(sb.toString());
  424. }
  425. if (offset < 0 || offset + MacAddress.SIZE_IN_BYTES > array.length) {
  426. StringBuilder sb = new StringBuilder(100);
  427. sb.append("array: ").append(toHexString(array, " "))
  428. .append(" offset: ").append(offset)
  429. .append(" bo: ").append(bo);
  430. throw new ArrayIndexOutOfBoundsException(sb.toString());
  431. }
  432. if (bo.equals(LITTLE_ENDIAN)) {
  433. return MacAddress.getByAddress(
  434. reverse(getSubArray(array, offset, MacAddress.SIZE_IN_BYTES))
  435. );
  436. }
  437. else {
  438. return MacAddress.getByAddress(
  439. getSubArray(array, offset, MacAddress.SIZE_IN_BYTES)
  440. );
  441. }
  442. }
  443. /**
  444. *
  445. * @param value
  446. * @return byte array
  447. */
  448. public static byte[] toByteArray(MacAddress value) {
  449. return toByteArray(value, ByteOrder.BIG_ENDIAN);
  450. }
  451. /**
  452. *
  453. * @param value
  454. * @param bo
  455. * @return byte array
  456. */
  457. public static byte[] toByteArray(MacAddress value, ByteOrder bo) {
  458. if (bo.equals(LITTLE_ENDIAN)) {
  459. return reverse(value.getAddress());
  460. }
  461. else {
  462. return value.getAddress();
  463. }
  464. }
  465. /**
  466. *
  467. * @param array
  468. * @param offset
  469. * @return a new Inet4Address object.
  470. */
  471. public static Inet4Address getInet4Address(byte[] array, int offset) {
  472. return getInet4Address(array, offset, ByteOrder.BIG_ENDIAN);
  473. }
  474. /**
  475. *
  476. * @param array
  477. * @param offset
  478. * @param bo
  479. * @return a new Inet4Address object.
  480. */
  481. public static Inet4Address getInet4Address(
  482. byte[] array, int offset, ByteOrder bo
  483. ) {
  484. if (array == null || bo == null) {
  485. StringBuilder sb = new StringBuilder(40);
  486. sb.append("array: ").append(array)
  487. .append(" bo: ").append(bo);
  488. throw new NullPointerException(sb.toString());
  489. }
  490. if (offset < 0 || offset + INET4_ADDRESS_SIZE_IN_BYTES > array.length) {
  491. StringBuilder sb = new StringBuilder(50);
  492. sb.append("array: ").append(toHexString(array, " "))
  493. .append(" offset: ").append(offset)
  494. .append(" bo: ").append(bo);
  495. throw new ArrayIndexOutOfBoundsException(sb.toString());
  496. }
  497. try {
  498. if (bo.equals(LITTLE_ENDIAN)) {
  499. return (Inet4Address)InetAddress.getByAddress(
  500. reverse(
  501. getSubArray(
  502. array,
  503. offset,
  504. INET4_ADDRESS_SIZE_IN_BYTES
  505. )
  506. )
  507. );
  508. }
  509. else {
  510. return (Inet4Address)InetAddress.getByAddress(
  511. getSubArray(
  512. array,
  513. offset,
  514. INET4_ADDRESS_SIZE_IN_BYTES
  515. )
  516. );
  517. }
  518. } catch (UnknownHostException e) {
  519. throw new AssertionError(e);
  520. }
  521. }
  522. /**
  523. *
  524. * @param array
  525. * @param offset
  526. * @return a new Inet6Address object.
  527. */
  528. public static Inet6Address getInet6Address(byte[] array, int offset) {
  529. return getInet6Address(array, offset, ByteOrder.BIG_ENDIAN);
  530. }
  531. /**
  532. *
  533. * @param array
  534. * @param offset
  535. * @param bo
  536. * @return a new Inet6Address object.
  537. */
  538. public static Inet6Address getInet6Address(
  539. byte[] array, int offset, ByteOrder bo
  540. ) {
  541. if (array == null || bo == null) {
  542. StringBuilder sb = new StringBuilder(40);
  543. sb.append("array: ").append(array)
  544. .append(" bo: ").append(bo);
  545. throw new NullPointerException(sb.toString());
  546. }
  547. if (offset < 0 || offset + INET6_ADDRESS_SIZE_IN_BYTES > array.length) {
  548. StringBuilder sb = new StringBuilder(50);
  549. sb.append("array: ").append(toHexString(array, " "))
  550. .append(" offset: ").append(offset)
  551. .append(" bo: ").append(bo);
  552. throw new ArrayIndexOutOfBoundsException(sb.toString());
  553. }
  554. try {
  555. if (bo.equals(LITTLE_ENDIAN)) {
  556. return (Inet6Address)InetAddress.getByAddress(
  557. reverse(
  558. getSubArray(
  559. array,
  560. offset,
  561. INET6_ADDRESS_SIZE_IN_BYTES
  562. )
  563. )
  564. );
  565. }
  566. else {
  567. return (Inet6Address)InetAddress.getByAddress(
  568. getSubArray(
  569. array,
  570. offset,
  571. INET6_ADDRESS_SIZE_IN_BYTES
  572. )
  573. );
  574. }
  575. } catch (UnknownHostException e) {
  576. throw new AssertionError(e);
  577. }
  578. }
  579. /**
  580. *
  581. * @param value
  582. * @return byte array
  583. */
  584. public static byte[] toByteArray(InetAddress value) {
  585. return toByteArray(value, ByteOrder.BIG_ENDIAN);
  586. }
  587. /**
  588. *
  589. * @param value
  590. * @param bo
  591. * @return byte array
  592. */
  593. public static byte[] toByteArray(InetAddress value, ByteOrder bo) {
  594. if (bo.equals(LITTLE_ENDIAN)) {
  595. return reverse(value.getAddress());
  596. }
  597. else {
  598. return value.getAddress();
  599. }
  600. }
  601. /**
  602. *
  603. * @param array
  604. * @param offset
  605. * @param length
  606. * @return sub array
  607. */
  608. public static byte[] getSubArray(byte[] array, int offset, int length) {
  609. if (array == null) {
  610. throw new NullPointerException("array may not be null");
  611. }
  612. if (offset < 0 || length < 0 || offset + length > array.length) {
  613. StringBuilder sb = new StringBuilder(50);
  614. sb.append("array: ").append(toHexString(array, " "))
  615. .append(" offset: ").append(offset)
  616. .append(" length: ").append(length);
  617. throw new ArrayIndexOutOfBoundsException(sb.toString());
  618. }
  619. byte[] subArray = new byte[length];
  620. System.arraycopy(array, offset, subArray, 0, length);
  621. return subArray;
  622. }
  623. /**
  624. *
  625. * @param array
  626. * @param separator
  627. * @return hex string
  628. */
  629. public static String toHexString(byte[] array, String separator) {
  630. StringBuffer buf = new StringBuffer();
  631. for (int i = 0; i < array.length; i++) {
  632. buf.append(String.format("%02x", array[i]));
  633. buf.append(separator);
  634. }
  635. if (separator.length() != 0 && array.length > 0) {
  636. buf.delete(buf.lastIndexOf(separator), buf.length());
  637. }
  638. return buf.toString();
  639. }
  640. /**
  641. *
  642. * @param array
  643. * @param separator
  644. * @param offset
  645. * @param length
  646. * @return hex string
  647. */
  648. public static String toHexString(
  649. byte[] array, String separator, int offset, int length
  650. ) {
  651. if (offset < 0 || length < 0 || offset + length > array.length) {
  652. StringBuilder sb = new StringBuilder(100);
  653. sb.append("array: ").append(toHexString(array, " "))
  654. .append(" offset: ").append(offset)
  655. .append(" length: ").append(length);
  656. throw new ArrayIndexOutOfBoundsException(sb.toString());
  657. }
  658. StringBuffer buf = new StringBuffer();
  659. for (int i = offset; i < offset + length; i++) {
  660. buf.append(String.format("%02x", array[i]));
  661. buf.append(separator);
  662. }
  663. if (separator.length() != 0 && length > 0) {
  664. buf.delete(buf.lastIndexOf(separator), buf.length());
  665. }
  666. return buf.toString();
  667. }
  668. /**
  669. *
  670. * @param data
  671. * @return checksum
  672. */
  673. public static short calcChecksum(byte[] data) {
  674. int sum = 0;
  675. for (int i = 0; i < data.length; i += SHORT_SIZE_IN_BYTES) {
  676. sum += (0xFFFF) & getShort(data, i);
  677. }
  678. sum
  679. = (0xFFFF & sum)
  680. + ((0xFFFF0000 & sum) >> (BYTE_SIZE_IN_BITS * SHORT_SIZE_IN_BYTES));
  681. sum
  682. = (0xFFFF & sum)
  683. + ((0xFFFF0000 & sum) >> (BYTE_SIZE_IN_BITS * SHORT_SIZE_IN_BYTES));
  684. return (short)(0xFFFF & ~sum);
  685. }
  686. /**
  687. *
  688. * @param hexString
  689. * @param separator
  690. * @return a new byte array.
  691. */
  692. public static byte[] parseByteArray(String hexString, String separator) {
  693. if (
  694. hexString == null
  695. || separator == null
  696. ) {
  697. StringBuilder sb = new StringBuilder();
  698. sb.append("hexString: ")
  699. .append(hexString)
  700. .append(" separator: ")
  701. .append(separator);
  702. throw new NullPointerException(sb.toString());
  703. }
  704. if (hexString.startsWith("0x")) {
  705. hexString = hexString.substring(2);
  706. }
  707. String noSeparatorHexString;
  708. if (separator.length() == 0) {
  709. if (
  710. !NO_SEPARATOR_HEX_STRING_PATTERN.matcher(hexString).matches()
  711. ) {
  712. StringBuilder sb = new StringBuilder(100);
  713. sb.append("invalid hex string(")
  714. .append(hexString)
  715. .append("), not match pattern(")
  716. .append(NO_SEPARATOR_HEX_STRING_PATTERN.pattern())
  717. .append(")");
  718. throw new IllegalArgumentException(sb.toString());
  719. }
  720. noSeparatorHexString = hexString;
  721. }
  722. else {
  723. StringBuilder patternSb = new StringBuilder(60);
  724. patternSb.append("\\A[0-9a-fA-F][0-9a-fA-F](")
  725. .append(Pattern.quote(separator))
  726. .append("[0-9a-fA-F][0-9a-fA-F])*\\z");
  727. String patternString = patternSb.toString();
  728. Pattern pattern = Pattern.compile(patternString);
  729. if (!pattern.matcher(hexString).matches()) {
  730. StringBuilder sb = new StringBuilder(150);
  731. sb.append("invalid hex string(")
  732. .append(hexString)
  733. .append("), not match pattern(")
  734. .append(patternString)
  735. .append(")");
  736. throw new IllegalArgumentException(sb.toString());
  737. }
  738. noSeparatorHexString
  739. = hexString.replaceAll(Pattern.quote(separator), "");
  740. }
  741. int arrayLength = noSeparatorHexString.length() / 2;
  742. byte[] array = new byte[arrayLength];
  743. for (int i = 0; i < arrayLength; i++) {
  744. array[i]
  745. = (byte)Integer.parseInt(
  746. noSeparatorHexString.substring(i * 2, i * 2 + 2),
  747. 16
  748. );
  749. }
  750. return array;
  751. }
  752. }