347 lines
6.7 KiB
C++
347 lines
6.7 KiB
C++
#include "Packing.h"
|
|
|
|
/***************************
|
|
Packing
|
|
***************************/
|
|
|
|
#include <stdint.h>
|
|
|
|
namespace Oyster
|
|
{
|
|
namespace Packing
|
|
{
|
|
//bool (1-bit)
|
|
void Pack(unsigned char buffer[], bool i)
|
|
{
|
|
*buffer++ = i;
|
|
}
|
|
|
|
//char (8-bit)
|
|
void Pack(unsigned char buffer[], char i)
|
|
{
|
|
*buffer++ = i;
|
|
}
|
|
|
|
void Pack(unsigned char buffer[], unsigned char i)
|
|
{
|
|
*buffer++ = i;
|
|
}
|
|
|
|
//short (16-bit)
|
|
void Pack(unsigned char buffer[], short i)
|
|
{
|
|
*buffer++ = i >> 8;
|
|
*buffer++ = (char)i;
|
|
}
|
|
|
|
void Pack(unsigned char buffer[], unsigned short i)
|
|
{
|
|
*buffer++ = i >> 8;
|
|
*buffer++ = (char)i;
|
|
}
|
|
|
|
//int (32-bit)
|
|
void Pack(unsigned char buffer[], int i)
|
|
{
|
|
*buffer++ = i >> 24;
|
|
*buffer++ = i >> 16;
|
|
*buffer++ = i >> 8;
|
|
*buffer++ = i;
|
|
}
|
|
|
|
void Pack(unsigned char buffer[], unsigned int i)
|
|
{
|
|
*buffer++ = i >> 24;
|
|
*buffer++ = i >> 16;
|
|
*buffer++ = i >> 8;
|
|
*buffer++ = i;
|
|
}
|
|
|
|
//__int64 (64-bit)
|
|
void Pack(unsigned char buffer[], __int64 i)
|
|
{
|
|
*buffer++ = (char)(i >> 56);
|
|
*buffer++ = (char)(i >> 48);
|
|
*buffer++ = (char)(i >> 40);
|
|
*buffer++ = (char)(i >> 32);
|
|
*buffer++ = (char)(i >> 24);
|
|
*buffer++ = (char)(i >> 16);
|
|
*buffer++ = (char)(i >> 8);
|
|
*buffer++ = (char)i;
|
|
}
|
|
|
|
void Pack(unsigned char buffer[], unsigned __int64 i)
|
|
{
|
|
*buffer++ = (char)(i >> 56);
|
|
*buffer++ = (char)(i >> 48);
|
|
*buffer++ = (char)(i >> 40);
|
|
*buffer++ = (char)(i >> 32);
|
|
*buffer++ = (char)(i >> 24);
|
|
*buffer++ = (char)(i >> 16);
|
|
*buffer++ = (char)(i >> 8);
|
|
*buffer++ = (char)i;
|
|
}
|
|
|
|
//floating point (32, 64-bit)
|
|
void Pack(unsigned char buffer[], float i)
|
|
{
|
|
int tempFloat = (int)Pack754(i, 32, 8);
|
|
Pack(buffer, tempFloat);
|
|
}
|
|
|
|
void Pack(unsigned char buffer[], double i)
|
|
{
|
|
__int64 tempDouble = Pack754(i, 64, 11);
|
|
Pack(buffer, tempDouble);
|
|
}
|
|
|
|
//string
|
|
void Pack(unsigned char buffer[], char str[])
|
|
{
|
|
short len = (short)strlen(str);
|
|
Pack(buffer, len);
|
|
buffer += 2;
|
|
memcpy(buffer, str, len);
|
|
}
|
|
|
|
void Pack(unsigned char buffer[], std::string& str)
|
|
{
|
|
short len = (short)str.length();
|
|
Pack(buffer, len);
|
|
buffer += 2;
|
|
memcpy(buffer, str.c_str(), len);
|
|
}
|
|
|
|
unsigned __int64 Pack754(long double f, unsigned bits, unsigned expbits)
|
|
{
|
|
long double fnorm;
|
|
int shift;
|
|
long long sign, exp, significand;
|
|
unsigned significandbits = bits - expbits - 1; // -1 for sign bit
|
|
|
|
if (f == 0.0)
|
|
return 0; // get this special case out of the way
|
|
|
|
// check sign and begin normalization
|
|
if (f < 0)
|
|
{
|
|
sign = 1;
|
|
fnorm = -f;
|
|
}
|
|
else
|
|
{
|
|
sign = 0;
|
|
fnorm = f;
|
|
}
|
|
|
|
// get the normalized form of f and track the exponent
|
|
shift = 0;
|
|
while(fnorm >= 2.0)
|
|
{
|
|
fnorm /= 2.0;
|
|
shift++;
|
|
}
|
|
|
|
while(fnorm < 1.0)
|
|
{
|
|
fnorm *= 2.0;
|
|
shift--;
|
|
}
|
|
|
|
fnorm = fnorm - 1.0;
|
|
|
|
// calculate the binary form (non-float) of the significand data
|
|
significand = (long long)(fnorm * ((1LL << significandbits) + 0.5f));
|
|
|
|
// get the biased exponent
|
|
exp = shift + ((1 << (expbits - 1)) - 1); // shift + bias
|
|
|
|
// return the final answer
|
|
return (sign << (bits - 1)) | (exp << (bits - expbits - 1)) | significand;
|
|
}
|
|
|
|
/******************************
|
|
Unpacking
|
|
******************************/
|
|
|
|
//bool (1-bit)
|
|
bool Unpackb(unsigned char buffer[])
|
|
{
|
|
return *buffer;
|
|
}
|
|
|
|
//char (8-bit)
|
|
char Unpackc(unsigned char buffer[])
|
|
{
|
|
if(*buffer <= 0x7f)
|
|
{
|
|
return *buffer;
|
|
}
|
|
else
|
|
{
|
|
return (-1 - (unsigned char)(0xffu - *buffer));
|
|
}
|
|
}
|
|
|
|
unsigned char UnpackC(unsigned char buffer[])
|
|
{
|
|
return *buffer;
|
|
}
|
|
|
|
//short (16-bit)
|
|
short Unpacks(unsigned char buffer[])
|
|
{
|
|
short i = ((short)buffer[0] << 8) | buffer[1];
|
|
|
|
if(i > 0x7fffu)
|
|
{
|
|
i = -1 - (unsigned short)(0xffffu - i);
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
unsigned short UnpackS(unsigned char buffer[])
|
|
{
|
|
return ((unsigned int)buffer[0] << 8) | buffer[1];
|
|
}
|
|
|
|
//int (32-bit)
|
|
int Unpacki(unsigned char buffer[])
|
|
{
|
|
int i = ((int)buffer[0] << 24) |
|
|
((int)buffer[1] << 16) |
|
|
((int)buffer[2] << 8) |
|
|
((int)buffer[3]);
|
|
|
|
if(i > 0x7fffffffu)
|
|
{
|
|
i = -1 - (int)(0xffffffffu - i);
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
unsigned int UnpackI(unsigned char buffer[])
|
|
{
|
|
return ((unsigned int)buffer[0] << 24) |
|
|
((unsigned int)buffer[1] << 16) |
|
|
((unsigned int)buffer[2] << 8) |
|
|
((unsigned int)buffer[3]);
|
|
}
|
|
|
|
//__int64 (64-bit)
|
|
__int64 Unpacki64(unsigned char buffer[])
|
|
{
|
|
__int64 i = ((__int64)buffer[0] << 56) |
|
|
((__int64)buffer[1] << 48) |
|
|
((__int64)buffer[2] << 40) |
|
|
((__int64)buffer[3] << 32) |
|
|
((__int64)buffer[4] << 24) |
|
|
((__int64)buffer[5] << 16) |
|
|
((__int64)buffer[6] << 8) |
|
|
(buffer[7]);
|
|
|
|
if(i > 0x7fffffffffffffffu)
|
|
{
|
|
i = -1 - (__int64)(0xffffffffffffffffu - i);
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
unsigned __int64 UnpackI64(unsigned char buffer[])
|
|
{
|
|
|
|
return ((__int64)buffer[0] << 56) |
|
|
((__int64)buffer[1] << 48) |
|
|
((__int64)buffer[2] << 40) |
|
|
((__int64)buffer[3] << 32) |
|
|
((__int64)buffer[4] << 24) |
|
|
((__int64)buffer[5] << 16) |
|
|
((__int64)buffer[6] << 8) |
|
|
((__int64)buffer[7]);
|
|
}
|
|
|
|
//floating point (32, 64-bit)
|
|
float Unpackf(unsigned char buffer[])
|
|
{
|
|
int tempFloat = Unpacki(buffer);
|
|
return (float)Unpack754(tempFloat, 32, 8);
|
|
}
|
|
|
|
double Unpackd(unsigned char buffer[])
|
|
{
|
|
__int64 tempDouble = Unpacki64(buffer);
|
|
return Unpack754(tempDouble, 64, 11);
|
|
}
|
|
|
|
//string
|
|
char* UnpackCStr(unsigned char buffer[])
|
|
{
|
|
short len = UnpackS(buffer);
|
|
char* str = new char[len+1];
|
|
|
|
buffer += 2;
|
|
for(int i = 0; i < len; i++)
|
|
{
|
|
str[i] = buffer[i];
|
|
}
|
|
|
|
str[len] = '\0';
|
|
|
|
return str;
|
|
}
|
|
|
|
std::string UnpackStr(unsigned char buffer[])
|
|
{
|
|
short len = UnpackS(buffer);
|
|
std::string temp;
|
|
temp.resize(len);
|
|
|
|
buffer += 2;
|
|
for(int i = 0; i < len; i++)
|
|
{
|
|
temp[i] = buffer[i];
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
long double Unpack754(unsigned __int64 i, unsigned bits, unsigned expbits)
|
|
{
|
|
long double result;
|
|
long long shift;
|
|
unsigned bias;
|
|
unsigned significandbits = bits - expbits - 1; // -1 for sign bit
|
|
|
|
if (i == 0)
|
|
return 0.0;
|
|
|
|
// pull the significand
|
|
result = (long double)(i&((1LL << significandbits) - 1)); // mask
|
|
result /= (1LL << significandbits); // convert back to float
|
|
result += 1.0f; // add the one back on
|
|
|
|
// deal with the exponent
|
|
bias = (1 << (expbits - 1)) - 1;
|
|
shift = ((i >> significandbits) & ((1LL << expbits) - 1)) - bias;
|
|
while(shift > 0)
|
|
{
|
|
result *= 2.0;
|
|
shift--;
|
|
}
|
|
while(shift < 0)
|
|
{
|
|
result /= 2.0;
|
|
shift++;
|
|
}
|
|
|
|
// sign it
|
|
result *= (i >> (bits - 1)) & 1 ? -1.0 : 1.0;
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|