ich hab hier schon mal vor 1 2 Jahren über genau die selbe Klasse geschrieben die ich euch jetzt zeigen werde. Mein Problem ist dass diese BitStream-Klasse eigentlich zu den includes einer Biblothek gehören soll die ich schreibe. Ich schaffe es aber in GCC (4.4.1 hat Ubuntu soweit ich weiss) nicht dass als reines Header-File zu schreiben, da ich manche Methoden für bestimmte Dateitypen definiere und GCC das im C++-File haben will.
Das ist der Header
Code: Alles auswählen
#ifndef _INCLUDE_yogi_BITSTREAM_
#define _INCLUDE_yogi_BITSTREAM_
/*!
Copright: Kai "DrHalan" Mast - http://www.freakybytes.org
This file is part of yNetwork. See yNetwork.h for license information.
*/
#include <yNetwork/yNetwork.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
namespace yogi
{
class BitStream
{
public:
BitStream()
{
bitIndex = 0;
}
BitStream(const u32 packetSize)
{
bitIndex = 0;
buffer.resize(packetSize, 0);
}
BitStream(const c8* pCharBuffer, const u32 length)
{
bitIndex = 0;
//Load in the buffer to be used
buffer.resize(length);
memcpy(&buffer[0], pCharBuffer, length);
}
//! WRITE FUNCTIONS
template<class T> void write(const T value, const bool resize = true)
{
if(resize)
buffer.resize((bitIndex+(sizeof(T)*8)+7)/8);
for(u8 copyBits = 0; copyBits < (u8) (sizeof(T)*8); ++copyBits)
{
buffer[(bitIndex+copyBits)/8] |= ((value >> ((sizeof(T)*8-1)-copyBits)) & 0x1)<<(7-(bitIndex+copyBits)%8);
}
bitIndex += sizeof(T)*8;
}
template<class T> void writeArray(const std::vector<T> & value, const bool resize = true)
{
u16 size = u16(value.size());
this->write<u16>(size, resize);
if(resize)
buffer.resize((bitIndex+(sizeof(T)*8*size)+7)/8);
for(u32 u = 0; u < size; u++)
{
this->write(value[u], false);
}
}
//! Nearly the same as writeArray but you've to give the size manually
//! Also it takes a pointe to an T-Array
//! Mainly used by the UDP-Class itself
template<class T> void writeRawArray(const T* value, const u32 size, const bool resize = true)
{
if(resize)
buffer.resize((bitIndex+(size*8)+7)/8);
for(u32 u = 0; u < size; u++)
{
this->write<T>(value[u], false);
}
}
//! READ FUNCTIONS
template<class T> T read(const bool increment = true)
{
T value = 0;
for(c8 copyBits = 0; copyBits < (c8) (sizeof(T)*8); ++copyBits)
{
value <<= 1;
value |= (buffer[(bitIndex+copyBits)/8]>>(7-(bitIndex+copyBits)%8)) & 0x1;
}
if(increment)
bitIndex += sizeof(T)*8;
return value;
}
template<class T> std::vector<T> readArray(const bool increment = true)
{
u16 size = read<u16>(true);
std::vector<T> value;
value.resize(size);
for(u16 cycleArray = 0; cycleArray < size; ++cycleArray)
{
this->read<T>(true);
}
if(!increment)
bitIndex -= sizeof(T)*8*size+8;
return value;
}
//! Nearly the same as ready array but you've to give the size manually
//! Also it returns a pointer to a T-Array
//! Mainly used by the UDP-Class itself
template<class T> T* readRawArray(const u32 size, const bool increment = true)
{
T* value = new T[size];
for(u32 u = 0; u < size; u++)
{
value[u] = this->read<T>(true);
}
if(!increment)
bitIndex -= size*8;
return value;
}
//! Copy a Raw Array directly to another BitStream (e.g. used in TCP port)
template<class T> void copyRawArray(BitStream* other, const u32 size, const bool increment = true, const bool resize = true)
{
for(u32 u = 0; u < size; u++)
{
other->write<c8>(this->read<T>(true), resize);
}
if(!increment)
bitIndex -= size*8;
}
//! RESET AND SET BITINDEX
void resetBitIndex()
{
bitIndex = 0;
}
void setBitIndex(const s32 index)
{
bitIndex = index;
}
void setByteIndex(const u32 index)
{
bitIndex = 8*index;
}
u64 getBitIndex() const
{
return bitIndex;
}
u32 getByteIndex() const
{
return bitIndex/8;
}
u32 getLength() const
{
return u32(buffer.size());
}
c8* getData(const bool copy = false)
{
if(copy)
{
c8* dataCopy = new c8[this->getLength()];
memcpy(dataCopy, &buffer[0], this->getLength());
return dataCopy;
}
else
return &buffer[0];
}
std::string getDataAsString()
{
return std::string(this->getData(), this->getLength());
}
std::vector<c8> getDataAsVector() const
{
return buffer;
}
void resetBuffer()
{
for(std::vector<c8>::iterator bufferItr = buffer.begin(); bufferItr != buffer.end(); ++bufferItr)
{
(*bufferItr) = 0;
}
}
//! Some operators for easier acess
c8 operator[](const u32 pos) const
{
if(pos > buffer.size())
return 0;
return buffer[pos];
}
bool operator==(const BitStream& other) const
{
if(other.getLength() != this->getLength())
return false;
std::vector<c8> otherData = other.getDataAsVector();
for(u32 u = 0; u < this->getLength(); u++)
{
if(buffer[u] != otherData[u])
return false;
}
return true;
}
void operator+= (BitStream& other)
{
u64 oldindex = other.getBitIndex();
other.setBitIndex(0);
for(u32 u = 0; u < other.getLength(); u++)
{
this->write<c8>(other[u]);
}
bitIndex += other.getLength();
other.setBitIndex(oldindex);
}
void operator= (const std::string str)
{
buffer.resize(str.length());
for(u32 u = 0; u < str.length(); u++)
{
buffer[u] = str[u];
}
}
private:
//! The char-array holding the data
std::vector<c8> buffer;
//! The reading / writing position
u64 bitIndex;
};
//! Specialisations
template<> void BitStream::writeArray<f32>(const std::vector<f32> &value, const bool resize);
template<> void BitStream::write<bool>(const bool value, const bool resize);
template<> void BitStream::write<std::string>(std::string value, const bool resize);
template<> void BitStream::write<f32>(const f32 value, const bool resize);
template<> bool BitStream::read<bool>(const bool increment);
template<> f32 BitStream::read<f32>(const bool increment);
template<> std::vector<f32> BitStream::readArray<f32>(const bool increment);
template<> std::string BitStream::read<std::string>(const bool increment);
}
#endif
Code: Alles auswählen
#include "BitStream.h"
namespace yogi
{
//! Some specialized implementations
//! Makes it easy to improve the BitStreams perfomance without modifining the methods-names
//! (by adding new templates etc)
template<> void BitStream::writeArray<f32>(const std::vector<f32> &value, const bool resize)
{
s32 temp;
c8 size = c8(value.size());
this->write<c8>(size, resize);
if(resize)
buffer.resize((bitIndex+(sizeof(float)*8*size)+7)/8);
for(c8 cycleArray = 0; cycleArray < size; ++cycleArray)
{
memcpy(&temp,&value[cycleArray],sizeof(f32));
write<s32>(temp, resize);
}
}
template<> void BitStream::write<bool>(const bool value, const bool resize)
{
if(resize)
buffer.resize((bitIndex+8)/8);
buffer[(bitIndex)/8] |= (value)<<(7-(bitIndex)%8);
bitIndex++;
}
template<> void BitStream::write<std::string>(std::string value, const bool resize)
{
write<c8>(c8(value.size()), resize);
if(resize)
buffer.resize((bitIndex+((value.size())*8)+7)/8);
for(std::string::iterator it = value.begin(); it != value.end(); it++)
{
this->write<c8>(*it, false);
}
}
template<> void BitStream::write<f32>(const f32 value, const bool resize)
{
s32 Temp;
memcpy(&Temp,&value,sizeof(f32));
this->write<s32>(Temp, resize);
}
template<> bool BitStream::read<bool>(const bool increment)
{
bool value = (buffer[bitIndex/8] >> (7-bitIndex%8)) & 0x1;
if(increment)
bitIndex++;
return value;
}
template<> f32 BitStream::read<f32>(const bool increment)
{
s32 temp = read<s32>(increment);
f32 value;
memcpy(&value, &temp, sizeof(f32));
return value;
}
template<> std::vector<f32> BitStream::readArray<f32>(const bool increment)
{
s32 temp;
c8 size = read<c8>(true);
std::vector<f32> value;
value.resize(size);
for(c8 cycleArray = 0; cycleArray < size; cycleArray++)
{
temp = read<s32>(true);
memcpy(&value[cycleArray], &temp, sizeof(f32));
}
if(!increment)
bitIndex -= sizeof(f32)*8*size+8;
return value;
}
template<> std::string BitStream::read<std::string>(const bool increment)
{
std::string value;
s32 length = read<c8>(true);
value.resize(length);
for(std::string::iterator stringItr = value.begin(); stringItr != value.end(); stringItr++)
{
this->read<c8>(true);
}
if(!increment)
bitIndex -= length*8 + 8;
return value;
}
} //! end namespace yogi
grüße,
Halan