package org.jnode.fs.hfsplus.attributes;
import org.jnode.fs.hfsplus.HfsUnicodeString;
import org.jnode.fs.hfsplus.catalog.CatalogNodeId;
import org.jnode.fs.hfsplus.tree.AbstractKey;
import org.jnode.fs.hfsplus.tree.Key;
import org.jnode.util.BigEndian;
/**
* An attributes file key (HFSPlusAttrKey).
*
* @author Luke Quinane
*/
public class AttributeKey extends AbstractKey {
/**
* The key length.
*/
public static final int KEY_LENGTH = 14 + 127 + 1;
/**
* The padding value.
*/
private int pad;
/**
* The file ID.
*/
private CatalogNodeId fileId;
/**
* The start block.
*/
private long startBlock;
/**
* The attribute name.
*/
private HfsUnicodeString attributeName;
/**
* Reads in an attribute key.
*
* @param src the source buffer.
* @param offset the offset to read from.
*/
public AttributeKey(byte[] src, int offset) {
keyLength = BigEndian.getUInt16(src, offset) + 2;
pad = BigEndian.getUInt16(src, offset + 2);
fileId = new CatalogNodeId(src, offset + 4);
startBlock = BigEndian.getUInt32(src, offset + 8);
attributeName = new HfsUnicodeString(src, offset + 0xc);
}
/**
* Creates a new attribute key.
*
* @param fileId the file ID.
* @param attributeName the attribute name.
*/
public AttributeKey(CatalogNodeId fileId, String attributeName) {
this.fileId = fileId;
this.attributeName = new HfsUnicodeString(attributeName);
}
public CatalogNodeId getFileId() {
return fileId;
}
public HfsUnicodeString getAttributeName() {
return attributeName;
}
@Override
public int compareTo(Key key) {
int result = -1;
if (key instanceof AttributeKey) {
AttributeKey otherKey = (AttributeKey) key;
result = getFileId().compareTo(otherKey.getFileId());
if (result == 0) {
// Note: this is unlikely to be correct. See TN1150 section "Unicode Subtleties" for details
// For reading in data is should be safe since the B-Tree will be pre-sorted, but for adding new entries
// it will cause the order to be wrong.
result = this.getAttributeName().getUnicodeString()
.compareTo(otherKey.getAttributeName().getUnicodeString());
}
}
return result;
}
@Override
public int hashCode() {
return 789 ^ fileId.hashCode() + attributeName.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof AttributeKey)) {
return false;
}
AttributeKey otherKey = (AttributeKey) obj;
return
fileId.getId() == otherKey.fileId.getId() &&
attributeName.getUnicodeString().equals(otherKey.getAttributeName().getUnicodeString());
}
@Override
public byte[] getBytes() {
int length = this.getKeyLength();
byte[] data = new byte[length];
BigEndian.setInt16(data, 0, length);
BigEndian.setInt16(data, 2, pad);
System.arraycopy(fileId.getBytes(), 0, data, 4, 4);
BigEndian.setInt32(data, 8, (int) startBlock);
System.arraycopy(attributeName.getBytes(), 0, data, 0xc, (attributeName.getLength() * 2) + 2);
return data;
}
@Override
public String toString() {
return String.format("[length: %d, file-id: %d, attribute-name: '%s']", getKeyLength(), getFileId().getId(),
getAttributeName());
}
}