/*************************************************************************** * By Théophile Bastian, 2017 * M1 Network course project at ENS Cachan, Juliusz Chroboczek. * License: WTFPL v2 **************************************************************************/ /*************************************************************************** * Reused from a former project, by Théophile Bastian & Nathanaël Courant * git@github.com:tobast/sysres-pikern.git **************************************************************************/ #include "Bytes.h" #include #include #include 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(v); return *this; } Bytes& Bytes::operator<<(u8 v) { insertData(v); return *this; } Bytes& Bytes::operator<<(u16 v) { insertData(v); // insertData(htons(v)); return *this; } Bytes& Bytes::operator<<(u32 v) { insertData(v); // insertData(htonl(v)); return *this; } Bytes& Bytes::operator<<(u64 v) { insertData(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(v); return *this; } Bytes& Bytes::operator>>(u16& v) { extractData(v); // v = htons(v); return *this; } Bytes& Bytes::operator>>(u32& v) { extractData(v); // v = htonl(v); return *this; } Bytes& Bytes::operator>>(u64& v) { extractData(v); return *this; } Bytes& Bytes::operator>>(char& v) { extractData(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 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 void Bytes::insertData(T v) { for(int byte=sizeof(v)-1; byte >= 0; byte--) { data.push_back((u8) (v >> (8*byte))); } }