The file that I'm parsing consists of multiple records of various types. The records have a standard header (which makes it straightforward to determine the type), and a standard trailer. The fields in between, however, are XOR-encoded, with makes things more complicated. I've resorted to defining custom elements for strings, binary data, and integers, and things have gone pretty well. (Nevertheless, if there's a better approach, I would very much like to hear about it!)
However, the record that I'm working on now has fields which are floating point numbers (little-endian, eight bytes). Given the apparently limited classes and methods which are available to scripted elements (I'm working in Python), how can I construct the value to be passed to value.setFloat() from the bytes I get from byteView.readByte()?
OK, I've discovered that I can import the struct package, which I think will close the gap. However, now I'm getting an error:
Python: 'TypeError: in method 'Value_setFloat', argument 2 of type 'double''
The documentation suggests that value.setFloat() should accept a double (I was presuming that if I passed it a single-precision float, that the argument would be silently promoted). Is the documentation wrong, or is it just me?
Apparently the problem is that Python has a poor error message in this instance. The issue is that struct.unpack() returns a tuple which, if passed directly to value.setFloat() causes a type error (as it presumably should). However, it would have been nice if the error message had mentioned the type received as well as the type expected.
So, I believe the answer to my original question is code like the following:
def parseByteRange(element, byteView, bitPos, bitLength, results):
# this method parses data starting at bitPos, bitLength bits are remaining
bytePos = bitPos / 8
byteLength = bitLength / 8
byteString = ""
xorMask = getXorMask(results)
for i in range(byteLength):
byteRead = byteView.readByte(bytePos)
byteRead ^= xorMask
byteString += chr(byteRead)
bytePos += 1
# how many bytes were processed?
processedBytes = byteLength
iteration = 0
floatValue = (0.0,)
if byteLength == 4 :
floatValue = struct.unpack('<f', byteString)
elif byteLength == 8 :
floatValue = struct.unpack('<d', byteString)
logVerboseMessage("Unexpected float length: %d" % byteLength)
# create and set new value
value = NumberValue()
results.addElement(element, processedBytes, iteration, value)
# return number of processed bytes
(If anyone has any feedback on this, I would appreciate hearing it! -- Thanks!)