-
Notifications
You must be signed in to change notification settings - Fork 2
Custom Datatypes
In some cases, you will want to have closer control of how parts of a file are parsed. In this case, you can implement your own class and declare this for use in your ADF file.
Let's look at an example. Suppose the creators of the file format had a bit of a moment and decided that it would be a great idea to store all strings backwards, and terminated with a 0xFF byte. Whilst you could receive the backwards value and reverse it after the event, it would be easier if SPIFF handed the data to the event listeners with the string the right way round.
00000000 65 73 72 65 76 65 72 6e 61 63 66 66 69 70 73 FF |esrevernacffips.|
We can implement a class that scans the byte buffer, pulls all the bytes up to the 0xFF terminator, and then reverses the string.
First things first, your class must extend com.revbingo.spiff.datatypes.DataType. This will force you to implement the public Object evaluate(ByteBuffer buffer, Evalutor evaluator) method
package com.acme.datatypes;
import java.nio.ByteBuffer;
import com.revbingo.spiff.ExecutionException;
import com.revbingo.spiff.datatypes.Datatype;
import com.revbingo.spiff.evaluator.Evaluator;
public class ReversedStringDataType extends Datatype {
@Override
public Object evaluate(ByteBuffer buffer, Evaluator evaluator) throws ExecutionException {
// TODO Auto-generated method stub
return null;
}
}The evaluate method is passed a java.nio.ByteBuffer containing the contents of the file, and an Evaluator object. The Evaluator object allows you to evaluate expressions in context (e.g. evaluator.evaluateInt("numOfBytes - 3")). The ByteBuffer read position will be in the right place corresponding with where you declare the datatype in your ADF file, so you can just go ahead and call buffer.get() to read the next set of bytes from the file. Note that you have the power here to do some disruptive things to the buffer that may affect subsequent instructions (e.g. buffer.position() or buffer.clear()), so play nicely. The Object you return from this method is what will get passed to any EventListeners registered.
So let's (naively*) implement our code:
public Object evaluate(ByteBuffer buffer, Evaluator evaluator) throws ExecutionException {
StringBuffer stringBuffer = new StringBuffer();
byte nextByte;
while((nextByte = buffer.get()) != (byte) 0xFF) {
stringBuffer.append((char) nextByte);
}
return stringBuffer.reverse().toString();
}In order to use this, we need to declare it in the ADF file that we use it in. That's simple enough:
.datatype reversedString com.acme.datatypes.ReversedStringDataType
and then we can just use it:
byte someByte
int aNumber
reversedString spiffcanreverse
- If you're dealing with strings, then you ought to worry about encodings, but currently SPIFF cannot inform your class about encodings declared in the ADF file