I've been wanting to start a little side project which would be a small networking wrapper around enet. To get started I worked on creating this Packet class which would wrap all the data sent and received providing easy methods to add and retrieve the data. I did get the class working with char, c-strings, and std::strings but after trying to add support for integer types it hasn't worked so well. The class is based on code code from irrNetLite but I was trying to do it without the dependencies on the irrlicht types such as irr::array.
Here is the header file for the class:
LPacket.h
Code:
// BEGIN Includes
#include "LTypes.h"
#include <string>
#include <vector>
// END Includes
#ifndef LPACKET_H
#define LPACKET_H
class LPacket {
public:
LPacket();
LPacket(const char* buff, const unsigned int buffSize);
// Methods to append data to the packet
LPacket& operator << (c8 data);
LPacket& operator << (u8 data);
LPacket& operator << (u16 data);
LPacket& operator << (u32 data);
LPacket& operator << (s8 data);
LPacket& operator << (s16 data);
LPacket& operator << (s32 data);
LPacket& operator << (f32 data);
LPacket& operator << (f64 data);
LPacket& operator << (c8* data);
LPacket& operator << (std::string& data);
LPacket& operator << (LPacket& data);
// Methods to retrieve data from the packet
void operator >> (c8& data);
void operator >> (u8& data);
void operator >> (u16& data);
void operator >> (u32& data);
void operator >> (s8& data);
void operator >> (s16& data);
void operator >> (s32& data);
void operator >> (f32& data);
void operator >> (f64& data);
void operator >> (c8* data);
void operator >> (std::string& data);
/**
* Retrieve that packet's data.
*
* @return char*
*/
c8* getData();
/**
* Retrieve that packet's data.
*
* @return const char*
*/
const c8* getConstData();
/**
* Reset the internal read position.
*/
void resetPos();
/**
* Clear the packet contents.
*/
void clearData();
/**
* Retrieve the size in bytes of the packet.
*
* @return unsigned int
*/
u32 getSize();
private:
/**
* Position in packet.
*
* @var unsigned
*/
u32 pos;
/**
* Packet contents.
*
* @var std::vector<char>
*/
std::vector<u8> buffer;
};
#endif /* LPACKET_H */
Here is the CPP file for the class:
Code:
// BEGIN Includes
#include "LPacket.h"
#include <memory.h>
#include <stdio.h>
#include <iostream>
// END Includes
#ifndef LPACKET_CPP
#define LPACKET_CPP
/**
* Default constructor.
*/
LPacket::LPacket() {
this->pos = 0;
}
/**
* Contructor.
*
* @param const char* buff Intial buffer contents.
* @param const unsigned int buffSize Inital buffer size.
*/
LPacket::LPacket(const char* buff, const unsigned int buffSize) {
// @TODO: Implement
this->pos = 0;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (c8 data) {
// Append data
std::copy(&data, &data + 1, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (u8 data) {
// Append data
std::copy(&data, &data + 1, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (u16 data) {
// Append data
std::copy(&data, &data + 2, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (u32 data) {
// Append data
std::copy(&data, &data + 4, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (s8 data) {
// Append data
std::copy(&data, &data + 1, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (s16 data) {
// Append data
std::copy(&data, &data + 2, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (s32 data) {
// Append data
std::copy(&data, &data + 4, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (f32 data) {
// Append data
std::copy(&data, &data + 4, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (f64 data) {
// Append data
std::copy(&data, &data + 8, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (c8* data) {
unsigned short dataSize = (unsigned short)strlen(data) + 1;
// Append data size
std::copy(&dataSize, &dataSize + 2, std::back_inserter(this->buffer));
// Append data
std::copy(&data[0], &data[0] + dataSize, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (std::string& data) {
unsigned short dataSize = (unsigned short)data.size();
// Append data size
std::copy(&dataSize, &dataSize + 2, std::back_inserter(this->buffer));
// Append data
std::copy(&data[0], &data[0] + dataSize, std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to append data.
*/
LPacket& LPacket::operator << (LPacket& data) {
// Append packet
std::copy(data.getData(), data.getData() + data.getSize(), std::back_inserter(this->buffer));
return *this;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (c8& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 1, &data);
pos++;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (u8& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 1, &data);
pos++;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (u16& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 2, &data);
pos += 2;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (u32& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 4, &data);
pos += 4;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (s8& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 1, &data);
pos++;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (s16& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 2, &data);
pos += 2;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (s32& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 4, &data);
pos += 4;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (f32& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 4, &data);
pos += 4;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (f64& data) {
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 8, &data);
pos += 8;
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (c8* data) {
// Retrieve data size
unsigned short size;
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 2, &size);
pos += 2;
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + size, data);
pos += size;
data[size] = '\0';
}
/**
* Operator method to retrieve data.
*/
void LPacket::operator >> (std::string &data) {
// Retrieve data size
unsigned short size;
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + 2, &size);
pos += 2;
// Retrieve data
std::copy(&this->buffer[0] + pos, &this->buffer[0] + pos + size, std::back_inserter(data));
pos += size;
data.append("\0");
}
/**
* Retrieve that packet's data.
*
* @return char*
*/
c8* LPacket::getData() {
return (c8*)&this->buffer[0];
}
/**
* Retrieve that packet's data.
*
* @return const char*
*/
const c8* LPacket::getConstData() {
return (const c8*)&this->buffer[0];
}
/**
* Reset the internal read position.
*/
void LPacket::resetPos() {
pos = 0;
}
/**
* Clear the packet contents.
*/
void LPacket::clearData() {
this->buffer.clear();
}
/**
* Retrieve the size in bytes of the packet.
*
* @return unsigned int
*/
u32 LPacket::getSize() {
return this->buffer.size();
}
#endif /* LPACKET_CPP */
Here is the header file for types:
LTypes.h
Code:
// BEGIN Includes
// END Includes
#ifndef LTYPES_H
#define LTYPES_H
/**
* 8 bit unsigned variable.
*/
typedef unsigned char u8;
/**
* 8 bit signed variable.
*/
typedef signed char s8;
/**
* 8 bit character variable.
*/
typedef char c8;
/**
* 16 bit signed variable.
*/
typedef unsigned short u16;
/**
* 16 bit signed variable.
*/
typedef signed short s16;
/**
* 32 bit unsigned variable.
*/
typedef unsigned int u32;
/**
* 32 bit signed variable.
*/
typedef signed int s32;
/**
* 32 bit signed variable.
*
* Unused and supposedly only supported by Microsoft compilers, thus commented out.
*/
//typedef __int64 s64;
/**
* 32 bit floating point variable.
*/
typedef float f32;
/**
* 64 bit floating point variable.
*/
typedef double f64;
#endif /* LTYPES_H */
and finally here is the testing code:
Code:
#include "LPacket.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <memory.h>
int main(int argc, char **argv) {
// Declare our packet object
LPacket packet;
// Prepare some data to add to the packet
std::string s1 = "This is a string!";
std::string s2 = "This had better.";
char cS[21] = "C-Style strings!";
c8 c = 'i';
u32 i1 = 1024;
u16 i2 = 256;
// Add the data to the packet
packet << s1 << s2 << 'h';
packet << cS;
packet << c;
packet << i1;
packet << i2;
///
std::string rS1, rS2;
char rC1;
char rCS[21];
c8 rC2;
u32 rI1;
u16 rI2;
// Get the data from the packet
packet >> rS1;
packet >> rS2;
packet >> rC1;
packet >> rCS;
packet >> rC2;
packet >> rI1;
packet >> rI2;
// Output the recieved data
std::cout << "String - " << rS1 << std::endl;
std::cout << "String - " << rS2 << std::endl;
std::cout << "char - " << rC1 << std::endl;
std::cout << "char* - " << rCS << std::endl;
std::cout << "char - " << rC2 << std::endl;
std::cout << "u32 - " << rI1 << std::endl;
std::cout << "u16 - " << rI2 << std::endl;
return 0;
}
Expected output should be like so:
Code:
String - This is a string!
String - This had better.
char - h
char* - C-Style strings!
char - i
u32 - 1024
u16 - 256
Instead I get:
Code:
String - This is a string!
String - This had better.
char - h
char* - C-Style strings!
char -
u32 - 0
u16 - 0
An interesting thing I noticed when I tried to use GDB to debug (never really used it before though) was that initially the call to packet >> rC2; would work correctly and set rC2 to 'i', but after the call to packet >> rI1; or packet >> rI2; it would somehow change into some "garbage" value. I'm quite confused as to why that would happen.
I also compiled with: gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
Thus, if anyone could assist me with this I would be utterly grateful,
thanks in advance.