diff options
-rw-r--r-- | benchmarks/parsestream.upb.c | 6 | ||||
-rw-r--r-- | benchmarks/parsetoproto2.upb.cc | 9 | ||||
-rw-r--r-- | benchmarks/parsetostruct.upb.c | 6 | ||||
-rw-r--r-- | tests/test_decoder.c | 6 | ||||
-rw-r--r-- | tests/test_vs_proto2.cc | 7 | ||||
-rw-r--r-- | tests/tests.c | 1 | ||||
-rw-r--r-- | upb/bytestream.c | 21 | ||||
-rw-r--r-- | upb/bytestream.h | 27 | ||||
-rw-r--r-- | upb/def.c | 15 | ||||
-rw-r--r-- | upb/descriptor.c | 10 | ||||
-rw-r--r-- | upb/handlers.c | 4 | ||||
-rw-r--r-- | upb/pb/decoder.c | 2 | ||||
-rw-r--r-- | upb/pb/glue.c | 2 | ||||
-rw-r--r-- | upb/pb/textprinter.c | 30 | ||||
-rw-r--r-- | upb/upb.c | 55 | ||||
-rw-r--r-- | upb/upb.h | 48 |
16 files changed, 138 insertions, 111 deletions
diff --git a/benchmarks/parsestream.upb.c b/benchmarks/parsestream.upb.c index 80f9444..e5f6246 100644 --- a/benchmarks/parsestream.upb.c +++ b/benchmarks/parsestream.upb.c @@ -33,7 +33,8 @@ static bool initialize() upb_symtab *s = upb_symtab_new(); upb_read_descriptorfile(s, MESSAGE_DESCRIPTOR_FILE, &status); if(!upb_ok(&status)) { - upb_status_print(&status, stderr); + fprintf(stderr, "Error reading descriptor: %s\n", + upb_status_getstr(&status)); return false; } @@ -82,7 +83,6 @@ static size_t run(int i) return input_len; err: - fprintf(stderr, "Decode error: "); - upb_status_print(&status, stderr); + fprintf(stderr, "Decode error: %s", upb_status_getstr(&status)); return 0; } diff --git a/benchmarks/parsetoproto2.upb.cc b/benchmarks/parsetoproto2.upb.cc index 386eeaa..2e78c1e 100644 --- a/benchmarks/parsetoproto2.upb.cc +++ b/benchmarks/parsetoproto2.upb.cc @@ -228,7 +228,8 @@ static bool initialize() upb_def **defs = upb_load_descriptor(data, len, &n, &status); free(data); if(!upb_ok(&status)) { - upb_status_print(&status, stderr); + fprintf(stderr, "Error reading descriptor: %s\n", + upb_status_getstr(&status)); return false; } @@ -249,7 +250,8 @@ static bool initialize() upb_symtab_add(s, defs, n, &status); if(!upb_ok(&status)) { - upb_status_print(&status, stderr); + fprintf(stderr, "Error reading adding to symtab: %s\n", + upb_status_getstr(&status)); return false; } for(int i = 0; i < n; i++) upb_def_unref(defs[i]); @@ -301,7 +303,6 @@ static size_t run(int i) return len; err: - fprintf(stderr, "Decode error: "); - upb_status_print(&status, stderr); + fprintf(stderr, "Decode error: %s", upb_status_getstr(&status)); return 0; } diff --git a/benchmarks/parsetostruct.upb.c b/benchmarks/parsetostruct.upb.c index f44b650..d360f05 100644 --- a/benchmarks/parsetostruct.upb.c +++ b/benchmarks/parsetostruct.upb.c @@ -20,7 +20,8 @@ static bool initialize() upb_symtab *s = upb_symtab_new(); upb_read_descriptorfile(s, MESSAGE_DESCRIPTOR_FILE, &status); if(!upb_ok(&status)) { - upb_status_print(&status, stderr); + fprintf(stderr, "Error reading descriptor: %s\n", + upb_status_getstr(&status)); return false; } @@ -76,7 +77,6 @@ static size_t run(int i) return len; err: - fprintf(stderr, "Decode error: "); - upb_status_print(&status, stderr); + fprintf(stderr, "Decode error: %s", upb_status_getstr(&status)); return 0; } diff --git a/tests/test_decoder.c b/tests/test_decoder.c index e3fc1ea..2f3cc36 100644 --- a/tests/test_decoder.c +++ b/tests/test_decoder.c @@ -22,8 +22,7 @@ int main(int argc, char *argv[]) { upb_status status = UPB_STATUS_INIT; upb_read_descriptor(symtab, desc, desc_len, &status); if (!upb_ok(&status)) { - fprintf(stderr, "Error parsing descriptor: "); - upb_status_print(&status, stderr); + fprintf(stderr, "Error parsing descriptor: %s", upb_status_getstr(&status)); return 1; } free((void*)desc); @@ -59,8 +58,7 @@ int main(int argc, char *argv[]) { upb_decoder_decode(&d, &status); if (!upb_ok(&status)) { - fprintf(stderr, "Error parsing input: "); - upb_status_print(&status, stderr); + fprintf(stderr, "Error parsing input: %s", upb_status_getstr(&status)); } upb_status_uninit(&status); diff --git a/tests/test_vs_proto2.cc b/tests/test_vs_proto2.cc index b22c620..a313aa5 100644 --- a/tests/test_vs_proto2.cc +++ b/tests/test_vs_proto2.cc @@ -188,8 +188,7 @@ void parse_and_compare(MESSAGE_CIDENT *proto2_msg, upb_msg_clear(upb_msg, upb_md); upb_strtomsg(str, len, upb_msg, upb_md, &status); if (!upb_ok(&status)) { - fprintf(stderr, "Error parsing test protobuf: "); - upb_status_print(&status, stderr); + fprintf(stderr, "Error parsing protobuf: %s", upb_status_getstr(&status)); exit(1); } string_size = 0; @@ -226,8 +225,8 @@ int main(int argc, char *argv[]) } upb_read_descriptor(symtab, fds, fds_len, &status); if(!upb_ok(&status)) { - fprintf(stderr, "Error importing " MESSAGE_DESCRIPTOR_FILE ": "); - upb_status_print(&status, stderr); + fprintf(stderr, "Error importing " MESSAGE_DESCRIPTOR_FILE ": %s", + upb_status_getstr(&status)); return 1; } free((void*)fds); diff --git a/tests/tests.c b/tests/tests.c index 7941c2f..fc8e11d 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -19,7 +19,6 @@ static upb_symtab *load_test_proto() { } upb_status status = UPB_STATUS_INIT; upb_read_descriptor(s, descriptor, len, &status); - upb_status_print(&status, stderr); ASSERT(upb_ok(&status)); upb_status_uninit(&status); free(descriptor); diff --git a/upb/bytestream.c b/upb/bytestream.c index dc2fa61..95ba064 100644 --- a/upb/bytestream.c +++ b/upb/bytestream.c @@ -21,6 +21,15 @@ char *upb_strref_dup(struct _upb_strref *r) { return ret; } +void upb_bytesink_init(upb_bytesink *sink, upb_bytesink_vtbl *vtbl) { + sink->vtbl = vtbl; + upb_status_init(&sink->status); +} + +void upb_bytesink_uninit(upb_bytesink *sink) { + upb_status_uninit(&sink->status); +} + /* upb_stdio ******************************************************************/ int upb_stdio_cmpbuf(const void *_key, const void *_elem) { @@ -134,7 +143,7 @@ uint32_t upb_stdio_vprintf(upb_bytesink *sink, upb_status *status, upb_stdio *stdio = (upb_stdio*)((char*)sink - offsetof(upb_stdio, sink)); int written = vfprintf(stdio->file, fmt, args); if (written < 0) { - upb_status_setf(status, UPB_ERROR, "Error writing to stdio stream."); + upb_status_seterrf(status, "Error writing to stdio stream."); return -1; } return written; @@ -245,18 +254,16 @@ upb_bytesink *upb_stringsink_bytesink(upb_stringsink *s) { return &s->bytesink; } -static int32_t upb_stringsink_vprintf(void *_s, upb_status *status, - const char *fmt, va_list args) { - (void)status; // TODO: report realloc() errors. +static int32_t upb_stringsink_vprintf(void *_s, const char *fmt, va_list args) { + // TODO: detect realloc() errors. upb_stringsink *s = _s; int ret = upb_vrprintf(&s->str, &s->size, s->len, fmt, args); if (ret >= 0) s->len += ret; return ret; } -bool upb_stringsink_write(void *_s, const char *buf, size_t len, - upb_status *status) { - (void)status; // TODO: report realloc() errors. +bool upb_stringsink_write(void *_s, const char *buf, size_t len) { + // TODO: detect realloc() errors. upb_stringsink *s = _s; if (s->len + len > s->size) { while(s->len + len > s->size) s->size *= 2; diff --git a/upb/bytestream.h b/upb/bytestream.h index 6ea0328..741b7e7 100644 --- a/upb/bytestream.h +++ b/upb/bytestream.h @@ -145,9 +145,8 @@ INLINE void upb_strref_read(struct _upb_strref *r, char *buf) { /* upb_bytesink ***************************************************************/ -typedef bool upb_bytesink_write_func(void*, const char*, size_t, upb_status*); -typedef int32_t upb_bytesink_vprintf_func( - void*, upb_status*, const char *fmt, va_list args); +typedef bool upb_bytesink_write_func(void*, const char*, size_t); +typedef int32_t upb_bytesink_vprintf_func(void*, const char *fmt, va_list args); typedef struct { upb_bytesink_write_func *write; @@ -156,28 +155,26 @@ typedef struct { typedef struct { upb_bytesink_vtbl *vtbl; + upb_status status; } upb_bytesink; -INLINE void upb_bytesink_init(upb_bytesink *sink, upb_bytesink_vtbl *vtbl) { - sink->vtbl = vtbl; -} +// Should be called by derived classes. +void upb_bytesink_init(upb_bytesink *sink, upb_bytesink_vtbl *vtbl); +void upb_bytesink_uninit(upb_bytesink *sink); -INLINE bool upb_bytesink_write(upb_bytesink *sink, const char *buf, size_t len, - upb_status *s) { - return sink->vtbl->write(sink, buf, len, s); +INLINE bool upb_bytesink_write(upb_bytesink *s, const char *buf, size_t len) { + return s->vtbl->write(s, buf, len); } -INLINE bool upb_bytesink_writestr(upb_bytesink *sink, const char *str, - upb_status *s) { - return upb_bytesink_write(sink, str, strlen(str), s); +INLINE bool upb_bytesink_writestr(upb_bytesink *sink, const char *str) { + return upb_bytesink_write(sink, str, strlen(str)); } // Returns the number of bytes written or -1 on error. -INLINE int32_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status, - const char *fmt, ...) { +INLINE int32_t upb_bytesink_printf(upb_bytesink *sink, const char *fmt, ...) { va_list args; va_start(args, fmt); - uint32_t ret = sink->vtbl->vprintf(sink, status, fmt, args); + uint32_t ret = sink->vtbl->vprintf(sink, fmt, args); va_end(args); return ret; } @@ -294,8 +294,8 @@ static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) { bool success = upb_enumdef_ntoi(e, str, &val); free(str); if (!success) { - upb_status_setf(s, UPB_ERROR, "Default enum value (%s) is not a " - "member of the enum", str); + upb_status_seterrf( + s, "Default enum value (%s) is not a member of the enum", str); return false; } upb_value_setint32(&f->defaultval, val); @@ -668,8 +668,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status) { for (int i = 0; i < n; i++) { upb_def *def = defs[i]; if (upb_strtable_lookup(&addtab, def->fqname)) { - upb_status_setf(status, UPB_ERROR, - "Conflicting defs named '%s'", def->fqname); + upb_status_seterrf(status, "Conflicting defs named '%s'", def->fqname); upb_strtable_free(&addtab); return false; } @@ -701,7 +700,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status) { for(j = upb_msg_begin(m); !upb_msg_done(j); j = upb_msg_next(m, j)) { upb_fielddef *f = upb_msg_iter_field(j); if (f->type == 0) { - upb_status_setf(status, UPB_ERROR, "Field type was not set."); + upb_status_seterrf(status, "Field type was not set."); return false; } @@ -739,8 +738,8 @@ bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status) { upb_symtab_ent *found; if(!(found = upb_resolve(&addtab, base, name)) && !(found = upb_resolve(symtab, base, name))) { - upb_status_setf(status, UPB_ERROR, "could not resolve symbol '%s' " - "in context '%s'", name, base); + upb_status_seterrf(status, "could not resolve symbol '%s' " + "in context '%s'", name, base); return false; } @@ -750,7 +749,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status) { //fprintf(stderr, "found->def: %p\n", found->def); //fprintf(stderr, "found->def->type: %d\n", found->def->type); if(found->def->type != expected) { - upb_status_setf(status, UPB_ERROR, "Unexpected type"); + upb_status_seterrliteral(status, "Unexpected type"); return false; } if (!upb_fielddef_resolve(f, found->def, status)) return false; diff --git a/upb/descriptor.c b/upb/descriptor.c index 49ea5ae..90ba4f7 100644 --- a/upb/descriptor.c +++ b/upb/descriptor.c @@ -203,7 +203,7 @@ static void upb_enumdef_EnumValueDescriptorProto_endmsg(void *_r, upb_status *status) { upb_descreader *r = _r; if(!r->saw_number || !r->saw_name) { - upb_status_setf(status, UPB_ERROR, "Enum value missing name or number."); + upb_status_seterrliteral(status, "Enum value missing name or number."); return; } upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); @@ -247,11 +247,11 @@ static void upb_enumdef_EnumDescriptorProto_endmsg(void *_r, upb_status *status) upb_descreader *r = _r; upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); if (upb_descreader_last((upb_descreader*)_r)->fqname == NULL) { - upb_status_setf(status, UPB_ERROR, "Enum had no name."); + upb_status_seterrliteral(status, "Enum had no name."); return; } if (upb_inttable_count(&e->iton) == 0) { - upb_status_setf(status, UPB_ERROR, "Enum had no values."); + upb_status_seterrliteral(status, "Enum had no values."); return; } } @@ -383,7 +383,7 @@ static void upb_fielddef_endmsg(void *_r, upb_status *status) { if (!upb_fielddef_parsedefault(dstr, &val, f->type)) { // We don't worry too much about giving a great error message since the // compiler should have ensured this was correct. - upb_status_setf(status, UPB_ERROR, "Error converting default value."); + upb_status_seterrliteral(status, "Error converting default value."); return; } upb_fielddef_setdefault(f, val); @@ -477,7 +477,7 @@ static void upb_msgdef_endmsg(void *_r, upb_status *status) { upb_descreader *r = _r; upb_msgdef *m = upb_descreader_top(r); if(!m->base.fqname) { - upb_status_setf(status, UPB_ERROR, "Encountered message with no name."); + upb_status_seterrliteral(status, "Encountered message with no name."); return; } diff --git a/upb/handlers.c b/upb/handlers.c index 28b72d5..b2d9f94 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -227,7 +227,7 @@ upb_dispatcher_frame *upb_dispatch_startseq(upb_dispatcher *d, //indent(d); //fprintf(stderr, "START SEQ: %d\n", f->number); if((d->top+1) >= d->limit) { - upb_status_setf(&d->status, UPB_ERROR, "Nesting too deep."); + upb_status_seterrliteral(&d->status, "Nesting too deep."); _upb_dispatcher_unwind(d, UPB_BREAK); return d->top; // Dummy. } @@ -271,7 +271,7 @@ upb_dispatcher_frame *upb_dispatch_startsubmsg(upb_dispatcher *d, //indent(d); //fprintf(stderr, "START SUBMSG: %d\n", f->number); if((d->top+1) >= d->limit) { - upb_status_setf(&d->status, UPB_ERROR, "Nesting too deep."); + upb_status_seterrliteral(&d->status, "Nesting too deep."); _upb_dispatcher_unwind(d, UPB_BREAK); return d->top; // Dummy. } diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c index 5f2b6dc..fd04efc 100644 --- a/upb/pb/decoder.c +++ b/upb/pb/decoder.c @@ -39,7 +39,7 @@ static void upb_decoder_exit2(void *_d) { upb_decoder_exit(d); } static void upb_decoder_abort(upb_decoder *d, const char *msg) { - upb_status_setf(d->status, UPB_ERROR, msg); + upb_status_seterrliteral(d->status, msg); upb_decoder_exit(d); } diff --git a/upb/pb/glue.c b/upb/pb/glue.c index e13db3e..8034c54 100644 --- a/upb/pb/glue.c +++ b/upb/pb/glue.c @@ -127,7 +127,7 @@ void upb_read_descriptorfile(upb_symtab *symtab, const char *fname, size_t len; char *data = upb_readfile(fname, &len); if (!data) { - upb_status_setf(status, UPB_ERROR, "Couldn't read file: %s", fname); + upb_status_seterrf(status, "Couldn't read file: %s", fname); return; } upb_read_descriptor(symtab, data, len, status); diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index ce029d5..893953c 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -37,7 +37,7 @@ static int upb_textprinter_putescaped(upb_textprinter *p, upb_strref *strref, for (; src < end; src++) { if (dstend - dst < 4) { - CHECK(upb_bytesink_write(p->bytesink, dstbuf, dst - dstbuf, &p->status)); + CHECK(upb_bytesink_write(p->bytesink, dstbuf, dst - dstbuf)); dst = dstbuf; } @@ -65,7 +65,7 @@ static int upb_textprinter_putescaped(upb_textprinter *p, upb_strref *strref, last_hex_escape = is_hex_escape; } // Flush remaining data. - CHECK(upb_bytesink_write(p->bytesink, dst, dst - dstbuf, &p->status)); + CHECK(upb_bytesink_write(p->bytesink, dst, dst - dstbuf)); return 0; err: return -1; @@ -74,7 +74,7 @@ err: static int upb_textprinter_indent(upb_textprinter *p) { if(!p->single_line) for(int i = 0; i < p->indent_depth; i++) - CHECK(upb_bytesink_writestr(p->bytesink, " ", &p->status)); + CHECK(upb_bytesink_writestr(p->bytesink, " ")); return 0; err: return -1; @@ -82,9 +82,9 @@ err: static int upb_textprinter_endfield(upb_textprinter *p) { if(p->single_line) { - CHECK(upb_bytesink_writestr(p->bytesink, " ", &p->status)); + CHECK(upb_bytesink_writestr(p->bytesink, " ")); } else { - CHECK(upb_bytesink_writestr(p->bytesink, "\n", &p->status)); + CHECK(upb_bytesink_writestr(p->bytesink, "\n")); } return 0; err: @@ -96,16 +96,16 @@ static upb_flow_t upb_textprinter_value(void *_p, upb_value fval, upb_textprinter *p = _p; upb_fielddef *f = upb_value_getfielddef(fval); upb_textprinter_indent(p); - CHECK(upb_bytesink_printf(p->bytesink, &p->status, "%s: ", f->name)); + CHECK(upb_bytesink_printf(p->bytesink, "%s: ", f->name)); #define CASE(fmtstr, member) \ - CHECK(upb_bytesink_printf(p->bytesink, &p->status, fmtstr, upb_value_get ## member(val))); break; + CHECK(upb_bytesink_printf(p->bytesink, fmtstr, upb_value_get ## member(val))); break; switch(f->type) { // TODO: figure out what we should really be doing for these // floating-point formats. case UPB_TYPE(DOUBLE): - CHECK(upb_bytesink_printf(p->bytesink, &p->status, "%.*g", DBL_DIG, upb_value_getdouble(val))); break; + CHECK(upb_bytesink_printf(p->bytesink, "%.*g", DBL_DIG, upb_value_getdouble(val))); break; case UPB_TYPE(FLOAT): - CHECK(upb_bytesink_printf(p->bytesink, &p->status, "%.*g", FLT_DIG+2, upb_value_getfloat(val))); break; + CHECK(upb_bytesink_printf(p->bytesink, "%.*g", FLT_DIG+2, upb_value_getfloat(val))); break; case UPB_TYPE(INT64): case UPB_TYPE(SFIXED64): case UPB_TYPE(SINT64): @@ -122,7 +122,7 @@ static upb_flow_t upb_textprinter_value(void *_p, upb_value fval, if (label) { // We found a corresponding string for this enum. Otherwise we fall // through to the int32 code path. - CHECK(upb_bytesink_writestr(p->bytesink, label, &p->status)); + CHECK(upb_bytesink_writestr(p->bytesink, label)); break; } } @@ -134,10 +134,10 @@ static upb_flow_t upb_textprinter_value(void *_p, upb_value fval, CASE("%hhu", bool); case UPB_TYPE(STRING): case UPB_TYPE(BYTES): { - CHECK(upb_bytesink_writestr(p->bytesink, "\"", &p->status)); + CHECK(upb_bytesink_writestr(p->bytesink, "\"")); CHECK(upb_textprinter_putescaped(p, upb_value_getstrref(val), f->type == UPB_TYPE(STRING))); - CHECK(upb_bytesink_writestr(p->bytesink, "\"", &p->status)); + CHECK(upb_bytesink_writestr(p->bytesink, "\"")); break; } } @@ -151,10 +151,10 @@ static upb_sflow_t upb_textprinter_startsubmsg(void *_p, upb_value fval) { upb_textprinter *p = _p; upb_fielddef *f = upb_value_getfielddef(fval); upb_textprinter_indent(p); - bool ret = upb_bytesink_printf(p->bytesink, &p->status, "%s {", f->name); + bool ret = upb_bytesink_printf(p->bytesink, "%s {", f->name); if (!ret) return UPB_SBREAK; if (!p->single_line) - upb_bytesink_writestr(p->bytesink, "\n", &p->status); + upb_bytesink_writestr(p->bytesink, "\n"); p->indent_depth++; return UPB_CONTINUE_WITH(_p); } @@ -164,7 +164,7 @@ static upb_flow_t upb_textprinter_endsubmsg(void *_p, upb_value fval) { upb_textprinter *p = _p; p->indent_depth--; upb_textprinter_indent(p); - upb_bytesink_writestr(p->bytesink, "}", &p->status); + upb_bytesink_writestr(p->bytesink, "}"); upb_textprinter_endfield(p); return UPB_CONTINUE; } @@ -48,6 +48,7 @@ upb_value UPB_NO_VALUE = {{0}, -1}; void upb_status_init(upb_status *status) { status->buf = NULL; + status->bufsize = 0; upb_status_clear(status); } @@ -55,9 +56,8 @@ void upb_status_uninit(upb_status *status) { free(status->buf); } -void upb_status_setf(upb_status *s, enum upb_status_code code, - const char *msg, ...) { - s->code = code; +void upb_status_seterrf(upb_status *s, const char *msg, ...) { + s->code = UPB_ERROR; va_list args; va_start(args, msg); upb_vrprintf(&s->buf, &s->bufsize, 0, msg, args); @@ -65,37 +65,62 @@ void upb_status_setf(upb_status *s, enum upb_status_code code, s->str = s->buf; } +void upb_status_seterrliteral(upb_status *status, const char *msg) { + status->code = UPB_ERROR; + status->str = msg; + status->space = NULL; +} + void upb_status_copy(upb_status *to, upb_status *from) { + to->status = from->status; to->code = from->code; - if (from->str) { + to->space = from->space; + if (from->str == from->buf) { if (to->bufsize < from->bufsize) { to->bufsize = from->bufsize; to->buf = realloc(to->buf, to->bufsize); - to->str = to->buf; } - memcpy(to->str, from->str, from->bufsize); + memcpy(to->buf, from->buf, from->bufsize); + to->str = to->buf; } else { - to->str = NULL; + to->str = from->str; + } +} + +const char *upb_status_getstr(upb_status *status) { + if (status->str == NULL && status->space && status->space->code_to_string) { + status->space->code_to_string(status->code, status->buf, status->bufsize); + status->str = status->buf; } + return status->str; } void upb_status_clear(upb_status *status) { - status->code = UPB_OK; + status->status = UPB_OK; + status->code = 0; + status->space = NULL; status->str = NULL; } -void upb_status_print(upb_status *status, FILE *f) { - if(status->str) { - fprintf(f, "code: %d, msg: %s\n", status->code, status->str); - } else { - fprintf(f, "code: %d, no msg\n", status->code); - } +void upb_status_setcode(upb_status *status, upb_errorspace *space, int code) { + status->code = code; + status->space = space; + status->str = NULL; } void upb_status_fromerrno(upb_status *status) { - upb_status_setf(status, UPB_ERROR, "%s", strerror(errno)); + if (errno == 0) { + status->status = UPB_OK; + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { + status->status = UPB_WOULDBLOCK; + } else { + status->status = UPB_ERROR; + } + upb_status_setcode(status, &upb_posix_errorspace, errno); } +upb_errorspace upb_posix_errorspace = {"POSIX", NULL}; // TODO + int upb_vrprintf(char **buf, size_t *size, size_t ofs, const char *fmt, va_list args) { // Try once without reallocating. We have to va_copy because we might have @@ -187,46 +187,48 @@ extern upb_value UPB_NO_VALUE; /* upb_status *****************************************************************/ -// Status codes used as a return value. Codes >0 are not fatal and can be -// resumed. -enum upb_status_code { - // The operation completed successfully. - UPB_OK = 0, - - // The bytesrc is at EOF and all data was read successfully. - UPB_EOF = 1, - - // A read or write from a streaming src/sink could not be completed right now. - UPB_TRYAGAIN = 2, - - // An unrecoverable error occurred. - UPB_ERROR = -1, +enum { + UPB_OK, // The operation completed successfully. + UPB_WOULDBLOCK, // Stream is nonblocking and the operation would block. + UPB_ERROR, // An error occurred. }; +typedef struct { + const char *name; + // Writes a NULL-terminated string to "buf" containing an error message for + // the given error code, returning false if the message was too large to fit. + bool (*code_to_string)(int code, char *buf, size_t len); +} upb_errorspace; + // TODO: consider adding error space and code, to let ie. errno be stored // as a proper code, or application-specific error codes. typedef struct { - char code; - char *str; // NULL when no message is present. NULL-terminated. - char *buf; // Owned by the status. + char status; + int code; // Can be set to a more specific code (defined by error space). + upb_errorspace *space; + const char *str; // NULL when no message is present. NULL-terminated. + char *buf; // Owned by the status. size_t bufsize; } upb_status; -#define UPB_STATUS_INIT {UPB_OK, NULL, NULL, 0} +#define UPB_STATUS_INIT {UPB_OK, 0, NULL, NULL, NULL, 0} void upb_status_init(upb_status *status); void upb_status_uninit(upb_status *status); INLINE bool upb_ok(upb_status *status) { return status->code == UPB_OK; } -INLINE bool upb_iseof(upb_status *status) { return status->code == UPB_EOF; } -void upb_status_fromerrno(upb_status *status); -void upb_status_print(upb_status *status, FILE *f); void upb_status_clear(upb_status *status); -void upb_status_setf(upb_status *status, enum upb_status_code code, - const char *fmt, ...); +void upb_status_seterrliteral(upb_status *status, const char *msg); +void upb_status_seterrf(upb_status *s, const char *msg, ...); +void upb_status_setcode(upb_status *s, upb_errorspace *space, int code); +// The returned string is invalidated by any other call into the status. +const char *upb_status_getstr(upb_status *s); void upb_status_copy(upb_status *to, upb_status *from); +upb_errorspace upb_posix_errorspace; +void upb_status_fromerrno(upb_status *status); + // Like vaprintf, but uses *buf (which can be NULL) as a starting point and // reallocates it only if the new value will not fit. "size" is updated to // reflect the allocated size of the buffer. Returns false on memory alloc |