#include "Packing.h" /*************************** Packing ***************************/ #include 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; } } }