]> Dogcows Code - chaz/yoink/blobdiff - src/moof/packet.cc
the massive refactoring effort
[chaz/yoink] / src / moof / packet.cc
diff --git a/src/moof/packet.cc b/src/moof/packet.cc
new file mode 100644 (file)
index 0000000..0440b7d
--- /dev/null
@@ -0,0 +1,398 @@
+
+/*]  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 <algorithm>
+#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+#include <cstdlib>
+
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <SDL/SDL.h>
+
+#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 moof {
+       
+
+packet::packet(size_t size) :
+       buffer_((char*)malloc(size)),
+       size_(size) {}
+
+packet::packet(const char* data, size_t size) :
+       buffer_((char*)malloc(size)),
+       size_(size),
+       state_(size),
+       saved_(size)
+{
+       if (buffer_) memcpy(buffer_, data, size);
+       else throw std::length_error("out of memory");
+}
+
+
+packet::packet(const packet& copy) :
+       buffer_((char*)malloc(copy.size_)),
+       size_(copy.size_),
+       state_(copy.state_),
+       saved_(copy.saved_)
+{
+       if (buffer_) memcpy(buffer_, copy.buffer_, size_);
+       else throw std::length_error("out of memory");
+}
+
+packet& packet::operator = (const packet& copy)
+{
+       free(buffer_);
+       buffer_ = (char*)malloc(copy.size_);
+       size_ = copy.size_;
+       if (buffer_) memcpy(buffer_, copy.buffer_, size_);
+       else throw std::length_error("out of memory");
+
+       state_ = copy.state_;
+       saved_ = copy.saved_;
+       return *this;
+}
+
+
+packet::~packet()
+{
+       free(buffer_);
+}
+
+
+packet& packet::operator << (bool value)
+{
+       int bit = state_.write_bool_num % 8;
+       if (bit == 0)
+       {
+               state_.write_bool_mark = state_.write_mark;
+
+               unsigned char byte = 0;
+               if (write(&byte, 1) == 0) throw std::length_error("out of memory");
+       }
+
+       if (value) buffer_[state_.write_bool_mark] |= (1 << bit);
+       ++state_.write_bool_num;
+
+       return *this;
+}
+
+
+packet& packet::operator << (int8_t value)
+{
+       return *this << reinterpret_cast<uint8_t&>(value);
+}
+
+packet& packet::operator << (int16_t value)
+{
+       return *this << reinterpret_cast<uint16_t&>(value);
+}
+
+packet& packet::operator << (int32_t value)
+{
+       return *this << reinterpret_cast<uint32_t&>(value);
+}
+
+packet& packet::operator << (int64_t value)
+{
+       return *this << reinterpret_cast<uint64_t&>(value);
+}
+
+
+packet& packet::operator << (uint8_t value)
+{
+       if (write(&value, sizeof(value)) != sizeof(value))
+       {
+               throw std::length_error("out of memory");
+       }
+       return *this;
+}
+
+packet& packet::operator << (uint16_t value)
+{
+       value = htons(value);
+       if (write(&value, sizeof(value)) != sizeof(value))
+       {
+               throw std::length_error("out of memory");
+       }
+       return *this;
+}
+
+packet& packet::operator << (uint32_t value)
+{
+       value = htonl(value);
+       if (write(&value, sizeof(value)) != sizeof(value))
+       {
+               throw std::length_error("out of memory");
+       }
+       return *this;
+}
+
+packet& packet::operator << (uint64_t value)
+{
+       value = htonll(value);
+       if (write(&value, sizeof(value)) != sizeof(value))
+       {
+               throw std::length_error("out of memory");
+       }
+       return *this;
+}
+
+packet& packet::operator << (float value)
+{
+       // XXX: assumes the ieee-754
+       uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
+       *integer = htonl(*integer);
+       if (write(integer, sizeof(value)) != sizeof(value))
+       {
+               throw std::length_error("out of memory");
+       }
+       return *this;
+}
+
+packet& packet::operator << (double value)
+{
+       // XXX: assumes the ieee-754
+       uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
+       *integer = htonll(*integer);
+       if (write(integer, sizeof(value)) != sizeof(value))
+       {
+               throw std::length_error("out of memory");
+       }
+       return *this;
+}
+
+size_t packet::write(const void* bytes, size_t size)
+{
+       size_t num_bytes = std::min(size, size_ - state_.write_mark);
+       if (!buffer_ || num_bytes < size)
+       {
+               int num_pages = 1 + size / PAGE_SIZE;
+               int new_size = size_ + num_pages * PAGE_SIZE;
+               char* new_buffer = (char*)realloc(buffer_, new_size);
+               if (new_buffer)
+               {
+                       buffer_ = new_buffer;
+                       size_ = new_size;
+                       num_bytes = size;
+               }
+               if (!buffer_) return 0;
+       }
+       memcpy(buffer_ + state_.write_mark, bytes, num_bytes);
+       state_.write_mark += num_bytes;
+       return num_bytes;
+}
+
+
+packet& packet::operator >> (bool& value)
+{
+       int bit = state_.read_bool_num % 8;
+       if (bit == 0)
+       {
+               state_.read_bool_mark = state_.read_mark;
+
+               unsigned char byte = 0;
+               if (read(&byte, 1) == 0) throw std::out_of_range("end of packet");
+       }
+
+       value = 1 & (buffer_[state_.read_bool_mark] >> bit);
+       ++state_.read_bool_num;
+
+       return *this;
+}
+
+packet& packet::operator >> (int8_t& value)
+{
+       return *this >> reinterpret_cast<uint8_t&>(value);
+}
+
+packet& packet::operator >> (int16_t& value)
+{
+       return *this >> reinterpret_cast<uint16_t&>(value);
+}
+
+packet& packet::operator >> (int32_t& value)
+{
+       return *this >> reinterpret_cast<uint32_t&>(value);
+}
+
+packet& packet::operator >> (int64_t& value)
+{
+       return *this >> reinterpret_cast<uint64_t&>(value);
+}
+
+packet& packet::operator >> (uint8_t& value)
+{
+       if (read(&value, sizeof(value)) != sizeof(value))
+       {
+               throw std::out_of_range("end of packet");
+       }
+       return *this;
+}
+
+packet& packet::operator >> (uint16_t& value)
+{
+       if (read(&value, sizeof(value)) != sizeof(value))
+       {
+               throw std::out_of_range("end of packet");
+       }
+       value = ntohs(value);
+       return *this;
+}
+
+packet& packet::operator >> (uint32_t& value)
+{
+       if (read(&value, sizeof(value)) != sizeof(value))
+       {
+               throw std::out_of_range("end of packet");
+       }
+       value = ntohl(value);
+       return *this;
+}
+
+packet& packet::operator >> (uint64_t& value)
+{
+       if (read(&value, sizeof(value)) != sizeof(value))
+       {
+               throw std::out_of_range("end of packet");
+       }
+       value = ntohll(value);
+       return *this;
+}
+
+packet& packet::operator >> (float& value)
+{
+       // XXX: assumes the ieee-754
+       uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
+       if (read(integer, sizeof(value)) != sizeof(value))
+       {
+               throw std::out_of_range("end of packet");
+       }
+       *integer = htonl(*integer);
+       return *this;
+}
+
+packet& packet::operator >> (double& value)
+{
+       // XXX: assumes the ieee-754
+       uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
+       if (read(integer, sizeof(value)) != sizeof(value))
+       {
+               throw std::out_of_range("end of packet");
+       }
+       *integer = htonll(*integer);
+       return *this;
+}
+
+size_t packet::read(void* bytes, size_t size)
+{
+       size_t num_bytes = std::min(size, state_.write_mark - state_.read_mark);
+       memcpy(bytes, buffer_ + state_.read_mark, num_bytes);
+       state_.read_mark += num_bytes;
+       return num_bytes;
+}
+
+
+void packet::clear()
+{
+       state_.read_mark = state_.write_mark;
+       state_.read_bool_mark = 0;
+       state_.read_bool_num = 0;
+       state_.write_bool_mark = 0;
+       state_.write_bool_num = 0;
+}
+
+
+void packet::save()
+{
+       saved_ = state_;
+}
+
+void packet::revert()
+{
+       state_ = saved_;
+}
+
+
+} // namespace moof
+
This page took 0.030246 seconds and 4 git commands to generate.