Built a new ByteSlice interface in lib.cpp that will keep shuffling the bytes around much nicer. I'll change everything to use it next.

This commit is contained in:
Pietro Gagliardi 2018-05-27 15:36:16 -04:00
parent 481e1e30bb
commit 8231bd337f
2 changed files with 224 additions and 0 deletions

View File

@ -13,8 +13,10 @@
#else
#endif
#include <typeinfo>
#include <map>
#include <algorithm>
#include <string.h>
#include <stdint.h>
#include "lib.hpp"
class eofError : public Error {
@ -67,6 +69,199 @@ bool IsEOF(Error *e)
return typeid (*e) == typeid (eofError);
}
namespace {
struct sliceAlloc {
char *b;
size_t n;
uintmax_t refcount;
};
std::map<uintptr_t, struct sliceAlloc> sliceAllocs;
char *sliceAlloc(size_t n)
{
struct sliceAlloc sa;
sa.b = new char[n];
sa.n = n;
sa.refcount = 1;
sliceAllocs[(uintptr_t) (sa.b)] = sa;
return sa.b;
}
uintptr_t sliceLookup(char *b)
{
return *(sliceAllocs.lower_bound((uintptr_t) b));
}
void sliceRetain(char *b)
{
if (b == NULL)
return;
sliceAllocs[sliceLookup(b)].refcount++;
}
void sliceRelease(char *b)
{
uintptr_t key;
if (b == NULL)
return;
key = sliceLookup(b);
sliceAllocs[key].refcount--;
if (sliceAllocs[key].refcount == 0) {
delete[] sliceAllocs[key].b;
sliceAllocs.erase(key);
}
}
}
ByteSlice::ByteSlice(void)
{
this->data = NULL;
this->len = 0;
this->cap = 0;
}
ByteSlice::ByteSlice(const ByteSlice &b)
{
this->data = b.data;
sliceRetain(this->data);
this->len = b.len;
this->cap = b.cap;
}
ByteSlice::ByteSlice(ByteSlice &&b)
{
this->data = b.data;
b.data = NULL;
this->len = b.len;
b.len = 0;
this->cap = b.cap;
b.cap = 0;
}
ByteSlice::ByteSlice(const char *b, size_t n)
{
this->data = sliceAlloc(n);
memcpy(this->data, b, n * sizeof (char));
this->len = n;
this->cap = n;
}
ByteSlice::ByteSlice(size_t len, size_t cap)
{
this->data = sliceAlloc(cap);
memset(this->data, 0, len * sizeof (char));
this->len = len;
this->cap = cap;
}
ByteSlice::~ByteSlice(void)
{
sliceRelease(this->data);
}
ByteSlice &ByteSlice::operator=(const ByteSlice &b)
{
this->data = b.data;
sliceRetain(this->data);
this->len = b.len;
this->cap = b.cap;
return *this;
}
ByteSlice &ByteSlice::operator=(ByteSlice &&b)
{
this->data = b.data;
b.data = NULL;
this->len = b.len;
b.len = 0;
this->cap = b.cap;
b.cap = 0;
return *this;
}
ByteSlice ByteSlice::Slice(size_t start, size_t end)
{
ByteSlice b;
b.data = this->data + start;
sliceRetain(b.data);
b.len = end - start;
b.cap = this->cap - start;
return b;
}
char *ByteSlice::Data(void)
{
return this->data;
}
const char *ByteSlice::Data(void) const
{
return this->data;
}
size_t ByteSlice::Len(void) const
{
return this->len;
}
size_t ByteSlice::Cap(void) const
{
return this->cap;
}
ByteSlice ByteSlice::Slice(size_t start, size_t end)
{
ByteSlice b;
b.data = this->data + start;
sliceRetain(b.data);
b.len = end - start;
b.cap = this->cap - start;
return b;
}
ByteSlice ByteSlice::Append(const char *b, size_t n)
{
ByteSlice s;
if (this->len + n < this->cap) {
s.data = this->data;
sliceRetain(s.data);
s.len = this->len + n;
s.cap = this->cap;
memcpy(s.data + this->len, b, n * sizeof (char));
return s;
}
s.data = sliceAlloc(this->len + n);
memcpy(s.data, this->data, this->len * sizeof (char));
memcpy(s.data + this->len, b, n * sizeof (char));
s.len = this->len + n;
s.cap = this->len + n;
return s;
}
ByteSlice ByteSlice::Append(const ByteSlice &b)
{
return this->Append(b.data, b.len);
}
void ByteSlice::CopyFrom(const char *b, size_t n)
{
n = std::min(this->len, n);
memcpy(this->data, b, n);
}
void ByteSlice::CopyFrom(const ByteSlice &b)
{
this->CopyFrom(b.data, b.len);
}
Error *WriteVector(WriteCloser *w, std::vector<char> *v)
{
return w->Write(v->data(), v->size());

View File

@ -12,6 +12,35 @@ extern Error *NewEOF(void);
extern Error *NewErrShortWrite(void);
extern bool IsEOF(Error *e);
class ByteSlice {
char *data;
size_t len;
size_t cap;
public:
ByteSlice(void); // default constructor; equivalent to Go's nil slice
ByteSlice(const ByteSlice &b); // copy constructor
ByteSlice(ByteSlice &&b); // move constructor; sets b to ByteSlice()
ByteSlice(const char *b, size_t n);
ByteSlice(size_t len, size_t cap);
~ByteSlice(void);
// note: copy assignment does not use copy-and-swap because I get neither copy-and-swap nor ADL public friend swap functions (https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom, https://stackoverflow.com/questions/5695548/public-friend-swap-member-function)
// (and also [14:55:04] <discord> <devin> i don't see why you'd need swap-on-copy semantics for anything if you're really just trying to make copy assignments create two references to the same memory)
ByteSlice &operator=(const ByteSlice &b); // copy assignment
ByteSlice &operator=(ByteSlice &&b); // move assignment; sets b to ByteSlice()
char *Data(void);
const char *Data(void) const;
size_t Len(void) const;
size_t Cap(void) const;
ByteSlice Slice(size_t start, size_t end);
ByteSlice Append(const char *b, size_t n);
ByteSlice Append(const ByteSlice &b);
void CopyFrom(const char *b, size_t n);
void CopyFrom(const ByteSlice &b);
};
class ReadCloser {
public:
virtual ~ReadCloser(void) = default;