Search code examples
c#bit

Packing and unpacking a 32-bit number?


I have a project I'm working on where the file format stores the locations of various parts of the file in offsets. So, for example, the file will hold information about 8 different layers. There will be an offset in bytes to the data for each layer.

I'm having trouble calculating what that offset is as the way it is stored is confusing to me. I do have enough documentation to do it by hand but I don't know how to do it in code.

The docs say:

A packed offset is 32bits. The unpacked offset is also a 32 bit number to be used as a byte count. An offset is packed in memory as two words, or 4 bytes.

So, for example,

byte0 = aaaaaaaa
byte1 = bbbbbbbb
byte3 = cccccccc
byte4 = ddddeeee

The hi nibble of the low byte is appended to byte 0 and byte 2 as follows:

dddd aaaaaaaa cccccccc

Four 0 are added to the lo part (enforcing 16 byte chunkiness)

dddd aaaaaaaa cccccccc 0000

For completeness we specify that the high 8 bits of a 32 bit offset are 0.

The final unpacked offset looks like this:

00000000 ddddaaaa aaaacccc cccc0000

I can follow those instructions manually and come up with the correct numnber, but I don't know how to code that. I was copying another person's code who was working with the same filetype and they used:

offset = (val1 << 12) + (val2 << 4) + (val3 <<4) + (val4 >> 4)

val1, val2, val3, and val4 are just the 4 individual bytes. This worked fine for smaller numbers, but as soon as they got over a certain value, it no longer worked.

Can anyone help in getting this to work in C#?


Solution

  • Judging by your description, it looks like you need the following

    offset = val1 << 12 | val3 << 4 | (val4 & 0xF0) << 16;
    

    In this case, val1 means aaaaaaaa, val3 means cccccccc and val4 means dddddddd. val2 appears to be ignored.