CompactIndex
CompactIndex is a special integer data type used very often in the Unreal Engine. It is used to reduce the size of a integer. However in the worst case scenario it takes up one extra byte (5bytes instead of 4), but this isn't often the case. CompactIndex is for example used to store the length of a string.
A CompactIndex tries to use as less bytes as possible to store the integer's (32bit) value.
The bytes
1st Byte
The MSB (Most Significant Bit) flags if the string is in UTF-16 encoding instead of normal ASCII. Thus the MSB only has a meaning when used for string length.
MSB-1 defines if there's another byte following this byte that should be included with the CompactIndex.
The other 6 bits are used for the value. Therefor the maximum value in the first byte is (2^6)-1 = 63
2nd to 4th Byte
The MSB defines if there's another byte following this byte that should be included with the CompactIndex.
The rest is used for the value. (2^7)-1 = 127
5th Byte
The whole byte is used for the value. However, because the first 4 bytes already consume 27 of the 32 bits only 5 bits are used in this byte.
Integer to CompactIndex
B1 = 1st byte of the CompactIndex; B2 = 2nd byte of the CompactIndex; etc.
//TODO
final function IntToIndex( int Integer, out byte data[255], out byte ptr ) { local int val; val = abs(Integer); if( val != Integer ) data[ptr] = 0x80; // B1 sign bit data[ptr] += val & 0x3f; // B1 data, 6 bits val = val >> 6; if( val != 0 ) { data[ptr] += 0x40; // B1 continue bit data[++ptr] = val & 0x7f; // B2 data, 7 bits val = val >> 7; if( val != 0 ) { data[ptr] += 0x80; // B2 continue bit data[++ptr] = val & 0x7f; // B3 data, 7 bits val = val >> 7; if( val != 0 ) { data[ptr] += 0x80; // B3 continue bit data[++ptr] = val & 0x7f; // B4 data, 7 bits val = val >> 7; if( val != 0 ) { data[ptr] += 0x80; // B4 continue bit data[++ptr] = val & 0x1f; // B5 data, 5 bits } } } } }
CompactIndex to Integer
B1 = 1st byte of the CompactIndex; B2 = 2nd byte of the CompactIndex; etc.
Integer = B1 & 0x3F; if (B1 & 0x40) // got a 2nd byte { Integer += (B2 & 0x3F) << 6; if (B2 & 0x80) // got a 3rd byte { Integer += (B3 & 0x3F) << 13; if (B3 & 0x80) // got a 4th byte { Integer += (B4 & 0x3F) << 20; if (B4 & 0x80) // got a 5th byte { Integer += (B5 & 0x3F) << 27; } } } }
Example:
final function int IndexToInt( byte data[255], optional byte ptr ) { local byte B1,B2,B3,B4,B5; local int Integer; B1 = data[ptr++]; Integer = B1 & 0x3f; if((B1 & 0x40)!=0) { B2 = data[ptr++]; Integer += (B2 & 0x7f) << 6; if((B2 & 0x80)!=0) { B3 = data[ptr++]; Integer += (B3 & 0x7f) << 13; if((B3 & 0x80)!=0) { B4 = data[ptr++]; Integer += (B4 & 0x7f) << 20; if((B4 & 0x80)!=0) { B5 = data[ptr++]; Integer += B5 << 27; } } } } if((B1 & 0x80)!=0) Integer = -Integer; return Integer; }
El Muerte: need this description when I'm going to port by UE2 query specification to the wiki