Last active
July 17, 2023 20:48
-
-
Save michel-pi/ce639930a7985ff6f9eeb1971ff930b8 to your computer and use it in GitHub Desktop.
Packing integers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
namespace Data | |
{ | |
[StructLayout(LayoutKind.Explicit, Pack = 1)] | |
public struct PackedInteger | |
{ | |
/* | |
* Use cases: | |
* | |
* - Store multiple values in a single database field | |
* - Send multiple values as a single value over the network | |
* - Encode data | |
* | |
*/ | |
/* | |
* Packing four 2-byte integers into a 8-byte integer | |
* | |
* Adjust the order to your needs | |
* (logically it would be the other way round) | |
* (the curent implementation is in the logical order) | |
* | |
* Think: From MSB to LSB. | |
* To change order swap int1 with int4, int2 with int3 | |
* | |
* Value = (int1 << 48) | (int2 << 32) | (int3 << 16) | int4; | |
* | |
* int1 = (Value >> 48) & 0xFFFF | |
* int2 = (Value >> 32) & 0xFFFF | |
* int3 = (Value >> 16) & 0xFFFF | |
* int4 = Value & 0xFFFF | |
* | |
* REMEMBER: CAST TO CORRECT TARGET DATATYPE WHEN NEEDED. TEST YOUR CODE! | |
* | |
*/ | |
[FieldOffset(0)] public ulong Value; | |
/* | |
* MSB vs. LSB | |
* | |
* MSB - Most significant bits | |
* LSB - Least significant bits | |
* | |
* 110011 | |
* ^ MSB | |
* | |
* 110011 | |
* ^ LSB | |
* | |
* Examples: | |
* | |
* All fields init to 0 | |
* | |
* Storing a number in "Left" -> LSB | |
* Example: Left: 64 == Value: 64 | |
* | |
* ~ | |
* | |
* All fields init to 0 | |
* | |
* Storing a number in "Right" -> MSB | |
* Example: Right: 64 == Value: 274877906944 | |
* | |
*/ | |
[FieldOffset(0)] public uint Left; | |
[FieldOffset(4)] public uint Right; | |
public PackedInteger(uint left, uint right) | |
{ | |
Left = left; | |
Right = right; | |
} | |
public static PackedInteger Pack(uint left, uint right) | |
{ | |
// shift the second integer and store in MSB | |
// combine the first integer using "OR" and store in LSB | |
return new PackedInteger | |
{ | |
// CAST IS IMPORTANT! | |
Value = ((ulong)right << 32) | left | |
}; | |
} | |
public readonly ulong Unpack(out uint left, out uint right) | |
{ | |
// extract the LSB with a mask | |
left = (uint)(Value & 0xFFFFFFFF); // CAST IS IMPORTANT! | |
// extract the MSB by shifting | |
right = (uint)(Value >> 32); // CAST IS IMPORTANT! | |
return Value; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment