summaryrefslogtreecommitdiff
path: root/upb
diff options
context:
space:
mode:
Diffstat (limited to 'upb')
-rw-r--r--upb/bytestream.c21
-rw-r--r--upb/bytestream.h27
-rw-r--r--upb/def.c15
-rw-r--r--upb/descriptor.c10
-rw-r--r--upb/handlers.c4
-rw-r--r--upb/pb/decoder.c2
-rw-r--r--upb/pb/glue.c2
-rw-r--r--upb/pb/textprinter.c30
-rw-r--r--upb/upb.c55
-rw-r--r--upb/upb.h48
10 files changed, 122 insertions, 92 deletions
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;
}
diff --git a/upb/def.c b/upb/def.c
index 09eab7d..f83f5eb 100644
--- a/upb/def.c
+++ b/upb/def.c
@@ -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;
}
diff --git a/upb/upb.c b/upb/upb.c
index 006734e..bb85afc 100644
--- a/upb/upb.c
+++ b/upb/upb.c
@@ -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
diff --git a/upb/upb.h b/upb/upb.h
index c826e17..d8ecd9b 100644
--- a/upb/upb.h
+++ b/upb/upb.h
@@ -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
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback