mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2025-12-16 12:08:36 +00:00
183 lines
3.8 KiB
C++
183 lines
3.8 KiB
C++
#include "bytebuffer.h"
|
|
#include <string.h>
|
|
#include <sys/param.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifndef MIN
|
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
|
#endif
|
|
#ifndef MAX
|
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
|
#endif
|
|
|
|
namespace base {
|
|
|
|
ByteBuffer::ByteBuffer(dword cb) {
|
|
start_ = 0;
|
|
end_ = 0;
|
|
size_ = cb;
|
|
bytes_ = (byte *)malloc(size_);
|
|
pbbNext_ = NULL;
|
|
}
|
|
|
|
ByteBuffer::~ByteBuffer() {
|
|
if (bytes_ != NULL) {
|
|
free(bytes_);
|
|
}
|
|
}
|
|
|
|
bool ByteBuffer::ReadByte(byte *pb) {
|
|
return ReadBytes(pb, sizeof(byte));
|
|
}
|
|
|
|
bool ByteBuffer::ReadWord(word *pw) {
|
|
word w;
|
|
if (!ReadBytes((byte *)&w, sizeof(word))) {
|
|
return false;
|
|
} else {
|
|
*pw = NetToHostWord(w);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool ByteBuffer::ReadDword(dword *pdw) {
|
|
dword dw;
|
|
if (!ReadBytes((byte *)&dw, 4)) {
|
|
return false;
|
|
} else {
|
|
*pdw = NetToHostDword(dw);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool ByteBuffer::ReadString(char *psz, int cb) {
|
|
byte *pbStart = bytes_ + start_;
|
|
byte *pbEnd = bytes_ + MIN(cb, end_ - start_);
|
|
byte *pb = pbStart;
|
|
for (; pb < pbEnd; pb++) {
|
|
if (*pb == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Include the zero termination if found
|
|
if (*pb == 0) {
|
|
if (!ReadBytes((byte *)psz, (int)(pb - pbStart))) {
|
|
return false;
|
|
}
|
|
} else {
|
|
// Ensure there is room for a forced zero, and
|
|
// only read the # of bytes that fit.
|
|
if (cb > 0) {
|
|
if (pb == bytes_ + cb) {
|
|
pb--;
|
|
}
|
|
if (!ReadBytes((byte *)psz, (int)(pb - pbStart))) {
|
|
return false;
|
|
}
|
|
psz[cb - 1] = 0;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ByteBuffer::ReadBytes(byte *pb, int cb) {
|
|
if (cb > Length()) {
|
|
return false;
|
|
} else {
|
|
memcpy(pb, bytes_ + start_, cb);
|
|
start_ += cb;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void ByteBuffer::WriteByte(byte b) {
|
|
WriteBytes(&b, sizeof(byte));
|
|
}
|
|
|
|
void ByteBuffer::WriteWord(word w) {
|
|
w = HostToNetWord(w);
|
|
WriteBytes((byte *)&w, sizeof(word));
|
|
}
|
|
|
|
void ByteBuffer::WriteDword(dword dw) {
|
|
dw = HostToNetDword(dw);
|
|
WriteBytes((byte *)&dw, sizeof(dword));
|
|
}
|
|
|
|
void ByteBuffer::WriteString(const char *psz, bool zero) {
|
|
int cch = (int)strlen(psz);
|
|
int cbWrite = cch + (zero ? 1 : 0);
|
|
WriteBytes((const byte *)psz, cbWrite);
|
|
}
|
|
|
|
void ByteBuffer::WriteBytes(const byte *pb, int cb) {
|
|
Shift(0);
|
|
if (Length() + cb > Capacity()) {
|
|
Resize(Length() + cb);
|
|
}
|
|
memcpy(bytes_ + end_, pb, cb);
|
|
end_ += cb;
|
|
}
|
|
|
|
void ByteBuffer::Resize(int size) {
|
|
if (size > size_)
|
|
size = MAX(size, 3 * size_ / 2);
|
|
|
|
int len = MIN(end_ - start_, size);
|
|
byte* new_bytes = (byte *)malloc(size);
|
|
memcpy(new_bytes, bytes_ + start_, len);
|
|
free(bytes_);
|
|
|
|
start_ = 0;
|
|
end_ = len;
|
|
size_ = size;
|
|
bytes_ = new_bytes;
|
|
}
|
|
|
|
void ByteBuffer::Shift(int size) {
|
|
// Move start_ to the beginning. Either bytes
|
|
// have to be copied or Length() is zero and they don't need to be copied.
|
|
|
|
dword len = Length();
|
|
if (len == 0) {
|
|
start_ = 0;
|
|
end_ = 0;
|
|
}
|
|
if (size == 0 && start_ == 0) {
|
|
return;
|
|
}
|
|
|
|
// Does two things: eats bytes from the current buffer window,
|
|
// and moves the window to the beginning
|
|
|
|
if (size > len) {
|
|
return;
|
|
}
|
|
end_ = Length() - size;
|
|
memmove(bytes_, bytes_ + start_ + size, end_);
|
|
start_ = 0;
|
|
}
|
|
|
|
ByteBuffer *ByteBuffer::Clone() const {
|
|
ByteBuffer *bbT = new ByteBuffer(Length());
|
|
bbT->WriteBytes(Data(), Length());
|
|
return bbT;
|
|
}
|
|
|
|
void *ByteBuffer::Strip(int *pcb) {
|
|
Shift(0);
|
|
void *pv = bytes_;
|
|
if (pcb != NULL) {
|
|
*pcb = Length();
|
|
}
|
|
|
|
start_ = 0;
|
|
end_ = 0;
|
|
size_ = DEFAULT_SIZE;
|
|
bytes_ = (byte *)malloc(size_);
|
|
return pv;
|
|
}
|
|
|
|
} // namespace base
|