Refined upb_status.

pull/13171/head
Joshua Haberman 13 years ago
parent 48fedab345
commit 521ac7a89a
  1. 6
      benchmarks/parsestream.upb.c
  2. 9
      benchmarks/parsetoproto2.upb.cc
  3. 6
      benchmarks/parsetostruct.upb.c
  4. 6
      tests/test_decoder.c
  5. 7
      tests/test_vs_proto2.cc
  6. 1
      tests/tests.c
  7. 21
      upb/bytestream.c
  8. 27
      upb/bytestream.h
  9. 15
      upb/def.c
  10. 10
      upb/descriptor.c
  11. 4
      upb/handlers.c
  12. 2
      upb/pb/decoder.c
  13. 2
      upb/pb/glue.c
  14. 30
      upb/pb/textprinter.c
  15. 55
      upb/upb.c
  16. 48
      upb/upb.h

@ -33,7 +33,8 @@ static bool initialize()
upb_symtab *s = upb_symtab_new(); upb_symtab *s = upb_symtab_new();
upb_read_descriptorfile(s, MESSAGE_DESCRIPTOR_FILE, &status); upb_read_descriptorfile(s, MESSAGE_DESCRIPTOR_FILE, &status);
if(!upb_ok(&status)) { if(!upb_ok(&status)) {
upb_status_print(&status, stderr); fprintf(stderr, "Error reading descriptor: %s\n",
upb_status_getstr(&status));
return false; return false;
} }
@ -82,7 +83,6 @@ static size_t run(int i)
return input_len; return input_len;
err: err:
fprintf(stderr, "Decode error: "); fprintf(stderr, "Decode error: %s", upb_status_getstr(&status));
upb_status_print(&status, stderr);
return 0; return 0;
} }

@ -228,7 +228,8 @@ static bool initialize()
upb_def **defs = upb_load_descriptor(data, len, &n, &status); upb_def **defs = upb_load_descriptor(data, len, &n, &status);
free(data); free(data);
if(!upb_ok(&status)) { if(!upb_ok(&status)) {
upb_status_print(&status, stderr); fprintf(stderr, "Error reading descriptor: %s\n",
upb_status_getstr(&status));
return false; return false;
} }
@ -249,7 +250,8 @@ static bool initialize()
upb_symtab_add(s, defs, n, &status); upb_symtab_add(s, defs, n, &status);
if(!upb_ok(&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; return false;
} }
for(int i = 0; i < n; i++) upb_def_unref(defs[i]); for(int i = 0; i < n; i++) upb_def_unref(defs[i]);
@ -301,7 +303,6 @@ static size_t run(int i)
return len; return len;
err: err:
fprintf(stderr, "Decode error: "); fprintf(stderr, "Decode error: %s", upb_status_getstr(&status));
upb_status_print(&status, stderr);
return 0; return 0;
} }

@ -20,7 +20,8 @@ static bool initialize()
upb_symtab *s = upb_symtab_new(); upb_symtab *s = upb_symtab_new();
upb_read_descriptorfile(s, MESSAGE_DESCRIPTOR_FILE, &status); upb_read_descriptorfile(s, MESSAGE_DESCRIPTOR_FILE, &status);
if(!upb_ok(&status)) { if(!upb_ok(&status)) {
upb_status_print(&status, stderr); fprintf(stderr, "Error reading descriptor: %s\n",
upb_status_getstr(&status));
return false; return false;
} }
@ -76,7 +77,6 @@ static size_t run(int i)
return len; return len;
err: err:
fprintf(stderr, "Decode error: "); fprintf(stderr, "Decode error: %s", upb_status_getstr(&status));
upb_status_print(&status, stderr);
return 0; return 0;
} }

@ -22,8 +22,7 @@ int main(int argc, char *argv[]) {
upb_status status = UPB_STATUS_INIT; upb_status status = UPB_STATUS_INIT;
upb_read_descriptor(symtab, desc, desc_len, &status); upb_read_descriptor(symtab, desc, desc_len, &status);
if (!upb_ok(&status)) { if (!upb_ok(&status)) {
fprintf(stderr, "Error parsing descriptor: "); fprintf(stderr, "Error parsing descriptor: %s", upb_status_getstr(&status));
upb_status_print(&status, stderr);
return 1; return 1;
} }
free((void*)desc); free((void*)desc);
@ -59,8 +58,7 @@ int main(int argc, char *argv[]) {
upb_decoder_decode(&d, &status); upb_decoder_decode(&d, &status);
if (!upb_ok(&status)) { if (!upb_ok(&status)) {
fprintf(stderr, "Error parsing input: "); fprintf(stderr, "Error parsing input: %s", upb_status_getstr(&status));
upb_status_print(&status, stderr);
} }
upb_status_uninit(&status); upb_status_uninit(&status);

@ -188,8 +188,7 @@ void parse_and_compare(MESSAGE_CIDENT *proto2_msg,
upb_msg_clear(upb_msg, upb_md); upb_msg_clear(upb_msg, upb_md);
upb_strtomsg(str, len, upb_msg, upb_md, &status); upb_strtomsg(str, len, upb_msg, upb_md, &status);
if (!upb_ok(&status)) { if (!upb_ok(&status)) {
fprintf(stderr, "Error parsing test protobuf: "); fprintf(stderr, "Error parsing protobuf: %s", upb_status_getstr(&status));
upb_status_print(&status, stderr);
exit(1); exit(1);
} }
string_size = 0; string_size = 0;
@ -226,8 +225,8 @@ int main(int argc, char *argv[])
} }
upb_read_descriptor(symtab, fds, fds_len, &status); upb_read_descriptor(symtab, fds, fds_len, &status);
if(!upb_ok(&status)) { if(!upb_ok(&status)) {
fprintf(stderr, "Error importing " MESSAGE_DESCRIPTOR_FILE ": "); fprintf(stderr, "Error importing " MESSAGE_DESCRIPTOR_FILE ": %s",
upb_status_print(&status, stderr); upb_status_getstr(&status));
return 1; return 1;
} }
free((void*)fds); free((void*)fds);

@ -19,7 +19,6 @@ static upb_symtab *load_test_proto() {
} }
upb_status status = UPB_STATUS_INIT; upb_status status = UPB_STATUS_INIT;
upb_read_descriptor(s, descriptor, len, &status); upb_read_descriptor(s, descriptor, len, &status);
upb_status_print(&status, stderr);
ASSERT(upb_ok(&status)); ASSERT(upb_ok(&status));
upb_status_uninit(&status); upb_status_uninit(&status);
free(descriptor); free(descriptor);

@ -21,6 +21,15 @@ char *upb_strref_dup(struct _upb_strref *r) {
return ret; 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 ******************************************************************/ /* upb_stdio ******************************************************************/
int upb_stdio_cmpbuf(const void *_key, const void *_elem) { 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)); upb_stdio *stdio = (upb_stdio*)((char*)sink - offsetof(upb_stdio, sink));
int written = vfprintf(stdio->file, fmt, args); int written = vfprintf(stdio->file, fmt, args);
if (written < 0) { 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 -1;
} }
return written; return written;
@ -245,18 +254,16 @@ upb_bytesink *upb_stringsink_bytesink(upb_stringsink *s) {
return &s->bytesink; return &s->bytesink;
} }
static int32_t upb_stringsink_vprintf(void *_s, upb_status *status, static int32_t upb_stringsink_vprintf(void *_s, const char *fmt, va_list args) {
const char *fmt, va_list args) { // TODO: detect realloc() errors.
(void)status; // TODO: report realloc() errors.
upb_stringsink *s = _s; upb_stringsink *s = _s;
int ret = upb_vrprintf(&s->str, &s->size, s->len, fmt, args); int ret = upb_vrprintf(&s->str, &s->size, s->len, fmt, args);
if (ret >= 0) s->len += ret; if (ret >= 0) s->len += ret;
return ret; return ret;
} }
bool upb_stringsink_write(void *_s, const char *buf, size_t len, bool upb_stringsink_write(void *_s, const char *buf, size_t len) {
upb_status *status) { // TODO: detect realloc() errors.
(void)status; // TODO: report realloc() errors.
upb_stringsink *s = _s; upb_stringsink *s = _s;
if (s->len + len > s->size) { if (s->len + len > s->size) {
while(s->len + len > s->size) s->size *= 2; while(s->len + len > s->size) s->size *= 2;

@ -145,9 +145,8 @@ INLINE void upb_strref_read(struct _upb_strref *r, char *buf) {
/* upb_bytesink ***************************************************************/ /* upb_bytesink ***************************************************************/
typedef bool upb_bytesink_write_func(void*, const char*, size_t, upb_status*); typedef bool upb_bytesink_write_func(void*, const char*, size_t);
typedef int32_t upb_bytesink_vprintf_func( typedef int32_t upb_bytesink_vprintf_func(void*, const char *fmt, va_list args);
void*, upb_status*, const char *fmt, va_list args);
typedef struct { typedef struct {
upb_bytesink_write_func *write; upb_bytesink_write_func *write;
@ -156,28 +155,26 @@ typedef struct {
typedef struct { typedef struct {
upb_bytesink_vtbl *vtbl; upb_bytesink_vtbl *vtbl;
upb_status status;
} upb_bytesink; } upb_bytesink;
INLINE void upb_bytesink_init(upb_bytesink *sink, upb_bytesink_vtbl *vtbl) { // Should be called by derived classes.
sink->vtbl = vtbl; 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, INLINE bool upb_bytesink_write(upb_bytesink *s, const char *buf, size_t len) {
upb_status *s) { return s->vtbl->write(s, buf, len);
return sink->vtbl->write(sink, buf, len, s);
} }
INLINE bool upb_bytesink_writestr(upb_bytesink *sink, const char *str, INLINE bool upb_bytesink_writestr(upb_bytesink *sink, const char *str) {
upb_status *s) { return upb_bytesink_write(sink, str, strlen(str));
return upb_bytesink_write(sink, str, strlen(str), s);
} }
// Returns the number of bytes written or -1 on error. // Returns the number of bytes written or -1 on error.
INLINE int32_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status, INLINE int32_t upb_bytesink_printf(upb_bytesink *sink, const char *fmt, ...) {
const char *fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); 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); va_end(args);
return ret; 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); bool success = upb_enumdef_ntoi(e, str, &val);
free(str); free(str);
if (!success) { if (!success) {
upb_status_setf(s, UPB_ERROR, "Default enum value (%s) is not a " upb_status_seterrf(
"member of the enum", str); s, "Default enum value (%s) is not a member of the enum", str);
return false; return false;
} }
upb_value_setint32(&f->defaultval, val); 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++) { for (int i = 0; i < n; i++) {
upb_def *def = defs[i]; upb_def *def = defs[i];
if (upb_strtable_lookup(&addtab, def->fqname)) { if (upb_strtable_lookup(&addtab, def->fqname)) {
upb_status_setf(status, UPB_ERROR, upb_status_seterrf(status, "Conflicting defs named '%s'", def->fqname);
"Conflicting defs named '%s'", def->fqname);
upb_strtable_free(&addtab); upb_strtable_free(&addtab);
return false; 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)) { for(j = upb_msg_begin(m); !upb_msg_done(j); j = upb_msg_next(m, j)) {
upb_fielddef *f = upb_msg_iter_field(j); upb_fielddef *f = upb_msg_iter_field(j);
if (f->type == 0) { 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; 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; upb_symtab_ent *found;
if(!(found = upb_resolve(&addtab, base, name)) && if(!(found = upb_resolve(&addtab, base, name)) &&
!(found = upb_resolve(symtab, base, name))) { !(found = upb_resolve(symtab, base, name))) {
upb_status_setf(status, UPB_ERROR, "could not resolve symbol '%s' " upb_status_seterrf(status, "could not resolve symbol '%s' "
"in context '%s'", name, base); "in context '%s'", name, base);
return false; 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: %p\n", found->def);
//fprintf(stderr, "found->def->type: %d\n", found->def->type); //fprintf(stderr, "found->def->type: %d\n", found->def->type);
if(found->def->type != expected) { if(found->def->type != expected) {
upb_status_setf(status, UPB_ERROR, "Unexpected type"); upb_status_seterrliteral(status, "Unexpected type");
return false; return false;
} }
if (!upb_fielddef_resolve(f, found->def, status)) return false; if (!upb_fielddef_resolve(f, found->def, status)) return false;

@ -203,7 +203,7 @@ static void upb_enumdef_EnumValueDescriptorProto_endmsg(void *_r,
upb_status *status) { upb_status *status) {
upb_descreader *r = _r; upb_descreader *r = _r;
if(!r->saw_number || !r->saw_name) { 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; return;
} }
upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); 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_descreader *r = _r;
upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r));
if (upb_descreader_last((upb_descreader*)_r)->fqname == NULL) { 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; return;
} }
if (upb_inttable_count(&e->iton) == 0) { 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; return;
} }
} }
@ -383,7 +383,7 @@ static void upb_fielddef_endmsg(void *_r, upb_status *status) {
if (!upb_fielddef_parsedefault(dstr, &val, f->type)) { if (!upb_fielddef_parsedefault(dstr, &val, f->type)) {
// We don't worry too much about giving a great error message since the // We don't worry too much about giving a great error message since the
// compiler should have ensured this was correct. // 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; return;
} }
upb_fielddef_setdefault(f, val); upb_fielddef_setdefault(f, val);
@ -477,7 +477,7 @@ static void upb_msgdef_endmsg(void *_r, upb_status *status) {
upb_descreader *r = _r; upb_descreader *r = _r;
upb_msgdef *m = upb_descreader_top(r); upb_msgdef *m = upb_descreader_top(r);
if(!m->base.fqname) { 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; return;
} }

@ -227,7 +227,7 @@ upb_dispatcher_frame *upb_dispatch_startseq(upb_dispatcher *d,
//indent(d); //indent(d);
//fprintf(stderr, "START SEQ: %d\n", f->number); //fprintf(stderr, "START SEQ: %d\n", f->number);
if((d->top+1) >= d->limit) { 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); _upb_dispatcher_unwind(d, UPB_BREAK);
return d->top; // Dummy. return d->top; // Dummy.
} }
@ -271,7 +271,7 @@ upb_dispatcher_frame *upb_dispatch_startsubmsg(upb_dispatcher *d,
//indent(d); //indent(d);
//fprintf(stderr, "START SUBMSG: %d\n", f->number); //fprintf(stderr, "START SUBMSG: %d\n", f->number);
if((d->top+1) >= d->limit) { 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); _upb_dispatcher_unwind(d, UPB_BREAK);
return d->top; // Dummy. return d->top; // Dummy.
} }

@ -39,7 +39,7 @@ static void upb_decoder_exit2(void *_d) {
upb_decoder_exit(d); upb_decoder_exit(d);
} }
static void upb_decoder_abort(upb_decoder *d, const char *msg) { 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); upb_decoder_exit(d);
} }

@ -127,7 +127,7 @@ void upb_read_descriptorfile(upb_symtab *symtab, const char *fname,
size_t len; size_t len;
char *data = upb_readfile(fname, &len); char *data = upb_readfile(fname, &len);
if (!data) { 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; return;
} }
upb_read_descriptor(symtab, data, len, status); upb_read_descriptor(symtab, data, len, status);

@ -37,7 +37,7 @@ static int upb_textprinter_putescaped(upb_textprinter *p, upb_strref *strref,
for (; src < end; src++) { for (; src < end; src++) {
if (dstend - dst < 4) { 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; dst = dstbuf;
} }
@ -65,7 +65,7 @@ static int upb_textprinter_putescaped(upb_textprinter *p, upb_strref *strref,
last_hex_escape = is_hex_escape; last_hex_escape = is_hex_escape;
} }
// Flush remaining data. // 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; return 0;
err: err:
return -1; return -1;
@ -74,7 +74,7 @@ err:
static int upb_textprinter_indent(upb_textprinter *p) { static int upb_textprinter_indent(upb_textprinter *p) {
if(!p->single_line) if(!p->single_line)
for(int i = 0; i < p->indent_depth; i++) 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; return 0;
err: err:
return -1; return -1;
@ -82,9 +82,9 @@ err:
static int upb_textprinter_endfield(upb_textprinter *p) { static int upb_textprinter_endfield(upb_textprinter *p) {
if(p->single_line) { if(p->single_line) {
CHECK(upb_bytesink_writestr(p->bytesink, " ", &p->status)); CHECK(upb_bytesink_writestr(p->bytesink, " "));
} else { } else {
CHECK(upb_bytesink_writestr(p->bytesink, "\n", &p->status)); CHECK(upb_bytesink_writestr(p->bytesink, "\n"));
} }
return 0; return 0;
err: err:
@ -96,16 +96,16 @@ static upb_flow_t upb_textprinter_value(void *_p, upb_value fval,
upb_textprinter *p = _p; upb_textprinter *p = _p;
upb_fielddef *f = upb_value_getfielddef(fval); upb_fielddef *f = upb_value_getfielddef(fval);
upb_textprinter_indent(p); 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) \ #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) { switch(f->type) {
// TODO: figure out what we should really be doing for these // TODO: figure out what we should really be doing for these
// floating-point formats. // floating-point formats.
case UPB_TYPE(DOUBLE): 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): 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(INT64):
case UPB_TYPE(SFIXED64): case UPB_TYPE(SFIXED64):
case UPB_TYPE(SINT64): case UPB_TYPE(SINT64):
@ -122,7 +122,7 @@ static upb_flow_t upb_textprinter_value(void *_p, upb_value fval,
if (label) { if (label) {
// We found a corresponding string for this enum. Otherwise we fall // We found a corresponding string for this enum. Otherwise we fall
// through to the int32 code path. // through to the int32 code path.
CHECK(upb_bytesink_writestr(p->bytesink, label, &p->status)); CHECK(upb_bytesink_writestr(p->bytesink, label));
break; break;
} }
} }
@ -134,10 +134,10 @@ static upb_flow_t upb_textprinter_value(void *_p, upb_value fval,
CASE("%hhu", bool); CASE("%hhu", bool);
case UPB_TYPE(STRING): case UPB_TYPE(STRING):
case UPB_TYPE(BYTES): { 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), CHECK(upb_textprinter_putescaped(p, upb_value_getstrref(val),
f->type == UPB_TYPE(STRING))); f->type == UPB_TYPE(STRING)));
CHECK(upb_bytesink_writestr(p->bytesink, "\"", &p->status)); CHECK(upb_bytesink_writestr(p->bytesink, "\""));
break; break;
} }
} }
@ -151,10 +151,10 @@ static upb_sflow_t upb_textprinter_startsubmsg(void *_p, upb_value fval) {
upb_textprinter *p = _p; upb_textprinter *p = _p;
upb_fielddef *f = upb_value_getfielddef(fval); upb_fielddef *f = upb_value_getfielddef(fval);
upb_textprinter_indent(p); 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 (!ret) return UPB_SBREAK;
if (!p->single_line) if (!p->single_line)
upb_bytesink_writestr(p->bytesink, "\n", &p->status); upb_bytesink_writestr(p->bytesink, "\n");
p->indent_depth++; p->indent_depth++;
return UPB_CONTINUE_WITH(_p); 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; upb_textprinter *p = _p;
p->indent_depth--; p->indent_depth--;
upb_textprinter_indent(p); upb_textprinter_indent(p);
upb_bytesink_writestr(p->bytesink, "}", &p->status); upb_bytesink_writestr(p->bytesink, "}");
upb_textprinter_endfield(p); upb_textprinter_endfield(p);
return UPB_CONTINUE; return UPB_CONTINUE;
} }

@ -48,6 +48,7 @@ upb_value UPB_NO_VALUE = {{0}, -1};
void upb_status_init(upb_status *status) { void upb_status_init(upb_status *status) {
status->buf = NULL; status->buf = NULL;
status->bufsize = 0;
upb_status_clear(status); upb_status_clear(status);
} }
@ -55,9 +56,8 @@ void upb_status_uninit(upb_status *status) {
free(status->buf); free(status->buf);
} }
void upb_status_setf(upb_status *s, enum upb_status_code code, void upb_status_seterrf(upb_status *s, const char *msg, ...) {
const char *msg, ...) { s->code = UPB_ERROR;
s->code = code;
va_list args; va_list args;
va_start(args, msg); va_start(args, msg);
upb_vrprintf(&s->buf, &s->bufsize, 0, msg, args); 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; 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) { void upb_status_copy(upb_status *to, upb_status *from) {
to->status = from->status;
to->code = from->code; to->code = from->code;
if (from->str) { to->space = from->space;
if (from->str == from->buf) {
if (to->bufsize < from->bufsize) { if (to->bufsize < from->bufsize) {
to->bufsize = from->bufsize; to->bufsize = from->bufsize;
to->buf = realloc(to->buf, to->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 { } 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) { void upb_status_clear(upb_status *status) {
status->code = UPB_OK; status->status = UPB_OK;
status->code = 0;
status->space = NULL;
status->str = NULL; status->str = NULL;
} }
void upb_status_print(upb_status *status, FILE *f) { void upb_status_setcode(upb_status *status, upb_errorspace *space, int code) {
if(status->str) { status->code = code;
fprintf(f, "code: %d, msg: %s\n", status->code, status->str); status->space = space;
} else { status->str = NULL;
fprintf(f, "code: %d, no msg\n", status->code);
}
} }
void upb_status_fromerrno(upb_status *status) { 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, int upb_vrprintf(char **buf, size_t *size, size_t ofs,
const char *fmt, va_list args) { const char *fmt, va_list args) {
// Try once without reallocating. We have to va_copy because we might have // 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 *****************************************************************/ /* upb_status *****************************************************************/
// Status codes used as a return value. Codes >0 are not fatal and can be enum {
// resumed. UPB_OK, // The operation completed successfully.
enum upb_status_code { UPB_WOULDBLOCK, // Stream is nonblocking and the operation would block.
// The operation completed successfully. UPB_ERROR, // An error occurred.
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,
}; };
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 // TODO: consider adding error space and code, to let ie. errno be stored
// as a proper code, or application-specific error codes. // as a proper code, or application-specific error codes.
typedef struct { typedef struct {
char code; char status;
char *str; // NULL when no message is present. NULL-terminated. int code; // Can be set to a more specific code (defined by error space).
char *buf; // Owned by the status. upb_errorspace *space;
const char *str; // NULL when no message is present. NULL-terminated.
char *buf; // Owned by the status.
size_t bufsize; size_t bufsize;
} upb_status; } 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_init(upb_status *status);
void upb_status_uninit(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_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_clear(upb_status *status);
void upb_status_setf(upb_status *status, enum upb_status_code code, void upb_status_seterrliteral(upb_status *status, const char *msg);
const char *fmt, ...); 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); 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 // 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 // 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 // reflect the allocated size of the buffer. Returns false on memory alloc

Loading…
Cancel
Save