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_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;
}

@ -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;
}

@ -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;
}

@ -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);

@ -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);

@ -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);

@ -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;

@ -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;

@ -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;
}

@ -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.
}

@ -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);
}

@ -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);

@ -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

Loading…
Cancel
Save