summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2010-06-10 09:14:31 -0700
committerJoshua Haberman <joshua@reverberate.org>2010-06-10 09:14:31 -0700
commit563325435753fae01d2b45cceba8b9d14c8a7aad (patch)
treef4ce7aab922308d0f2f6a2d7cb742e76b3b791d3 /src
parent5743636ad19eafb11eddeefd29f2803052dadff2 (diff)
Implement proper type checking again.
Diffstat (limited to 'src')
-rw-r--r--src/upb.c28
-rw-r--r--src/upb.h12
-rw-r--r--src/upb_decoder.c11
-rw-r--r--src/upb_string.h2
4 files changed, 47 insertions, 6 deletions
diff --git a/src/upb.c b/src/upb.c
index bd41613..189dfe4 100644
--- a/src/upb.c
+++ b/src/upb.c
@@ -11,6 +11,34 @@
#include "upb.h"
+#define alignof(t) offsetof(struct { char c; t x; }, x)
+#define TYPE_INFO(wire_type, ctype, allows_delimited) \
+ {alignof(ctype), sizeof(ctype), wire_type, \
+ (1 << wire_type) | (allows_delimited << UPB_WIRE_TYPE_DELIMITED), \
+ #ctype},
+
+upb_type_info upb_types[] = {
+ {0, 0, 0, ""} // There is no type 0.
+ TYPE_INFO(UPB_WIRE_TYPE_64BIT, double, 1), // DOUBLE
+ TYPE_INFO(UPB_WIRE_TYPE_32BIT, float, 1), // FLOAT
+ TYPE_INFO(UPB_WIRE_TYPE_VARINT, int64_t, 1), // INT64
+ TYPE_INFO(UPB_WIRE_TYPE_VARINT, uint64_t, 1), // UINT64
+ TYPE_INFO(UPB_WIRE_TYPE_VARINT, int32_t, 1), // INT32
+ TYPE_INFO(UPB_WIRE_TYPE_64BIT, uint64_t, 1), // FIXED64
+ TYPE_INFO(UPB_WIRE_TYPE_32BIT, uint32_t, 1), // FIXED32
+ TYPE_INFO(UPB_WIRE_TYPE_VARINT, bool, 1), // BOOL
+ TYPE_INFO(UPB_WIRE_TYPE_DELIMITED, void*, 1), // STRING
+ TYPE_INFO(UPB_WIRE_TYPE_START_GROUP, void*, 0), // GROUP
+ TYPE_INFO(UPB_WIRE_TYPE_DELIMITED, void*, 1), // MESSAGE
+ TYPE_INFO(UPB_WIRE_TYPE_DELIMITED, void*, 1), // BYTES
+ TYPE_INFO(UPB_WIRE_TYPE_VARINT, uint32_t, 1), // UINT32
+ TYPE_INFO(UPB_WIRE_TYPE_VARINT, uint32_t, 1), // ENUM
+ TYPE_INFO(UPB_WIRE_TYPE_32BIT, int32_t, 1), // SFIXED32
+ TYPE_INFO(UPB_WIRE_TYPE_64BIT, int64_t, 1), // SFIXED64
+ TYPE_INFO(UPB_WIRE_TYPE_VARINT, int32_t, 1), // SINT32
+ TYPE_INFO(UPB_WIRE_TYPE_VARINT, int64_t, 1), // SINT64
+};
+
void upb_seterr(upb_status *status, enum upb_status_code code,
const char *msg, ...)
{
diff --git a/src/upb.h b/src/upb.h
index 1681763..6bf548c 100644
--- a/src/upb.h
+++ b/src/upb.h
@@ -98,6 +98,18 @@ INLINE bool upb_isstringtype(upb_field_type_t type) {
return type == UPB_TYPE(STRING) || type == UPB_TYPE(BYTES);
}
+// Info for a given field type.
+typedef struct {
+ uint8_t align;
+ uint8_t size;
+ upb_wire_type_t native_wire_type;
+ uint8_t allowed_wire_types; // For packable fields, also allows delimited.
+ char *ctype;
+} upb_type_info;
+
+// A static array of info about all of the field types, indexed by type number.
+extern upb_type_info upb_types[];
+
// The number of a field, eg. "optional string foo = 3".
typedef int32_t upb_field_number_t;
diff --git a/src/upb_decoder.c b/src/upb_decoder.c
index 5d352c2..c54a21a 100644
--- a/src/upb_decoder.c
+++ b/src/upb_decoder.c
@@ -12,9 +12,10 @@
#define UPB_GROUP_END_OFFSET UINT32_MAX
+// Returns true if the give wire type and field type combination is valid,
+// taking into account both packed and non-packed encodings.
static bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) {
- // Fake implementation.
- return ft + wt > 3;
+ return (1 << wt) & upb_types[ft].allowed_wire_types;
}
/* Functions to read wire values. *********************************************/
@@ -348,8 +349,8 @@ upb_fielddef *upb_decoder_getdef(upb_decoder *d)
bool upb_decoder_getval(upb_decoder *d, upb_valueptr val)
{
- int expected_type_for_field = 0;
- if(expected_type_for_field == UPB_WIRE_TYPE_DELIMITED) {
+ upb_wire_type_t native_wire_type = upb_types[d->field->type].native_wire_type;
+ if(native_wire_type == UPB_WIRE_TYPE_DELIMITED) {
// A string, bytes, or a length-delimited submessage. The latter isn't
// technically a string, but can be gotten as one to perform lazy parsing.
d->str = upb_string_tryrecycle(d->str);
@@ -385,7 +386,7 @@ bool upb_decoder_getval(upb_decoder *d, upb_valueptr val)
uint32_t bytes_available;
uint32_t bytes_consumed;
const uint8_t *buf = upb_decoder_getbuf(d, &bytes_available);
- switch(expected_type_for_field) {
+ switch(native_wire_type) {
case UPB_WIRE_TYPE_VARINT:
if((bytes_consumed = upb_get_v_uint32(buf, val.uint32)) > 10) goto err;
if(d->field->type == UPB_TYPE(SINT64)) *val.int64 = upb_zzdec_64(*val.int64);
diff --git a/src/upb_string.h b/src/upb_string.h
index 9a3957c..eab7f54 100644
--- a/src/upb_string.h
+++ b/src/upb_string.h
@@ -70,7 +70,7 @@ INLINE upb_strlen_t upb_string_len(upb_string *str) { return str->len; }
// upb_string_endread is called(). No other functions may be called on the
// string during this window except upb_string_len().
INLINE const char *upb_string_getrobuf(upb_string *str) { return str->ptr; }
-INLINE void upb_string_endread(upb_string *str);
+INLINE void upb_string_endread(upb_string *str) {}
// Attempts to recycle the string "str" so it may be reused and have different
// data written to it. The returned string is either "str" if it could be
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback