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:
parent
481e1e30bb
commit
8231bd337f
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue