Rewrote the library to use ByteSlice.
This commit is contained in:
parent
8231bd337f
commit
4a7e7ed983
|
@ -92,7 +92,7 @@ char *sliceAlloc(size_t n)
|
||||||
|
|
||||||
uintptr_t sliceLookup(char *b)
|
uintptr_t sliceLookup(char *b)
|
||||||
{
|
{
|
||||||
return *(sliceAllocs.lower_bound((uintptr_t) b));
|
return sliceAllocs.lower_bound((uintptr_t) b)->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sliceRetain(char *b)
|
void sliceRetain(char *b)
|
||||||
|
@ -184,17 +184,6 @@ ByteSlice &ByteSlice::operator=(ByteSlice &&b)
|
||||||
return *this;
|
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)
|
char *ByteSlice::Data(void)
|
||||||
{
|
{
|
||||||
return this->data;
|
return this->data;
|
||||||
|
@ -251,6 +240,11 @@ ByteSlice ByteSlice::Append(const ByteSlice &b)
|
||||||
return this->Append(b.data, b.len);
|
return this->Append(b.data, b.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ByteSlice ByteSlice::AppendString(const char *str)
|
||||||
|
{
|
||||||
|
return this->Append(str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
void ByteSlice::CopyFrom(const char *b, size_t n)
|
void ByteSlice::CopyFrom(const char *b, size_t n)
|
||||||
{
|
{
|
||||||
n = std::min(this->len, n);
|
n = std::min(this->len, n);
|
||||||
|
@ -262,11 +256,6 @@ void ByteSlice::CopyFrom(const ByteSlice &b)
|
||||||
this->CopyFrom(b.data, b.len);
|
this->CopyFrom(b.data, b.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error *WriteVector(WriteCloser *w, std::vector<char> *v)
|
|
||||||
{
|
|
||||||
return w->Write(v->data(), v->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
#define nbuf 1024
|
#define nbuf 1024
|
||||||
|
|
||||||
Scanner::Scanner(ReadCloser *r)
|
Scanner::Scanner(ReadCloser *r)
|
||||||
|
@ -275,7 +264,7 @@ Scanner::Scanner(ReadCloser *r)
|
||||||
this->buf = new char[nbuf];
|
this->buf = new char[nbuf];
|
||||||
this->p = this->buf;
|
this->p = this->buf;
|
||||||
this->n = 0;
|
this->n = 0;
|
||||||
this->line = new std::vector<char>;
|
this->line = ByteSlice(0, nbuf);
|
||||||
this->err = NULL;
|
this->err = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +272,6 @@ Scanner::~Scanner(void)
|
||||||
{
|
{
|
||||||
if (this->err != NULL)
|
if (this->err != NULL)
|
||||||
delete this->err;
|
delete this->err;
|
||||||
delete this->line;
|
|
||||||
delete[] this->buf;
|
delete[] this->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +281,7 @@ bool Scanner::Scan(void)
|
||||||
|
|
||||||
if (this->err != NULL)
|
if (this->err != NULL)
|
||||||
return false;
|
return false;
|
||||||
this->line->clear();
|
this->line = this->line.Slice(0, 0);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (this->n > 0) {
|
if (this->n > 0) {
|
||||||
size_t j;
|
size_t j;
|
||||||
|
@ -305,7 +293,7 @@ bool Scanner::Scan(void)
|
||||||
haveline = true;
|
haveline = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this->line->insert(this->line->end(), this->p, this->p + j);
|
this->line = this->line.Append(this->p, j);
|
||||||
this->p += j;
|
this->p += j;
|
||||||
this->n -= j;
|
this->n -= j;
|
||||||
if (haveline) {
|
if (haveline) {
|
||||||
|
@ -325,14 +313,9 @@ bool Scanner::Scan(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Scanner::Bytes(void) const
|
ByteSlice Scanner::Bytes(void) const
|
||||||
{
|
{
|
||||||
return this->line->data();
|
return this->line;
|
||||||
}
|
|
||||||
|
|
||||||
size_t Scanner::Len(void) const
|
|
||||||
{
|
|
||||||
return this->line->size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error *Scanner::Err(void) const
|
Error *Scanner::Err(void) const
|
||||||
|
@ -342,59 +325,24 @@ Error *Scanner::Err(void) const
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppendString(std::vector<char> *v, const char *str)
|
std::vector<ByteSlice> ByteSliceFields(ByteSlice s)
|
||||||
{
|
{
|
||||||
v->insert(v->end(), str, str + strlen(str));
|
std::vector<ByteSlice> ret;
|
||||||
}
|
const char *data;
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
Slice::Slice(const char *p, size_t n)
|
data = s.Data();
|
||||||
{
|
i = 0;
|
||||||
this->p = p;
|
while (i < s.Len()) {
|
||||||
this->n = n;
|
if (data[i] == ' ' || data[i] == '\t') {
|
||||||
}
|
i++;
|
||||||
|
|
||||||
const char *Slice::Data(void) const
|
|
||||||
{
|
|
||||||
return this->p;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Slice::Len(void) const
|
|
||||||
{
|
|
||||||
return this->n;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Slice *> *TokenizeWhitespace(const char *buf, size_t n)
|
|
||||||
{
|
|
||||||
std::vector<Slice *> *ret;
|
|
||||||
const char *p, *q;
|
|
||||||
const char *end;
|
|
||||||
|
|
||||||
ret = new std::vector<Slice *>;
|
|
||||||
p = buf;
|
|
||||||
end = buf + n;
|
|
||||||
while (p < end) {
|
|
||||||
if (*p == ' ' || *p == '\t') {
|
|
||||||
p++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (q = p; q < end; q++)
|
for (j = i + 1; j < s.Len(); j++)
|
||||||
if (*q == ' ' || *q == '\t')
|
if (data[j] == ' ' || data[j] == '\t')
|
||||||
break;
|
break;
|
||||||
ret->push_back(new Slice(p, q - p));
|
ret.push_back(s.Slice(i, j));
|
||||||
p = q;
|
i = j;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeTokenized(std::vector<Slice *> *v)
|
|
||||||
{
|
|
||||||
std::for_each(v->begin(), v->end(), [](Slice *s) {
|
|
||||||
delete s;
|
|
||||||
});
|
|
||||||
delete v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppendSlice(std::vector<char> *v, Slice *s)
|
|
||||||
{
|
|
||||||
v->insert(v->end(), s->Data(), s->Data() + s->Len());
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ extern Error *NewEOF(void);
|
||||||
extern Error *NewErrShortWrite(void);
|
extern Error *NewErrShortWrite(void);
|
||||||
extern bool IsEOF(Error *e);
|
extern bool IsEOF(Error *e);
|
||||||
|
|
||||||
|
// super lightweight (can be passed by value without any data being copied) wrapper around an array of bytes that can be sliced further without copying (std::vector can't do that easily)
|
||||||
|
// this is modelled after Go's slices
|
||||||
class ByteSlice {
|
class ByteSlice {
|
||||||
char *data;
|
char *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -37,6 +39,7 @@ public:
|
||||||
ByteSlice Slice(size_t start, size_t end);
|
ByteSlice Slice(size_t start, size_t end);
|
||||||
ByteSlice Append(const char *b, size_t n);
|
ByteSlice Append(const char *b, size_t n);
|
||||||
ByteSlice Append(const ByteSlice &b);
|
ByteSlice Append(const ByteSlice &b);
|
||||||
|
ByteSlice AppendString(const char *str);
|
||||||
void CopyFrom(const char *b, size_t n);
|
void CopyFrom(const char *b, size_t n);
|
||||||
void CopyFrom(const ByteSlice &b);
|
void CopyFrom(const ByteSlice &b);
|
||||||
};
|
};
|
||||||
|
@ -45,49 +48,33 @@ class ReadCloser {
|
||||||
public:
|
public:
|
||||||
virtual ~ReadCloser(void) = default;
|
virtual ~ReadCloser(void) = default;
|
||||||
|
|
||||||
virtual Error *Read(void *buf, size_t n, size_t *actual) = 0;
|
virtual Error *Read(ByteSlice b, size_t *n) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WriteCloser {
|
class WriteCloser {
|
||||||
public:
|
public:
|
||||||
virtual ~WriteCloser(void) = default;
|
virtual ~WriteCloser(void) = default;
|
||||||
|
|
||||||
virtual Error *Write(void *buf, size_t n) = 0;
|
virtual Error *Write(const ByteSlice b) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Error *OpenRead(const char *filename, ReadCloser **r);
|
extern Error *OpenRead(const char *filename, ReadCloser **r);
|
||||||
extern Error *CreateWrite(const char *filename, WriteCloser **w);
|
extern Error *CreateWrite(const char *filename, WriteCloser **w);
|
||||||
extern Error *WriteVector(WriteCloser *w, std::vector<char> *v);
|
|
||||||
|
|
||||||
class Scanner {
|
class Scanner {
|
||||||
ReadCloser *r;
|
ReadCloser *r;
|
||||||
char *buf;
|
char *buf;
|
||||||
const char *p;
|
const char *p;
|
||||||
size_t n;
|
size_t n;
|
||||||
std::vector<char> *line;
|
ByteSlice line;
|
||||||
Error *err;
|
Error *err;
|
||||||
public:
|
public:
|
||||||
Scanner(ReadCloser *r);
|
Scanner(ReadCloser *r);
|
||||||
~Scanner(void);
|
~Scanner(void);
|
||||||
|
|
||||||
bool Scan(void);
|
bool Scan(void);
|
||||||
const char *Bytes(void) const;
|
ByteSlice Bytes(void) const;
|
||||||
size_t Len(void) const;
|
|
||||||
Error *Err(void) const;
|
Error *Err(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void AppendString(std::vector<char> *v, const char *str);
|
extern std::vector<ByteSlice> ByteSliceFields(ByteSlice s);
|
||||||
|
|
||||||
class Slice {
|
|
||||||
const char *p;
|
|
||||||
size_t n;
|
|
||||||
public:
|
|
||||||
Slice(const char *p, size_t n);
|
|
||||||
|
|
||||||
const char *Data(void) const;
|
|
||||||
size_t Len(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern std::vector<Slice *> *TokenizeWhitespace(const char *buf, size_t n);
|
|
||||||
extern void FreeTokenized(std::vector<Slice *> *v);
|
|
||||||
extern void AppendSlice(std::vector<char> *v, Slice *s);
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
posixReadCloser(int fd);
|
posixReadCloser(int fd);
|
||||||
virtual ~posixReadCloser(void);
|
virtual ~posixReadCloser(void);
|
||||||
|
|
||||||
virtual Error *Read(void *buf, size_t n, size_t *actual);
|
virtual Error *Read(ByteSlice b, size_t *n);
|
||||||
};
|
};
|
||||||
|
|
||||||
posixReadCloser::posixReadCloser(int fd)
|
posixReadCloser::posixReadCloser(int fd)
|
||||||
|
@ -48,17 +48,17 @@ posixReadCloser::~posixReadCloser(void)
|
||||||
close(this->fd);
|
close(this->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error *posixReadCloser::Read(void *buf, size_t n, size_t *actual)
|
Error *posixReadCloser::Read(ByteSlice b, size_t *n)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
*actual = 0;
|
*n = 0;
|
||||||
ret = read(this->fd, buf, n);
|
ret = read(this->fd, b.Data(), b.Len());
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return new posixError(errno);
|
return new posixError(errno);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return NewEOF();
|
return NewEOF();
|
||||||
*actual = ret;
|
*n = ret;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ public:
|
||||||
posixWriteCloser(int fd);
|
posixWriteCloser(int fd);
|
||||||
virtual ~posixWriteCloser(void);
|
virtual ~posixWriteCloser(void);
|
||||||
|
|
||||||
virtual Error *Write(void *buf, size_t n);
|
virtual Error *Write(const ByteSlice b);
|
||||||
};
|
};
|
||||||
|
|
||||||
posixWriteCloser::posixWriteCloser(int fd)
|
posixWriteCloser::posixWriteCloser(int fd)
|
||||||
|
@ -81,14 +81,14 @@ posixWriteCloser::~posixWriteCloser(void)
|
||||||
close(this->fd);
|
close(this->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error *posixWriteCloser::Write(void *buf, size_t n)
|
Error *posixWriteCloser::Write(const ByteSlice &b)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
ret = write(this->fd, buf, n);
|
ret = write(this->fd, b.Data(), b.Len());
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return new posixError(errno);
|
return new posixError(errno);
|
||||||
if (((size_t) ret) != n)
|
if (((size_t) ret) != b.Len())
|
||||||
return NewErrShortWrite();
|
return NewErrShortWrite();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue