M1-nw-project/Bytes.cpp

171 lines
3.9 KiB
C++

/***************************************************************************
* By Théophile Bastian, 2017
* M1 Network course project at ENS Cachan, Juliusz Chroboczek.
* License: WTFPL v2 <http://www.wtfpl.net/>
**************************************************************************/
/***************************************************************************
* Reused from a former project, by Théophile Bastian & Nathanaël Courant
* git@github.com:tobast/sysres-pikern.git
**************************************************************************/
#include "Bytes.h"
#include <cstring>
#include <algorithm>
#include <arpa/inet.h>
using namespace std;
Bytes::Bytes() : data(), firstIndex(0) {}
Bytes::Bytes(const void* buff, size_t len) : data(), firstIndex(0) {
data.reserve(len);
for(size_t pos=0; pos < len; pos++)
data.push_back(((u8*)buff)[pos]);
}
u8& Bytes::operator[](const size_t pos) {
if(pos < size())
return data[pos+firstIndex];
throw OutOfRange();
}
u8 Bytes::operator[](const size_t pos) const {
if(pos < size())
return data[pos+firstIndex];
throw OutOfRange();
}
u16 Bytes::ushortAt(const size_t pos) const {
if(pos+1 < size())
return (((u16)data[pos+firstIndex+1])<<8)+data[pos+firstIndex];
throw OutOfRange();
}
size_t Bytes::size() const {
return data.size() - firstIndex;
}
Bytes& Bytes::operator<<(char v) {
insertData<char>(v);
return *this;
}
Bytes& Bytes::operator<<(u8 v) {
insertData<u8>(v);
return *this;
}
Bytes& Bytes::operator<<(u16 v) {
insertData<u16>(v);
// insertData<u16>(htons(v));
return *this;
}
Bytes& Bytes::operator<<(u32 v) {
insertData<u32>(v);
// insertData<u32>(htonl(v));
return *this;
}
Bytes& Bytes::operator<<(u64 v) {
insertData<u64>(v);
return *this;
}
Bytes& Bytes::operator<<(const Bytes& v) {
data.reserve(data.size() + v.size());
for(size_t byte=0; byte < v.size(); byte++)
data.push_back(v[byte]);
return *this;
}
Bytes& Bytes::operator<<(const char* str) {
unsigned len = strlen(str);
data.reserve(data.size() + len);
for(unsigned byte=0; byte < len; byte++)
data.push_back(str[byte]);
return *this;
}
Bytes& Bytes::operator>>(u8& v) {
extractData<u8>(v);
return *this;
}
Bytes& Bytes::operator>>(u16& v) {
extractData<u16>(v);
// v = htons(v);
return *this;
}
Bytes& Bytes::operator>>(u32& v) {
extractData<u32>(v);
// v = htonl(v);
return *this;
}
Bytes& Bytes::operator>>(u64& v) {
extractData<u64>(v);
return *this;
}
Bytes& Bytes::operator>>(char& v) {
extractData<char>(v);
return *this;
}
Bytes Bytes::extract(size_t len) {
Bytes out = sub(0, len); // Handles out of range
firstIndex += len;
return out;
}
void Bytes::operator=(const Bytes& oth) {
firstIndex=0;
data.clear();
data.reserve(oth.size());
for(size_t pos=0; pos < oth.size(); pos++)
data.push_back(oth[pos]);
}
Bytes Bytes::sub(size_t beg, size_t len) const {
if(beg+len > size())
throw OutOfRange();
Bytes out;
for(size_t byte=0; byte < len; byte++)
out << (*this)[byte+beg];
return out;
}
void Bytes::writeToBuffer(void* buff, unsigned maxLen) const {
if(maxLen == 0)
maxLen = size();
for(size_t pos=0; pos < min((size_t)maxLen, size()); pos++)
((u8*)buff)[pos] = (*this)[pos];
}
char charOfDigit(u8 dig) {
if(dig < 10)
return dig+'0';
return dig+'A'-10;
}
void hexdumpByte(Bytes& dest, u8 b) {
dest << charOfDigit(b/16) << charOfDigit(b & 0xf);
}
void Bytes::hexdump(Bytes& dest) const {
for(unsigned pos=0; pos < size(); pos++) {
hexdumpByte(dest, (*this)[pos]);
if(pos % 32 == 31)
dest << '\n';
else if(pos % 4 == 3)
dest << ' ';
}
if(size() % 32 != 0)
dest << '\n';
}
template<typename T> void Bytes::extractData(T& v) {
if(size() < sizeof(v))
throw OutOfRange();
for(size_t byte=0; byte < sizeof(v); byte++)
v = (v<<8) | data[firstIndex+byte];
firstIndex += sizeof(v);
}
template<typename T> void Bytes::insertData(T v) {
for(int byte=sizeof(v)-1; byte >= 0; byte--) {
data.push_back((u8) (v >> (8*byte)));
}
}