문제

Basically I've read in 5 bytes that correspond to a quantity, but I would like to convert it to a Word64. What's the best way to do this?

Edit: I should also say that this is run in an inner loop so performance is critical. Ideally I'd like to do something like:

uint64_t word = 0;
char bytes[5] = getbytes(5)
word += (bytes[0] << 32) 
        + (bytes[1] << 24) 
        + (bytes[2] << 16) 
        + (bytes[3] << 8) 
        + (bytes[4])

Or something similar.

도움이 되었습니까?

해결책

If you just want a simple function, assuming big-endian byte order, this one should do the job:

foo :: B.ByteString -> Word64
foo = B.foldl' (\x y -> x * 256 + fromIntegral y) 0

However, if you are reading lots of binary data, you might want to look into using the binary package.

다른 팁

As Hammar said, binary (and the strict bytestring version, cereal) is great, but they are measuably slower than the fastest solutions (they perform the same shifting proposed in Hammar's solution).

I've found that a simple FFI routine is the fastest solution:

getNthWord n b = inlinePerformIO (unsafeUseAsCString b (flip peekElemOff n . castPtr))

If you're willing to add a build-dep, an equally fast solution is to use Vector.Storable from the vector package.

Note neither of these handle your 5 byte big endian format, so you'd need to alter the data producer for this to be useful.

PS The FFI solution assumes word alignment. I originally had a bug when users ran that routine on non-x86 systems.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top