diff --git a/windows/tools/hresultwrap.cpp b/windows/tools/hresultwrap.cpp index 4fda9236..c6cfc303 100644 --- a/windows/tools/hresultwrap.cpp +++ b/windows/tools/hresultwrap.cpp @@ -4,97 +4,98 @@ #include #include "lib.hpp" -struct item { - Slice *name; - Slice *callingConvention; - Slice **params; - size_t nParams; - Slice *returns; +namespace { + +class items { +public: + ByteSlice name; + ByteSlice callingConvention; + std::vector params; + ByteSlice returns; bool keepReturn; - Slice *cond[2]; + ByteSlice cond[2]; }; -bool generate(const char *line, size_t n, FILE *fout) +#define noutbuf 2048 + +bool generate(ByteSlice line, FILE *fout) { - std::vector genout; - std::vector *tokens; + ByteSlice genout; + std::vector tokens; size_t i, j; - struct item item; + items item; size_t nw; - tokens = TokenizeWhitespace(line, n); + tokens = ByteSliceFields(line); - memset(&item, 0, sizeof (struct item)); + new (&item) items; i = 0; - item.returns = tokens->at(i); - if (item.returns->Data()[0] == '*') { - item.returns = new Slice(item.returns->Data() + 1, item.returns->Len() - 1); + item.returns = tokens.at(i); + item.keepReturn = false; + if (item.returns.Data()[0] == '*') { + item.returns = item.returns.Slice(1, item.returns.Len()); item.keepReturn = true; } i++; - if (tokens->size() % 2 == 1) { - item.callingConvention = tokens->at(i); + if (tokens.size() % 2 == 1) { + item.callingConvention = tokens.at(i); i++; } - item.name = tokens->at(i); + item.name = tokens.at(i); i++; - item.cond[0] = tokens->at(tokens->size() - 2); - item.cond[1] = tokens->at(tokens->size() - 1); - item.nParams = (tokens->size() - 2) - i; - item.params = new Slice *[item.nParams]; - for (j = 0; j < item.nParams; j++) { - item.params[j] = tokens->at(i); + item.cond[0] = tokens.at(tokens.size() - 2); + item.cond[1] = tokens.at(tokens.size() - 1); + item.params.reserve((tokens.size() - 2) - i); + for (j = 0; j < item.params.capacity(); j++) { + item.params.push_back(tokens.at(i)); i++; } - AppendString(&genout, "HRESULT "); - if (item.callingConvention != NULL) { - AppendSlice(&genout, item.callingConvention); - genout.push_back(' '); + genout = ByteSlice(0, noutbuf); + genout = genout.AppendString("HRESULT "); + if (item.callingConvention.Len() != 0) { + genout = genout.Append(item.callingConvention); + genout = genout.AppendString(" "); } - AppendSlice(&genout, item.name); - genout.push_back('('); - for (i = 0; i < item.nParams; i += 2) { - AppendSlice(&genout, item.params[i]); - genout.push_back(' '); - AppendSlice(&genout, item.params[i + 1]); - genout.push_back(','); - genout.push_back(' '); + genout = genout.Append(item.name); + genout = genout.AppendString("("); + for (i = 0; i < item.params.size(); i += 2) { + genout = genout.Append(item.params[i]); + genout = genout.AppendString(" "); + genout = genout.Append(item.params[i + 1]); + genout = genout.AppendString(", "); } if (item.keepReturn) { - AppendSlice(&genout, item.returns); - AppendString(&genout, " *ret"); - } else if (item.nParams != 0) { + genout = genout.Append(item.returns); + genout = genout.AppendString(" *ret"); + } else if (item.params.size() != 0) // remove the trailing comma and space - genout.pop_back(); - genout.pop_back(); - } else - AppendString(&genout, "void"); - genout.push_back(')'); - genout.push_back('\n'); + genout = genout.Slice(0, genout.Len() - 2); + else + genout = genout.AppendString("void"); + genout = genout.AppendString(")\n"); - delete[] item.params; - if (item.keepReturn) - delete item.returns; - FreeTokenized(tokens); + item.~items(); - genout.push_back('\n'); - nw = fwrite(genout.data(), sizeof (char), genout.size(), fout); - return nw == genout.size(); + genout = genout.AppendString("\n"); + nw = fwrite(genout.Data(), sizeof (char), genout.Len(), fout); + return nw == genout.Len(); } -bool process(const char *line, size_t n, FILE *fout) +bool process(ByteSlice line, FILE *fout) { size_t nw; - if (n > 0 && line[0] == '@') - return generate(line + 1, n - 1, fout); - nw = fwrite(line, sizeof (char), n, fout); - if (nw != n) + if (line.Len() > 0 && line.Data()[0] == '@') + return generate(line.Slice(1, line.Len()), fout); + nw = fwrite(line.Data(), sizeof (char), line.Len(), fout); + if (nw != line.Len()) return false; return fwrite("\n", sizeof (char), 1, fout) == 1; } +} + int main(int argc, char *argv[]) { ReadCloser *fin = NULL; @@ -120,17 +121,11 @@ int main(int argc, char *argv[]) } s = new Scanner(fin); - while (s->Scan()) { - const char *line; - size_t n; - - line = s->Bytes(); - n = s->Len(); - if (!process(line, n, fout)) { + while (s->Scan()) + if (!process(s->Bytes(), fout)) { fprintf(stderr, "error writing to %s\n", argv[2]); goto done; } - } if (s->Err() != 0) { fprintf(stderr, "error reading from %s: %s\n", argv[1], s->Err()->String()); goto done; diff --git a/windows/tools/lib.cpp b/windows/tools/lib.cpp index 36bf174d..310ab7b0 100644 --- a/windows/tools/lib.cpp +++ b/windows/tools/lib.cpp @@ -159,6 +159,12 @@ ByteSlice::ByteSlice(size_t len, size_t cap) 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); @@ -305,7 +311,7 @@ bool Scanner::Scan(void) // 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, nbuf * sizeof (char), &n); + this->err = this->r->Read(this->buf, &n); if (this->err != NULL) return false; this->p = this->buf; diff --git a/windows/tools/lib.hpp b/windows/tools/lib.hpp index 2de42036..27405481 100644 --- a/windows/tools/lib.hpp +++ b/windows/tools/lib.hpp @@ -24,6 +24,7 @@ public: 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 ~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)