/*] Copyright (c) 2009-2010, Charles McGarvey [************************** **] All rights reserved. * * vi:ts=4 sw=4 tw=75 * * Distributable under the terms and conditions of the 2-clause BSD license; * see the file COPYING for a complete text of the license. * **************************************************************************/ #include "../config.h" #include #if HAVE_BYTESWAP_H #include #endif #include #if HAVE_ARPA_INET_H #include #endif #include #include "Packet.hh" #ifndef bswap_16 #define bswap_16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) #endif #ifndef bswap_32 #define bswap_32(x) ((((x) & 0xff000000) >> 24) | \ (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | \ (((x) & 0x000000ff) << 24)) #endif #ifndef bswap_64 #define bswap_64(x) (((x) << 56) | \ (((x) << 40) & 0xff000000000000ULL) | \ (((x) << 24) & 0xff0000000000ULL) | \ (((x) << 8) & 0xff00000000ULL) | \ (((x) >> 8) & 0xff000000ULL) | \ (((x) >> 24) & 0xff0000ULL) | \ (((x) >> 40) & 0xff00ULL) | \ ((x) >> 56)) #endif #if !HAVE_ARPA_INET_H static uint16_t htons(uint16_t x) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN return bswap_16(x); #else return x; #endif } static uint16_t ntohs(uint16_t x) { return htons(x); } static uint32_t htonl(uint32_t x) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN return bswap_32(x); #else return x; #endif } static uint32_t ntohl(uint32_t x) { return htonl(x); } #endif static uint64_t htonll(uint64_t x) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN return bswap_64(x); #else return x; #endif } static uint64_t ntohll(uint64_t x) { return htonll(x); } namespace Mf { Packet::Packet(size_t capacity) : mBuffer((char*)malloc(capacity)), mSize(capacity), mR(0), mW(0), mOriginalW(0), mBoolR(0), mBoolW(0), mBoolNumR(0), mBoolNumW(0) {} Packet::Packet(const char* data, size_t size) : mBuffer((char*)malloc(size)), mSize(size), mR(0), mW(size), mOriginalW(size), mBoolR(0), mBoolW(0), mBoolNumR(0), mBoolNumW(0) { if (mBuffer) memcpy(mBuffer, data, size); } Packet::Packet(const Packet& copy) : mBuffer((char*)malloc(copy.mSize)), mSize(copy.mSize), mR(copy.mR), mW(copy.mW), mOriginalW(copy.mOriginalW), mBoolR(copy.mBoolR), mBoolW(copy.mBoolW), mBoolNumR(copy.mBoolNumR), mBoolNumW(copy.mBoolNumW) { if (mBuffer) memcpy(mBuffer, copy.mBuffer, mSize); } Packet& Packet::operator=(const Packet& copy) { free(mBuffer); mBuffer = (char*)malloc(copy.mSize); mSize = copy.mSize; mR = copy.mR; mW = copy.mW; mOriginalW = copy.mOriginalW; mBoolR = copy.mBoolR; mBoolW = copy.mBoolW; mBoolNumR = copy.mBoolNumR; mBoolNumW = copy.mBoolNumW; if (mBuffer) memcpy(mBuffer, copy.mBuffer, mSize); return *this; } Packet::~Packet() { free(mBuffer); } bool Packet::put(bool value) { int bit = mBoolNumW % 8; if (bit == 0) { mBoolW = mW; unsigned char byte = 0; if (write(&byte, 1) == 0) return false; } if (value) mBuffer[mBoolW] |= (1 << bit); ++mBoolNumW; return true; } bool Packet::put(int8_t value) { return put(uint8_t(value)); } bool Packet::put(int16_t value) { return put(uint16_t(value)); } bool Packet::put(int32_t value) { return put(uint32_t(value)); } bool Packet::put(int64_t value) { return put(uint64_t(value)); } bool Packet::put(uint8_t value) { return write(&value, sizeof(value)) == sizeof(value); } bool Packet::put(uint16_t value) { value = htons(value); return write(&value, sizeof(value)) == sizeof(value); } bool Packet::put(uint32_t value) { value = htonl(value); return write(&value, sizeof(value)) == sizeof(value); } bool Packet::put(uint64_t value) { value = htonll(value); return write(&value, sizeof(value)) == sizeof(value); } bool Packet::put(float value) { // XXX: assumes the ieee-754 uint32_t* integer = reinterpret_cast(&value); *integer = htonl(*integer); return write(integer, sizeof(value)) == sizeof(value); } bool Packet::put(double value) { // XXX: assumes the ieee-754 uint64_t* integer = reinterpret_cast(&value); *integer = htonll(*integer); return write(integer, sizeof(value)) == sizeof(value); } size_t Packet::write(const void* bytes, size_t size) { size_t nBytes = std::min(size, mSize - mW); if (!mBuffer || nBytes < size) { int nPages = 1 + size / PAGE_SIZE; int newSize = mSize + nPages * PAGE_SIZE; char* newBuffer = (char*)realloc(mBuffer, newSize); if (newBuffer) { mBuffer = newBuffer; mSize = newSize; nBytes = size; } if (!mBuffer) return 0; } memcpy(mBuffer + mW, bytes, nBytes); mW += nBytes; return nBytes; } bool Packet::get(bool& value, int flags) { int bit = mBoolNumR % 8; if (bit == 0) { mBoolR = mR; unsigned char byte = 0; if (read(&byte, 1, flags) == 0) return false; } value = 1 & (mBuffer[mBoolR] >> bit); if (!(flags & PEEK)) ++mBoolNumR; return true; } bool Packet::get(int8_t& value, int flags) { return get((uint8_t&)value, flags); } bool Packet::get(int16_t& value, int flags) { return get((uint16_t&)value, flags); } bool Packet::get(int32_t& value, int flags) { return get((uint32_t&)value, flags); } bool Packet::get(int64_t& value, int flags) { return get((uint64_t&)value, flags); } bool Packet::get(uint8_t& value, int flags) { size_t numBytes = read(&value, sizeof(value), flags); return numBytes == sizeof(value); } bool Packet::get(uint16_t& value, int flags) { size_t numBytes = read(&value, sizeof(value), flags); value = ntohs(value); return numBytes == sizeof(value); } bool Packet::get(uint32_t& value, int flags) { size_t numBytes = read(&value, sizeof(value), flags); value = ntohl(value); return numBytes == sizeof(value); } bool Packet::get(uint64_t& value, int flags) { size_t numBytes = read(&value, sizeof(value), flags); value = ntohll(value); return numBytes == sizeof(value); } bool Packet::get(float& value, int flags) { // XXX: assumes the ieee-754 uint32_t* integer = reinterpret_cast(&value); size_t numBytes = read(integer, sizeof(value)); *integer = htonl(*integer); return numBytes == sizeof(value); } bool Packet::get(double& value, int flags) { // XXX: assumes the ieee-754 uint64_t* integer = reinterpret_cast(&value); size_t numBytes = read(integer, sizeof(value)); *integer = htonll(*integer); return numBytes == sizeof(value); } size_t Packet::read(void* bytes, size_t size, int flags) { size_t nBytes = std::min(size, mW - mR); memcpy(bytes, mBuffer + mR, nBytes); if (!(flags & PEEK)) mR += nBytes; return nBytes; } void Packet::clear() { mR = 0; mW = 0; mBoolR = 0; mBoolW = 0; mBoolNumR = 0; mBoolNumW = 0; } void Packet::reset() { mR = 0; mW = mOriginalW; mBoolR = 0; mBoolW = 0; mBoolNumR = 0; mBoolNumW = 0; } } // namespace Mf