mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-1903 refactor out ArrayUtilities, fix BitFieldDataType ENDIANness
Nuke ArrayUtilties and replace it with built-in methods available in jdk Arrays class or use DataConverter for endianness conversion. Exclude ENDIAN setting for BitFieldDataType.
This commit is contained in:
parent
a94082bb67
commit
2a4a7747e6
10 changed files with 44 additions and 204 deletions
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.file.formats.coff;
|
package ghidra.file.formats.coff;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
|
@ -24,7 +26,6 @@ import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
||||||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
|
|
||||||
public class CoffArchiveFileSystemFactory implements
|
public class CoffArchiveFileSystemFactory implements
|
||||||
GFileSystemFactoryByteProvider<CoffArchiveFileSystem>, GFileSystemProbeBytesOnly {
|
GFileSystemFactoryByteProvider<CoffArchiveFileSystem>, GFileSystemProbeBytesOnly {
|
||||||
|
@ -48,7 +49,8 @@ public class CoffArchiveFileSystemFactory implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
||||||
return ArrayUtilities.arrayRangesEquals(CoffArchiveConstants.MAGIC_BYTES, 0, startBytes, 0,
|
return Arrays.equals(
|
||||||
CoffArchiveConstants.MAGIC_BYTES.length);
|
CoffArchiveConstants.MAGIC_BYTES, 0, CoffArchiveConstants.MAGIC_BYTES.length,
|
||||||
|
startBytes, 0, CoffArchiveConstants.MAGIC_BYTES.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,12 @@ import java.io.IOException;
|
||||||
import ghidra.app.util.bin.*;
|
import ghidra.app.util.bin.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
|
|
||||||
public class Apple8900Header implements StructConverter {
|
public class Apple8900Header implements StructConverter {
|
||||||
|
|
||||||
private byte[] magic;
|
private byte[] magic; // "8900"
|
||||||
private byte[] version;
|
private byte[] version; // "1.0"
|
||||||
private byte encrypted;
|
private byte encrypted; // format, plaintext=0x4, encrypted=0x3
|
||||||
private byte[] unknown0;
|
private byte[] unknown0;
|
||||||
private int sizeOfData;
|
private int sizeOfData;
|
||||||
private int footerSignatureOffset;
|
private int footerSignatureOffset;
|
||||||
|
@ -61,7 +60,7 @@ public class Apple8900Header implements StructConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return new String(ArrayUtilities.reverse(version));
|
return new String(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEncrypted() {
|
public boolean isEncrypted() {
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.file.formats.ios.dmg;
|
package ghidra.file.formats.ios.dmg;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -29,7 +31,6 @@ import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.CryptoException;
|
import ghidra.util.exception.CryptoException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles probing for and creating {@link DmgClientFileSystem} instances.
|
* Handles probing for and creating {@link DmgClientFileSystem} instances.
|
||||||
|
@ -58,10 +59,10 @@ public class DmgClientFileSystemFactory implements
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isEncrypted(byte[] startBytes) {
|
private static boolean isEncrypted(byte[] startBytes) {
|
||||||
return ArrayUtilities.arrayRangesEquals(startBytes, 0, DmgConstants.DMG_MAGIC_BYTES_v1, 0,
|
return Arrays.equals(startBytes, 0, DmgConstants.DMG_MAGIC_BYTES_v1.length,
|
||||||
DmgConstants.DMG_MAGIC_BYTES_v1.length) ||
|
DmgConstants.DMG_MAGIC_BYTES_v1, 0, DmgConstants.DMG_MAGIC_BYTES_v1.length) ||
|
||||||
ArrayUtilities.arrayRangesEquals(startBytes, 0, DmgConstants.DMG_MAGIC_BYTES_v2, 0,
|
Arrays.equals(startBytes, 0, DmgConstants.DMG_MAGIC_BYTES_v2.length,
|
||||||
DmgConstants.DMG_MAGIC_BYTES_v2.length);
|
DmgConstants.DMG_MAGIC_BYTES_v2, 0, DmgConstants.DMG_MAGIC_BYTES_v2.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isEncrypted(ByteProvider bp) {
|
private static boolean isEncrypted(ByteProvider bp) {
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.file.formats.ios.img2;
|
package ghidra.file.formats.ios.img2;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
|
@ -23,7 +25,6 @@ import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
||||||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
|
|
||||||
public class Img2FileSystemFactory implements GFileSystemFactoryByteProvider<Img2FileSystem>, GFileSystemProbeBytesOnly {
|
public class Img2FileSystemFactory implements GFileSystemFactoryByteProvider<Img2FileSystem>, GFileSystemProbeBytesOnly {
|
||||||
|
|
||||||
|
@ -34,8 +35,8 @@ public class Img2FileSystemFactory implements GFileSystemFactoryByteProvider<Img
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
||||||
return ArrayUtilities.arrayRangesEquals(startBytes, 0, Img2Constants.IMG2_SIGNATURE_BYTES,
|
return Arrays.equals(startBytes, 0, Img2Constants.IMG2_SIGNATURE_BYTES.length,
|
||||||
0, Img2Constants.IMG2_SIGNATURE_BYTES.length);
|
Img2Constants.IMG2_SIGNATURE_BYTES, 0, Img2Constants.IMG2_SIGNATURE_BYTES.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.file.formats.ios.img3;
|
package ghidra.file.formats.ios.img3;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
|
@ -23,19 +25,18 @@ import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
||||||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
|
|
||||||
public class Img3FileSystemFactory
|
public class Img3FileSystemFactory
|
||||||
implements GFileSystemFactoryByteProvider<Img3FileSystem>, GFileSystemProbeBytesOnly {
|
implements GFileSystemFactoryByteProvider<Img3FileSystem>, GFileSystemProbeBytesOnly {
|
||||||
@Override
|
@Override
|
||||||
public int getBytesRequired() {
|
public int getBytesRequired() {
|
||||||
return Img3Constants.IMG3_SIGNATURE_LENGTH;
|
return Img3Constants.IMG3_SIGNATURE_BYTES.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
||||||
return ArrayUtilities.arrayRangesEquals(startBytes, 0, Img3Constants.IMG3_SIGNATURE_BYTES,
|
return Arrays.equals(startBytes, 0, Img3Constants.IMG3_SIGNATURE_BYTES.length,
|
||||||
0, Img3Constants.IMG3_SIGNATURE_LENGTH);
|
Img3Constants.IMG3_SIGNATURE_BYTES, 0, Img3Constants.IMG3_SIGNATURE_BYTES.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.file.formats.java;
|
package ghidra.file.formats.java;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
@ -26,7 +28,6 @@ import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
||||||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates instances of {@link JavaClassDecompilerFileSystem}.
|
* Creates instances of {@link JavaClassDecompilerFileSystem}.
|
||||||
|
@ -42,8 +43,8 @@ public class JavaClassDecompilerFileSystemFactory implements
|
||||||
@Override
|
@Override
|
||||||
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
||||||
return JadProcessWrapper.isJadPresent() &&
|
return JadProcessWrapper.isJadPresent() &&
|
||||||
ArrayUtilities.arrayRangesEquals(startBytes, 0, JavaClassConstants.MAGIC_BYTES, 0,
|
Arrays.equals(startBytes, 0, JavaClassConstants.MAGIC_BYTES.length,
|
||||||
JavaClassConstants.MAGIC_BYTES.length) &&
|
JavaClassConstants.MAGIC_BYTES, 0, JavaClassConstants.MAGIC_BYTES.length) &&
|
||||||
"class".equalsIgnoreCase(FilenameUtils.getExtension(containerFSRL.getName()));
|
"class".equalsIgnoreCase(FilenameUtils.getExtension(containerFSRL.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package docking.widgets.table;
|
package docking.widgets.table;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.*;
|
import javax.swing.event.*;
|
||||||
|
@ -30,7 +31,6 @@ import org.apache.logging.log4j.Logger;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.datastruct.WeakDataStructureFactory;
|
import ghidra.util.datastruct.WeakDataStructureFactory;
|
||||||
import ghidra.util.datastruct.WeakSet;
|
import ghidra.util.datastruct.WeakSet;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
import utilities.util.reflection.ReflectionUtilities;
|
import utilities.util.reflection.ReflectionUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -405,7 +405,7 @@ public class RowObjectSelectionManager<T> extends DefaultListSelectionModel
|
||||||
|
|
||||||
private boolean restoreSelectedRows(int[] rows) {
|
private boolean restoreSelectedRows(int[] rows) {
|
||||||
traceRows("restoreSelectedRows(): ", rows);
|
traceRows("restoreSelectedRows(): ", rows);
|
||||||
if (ArrayUtilities.isArrayPrimativeEqual(rows, table.getSelectedRows())) {
|
if (Arrays.equals(rows, table.getSelectedRows())) {
|
||||||
trace("\tselection hasn't changed--nothing to do");
|
trace("\tselection hasn't changed--nothing to do");
|
||||||
// the selection is the same, nothing to change; don't send out excess events
|
// the selection is the same, nothing to change; don't send out excess events
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -24,8 +24,8 @@ import ghidra.pcode.utils.Utils;
|
||||||
import ghidra.program.model.data.StringRenderParser.StringParseException;
|
import ghidra.program.model.data.StringRenderParser.StringParseException;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
|
import ghidra.util.DataConverter;
|
||||||
import ghidra.util.StringFormat;
|
import ghidra.util.StringFormat;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base type for integer data types such as {@link CharDataType chars}, {@link IntegerDataType
|
* Base type for integer data types such as {@link CharDataType chars}, {@link IntegerDataType
|
||||||
|
@ -166,25 +166,14 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ENDIAN.isBigEndian(settings, buf)) {
|
DataConverter dc = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf));
|
||||||
bytes = ArrayUtilities.reverse(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size > 8) {
|
if (size > 8) {
|
||||||
if (!isSigned()) {
|
return dc.getBigInteger(bytes, size, isSigned());
|
||||||
// ensure that bytes are treated as unsigned
|
|
||||||
byte[] unsignedBytes = new byte[bytes.length + 1];
|
|
||||||
System.arraycopy(bytes, 0, unsignedBytes, 1, bytes.length);
|
|
||||||
bytes = unsignedBytes;
|
|
||||||
}
|
|
||||||
return new BigInteger(bytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use long when possible
|
// Use long when possible
|
||||||
long val = 0;
|
long val = dc.getValue(bytes, size);
|
||||||
for (byte b : bytes) {
|
|
||||||
val = (val << 8) + (b & 0x0ffL);
|
|
||||||
}
|
|
||||||
return new Scalar(size * 8, val, isSigned());
|
return new Scalar(size * 8, val, isSigned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,11 +283,8 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
|
||||||
return "??";
|
return "??";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ENDIAN.isBigEndian(settings, buf)) {
|
BigInteger value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf))
|
||||||
bytes = ArrayUtilities.reverse(bytes);
|
.getBigInteger(bytes, size, true);
|
||||||
}
|
|
||||||
|
|
||||||
BigInteger value = new BigInteger(bytes);
|
|
||||||
|
|
||||||
if (getFormatSettingsDefinition().getFormat(settings) == FormatSettingsDefinition.CHAR) {
|
if (getFormatSettingsDefinition().getFormat(settings) == FormatSettingsDefinition.CHAR) {
|
||||||
return StringDataInstance.getCharRepresentation(this, bytes, settings);
|
return StringDataInstance.getCharRepresentation(this, bytes, settings);
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.data;
|
package ghidra.program.model.data;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.docking.settings.*;
|
import ghidra.docking.settings.*;
|
||||||
|
@ -22,7 +24,6 @@ import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
import ghidra.util.DataConverter;
|
import ghidra.util.DataConverter;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import utilities.util.ArrayUtilities;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>BitFieldDataType</code> provides a means of defining a minimally sized bit-field
|
* <code>BitFieldDataType</code> provides a means of defining a minimally sized bit-field
|
||||||
|
@ -251,7 +252,11 @@ public class BitFieldDataType extends AbstractDataType {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final SettingsDefinition[] getSettingsDefinitions() {
|
public final SettingsDefinition[] getSettingsDefinitions() {
|
||||||
return baseDataType.getSettingsDefinitions();
|
// exclude any ENDIAN setting that the base data type might support
|
||||||
|
List<SettingsDefinition> baseDTSettings =
|
||||||
|
new ArrayList<>(Arrays.asList(baseDataType.getSettingsDefinitions()));
|
||||||
|
baseDTSettings.remove(EndianSettingsDefinition.DEF);
|
||||||
|
return baseDTSettings.toArray(SettingsDefinition[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -369,16 +374,6 @@ public class BitFieldDataType extends AbstractDataType {
|
||||||
return BigInteger.ZERO;
|
return BigInteger.ZERO;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
byte[] bytes = new byte[storageSize];
|
|
||||||
if (buf.getBytes(bytes, 0) != storageSize) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EndianSettingsDefinition.ENDIAN.isBigEndian(settings, buf)) {
|
|
||||||
bytes = ArrayUtilities.reverse(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
BigInteger big = buf.getBigInteger(0, storageSize, false);
|
BigInteger big = buf.getBigInteger(0, storageSize, false);
|
||||||
BigInteger pow = BigInteger.valueOf(2).pow(effectiveBitSize);
|
BigInteger pow = BigInteger.valueOf(2).pow(effectiveBitSize);
|
||||||
BigInteger mask = pow.subtract(BigInteger.ONE);
|
BigInteger mask = pow.subtract(BigInteger.ONE);
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package utilities.util;
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import ghidra.util.SystemUtilities;
|
|
||||||
|
|
||||||
public final class ArrayUtilities {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a new copy of the specified byte {@code array} with the elements in reversed order.
|
|
||||||
*
|
|
||||||
* @param array byte array to reverse
|
|
||||||
* @return new array instance with elements in reverse order
|
|
||||||
*/
|
|
||||||
public static byte[] reverse(byte[] array) {
|
|
||||||
|
|
||||||
byte[] reversed = new byte[array.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < reversed.length; i++) {
|
|
||||||
reversed[i] = array[array.length - 1 - i];
|
|
||||||
}
|
|
||||||
return reversed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares two primitive arrays for equality
|
|
||||||
*
|
|
||||||
* @param o1 the first array
|
|
||||||
* @param o2 the second array
|
|
||||||
* @return true if each element of the array is equal
|
|
||||||
* @throws IllegalArgumentException if either argument is not an array
|
|
||||||
*/
|
|
||||||
public static boolean isArrayPrimativeEqual(Object o1, Object o2) {
|
|
||||||
if (o1 == null) {
|
|
||||||
return (o2 == null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o2 == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<? extends Object> class1 = o1.getClass();
|
|
||||||
if (!class1.isArray()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Object parameters must be an array! Instead found class: " + class1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<? extends Object> class2 = o2.getClass();
|
|
||||||
if (!class2.isArray()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Object parameters must be an array! Instead found class: " + class2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.getLength(o1) != Array.getLength(o2)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < Array.getLength(o1); i++) {
|
|
||||||
if (!SystemUtilities.isEqual(Array.get(o1, i), Array.get(o2, i))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a portion of byte array b1 equals an equally sized portion of byte array
|
|
||||||
* b2.
|
|
||||||
* <p>
|
|
||||||
* If the sizes of b1 or b2 do not allow for a full comparison of {@code len} bytes, this
|
|
||||||
* function will return false.
|
|
||||||
* <p>
|
|
||||||
* @param b1 first byte array
|
|
||||||
* @param start_b1 offset to start comparison in b1
|
|
||||||
* @param b2 second byte array
|
|
||||||
* @param start_b2 offset to start comparison in b2
|
|
||||||
* @param len number of bytes to compare
|
|
||||||
* @return true or false if the portion is equal
|
|
||||||
*/
|
|
||||||
public static boolean arrayRangesEquals(byte[] b1, int start_b1, byte[] b2, int start_b2,
|
|
||||||
int len) {
|
|
||||||
if (start_b1 + len > b1.length || start_b2 + len > b2.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (b1[start_b1 + i] != b2[start_b2 + i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a copy of the given array with the provided element appended. The length of
|
|
||||||
* the returned array will be one element greater than the given array.
|
|
||||||
*
|
|
||||||
* @param array The array to copy.
|
|
||||||
* @param element The element to append to the copy.
|
|
||||||
* @return A copy of the given array with the provided element appended.
|
|
||||||
*/
|
|
||||||
public static <T> T[] copyAndAppend(T[] array, T element) {
|
|
||||||
T[] newArray = Arrays.copyOf(array, array.length + 1);
|
|
||||||
newArray[array.length] = element;
|
|
||||||
return newArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare two byte arrays by their corresponding entries
|
|
||||||
*
|
|
||||||
* If the two arrays have differing lengths, the shorter precedes the longer. Otherwise, they
|
|
||||||
* are compared as in C's {@code memcmp}, except that Java {@code byte}s are signed.
|
|
||||||
* @param a the first array
|
|
||||||
* @param b the second array
|
|
||||||
* @return a comparison result as in {@link Comparable#compareTo(Object)}
|
|
||||||
*/
|
|
||||||
public static int compare(byte[] a, byte[] b) {
|
|
||||||
int result;
|
|
||||||
result = a.length - b.length;
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < a.length; i++) {
|
|
||||||
result = a[i] - b[i];
|
|
||||||
if (result != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue