Skip to content

Commit 2311c5e

Browse files
committed
[CODEC-259] Hex: consume all ByteBuffer.remaining() bytes.
1 parent a84f53d commit 2311c5e

2 files changed

Lines changed: 82 additions & 18 deletions

File tree

  • src
    • main/java/org/apache/commons/codec/binary
    • test/java/org/apache/commons/codec/binary

src/main/java/org/apache/commons/codec/binary/Hex.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ public static char[] encodeHex(final byte[] data) {
125125
* returned array will be double the length of the passed array, as it takes two characters to represent any given
126126
* byte.
127127
*
128+
* <p>All bytes identified by {@link ByteBuffer#remaining()} will be used; after this method
129+
* the value {@link ByteBuffer#remaining() remaining()} will be zero.</p>
130+
*
128131
* @param data a byte buffer to convert to Hex characters
129132
* @return A char[] containing lower-case hexadecimal characters
130133
* @since 1.11
@@ -152,6 +155,9 @@ public static char[] encodeHex(final byte[] data, final boolean toLowerCase) {
152155
* returned array will be double the length of the passed array, as it takes two characters to represent any given
153156
* byte.
154157
*
158+
* <p>All bytes identified by {@link ByteBuffer#remaining()} will be used; after this method
159+
* the value {@link ByteBuffer#remaining() remaining()} will be zero.</p>
160+
*
155161
* @param data a byte buffer to convert to Hex characters
156162
* @param toLowerCase <code>true</code> converts to lowercase, <code>false</code> to uppercase
157163
* @return A char[] containing hexadecimal characters in the selected case
@@ -188,6 +194,9 @@ protected static char[] encodeHex(final byte[] data, final char[] toDigits) {
188194
* returned array will be double the length of the passed array, as it takes two characters to represent any given
189195
* byte.
190196
*
197+
* <p>All bytes identified by {@link ByteBuffer#remaining()} will be used; after this method
198+
* the value {@link ByteBuffer#remaining() remaining()} will be zero.</p>
199+
*
191200
* @param byteBuffer a byte buffer to convert to Hex characters
192201
* @param toDigits the output alphabet (must be at least 16 characters)
193202
* @return A char[] containing the appropriate characters from the alphabet For best results, this should be either
@@ -227,6 +236,9 @@ public static String encodeHexString(final byte[] data, final boolean toLowerCas
227236
* Converts a byte buffer into a String representing the hexadecimal values of each byte in order. The returned
228237
* String will be double the length of the passed array, as it takes two characters to represent any given byte.
229238
*
239+
* <p>All bytes identified by {@link ByteBuffer#remaining()} will be used; after this method
240+
* the value {@link ByteBuffer#remaining() remaining()} will be zero.</p>
241+
*
230242
* @param data a byte buffer to convert to Hex characters
231243
* @return A String containing lower-case hexadecimal characters
232244
* @since 1.11
@@ -239,6 +251,9 @@ public static String encodeHexString(final ByteBuffer data) {
239251
* Converts a byte buffer into a String representing the hexadecimal values of each byte in order. The returned
240252
* String will be double the length of the passed array, as it takes two characters to represent any given byte.
241253
*
254+
* <p>All bytes identified by {@link ByteBuffer#remaining()} will be used; after this method
255+
* the value {@link ByteBuffer#remaining() remaining()} will be zero.</p>
256+
*
242257
* @param data a byte buffer to convert to Hex characters
243258
* @param toLowerCase <code>true</code> converts to lowercase, <code>false</code> to uppercase
244259
* @return A String containing lower-case hexadecimal characters
@@ -248,13 +263,20 @@ public static String encodeHexString(final ByteBuffer data, final boolean toLowe
248263
return new String(encodeHex(data, toLowerCase));
249264
}
250265

266+
/**
267+
* Convert the byte buffer to a a byte array. All bytes identified by
268+
* {@link ByteBuffer#remaining()} will be used.
269+
*
270+
* @param byteBuffer the byte buffer
271+
* @return the byte[]
272+
*/
251273
private static byte[] toByteArray(final ByteBuffer byteBuffer) {
252274
final int remaining = byteBuffer.remaining();
253275
// Use the underlying buffer if possible
254276
if (byteBuffer.hasArray()) {
255277
final byte[] byteArray = byteBuffer.array();
256278
if (remaining == byteArray.length) {
257-
//byteBuffer.position(remaining);
279+
byteBuffer.position(remaining);
258280
return byteArray;
259281
}
260282
}
@@ -332,6 +354,9 @@ public byte[] decode(final byte[] array) throws DecoderException {
332354
* The returned array will be half the length of the passed array, as it takes two characters to represent any given
333355
* byte. An exception is thrown if the passed char array has an odd number of elements.
334356
*
357+
* <p>All bytes identified by {@link ByteBuffer#remaining()} will be used; after this method
358+
* the value {@link ByteBuffer#remaining() remaining()} will be zero.</p>
359+
*
335360
* @param buffer An array of character bytes containing hexadecimal digits
336361
* @return A byte array containing binary data decoded from the supplied byte array (representing characters).
337362
* @throws DecoderException Thrown if an odd number of characters is supplied to this function
@@ -393,10 +418,12 @@ public byte[] encode(final byte[] array) {
393418
* Converts byte buffer into an array of bytes for the characters representing the hexadecimal values of each byte
394419
* in order. The returned array will be double the length of the passed array, as it takes two characters to
395420
* represent any given byte.
396-
* <p>
397-
* The conversion from hexadecimal characters to the returned bytes is performed with the charset named by
398-
* {@link #getCharset()}.
399-
* </p>
421+
*
422+
* <p>The conversion from hexadecimal characters to the returned bytes is performed with the charset named by
423+
* {@link #getCharset()}.</p>
424+
*
425+
* <p>All bytes identified by {@link ByteBuffer#remaining()} will be used; after this method
426+
* the value {@link ByteBuffer#remaining() remaining()} will be zero.</p>
400427
*
401428
* @param array a byte buffer to convert to Hex characters
402429
* @return A byte[] containing the bytes of the lower-case hexadecimal characters

src/test/java/org/apache/commons/codec/binary/HexTest.java

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ public void testDecodeByteBufferAllocatedButEmpty() throws DecoderException {
249249
// Effectively set remaining == 0 => empty
250250
bb.flip();
251251
assertTrue(Arrays.equals(new byte[0], new Hex().decode(bb)));
252+
assertEquals(0, bb.remaining());
252253
}
253254

254255
@Test
@@ -258,16 +259,19 @@ public void testDecodeByteBufferObjectEmpty() throws DecoderException {
258259

259260
@Test
260261
public void testDecodeByteBufferOddCharacters() {
261-
checkDecodeHexByteBufferOddCharacters(ByteBuffer.wrap(new byte[] { 65 }));
262+
final ByteBuffer bb = allocate(1);
263+
bb.put((byte) 65);
264+
bb.flip();
265+
checkDecodeHexByteBufferOddCharacters(bb);
262266
}
263267

264268
@Test
265269
public void testDecodeByteBufferWithLimitOddCharacters() {
266-
final ByteBuffer buffer = allocate(10);
267-
buffer.put(1, (byte) 65);
268-
buffer.position(1);
269-
buffer.limit(2);
270-
checkDecodeHexByteBufferOddCharacters(buffer);
270+
final ByteBuffer bb = allocate(10);
271+
bb.put(1, (byte) 65);
272+
bb.position(1);
273+
bb.limit(2);
274+
checkDecodeHexByteBufferOddCharacters(bb);
271275
}
272276

273277
@Test
@@ -334,6 +338,7 @@ public void testDecodeByteBufferWithLimit() throws DecoderException {
334338
bb.position(i * 2);
335339
bb.limit(i * 2 + 4);
336340
assertEquals(new String(Arrays.copyOfRange(expected, i, i + 2)), new String(new Hex().decode(bb)));
341+
assertEquals(0, bb.remaining());
337342
}
338343
}
339344

@@ -358,6 +363,7 @@ public void testEncodeByteBufferAllocatedButEmpty() {
358363
// Effectively set remaining == 0 => empty
359364
bb.flip();
360365
assertTrue(Arrays.equals(new byte[0], new Hex().encode(bb)));
366+
assertEquals(0, bb.remaining());
361367
}
362368

363369
@Test
@@ -457,25 +463,41 @@ public void testEncodeHexByteBufferHelloWorldLowerCaseHex() {
457463
final ByteBuffer b = StringUtils.getByteBufferUtf8("Hello World");
458464
final String expected = "48656c6c6f20576f726c64";
459465
char[] actual;
466+
// Default lower-case
460467
actual = Hex.encodeHex(b);
461468
assertEquals(expected, new String(actual));
469+
assertEquals(0, b.remaining());
470+
// lower-case
471+
b.flip();
462472
actual = Hex.encodeHex(b, true);
463473
assertEquals(expected, new String(actual));
474+
assertEquals(0, b.remaining());
475+
// upper-case
476+
b.flip();
464477
actual = Hex.encodeHex(b, false);
465-
assertFalse(expected.equals(new String(actual)));
478+
assertEquals(expected.toUpperCase(), new String(actual));
479+
assertEquals(0, b.remaining());
466480
}
467481

468482
@Test
469483
public void testEncodeHexByteBufferHelloWorldUpperCaseHex() {
470484
final ByteBuffer b = StringUtils.getByteBufferUtf8("Hello World");
471485
final String expected = "48656C6C6F20576F726C64";
472486
char[] actual;
487+
// Default lower-case
473488
actual = Hex.encodeHex(b);
474-
assertFalse(expected.equals(new String(actual)));
489+
assertEquals(expected.toLowerCase(), new String(actual));
490+
assertEquals(0, b.remaining());
491+
// lower-case
492+
b.flip();
475493
actual = Hex.encodeHex(b, true);
476-
assertFalse(expected.equals(new String(actual)));
494+
assertEquals(expected.toLowerCase(), new String(actual));
495+
assertEquals(0, b.remaining());
496+
// upper-case
497+
b.flip();
477498
actual = Hex.encodeHex(b, false);
478-
assertTrue(expected.equals(new String(actual)));
499+
assertEquals(expected, new String(actual));
500+
assertEquals(0, b.remaining());
479501
}
480502

481503
@Test
@@ -486,13 +508,18 @@ public void testEncodeHex_ByteBufferOfZeroes() {
486508

487509
@Test
488510
public void testEncodeHex_ByteBufferWithLimit() {
489-
final ByteBuffer bb = ByteBuffer.wrap(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
511+
final ByteBuffer bb = allocate(16);
512+
for (int i = 0; i < 16; i++) {
513+
bb.put((byte) i);
514+
}
515+
bb.flip();
490516
final String expected = "000102030405060708090a0b0c0d0e0f";
491517
// Test pairs of bytes
492518
for (int i = 0; i < 15; i++) {
493519
bb.position(i);
494520
bb.limit(i + 2);
495521
assertEquals(expected.substring(i * 2, i * 2 + 4), new String(Hex.encodeHex(bb)));
522+
assertEquals(0, bb.remaining());
496523
}
497524
}
498525

@@ -507,9 +534,11 @@ public void testEncodeHexByteString_ByteBufferOfZeroesWithLimit() {
507534
final ByteBuffer bb = allocate(36);
508535
bb.limit(3);
509536
assertEquals("000000", Hex.encodeHexString(bb));
537+
assertEquals(0, bb.remaining());
510538
bb.position(1);
511539
bb.limit(3);
512540
assertEquals("0000", Hex.encodeHexString(bb));
541+
assertEquals(0, bb.remaining());
513542
}
514543

515544
@Test
@@ -530,12 +559,18 @@ public void testEncodeHexByteString_ByteArrayBoolean_ToUpperCase() {
530559

531560
@Test
532561
public void testEncodeHexByteString_ByteBufferBoolean_ToLowerCase() {
533-
assertEquals("0a", Hex.encodeHexString(ByteBuffer.wrap(new byte[] { 10 }), true));
562+
final ByteBuffer bb = allocate(1);
563+
bb.put((byte) 10);
564+
bb.flip();
565+
assertEquals("0a", Hex.encodeHexString(bb, true));
534566
}
535567

536568
@Test
537569
public void testEncodeHexByteString_ByteBufferBoolean_ToUpperCase() {
538-
assertEquals("0A", Hex.encodeHexString(ByteBuffer.wrap(new byte[] { 10 }), false));
570+
final ByteBuffer bb = allocate(1);
571+
bb.put((byte) 10);
572+
bb.flip();
573+
assertEquals("0A", Hex.encodeHexString(bb, false));
539574
}
540575

541576
@Test
@@ -545,6 +580,7 @@ public void testEncodeHexByteString_ByteBufferWithLimitBoolean_ToLowerCase() {
545580
bb.position(1);
546581
bb.limit(2);
547582
assertEquals("0a", Hex.encodeHexString(bb, true));
583+
assertEquals(0, bb.remaining());
548584
}
549585

550586
@Test
@@ -554,6 +590,7 @@ public void testEncodeHexByteString_ByteBufferWithLimitBoolean_ToUpperCase() {
554590
bb.position(1);
555591
bb.limit(2);
556592
assertEquals("0A", Hex.encodeHexString(bb, false));
593+
assertEquals(0, bb.remaining());
557594
}
558595

559596
@Test

0 commit comments

Comments
 (0)