More TODOs and removed the old C++.
This commit is contained in:
parent
b3de605d50
commit
ea1fde52ad
|
@ -26,4 +26,4 @@ static inline HRESULT lastErrorToHRESULT(DWORD lasterr, const char *funcname)
|
||||||
{{end}} if (xyzret != {{.Failval}})
|
{{end}} if (xyzret != {{.Failval}})
|
||||||
return S_OK;
|
return S_OK;
|
||||||
return lastErrToHRESULT(xyzlasterr, "{{.Name}}()");
|
return lastErrToHRESULT(xyzlasterr, "{{.Name}}()");
|
||||||
}{{end}}
|
}{{/*TODO cleanup*/}}{{end}}
|
||||||
|
|
|
@ -1,261 +0,0 @@
|
||||||
// 21 may 2018
|
|
||||||
#include <vector>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "lib.hpp"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class Function {
|
|
||||||
ByteSlice name;
|
|
||||||
ByteSlice callingConvention;
|
|
||||||
std::vector<ByteSlice> params;
|
|
||||||
ByteSlice returns;
|
|
||||||
bool keepReturn;
|
|
||||||
ByteSlice cond[2];
|
|
||||||
public:
|
|
||||||
Function(ByteSlice line);
|
|
||||||
|
|
||||||
ByteSlice Signature(void) const;
|
|
||||||
ByteSlice Call(void) const;
|
|
||||||
ByteSlice Body(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
Function::Function(ByteSlice line)
|
|
||||||
{
|
|
||||||
std::vector<ByteSlice> fields;
|
|
||||||
size_t start;
|
|
||||||
|
|
||||||
fields = ByteSliceFields(line);
|
|
||||||
|
|
||||||
this->returns = fields[0];
|
|
||||||
this->keepReturn = false;
|
|
||||||
if (this->returns.Data()[0] == '*') {
|
|
||||||
this->returns = this->returns.Slice(1, this->returns.Len());
|
|
||||||
this->keepReturn = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = 2;
|
|
||||||
this->callingConvention = ByteSlice().AppendString(u8"WINAPI");
|
|
||||||
this->name = fields[1];
|
|
||||||
if (fields.size() % 2 == 1) {
|
|
||||||
start = 3;
|
|
||||||
this->callingConvention = fields[1];
|
|
||||||
this->name = fields[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
this->cond[1] = fields.back();
|
|
||||||
fields.pop_back();
|
|
||||||
this->cond[0] = fields.back();
|
|
||||||
fields.pop_back();
|
|
||||||
|
|
||||||
this->params = std::vector<ByteSlice>(fields.begin() + start, fields.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
#define nfuncoutbuf 256
|
|
||||||
|
|
||||||
ByteSlice Function::Signature(void) const
|
|
||||||
{
|
|
||||||
ByteSlice out;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
out = ByteSlice(0, nfuncoutbuf);
|
|
||||||
|
|
||||||
out = out.AppendString(u8"HRESULT ");
|
|
||||||
out = out.Append(this->callingConvention);
|
|
||||||
out = out.AppendString(u8" ");
|
|
||||||
out = out.Append(this->name);
|
|
||||||
|
|
||||||
out = out.AppendString(u8"(");
|
|
||||||
for (i = 0; i < this->params.size(); i += 2) {
|
|
||||||
out = out.Append(this->params[i]);
|
|
||||||
out = out.AppendString(u8" ");
|
|
||||||
out = out.Append(this->params[i + 1]);
|
|
||||||
out = out.AppendString(u8", ");
|
|
||||||
}
|
|
||||||
if (this->keepReturn) {
|
|
||||||
out = out.Append(this->returns);
|
|
||||||
out = out.AppendString(u8" *ret");
|
|
||||||
} else if (this->params.size() != 0)
|
|
||||||
// remove the trailing comma and space
|
|
||||||
out = out.Slice(0, out.Len() - 2);
|
|
||||||
else
|
|
||||||
out = out.AppendString(u8"void");
|
|
||||||
out = out.AppendString(u8")");
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteSlice Function::Call(void) const
|
|
||||||
{
|
|
||||||
ByteSlice out;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
out = ByteSlice(0, nfuncoutbuf);
|
|
||||||
out = out.Append(this->name);
|
|
||||||
out = out.AppendString(u8"(");
|
|
||||||
for (i = 0; i < this->params.size(); i += 2) {
|
|
||||||
out = out.Append(this->params[i + 1]);
|
|
||||||
out = out.AppendString(u8", ");
|
|
||||||
}
|
|
||||||
if (this->params.size() != 0)
|
|
||||||
// remove the trailing comma and space
|
|
||||||
out = out.Slice(0, out.Len() - 2);
|
|
||||||
out = out.AppendString(u8")");
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define nbodybuf 1024
|
|
||||||
|
|
||||||
ByteSlice Function::Body(void) const
|
|
||||||
{
|
|
||||||
ByteSlice out;
|
|
||||||
|
|
||||||
out = ByteSlice(0, nbodybuf);
|
|
||||||
out = out.AppendString(u8"{\n");
|
|
||||||
|
|
||||||
if (!this->keepReturn) {
|
|
||||||
out = out.AppendString(u8"\t");
|
|
||||||
out = out.Append(this->returns);
|
|
||||||
out = out.AppendString(u8" ret;\n");
|
|
||||||
}
|
|
||||||
out = out.AppendString(u8"\tDWORD lasterr;\n");
|
|
||||||
out = out.AppendString(u8"\n");
|
|
||||||
|
|
||||||
if (this->keepReturn) {
|
|
||||||
out = out.AppendString(u8"\tif (ret == NULL)\n");
|
|
||||||
out = out.AppendString(u8"\t\treturn E_POINTER;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
out = out.AppendString(u8"\tSetLastError(0);\n");
|
|
||||||
out = out.AppendString(u8"\t");
|
|
||||||
if (this->keepReturn)
|
|
||||||
out = out.AppendString(u8"*");
|
|
||||||
out = out.AppendString(u8"ret = ");
|
|
||||||
out = out.Append(this->Call());
|
|
||||||
out = out.AppendString(u8";\n");
|
|
||||||
out = out.AppendString(u8"\tlasterr = GetLastError();\n");
|
|
||||||
|
|
||||||
out = out.AppendString(u8"\tif (");
|
|
||||||
if (this->keepReturn)
|
|
||||||
out = out.AppendString(u8"*");
|
|
||||||
out = out.AppendString(u8"ret ");
|
|
||||||
out = out.Append(this->cond[0]);
|
|
||||||
out = out.AppendString(u8" ");
|
|
||||||
out = out.Append(this->cond[1]);
|
|
||||||
out = out.AppendString(u8")\n");
|
|
||||||
out = out.AppendString(u8"\t\treturn lastErrorToHRESULT(lasterr, \"");
|
|
||||||
out = out.Append(this->name);
|
|
||||||
out = out.AppendString(u8"()\");\n");
|
|
||||||
out = out.AppendString(u8"\treturn S_OK;\n");
|
|
||||||
|
|
||||||
out = out.AppendString(u8"}");
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Processor {
|
|
||||||
bool previousLineBlank;
|
|
||||||
|
|
||||||
ByteSlice generate(ByteSlice line);
|
|
||||||
public:
|
|
||||||
Processor(void);
|
|
||||||
|
|
||||||
ByteSlice Process(ByteSlice line);
|
|
||||||
};
|
|
||||||
|
|
||||||
Processor::Processor(void)
|
|
||||||
{
|
|
||||||
this->previousLineBlank = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define noutbuf 2048
|
|
||||||
|
|
||||||
ByteSlice Processor::generate(ByteSlice line)
|
|
||||||
{
|
|
||||||
ByteSlice genout;
|
|
||||||
Function *f;
|
|
||||||
|
|
||||||
genout = ByteSlice(0, noutbuf);
|
|
||||||
if (!this->previousLineBlank)
|
|
||||||
genout = genout.AppendString("\n");
|
|
||||||
|
|
||||||
f = new Function(line);
|
|
||||||
genout = genout.Append(f->Signature());
|
|
||||||
genout = genout.AppendString(u8"\n");
|
|
||||||
genout = genout.Append(f->Body());
|
|
||||||
delete f;
|
|
||||||
|
|
||||||
genout = genout.AppendString(u8"\n");
|
|
||||||
this->previousLineBlank = false;
|
|
||||||
return genout;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteSlice Processor::Process(ByteSlice line)
|
|
||||||
{
|
|
||||||
if (line.Len() > 0 && line.Data()[0] == '@')
|
|
||||||
return this->generate(line.Slice(1, line.Len()));
|
|
||||||
if (line.Len() == 0) {
|
|
||||||
if (this->previousLineBlank)
|
|
||||||
return ByteSlice();
|
|
||||||
this->previousLineBlank = true;
|
|
||||||
} else
|
|
||||||
this->previousLineBlank = false;
|
|
||||||
return line.AppendString("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
ReadCloser *fin = NULL;
|
|
||||||
WriteCloser *fout = NULL;
|
|
||||||
Scanner *s = NULL;
|
|
||||||
Processor p;
|
|
||||||
ByteSlice b;
|
|
||||||
int ret = 1;
|
|
||||||
Error *err = NULL;
|
|
||||||
|
|
||||||
if (argc != 3) {
|
|
||||||
fprintf(stderr, "usage: %s infile outfile\n", argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = OpenRead(argv[1], &fin);
|
|
||||||
if (err != NULL) {
|
|
||||||
fprintf(stderr, "error opening %s: %s\n", argv[1], err->String());
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
err = CreateWrite(argv[2], &fout);
|
|
||||||
if (err != NULL) {
|
|
||||||
fprintf(stderr, "error creating %s: %s\n", argv[2], err->String());
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = new Scanner(fin);
|
|
||||||
while (s->Scan()) {
|
|
||||||
b = p.Process(s->Bytes());
|
|
||||||
err = fout->Write(b);
|
|
||||||
if (err != NULL) {
|
|
||||||
fprintf(stderr, "error writing to %s: %s\n", argv[2], err->String());
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = s->Err();
|
|
||||||
if (err != NULL) {
|
|
||||||
fprintf(stderr, "error reading from %s: %s\n", argv[1], err->String());
|
|
||||||
err = NULL; // we don't own err here
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
done:
|
|
||||||
if (s != NULL)
|
|
||||||
delete s;
|
|
||||||
if (fout != NULL)
|
|
||||||
delete fout;
|
|
||||||
if (fin != NULL)
|
|
||||||
delete fin;
|
|
||||||
if (err != NULL)
|
|
||||||
delete err;
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,349 +0,0 @@
|
||||||
// 21 may 2018
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
|
|
||||||
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
|
|
||||||
#include <io.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#define openfunc _open
|
|
||||||
#define openflags (_O_RDONLY | _O_BINARY)
|
|
||||||
#define openmode (_S_IREAD)
|
|
||||||
#define readfunc _read
|
|
||||||
#define readtype int
|
|
||||||
#define closefunc _close
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <map>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "lib.hpp"
|
|
||||||
|
|
||||||
class eofError : public Error {
|
|
||||||
public:
|
|
||||||
virtual ~eofError(void);
|
|
||||||
|
|
||||||
virtual const char *String(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
eofError::~eofError(void)
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *eofError::String(void) const
|
|
||||||
{
|
|
||||||
return "EOF";
|
|
||||||
}
|
|
||||||
|
|
||||||
class shortWriteError : public Error {
|
|
||||||
public:
|
|
||||||
virtual ~shortWriteError(void);
|
|
||||||
|
|
||||||
virtual const char *String(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
shortWriteError::~shortWriteError(void)
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *shortWriteError::String(void) const
|
|
||||||
{
|
|
||||||
return "short write";
|
|
||||||
}
|
|
||||||
|
|
||||||
Error *NewEOF(void)
|
|
||||||
{
|
|
||||||
return new eofError;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error *NewErrShortWrite(void)
|
|
||||||
{
|
|
||||||
return new shortWriteError;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsEOF(Error *e)
|
|
||||||
{
|
|
||||||
// typeid does not work directly with pointers, alas (see https://stackoverflow.com/questions/4202877/typeid-for-polymorphic-types)
|
|
||||||
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)->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
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(int len, size_t cap) :
|
|
||||||
ByteSlice::ByteSlice((size_t) len, cap)
|
|
||||||
{
|
|
||||||
// do nothing else
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteSlice ByteSlice::AppendString(const char *str)
|
|
||||||
{
|
|
||||||
return this->Append(str, strlen(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define nbuf 1024
|
|
||||||
|
|
||||||
Scanner::Scanner(ReadCloser *r)
|
|
||||||
{
|
|
||||||
this->r = r;
|
|
||||||
this->buf = ByteSlice(nbuf, nbuf);
|
|
||||||
this->p = ByteSlice();
|
|
||||||
this->line = ByteSlice(0, nbuf);
|
|
||||||
this->err = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scanner::~Scanner(void)
|
|
||||||
{
|
|
||||||
if (this->err != NULL)
|
|
||||||
delete this->err;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scanner::Scan(void)
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
if (this->err != NULL)
|
|
||||||
return false;
|
|
||||||
this->line = this->line.Slice(0, 0);
|
|
||||||
for (;;) {
|
|
||||||
if (this->p.Len() > 0) {
|
|
||||||
size_t j;
|
|
||||||
bool haveline;
|
|
||||||
|
|
||||||
haveline = false;
|
|
||||||
for (j = 0; j < this->p.Len(); j++)
|
|
||||||
if (this->p.Data()[j] == '\n') {
|
|
||||||
haveline = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this->line = this->line.Append(this->p.Slice(0, j));
|
|
||||||
this->p = this->p.Slice(j, this->p.Len());
|
|
||||||
if (haveline) {
|
|
||||||
// swallow the \n for the next time through
|
|
||||||
this->p = this->p.Slice(1, this->p.Len());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// otherwise, the buffer was exhausted in the middle of a line, so fall through
|
|
||||||
}
|
|
||||||
// need to refill the buffer
|
|
||||||
this->err = this->r->Read(this->buf, &n);
|
|
||||||
if (this->err != NULL)
|
|
||||||
return false;
|
|
||||||
this->p = this->buf.Slice(0, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteSlice Scanner::Bytes(void) const
|
|
||||||
{
|
|
||||||
return this->line;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error *Scanner::Err(void) const
|
|
||||||
{
|
|
||||||
if (!IsEOF(this->err))
|
|
||||||
return this->err;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ByteSlice> ByteSliceFields(ByteSlice s)
|
|
||||||
{
|
|
||||||
std::vector<ByteSlice> ret;
|
|
||||||
const char *data;
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
data = s.Data();
|
|
||||||
i = 0;
|
|
||||||
while (i < s.Len()) {
|
|
||||||
if (data[i] == ' ' || data[i] == '\t') {
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (j = i + 1; j < s.Len(); j++)
|
|
||||||
if (data[j] == ' ' || data[j] == '\t')
|
|
||||||
break;
|
|
||||||
ret.push_back(s.Slice(i, j));
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
// 21 may 2018
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class Error {
|
|
||||||
public:
|
|
||||||
virtual ~Error(void) = default;
|
|
||||||
|
|
||||||
virtual const char *String(void) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Error *NewEOF(void);
|
|
||||||
extern Error *NewErrShortWrite(void);
|
|
||||||
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 {
|
|
||||||
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(int len, size_t cap); // deal with stupid rule about 0 (see https://stackoverflow.com/a/4610586/3408572)
|
|
||||||
~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);
|
|
||||||
ByteSlice AppendString(const char *str);
|
|
||||||
void CopyFrom(const char *b, size_t n);
|
|
||||||
void CopyFrom(const ByteSlice &b);
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReadCloser {
|
|
||||||
public:
|
|
||||||
virtual ~ReadCloser(void) = default;
|
|
||||||
|
|
||||||
virtual Error *Read(ByteSlice b, size_t *n) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WriteCloser {
|
|
||||||
public:
|
|
||||||
virtual ~WriteCloser(void) = default;
|
|
||||||
|
|
||||||
virtual Error *Write(const ByteSlice b) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Error *OpenRead(const char *filename, ReadCloser **r);
|
|
||||||
extern Error *CreateWrite(const char *filename, WriteCloser **w);
|
|
||||||
|
|
||||||
class Scanner {
|
|
||||||
ReadCloser *r;
|
|
||||||
ByteSlice buf;
|
|
||||||
ByteSlice p;
|
|
||||||
ByteSlice line;
|
|
||||||
Error *err;
|
|
||||||
public:
|
|
||||||
Scanner(ReadCloser *r);
|
|
||||||
~Scanner(void);
|
|
||||||
|
|
||||||
bool Scan(void);
|
|
||||||
ByteSlice Bytes(void) const;
|
|
||||||
Error *Err(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern std::vector<ByteSlice> ByteSliceFields(ByteSlice s);
|
|
|
@ -1,118 +0,0 @@
|
||||||
// 25 may 2018
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "lib.hpp"
|
|
||||||
|
|
||||||
class posixError : public Error {
|
|
||||||
int error;
|
|
||||||
public:
|
|
||||||
posixError(int error);
|
|
||||||
virtual ~posixError(void);
|
|
||||||
|
|
||||||
virtual const char *String(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
posixError::posixError(int error)
|
|
||||||
{
|
|
||||||
this->error = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
posixError::~posixError(void)
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *posixError::String(void) const
|
|
||||||
{
|
|
||||||
return strerror(this->error);
|
|
||||||
}
|
|
||||||
|
|
||||||
class posixReadCloser : public ReadCloser {
|
|
||||||
int fd;
|
|
||||||
public:
|
|
||||||
posixReadCloser(int fd);
|
|
||||||
virtual ~posixReadCloser(void);
|
|
||||||
|
|
||||||
virtual Error *Read(ByteSlice b, size_t *n);
|
|
||||||
};
|
|
||||||
|
|
||||||
posixReadCloser::posixReadCloser(int fd)
|
|
||||||
{
|
|
||||||
this->fd = fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
posixReadCloser::~posixReadCloser(void)
|
|
||||||
{
|
|
||||||
close(this->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error *posixReadCloser::Read(ByteSlice b, size_t *n)
|
|
||||||
{
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
*n = 0;
|
|
||||||
ret = read(this->fd, b.Data(), b.Len());
|
|
||||||
if (ret < 0)
|
|
||||||
return new posixError(errno);
|
|
||||||
if (ret == 0)
|
|
||||||
return NewEOF();
|
|
||||||
*n = ret;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
class posixWriteCloser : public WriteCloser {
|
|
||||||
int fd;
|
|
||||||
public:
|
|
||||||
posixWriteCloser(int fd);
|
|
||||||
virtual ~posixWriteCloser(void);
|
|
||||||
|
|
||||||
virtual Error *Write(const ByteSlice b);
|
|
||||||
};
|
|
||||||
|
|
||||||
posixWriteCloser::posixWriteCloser(int fd)
|
|
||||||
{
|
|
||||||
this->fd = fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
posixWriteCloser::~posixWriteCloser(void)
|
|
||||||
{
|
|
||||||
close(this->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
Error *posixWriteCloser::Write(const ByteSlice b)
|
|
||||||
{
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
ret = write(this->fd, b.Data(), b.Len());
|
|
||||||
if (ret < 0)
|
|
||||||
return new posixError(errno);
|
|
||||||
if (((size_t) ret) != b.Len())
|
|
||||||
return NewErrShortWrite();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error *OpenRead(const char *filename, ReadCloser **r)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
*r = NULL;
|
|
||||||
fd = open(filename, O_RDONLY, 0644);
|
|
||||||
if (fd < 0)
|
|
||||||
return new posixError(errno);
|
|
||||||
*r = new posixReadCloser(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error *CreateWrite(const char *filename, WriteCloser **w)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
*w = NULL;
|
|
||||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
||||||
if (fd < 0)
|
|
||||||
return new posixError(errno);
|
|
||||||
*w = new posixWriteCloser(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
Loading…
Reference in New Issue