Skip to content

Commit c3f7239

Browse files
committed
Add new from() constructor using char[] which accept offset + length
fixes #24
1 parent 6ad6e19 commit c3f7239

File tree

5 files changed

+115
-7
lines changed

5 files changed

+115
-7
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* add support for Base32 RFC4648 non-hex alphabet encoding/parsing #21
77
* add constructor for `IntBuffer` and `CharBuffer`
88
* `parse()` methods now expect more flexible `CharSequence` instead of `String` #23
9+
* `from()` constructor reading from `char[]` has new version that accepts offset and length #24
910

1011
### Breaking
1112

src/main/java/at/favre/lib/bytes/Bytes.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public static Bytes fromNullSafe(byte[] byteArrayToCopy) {
199199
* Creates a new instance from a slice of given array
200200
*
201201
* @param array to slice
202-
* @param offset stat position
202+
* @param offset start position
203203
* @param length length
204204
* @return new instance
205205
*/
@@ -520,10 +520,20 @@ public static Bytes from(char[] charArray) {
520520
* @return new instance
521521
*/
522522
public static Bytes from(char[] charArray, Charset charset) {
523-
ByteBuffer bb = charset.encode(CharBuffer.wrap(charArray));
524-
byte[] bytes = new byte[bb.remaining()];
525-
bb.get(bytes);
526-
return from(bytes);
523+
return from(charArray, charset, 0, charArray.length);
524+
}
525+
526+
/**
527+
* Creates a new instance from given char array with given range. The array will be handles like an encoded string
528+
*
529+
* @param charArray to get the internal byte array from
530+
* @param charset charset to be used to decode the char array
531+
* @param offset start position (from given char array not encoded byte array out)
532+
* @param length length in relation to offset (from given char array not encoded byte array out)
533+
* @return new instance
534+
*/
535+
public static Bytes from(char[] charArray, Charset charset, int offset, int length) {
536+
return from(Util.charToByteArray(charArray, charset, offset, length));
527537
}
528538

529539
/**

src/main/java/at/favre/lib/bytes/Util.java

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,27 @@
2121

2222
package at.favre.lib.bytes;
2323

24-
import java.io.*;
24+
import java.io.ByteArrayOutputStream;
25+
import java.io.DataInput;
26+
import java.io.File;
27+
import java.io.IOException;
28+
import java.io.InputStream;
2529
import java.nio.ByteBuffer;
2630
import java.nio.ByteOrder;
31+
import java.nio.CharBuffer;
32+
import java.nio.charset.Charset;
2733
import java.nio.file.Files;
28-
import java.util.*;
34+
import java.util.ArrayList;
35+
import java.util.Arrays;
36+
import java.util.Collection;
37+
import java.util.HashMap;
38+
import java.util.Iterator;
39+
import java.util.List;
40+
import java.util.Map;
41+
import java.util.NoSuchElementException;
42+
import java.util.Objects;
43+
import java.util.Random;
44+
import java.util.UUID;
2945

3046
/**
3147
* Common Util methods to convert or modify byte arrays
@@ -373,6 +389,37 @@ static byte[] readFromFile(File file) {
373389
}
374390
}
375391

392+
/**
393+
* Converts a char array to a byte array with given charset and range
394+
*
395+
* @param charArray to get the byte array from
396+
* @param charset charset to be used to decode the char array
397+
* @param offset to start reading the char array from (must be smaller than length and gt 0)
398+
* @param length from offset (must be between 0 and charArray.length)
399+
* @return byte array of encoded chars
400+
*/
401+
static byte[] charToByteArray(char[] charArray, Charset charset, int offset, int length) {
402+
if (offset < 0 || offset > charArray.length)
403+
throw new IllegalArgumentException("offset must be gt 0 and smaller than array length");
404+
if (length < 0 || length > charArray.length)
405+
throw new IllegalArgumentException("length must be at least 1 and less than array length");
406+
if (offset + length > charArray.length)
407+
throw new IllegalArgumentException("length + offset must be smaller than array length");
408+
409+
if (length == 0) return new byte[0];
410+
411+
CharBuffer charBuffer = CharBuffer.wrap(charArray);
412+
413+
if (offset != 0 || length != charBuffer.remaining()) {
414+
charBuffer = charBuffer.subSequence(offset, offset + length);
415+
}
416+
417+
ByteBuffer bb = charset.encode(charBuffer);
418+
byte[] bytes = new byte[bb.remaining()];
419+
bb.get(bytes);
420+
return bytes;
421+
}
422+
376423
/**
377424
* Shows the length and a preview of max 8 bytes of the given byte
378425
*

src/test/java/at/favre/lib/bytes/BytesConstructorTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ public void fromCharArray() {
294294
assertArrayEquals(String.valueOf(s1.toCharArray()).getBytes(StandardCharsets.ISO_8859_1), Bytes.from(s1.toCharArray(), StandardCharsets.ISO_8859_1).array());
295295
assertArrayEquals(String.valueOf(s1.toCharArray()).getBytes(StandardCharsets.UTF_16), Bytes.from(s1.toCharArray(), StandardCharsets.UTF_16).array());
296296
assertArrayEquals(String.valueOf(s1.toCharArray()).getBytes(StandardCharsets.UTF_8), Bytes.from(s1.toCharArray(), StandardCharsets.UTF_8).array());
297+
assertArrayEquals(String.valueOf(s1.substring(0, 1).toCharArray()).getBytes(StandardCharsets.UTF_8), Bytes.from(s1.toCharArray(), StandardCharsets.UTF_8, 0, 1).array());
298+
assertArrayEquals(String.valueOf(s1.substring(3, 7).toCharArray()).getBytes(StandardCharsets.UTF_8), Bytes.from(s1.toCharArray(), StandardCharsets.UTF_8, 3, 4).array());
297299
assertArrayEquals(Bytes.empty().array(), Bytes.from(CharBuffer.allocate(0)).array());
298300
}
299301

src/test/java/at/favre/lib/bytes/UtilTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.junit.Test;
2626

2727
import java.math.BigInteger;
28+
import java.nio.charset.Charset;
29+
import java.nio.charset.StandardCharsets;
2830
import java.util.Arrays;
2931
import java.util.List;
3032
import java.util.Random;
@@ -299,4 +301,50 @@ public void testRightShiftAgainstRefImpl() {
299301
}
300302
}
301303
}
304+
305+
@Test
306+
public void testCharToByteArray() {
307+
Charset[] charsets = new Charset[]{StandardCharsets.UTF_8, StandardCharsets.US_ASCII, StandardCharsets.UTF_16};
308+
for (Charset charset : charsets) {
309+
checkCharArrayToByteArray("".toCharArray(), charset);
310+
checkCharArrayToByteArray("A".toCharArray(), charset);
311+
checkCharArrayToByteArray("12".toCharArray(), charset);
312+
checkCharArrayToByteArray("XYZ".toCharArray(), charset);
313+
checkCharArrayToByteArray("abcdefg".toCharArray(), charset);
314+
checkCharArrayToByteArray("71oh872gdl2dhp81g".toCharArray(), charset);
315+
316+
}
317+
318+
checkCharArrayToByteArray("யe2ாமறிந்தиют убSîne klâwenasd1".toCharArray(), StandardCharsets.UTF_8);
319+
}
320+
321+
private void checkCharArrayToByteArray(char[] subject, Charset charset) {
322+
for (int lenI = 1; lenI < subject.length + 1; lenI++) {
323+
for (int offsetI = 0; offsetI < subject.length; offsetI++) {
324+
if (offsetI + lenI > subject.length) break;
325+
byte[] bytes = Util.charToByteArray(subject, charset, offsetI, lenI);
326+
assertEquals(Bytes.wrap(bytes), Bytes.wrap(new String(subject).substring(offsetI, offsetI + lenI).getBytes(charset)));
327+
}
328+
}
329+
compareArrayToByteArrayWithoutOffset(subject, charset);
330+
}
331+
332+
private void compareArrayToByteArrayWithoutOffset(char[] subject, Charset charset) {
333+
assertArrayEquals(Util.charToByteArray(subject, charset, 0, subject.length), new String(subject).getBytes(charset));
334+
}
335+
336+
@Test(expected = IllegalArgumentException.class)
337+
public void testCharToByteArrayIllegalOffset() {
338+
Util.charToByteArray("abcdef".toCharArray(), StandardCharsets.UTF_8, -1, 1);
339+
}
340+
341+
@Test(expected = IllegalArgumentException.class)
342+
public void testCharToByteArrayIllegalLength() {
343+
Util.charToByteArray("abcdef".toCharArray(), StandardCharsets.UTF_8, 0, -1);
344+
}
345+
346+
@Test(expected = IllegalArgumentException.class)
347+
public void testCharToByteArrayIllegalOffsetPlusLength() {
348+
Util.charToByteArray("abcdef".toCharArray(), StandardCharsets.UTF_8, 4, 3);
349+
}
302350
}

0 commit comments

Comments
 (0)