Skip to content

Commit 201457e

Browse files
committed
Add more javadoc and analysis and some minor refactoring
1 parent 84382ae commit 201457e

File tree

2 files changed

+195
-27
lines changed

2 files changed

+195
-27
lines changed

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

Lines changed: 181 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,15 @@ private Converter() {
436436
* collection.toArray()}. Calling this method is as thread-safe as calling
437437
* that method.
438438
*
439+
* <p>
440+
* <strong>Analysis</strong>
441+
* <ul>
442+
* <li>Time Complexity: <code>O(n)</code></li>
443+
* <li>Space Complexity: <code>O(n)</code></li>
444+
* <li>Alters Parameters: <code>false</code></li>
445+
* </ul>
446+
* </p>
447+
*
439448
* @param collection a collection of {@code Byte} objects
440449
* @return an array containing the same values as {@code collection}, in the
441450
* same order, converted to primitives
@@ -457,6 +466,15 @@ static byte[] toArray(Collection<java.lang.Byte> collection) {
457466
* Converts this primitive array to an boxed object array.
458467
* Will create a new array and not reuse the array reference.
459468
*
469+
* <p>
470+
* <strong>Analysis</strong>
471+
* <ul>
472+
* <li>Time Complexity: <code>O(n)</code></li>
473+
* <li>Space Complexity: <code>O(n)</code></li>
474+
* <li>Alters Parameters: <code>false</code></li>
475+
* </ul>
476+
* </p>
477+
*
460478
* @param array to convert
461479
* @return new array
462480
*/
@@ -472,6 +490,15 @@ static java.lang.Byte[] toBoxedArray(byte[] array) {
472490
* Converts given array to list of boxed bytes. Will create a new list
473491
* and not reuse the array reference.
474492
*
493+
* <p>
494+
* <strong>Analysis</strong>
495+
* <ul>
496+
* <li>Time Complexity: <code>O(n)</code></li>
497+
* <li>Space Complexity: <code>O(n)</code></li>
498+
* <li>Alters Parameters: <code>false</code></li>
499+
* </ul>
500+
* </p>
501+
*
475502
* @param array to convert
476503
* @return list with same length and content as array
477504
*/
@@ -487,6 +514,15 @@ static List<java.lang.Byte> toList(byte[] array) {
487514
* Converts this object array to an primitives type array.
488515
* Will create a new array and not reuse the array reference.
489516
*
517+
* <p>
518+
* <strong>Analysis</strong>
519+
* <ul>
520+
* <li>Time Complexity: <code>O(n)</code></li>
521+
* <li>Space Complexity: <code>O(n)</code></li>
522+
* <li>Alters Parameters: <code>false</code></li>
523+
* </ul>
524+
* </p>
525+
*
490526
* @param objectArray to convert
491527
* @return new array
492528
*/
@@ -502,13 +538,24 @@ static byte[] toPrimitiveArray(java.lang.Byte[] objectArray) {
502538
* Creates a byte array from given int array.
503539
* The resulting byte array will have length intArray * 4.
504540
*
541+
* <p>
542+
* <strong>Analysis</strong>
543+
* <ul>
544+
* <li>Time Complexity: <code>O(n)</code></li>
545+
* <li>Space Complexity: <code>O(n)</code></li>
546+
* <li>Alters Parameters: <code>false</code></li>
547+
* </ul>
548+
* </p>
549+
*
505550
* @param intArray to convert
506551
* @return resulting byte array
507552
*/
508553
static byte[] toByteArray(int[] intArray) {
509554
byte[] primitivesArray = new byte[intArray.length * 4];
555+
ByteBuffer buffer = ByteBuffer.allocate(4);
510556
for (int i = 0; i < intArray.length; i++) {
511-
byte[] intBytes = ByteBuffer.allocate(4).putInt(intArray[i]).array();
557+
buffer.clear();
558+
byte[] intBytes = buffer.putInt(intArray[i]).array();
512559
System.arraycopy(intBytes, 0, primitivesArray, (i * 4), intBytes.length);
513560
}
514561
return primitivesArray;
@@ -518,13 +565,24 @@ static byte[] toByteArray(int[] intArray) {
518565
* Creates a byte array from given long array.
519566
* The resulting byte array will have length longArray * 8
520567
*
568+
* <p>
569+
* <strong>Analysis</strong>
570+
* <ul>
571+
* <li>Time Complexity: <code>O(n)</code></li>
572+
* <li>Space Complexity: <code>O(n)</code></li>
573+
* <li>Alters Parameters: <code>false</code></li>
574+
* </ul>
575+
* </p>
576+
*
521577
* @param longArray to convert
522578
* @return resulting byte array
523579
*/
524580
static byte[] toByteArray(long[] longArray) {
525581
byte[] primitivesArray = new byte[longArray.length * 8];
582+
ByteBuffer buffer = ByteBuffer.allocate(8);
526583
for (int i = 0; i < longArray.length; i++) {
527-
byte[] longBytes = ByteBuffer.allocate(8).putLong(longArray[i]).array();
584+
buffer.clear();
585+
byte[] longBytes = buffer.putLong(longArray[i]).array();
528586
System.arraycopy(longBytes, 0, primitivesArray, (i * 8), longBytes.length);
529587
}
530588
return primitivesArray;
@@ -533,6 +591,15 @@ static byte[] toByteArray(long[] longArray) {
533591
/**
534592
* Converts a char array to a byte array with given charset and range
535593
*
594+
* <p>
595+
* <strong>Analysis</strong>
596+
* <ul>
597+
* <li>Time Complexity: <code>O(n)</code></li>
598+
* <li>Space Complexity: <code>O(n)</code></li>
599+
* <li>Alters Parameters: <code>false</code></li>
600+
* </ul>
601+
* </p>
602+
*
536603
* @param charArray to get the byte array from
537604
* @param charset charset to be used to decode the char array
538605
* @param offset to start reading the char array from (must be smaller than length and gt 0)
@@ -567,6 +634,15 @@ static byte[] charToByteArray(char[] charArray, Charset charset, int offset, int
567634
/**
568635
* Convert given byte array in given encoding to char array
569636
*
637+
* <p>
638+
* <strong>Analysis</strong>
639+
* <ul>
640+
* <li>Time Complexity: <code>O(n)</code></li>
641+
* <li>Space Complexity: <code>O(n)</code></li>
642+
* <li>Alters Parameters: <code>false</code></li>
643+
* </ul>
644+
* </p>
645+
*
570646
* @param bytes as data source
571647
* @param charset of the byte array
572648
* @param byteOrder the order of the bytes array
@@ -596,6 +672,15 @@ static char[] byteToCharArray(byte[] bytes, Charset charset, ByteOrder byteOrder
596672
* [b1, b2, b3, b4] = [int1]
597673
* </pre>
598674
*
675+
* <p>
676+
* <strong>Analysis</strong>
677+
* <ul>
678+
* <li>Time Complexity: <code>O(n)</code></li>
679+
* <li>Space Complexity: <code>O(n)</code></li>
680+
* <li>Alters Parameters: <code>false</code></li>
681+
* </ul>
682+
* </p>
683+
*
599684
* @param bytes to convert to int array, must be % 4 == 0 to work correctly
600685
* @param byteOrder of the byte array
601686
* @return int array
@@ -614,6 +699,15 @@ static int[] toIntArray(byte[] bytes, ByteOrder byteOrder) {
614699
* [b1, b2, b3, b4, b5, b6, b7, b8] = [long1]
615700
* </pre>
616701
*
702+
* <p>
703+
* <strong>Analysis</strong>
704+
* <ul>
705+
* <li>Time Complexity: <code>O(n)</code></li>
706+
* <li>Space Complexity: <code>O(n)</code></li>
707+
* <li>Alters Parameters: <code>false</code></li>
708+
* </ul>
709+
* </p>
710+
*
617711
* @param bytes to convert to long array, must be % 8 == 0 to work correctly
618712
* @param byteOrder of the byte array
619713
* @return long array
@@ -629,6 +723,15 @@ static long[] toLongArray(byte[] bytes, ByteOrder byteOrder) {
629723
* Convert UUID to a newly generated 16 byte long array representation. Puts the 8 byte most significant bits and
630724
* 8 byte least significant bits into an byte array.
631725
*
726+
* <p>
727+
* <strong>Analysis</strong>
728+
* <ul>
729+
* <li>Time Complexity: <code>O(1)</code></li>
730+
* <li>Space Complexity: <code>O(1)</code></li>
731+
* <li>Alters Parameters: <code>false</code></li>
732+
* </ul>
733+
* </p>
734+
*
632735
* @param uuid to convert to array
633736
* @return buffer containing the 16 bytes
634737
*/
@@ -647,6 +750,25 @@ static final class Obj {
647750
private Obj() {
648751
}
649752

753+
/**
754+
* Equals method comparing 2 byte arrays.
755+
* This utilizes a quick return of the array differs on any given property so not suitable
756+
* for security relevant checks. See {@link Util.Byte#constantTimeEquals(byte[], byte[])}
757+
* for that.
758+
*
759+
* <p>
760+
* <strong>Analysis</strong>
761+
* <ul>
762+
* <li>Time Complexity: <code>O(n)</code></li>
763+
* <li>Space Complexity: <code>O(1)</code></li>
764+
* <li>Alters Parameters: <code>false</code></li>
765+
* </ul>
766+
* </p>
767+
*
768+
* @param obj subject a
769+
* @param anotherArray subject b to compare to a
770+
* @return if a.len == b.len and for every 0..len a[i] == b[i]
771+
*/
650772
static boolean equals(byte[] obj, java.lang.Byte[] anotherArray) {
651773
if (anotherArray == null) return false;
652774
if (obj.length != anotherArray.length) return false;
@@ -661,6 +783,15 @@ static boolean equals(byte[] obj, java.lang.Byte[] anotherArray) {
661783
/**
662784
* Hashcode implementation for a byte array and given byte order
663785
*
786+
* <p>
787+
* <strong>Analysis</strong>
788+
* <ul>
789+
* <li>Time Complexity: <code>O(n)</code></li>
790+
* <li>Space Complexity: <code>O(1)</code></li>
791+
* <li>Alters Parameters: <code>false</code></li>
792+
* </ul>
793+
* </p>
794+
*
664795
* @param byteArray to calculate hashCode of
665796
* @param byteOrder to calculate hashCode of
666797
* @return hashCode
@@ -674,6 +805,15 @@ static int hashCode(byte[] byteArray, ByteOrder byteOrder) {
674805
/**
675806
* Shows the length and a preview of max 8 bytes of the given byte
676807
*
808+
* <p>
809+
* <strong>Analysis</strong>
810+
* <ul>
811+
* <li>Time Complexity: <code>O(1)</code></li>
812+
* <li>Space Complexity: <code>O(1)</code></li>
813+
* <li>Alters Parameters: <code>false</code></li>
814+
* </ul>
815+
* </p>
816+
*
677817
* @param bytes to convert to string
678818
* @return string representation
679819
*/
@@ -698,38 +838,66 @@ static final class Validation {
698838
private Validation() {
699839
}
700840

701-
private static void checkFile(java.io.File file) {
702-
if (file == null || !file.exists() || !file.isFile()) {
703-
throw new IllegalArgumentException("file must not be null, has to exist and must be a file (not a directory) " + file);
704-
}
705-
}
706-
841+
/**
842+
* Check if a length of an primitive (e.g. int = 4 byte) fits in given length from given start index.
843+
* Throws exception with descriptive exception message.
844+
*
845+
* @param length of the whole array
846+
* @param index to start from array length
847+
* @param primitiveLength length of the primitive type to check
848+
* @param type for easier debugging the human readable type of the checked primitive
849+
* to put in exception message
850+
* @throws IndexOutOfBoundsException if index + primitiveLength > length
851+
*/
707852
static void checkIndexBounds(int length, int index, int primitiveLength, String type) {
708853
if (index < 0 || index + primitiveLength > length) {
709854
throw new IndexOutOfBoundsException("cannot get " + type + " from index out of bounds: " + index);
710855
}
711856
}
712857

858+
/**
859+
* Check if given length is an expected length.
860+
* Throws exception with descriptive exception message.
861+
*
862+
* @param length of the whole array
863+
* @param expectedLength how length is expected
864+
* @param type for easier debugging the human readable type of the checked primitive
865+
* to put in exception message
866+
* @throws IllegalArgumentException if length != expectedLength
867+
*/
713868
static void checkExactLength(int length, int expectedLength, String type) {
714869
if (length != expectedLength) {
715-
throw new IllegalStateException("cannot convert to " + type + " if length != " + expectedLength + " bytes (was " + length + ")");
870+
throw new IllegalArgumentException("cannot convert to " + type + " if length != " + expectedLength + " bytes (was " + length + ")");
716871
}
717872
}
718873

719874
/**
720-
* Checks if given length is divisable by mod factor (with zero rest).
721-
* This can be used to check of a byte array can be convertet to an e.g. int array which is
875+
* Checks if given length is divisible by mod factor (with zero rest).
876+
* This can be used to check of a byte array can be converted to an e.g. int array which is
722877
* multiples of 4.
723878
*
724879
* @param length of the byte array
725880
* @param modFactor to divide the length
726881
* @param errorSubject human readable message of the exact error subject
882+
* @throws IllegalArgumentException if length % modFactor != 0
727883
*/
728884
static void checkModLength(int length, int modFactor, String errorSubject) {
729885
if (length % modFactor != 0) {
730886
throw new IllegalArgumentException("Illegal length for " + errorSubject + ". Byte array length must be multiple of " + modFactor + ", length was " + length);
731887
}
732888
}
889+
890+
/**
891+
* Check if the file exists and is a file.
892+
*
893+
* @param file to check
894+
* @throws IllegalArgumentException if either file is null, does not exists or is not a file
895+
*/
896+
private static void checkFileExists(java.io.File file) {
897+
if (file == null || !file.exists() || !file.isFile()) {
898+
throw new IllegalArgumentException("file must not be null, has to exist and must be a file (not a directory) " + file);
899+
}
900+
}
733901
}
734902

735903
/**
@@ -803,7 +971,7 @@ static byte[] readFromDataInput(DataInput dataInput, int length) {
803971
* @return byte content
804972
*/
805973
static byte[] readFromFile(java.io.File file) {
806-
Validation.checkFile(file);
974+
Validation.checkFileExists(file);
807975

808976
try {
809977
return Files.readAllBytes(file.toPath());
@@ -821,7 +989,7 @@ static byte[] readFromFile(java.io.File file) {
821989
* @return byte array with length length
822990
*/
823991
static byte[] readFromFile(java.io.File file, int offset, int length) {
824-
Validation.checkFile(file);
992+
Validation.checkFileExists(file);
825993
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
826994
raf.seek(offset);
827995
return readFromDataInput(raf, length);

0 commit comments

Comments
 (0)