GT-3294 Added support for DB FixedField with improved indexing.

This commit is contained in:
ghidra1 2020-02-24 18:02:01 -05:00
parent 14d4c87ef4
commit fcb3151f94
224 changed files with 9574 additions and 7913 deletions

View file

@ -0,0 +1,215 @@
/* ###
* 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 db;
import java.io.IOException;
import db.buffers.DataBuffer;
import generic.util.UnsignedDataUtils;
import ghidra.util.BigEndianDataConverter;
/**
* <code>FixedField10</code> is a 10-byte fixed-length binary field.
*/
public class FixedField10 extends FixedField {
/**
* Minimum long field value
*/
public static FixedField10 MIN_VALUE = new FixedField10(0L, (short) 0, true);
/**
* Maximum long field value
*/
public static FixedField10 MAX_VALUE = new FixedField10(-1L, (short) -1, true);
/**
* Instance intended for defining a {@link Table} {@link Schema}
*/
@SuppressWarnings("hiding")
public static final FixedField10 INSTANCE = MIN_VALUE;
// This implementation uses both a data byte array and short+long variables
// for data storage. While the short+long is always available, the data
// byte array is only set when needed or supplied during construction.
// The use of the short+long is done to speed-up comparison with other
// FixedField10 instances or directly from a DataBuffer.
private short lo2;
private long hi8;
/**
* Construct a 10-byte fixed-length field with an initial value of 0.
*/
public FixedField10() {
super(null, false);
}
/**
* Construct a 10-byte fixed-length field with an initial value of data.
* @param data initial 10-byte binary value
* @throws IllegalArgumentException thrown if data is not 10-bytes in length
*/
public FixedField10(byte[] data) {
this(data, false);
}
/**
* Construct a 10-byte fixed-length binary field with an initial value of data.
* @param data initial 10-byte binary value
* @param immutable true if field value is immutable
* @throws IllegalArgumentException thrown if data is not 10-bytes in length
*/
public FixedField10(byte[] data, boolean immutable) {
super(null, immutable);
setBinaryData(data);
}
FixedField10(long hi8, short lo2, boolean immutable) {
super(null, immutable);
this.hi8 = hi8;
this.lo2 = lo2;
}
@Override
public int compareTo(Field o) {
if (!(o instanceof FixedField10)) {
throw new UnsupportedOperationException("may only compare similar Field types");
}
FixedField10 f = (FixedField10) o;
if (hi8 != f.hi8) {
return UnsignedDataUtils.unsignedLessThan(hi8, f.hi8) ? -1 : 1;
}
if (lo2 != f.lo2) {
return UnsignedDataUtils.unsignedLessThan(lo2, f.lo2) ? -1 : 1;
}
return 0;
}
@Override
int compareTo(DataBuffer buffer, int offset) {
long otherHi8 = buffer.getLong(offset);
if (hi8 != otherHi8) {
return UnsignedDataUtils.unsignedLessThan(hi8, otherHi8) ? -1 : 1;
}
short otherLo2 = buffer.getShort(offset + 8);
if (lo2 != otherLo2) {
return UnsignedDataUtils.unsignedLessThan(lo2, otherLo2) ? -1 : 1;
}
return 0;
}
@Override
public FixedField copyField() {
return new FixedField10(hi8, lo2, false);
}
@Override
public FixedField newField() {
return new FixedField10();
}
@Override
FixedField getMinValue() {
return MIN_VALUE;
}
@Override
FixedField getMaxValue() {
return MAX_VALUE;
}
@Override
public byte[] getBinaryData() {
if (data != null) {
return data;
}
data = new byte[10];
BigEndianDataConverter.INSTANCE.putLong(data, 0, hi8);
BigEndianDataConverter.INSTANCE.putShort(data, 8, lo2);
return data;
}
@Override
public void setBinaryData(byte[] data) {
if (data.length != 10) {
throw new IllegalArgumentException("Invalid FixedField10 length: " + data.length);
}
this.data = data;
hi8 = BigEndianDataConverter.INSTANCE.getLong(data, 0);
lo2 = BigEndianDataConverter.INSTANCE.getShort(data, 8);
}
@Override
byte getFieldType() {
return FIXED_10_TYPE;
}
@Override
int write(Buffer buf, int offset) throws IOException {
if (data != null) {
return buf.put(offset, data);
}
offset = buf.putLong(offset, hi8);
return buf.putShort(offset, lo2);
}
@Override
int read(Buffer buf, int offset) throws IOException {
checkImmutable();
data = null; // be lazy
hi8 = buf.getLong(offset);
lo2 = buf.getShort(offset + 8);
return offset + 10;
}
@Override
int readLength(Buffer buf, int offset) throws IOException {
return 10;
}
@Override
int length() {
return 10;
}
@Override
public int hashCode() {
final int prime = 31;
int result = (int) (hi8 ^ (hi8 >>> 32));
result = prime * result + lo2;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
FixedField10 other = (FixedField10) obj;
if (hi8 != other.hi8)
return false;
if (lo2 != other.lo2)
return false;
return true;
}
@Override
public String getValueAsString() {
return "{" + BinaryField.getValueAsString(getBinaryData()) + "}";
}
}