From b0ef7f0b6778addc91ce04ca1d6e835d44387c83 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 2 Jul 2009 20:19:06 -0700 Subject: More fixes, completions, still doesn't quite work. --- Makefile | 2 +- descriptor.h | 5 +++++ tests.c | 12 ++++++++++++ upb.h | 2 ++ upb_context.c | 21 +++++++++++++++++---- upb_context.h | 6 +++++- upb_msg.c | 31 +++++++++++++++++++++++++++++-- upb_msg.h | 2 +- upb_parse.c | 4 ++-- upb_parse.h | 2 +- upb_table.c | 34 +++++++++++++++++++++++++++++----- 11 files changed, 104 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index b2af7b5..7f1fcd6 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CXX=g++ CFLAGS=-std=c99 -CPPFLAGS=-O3 -DNDEBUG -Wall -Wextra -pedantic -g -DUPB_UNALIGNED_READS_OK -fomit-frame-pointer +CPPFLAGS=-Wall -Wextra -pedantic -g -DUPB_UNALIGNED_READS_OK -fomit-frame-pointer OBJ=upb_parse.o upb_table.o upb_msg.o upb_context.o descriptor.o all: $(OBJ) test_table tests clean: diff --git a/descriptor.h b/descriptor.h index ea6fa78..1e7e927 100644 --- a/descriptor.h +++ b/descriptor.h @@ -1,5 +1,8 @@ /* Auto-generated from descriptor.proto. Do not edit. */ +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_H_ + #include "upb_msg.h" /* Enums. */ @@ -401,3 +404,5 @@ struct google_protobuf_UninterpretedOption { UPB_DEFINE_MSG_ARRAY(google_protobuf_UninterpretedOption) extern google_protobuf_FileDescriptorProto google_protobuf_filedescriptor; + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_H_ */ diff --git a/tests.c b/tests.c index de8e951..c42ebd9 100644 --- a/tests.c +++ b/tests.c @@ -1,7 +1,12 @@ + #include #include #include +#include "descriptor.c" #include "upb_parse.c" +#include "upb_context.c" +#include "upb_msg.c" +#include "upb_table.c" void test_get_v_uint64_t() { @@ -51,9 +56,16 @@ void test_get_v_uint64_t() assert(status == UPB_STATUS_NEED_MORE_DATA); } +void test_upb_context() { + struct upb_context c; + assert(upb_context_init(&c)); + upb_context_free(&c); +} + int main() { test_get_v_uint64_t(); + test_upb_context(); printf("All tests passed.\n"); return 0; } diff --git a/upb.h b/upb.h index 563314c..ebf73c0 100644 --- a/upb.h +++ b/upb.h @@ -34,6 +34,8 @@ extern "C" { /* The maximum number of fields that any one .proto type can have. */ #define UPB_MAX_FIELDS (1<<16) +INLINE uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; } + /* Represents a string or bytes. */ struct upb_string { /* We expect the data to be 8-bit clean (uint8_t), but char* is such an diff --git a/upb_context.c b/upb_context.c index e124583..d469e54 100644 --- a/upb_context.c +++ b/upb_context.c @@ -22,8 +22,13 @@ bool upb_context_init(struct upb_context *c) { upb_strtable_init(&c->symtab, 16, sizeof(struct upb_symtab_entry)); /* Add all the types in descriptor.proto so we can parse descriptors. */ - if(!upb_context_addfd(c, &google_protobuf_filedescriptor)) + if(!upb_context_addfd(c, &google_protobuf_filedescriptor)) { + assert(false); return false; /* Indicates that upb is buggy or corrupt. */ + } + c->fd_size = 16; + c->fd_len = 0; + c->fd = malloc(sizeof(*c->fd)); return true; } @@ -31,6 +36,7 @@ void upb_context_free(struct upb_context *c) { upb_strtable_free(&c->symtab); for(size_t i = 0; i < c->fd_len; i++) free(c->fd[i]); + free(c->fd); } struct upb_symtab_entry *upb_context_lookup(struct upb_context *c, @@ -112,7 +118,8 @@ static bool insert_enum(struct upb_strtable *t, google_protobuf_EnumDescriptorProto *ed, struct upb_string *base) { - if(!ed->set_flags.has.name) return false; + // TODO: re-enable when compiler sets this flag + //if(!ed->set_flags.has.name) return false; /* We own this and must free it on destruct. */ struct upb_string fqname = join(base, ed->name); @@ -137,7 +144,8 @@ static bool insert_message(struct upb_strtable *t, google_protobuf_DescriptorProto *d, struct upb_string *base) { - if(!d->set_flags.has.name) return false; + /* TODO: re-enable when compiler sets this flag. */ + //if(!d->set_flags.has.name) return false; /* We own this and must free it on destruct. */ struct upb_string fqname = join(base, d->name); @@ -232,9 +240,14 @@ error: } bool upb_context_parsefd(struct upb_context *c, struct upb_string *fd_str) { - google_protobuf_FileDescriptorProto *fd = upb_alloc_and_parse(c->fd_msg, fd_str); + google_protobuf_FileDescriptorProto *fd = + upb_alloc_and_parse(c->fd_msg, fd_str, true); if(!fd) return false; if(!upb_context_addfd(c, fd)) return false; + if(c->fd_size == c->fd_len) { + c->fd_size *= 2; + c->fd = realloc(c->fd, c->fd_size); + } c->fd[c->fd_len++] = fd; /* Need to keep a ref since we own it. */ return true; } diff --git a/upb_context.h b/upb_context.h index cd62e30..01b8489 100644 --- a/upb_context.h +++ b/upb_context.h @@ -82,7 +82,11 @@ INLINE struct upb_symtab_entry *upb_context_symnext( * defined in this context. * * Caller retains ownership of fd, but the context will contain references to - * it, so it must outlive the context. */ + * it, so it must outlive the context. + * + * upb_context_addfd only returns true or false; it does not give any hint + * about what happened in the case of failure. This is because the descriptor + * is expected to have been validated at the time it was parsed/generated. */ bool upb_context_addfd(struct upb_context *c, google_protobuf_FileDescriptorProto *fd); diff --git a/upb_msg.c b/upb_msg.c index 1c79f57..d508b6d 100644 --- a/upb_msg.c +++ b/upb_msg.c @@ -10,8 +10,6 @@ #define ALIGN_UP(p, t) (t + ((p - 1) & (~t - 1))) -static uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; } - static int div_round_up(int numerator, int denominator) { /* cf. http://stackoverflow.com/questions/17944/how-to-round-up-the-result-of-integer-division */ return numerator > 0 ? (numerator - 1) / denominator + 1 : 0; @@ -101,6 +99,20 @@ void *upb_msg_new(struct upb_msg *m) //void upb_msg_free(void *msg, struct upb_msg *m, bool free_submsgs); +void upb_msg_ref(struct upb_msg *m, struct upb_msg_field *f, + union upb_symbol_ref ref) { + struct google_protobuf_FieldDescriptorProto *d = + upb_msg_field_descriptor(f, m); + struct upb_fieldsbynum_entry *int_e = upb_inttable_lookup( + &m->fields_by_num, d->number, sizeof(struct upb_fieldsbynum_entry)); + struct upb_fieldsbyname_entry *str_e = + upb_strtable_lookup(&m->fields_by_name, d->name); + assert(int_e && str_e); + f->ref = ref; + int_e->f.ref = ref; + str_e->f.ref = ref; +} + struct mm_upb_string { struct upb_string s; uint32_t size; @@ -262,3 +274,18 @@ upb_status_t upb_msg_parse(struct upb_msg_parse_state *s, { return upb_parse(&s->s, data, len, read); } + +void *upb_alloc_and_parse(struct upb_msg *m, struct upb_string *str, bool byref) +{ + struct upb_msg_parse_state s; + void *msg = upb_msg_new(m); + upb_msg_parse_init(&s, msg, m, false, byref); + size_t read; + upb_status_t status = upb_msg_parse(&s, str->ptr, str->byte_len, &read); + if(status == UPB_STATUS_OK && read == str->byte_len) { + return msg; + } else { + upb_msg_free(msg); + return NULL; + } +} diff --git a/upb_msg.h b/upb_msg.h index 48b411f..e751c27 100644 --- a/upb_msg.h +++ b/upb_msg.h @@ -242,7 +242,7 @@ void upb_msg_parse_free(struct upb_msg_parse_state *s); upb_status_t upb_msg_parse(struct upb_msg_parse_state *s, void *data, size_t len, size_t *read); -void *upb_alloc_and_parse(struct upb_msg *m, struct upb_string *s); +void *upb_alloc_and_parse(struct upb_msg *m, struct upb_string *s, bool byref); /* Note! These two may not be use on a upb_string* that was initialized by * means other than these functions. */ diff --git a/upb_parse.c b/upb_parse.c index 559e227..8b86418 100644 --- a/upb_parse.c +++ b/upb_parse.c @@ -247,7 +247,7 @@ upb_status_t upb_parse_value(void **buf, void *end, upb_field_type_t ft, #undef CASE } -void upb_parse_state_init(struct upb_parse_state *state, size_t udata_size) +void upb_parse_init(struct upb_parse_state *state, size_t udata_size) { state->offset = 0; size_t stack_bytes = (sizeof(*state->stack) + udata_size) * UPB_MAX_NESTING; @@ -256,7 +256,7 @@ void upb_parse_state_init(struct upb_parse_state *state, size_t udata_size) state->udata_size = udata_size; } -void upb_parse_state_free(struct upb_parse_state *state) +void upb_parse_free(struct upb_parse_state *state) { free(state->stack); } diff --git a/upb_parse.h b/upb_parse.h index 83104f1..182cb9e 100644 --- a/upb_parse.h +++ b/upb_parse.h @@ -89,7 +89,7 @@ upb_status_t upb_parse(struct upb_parse_state *s, void *buf, size_t len, extern upb_wire_type_t upb_expected_wire_types[]; /* Returns true if wt is the correct on-the-wire type for ft. */ INLINE bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) { - return upb_expected_wire_types[ft] == wt; + return upb_type_info[ft].expected_wire_type == wt; } /* Data-consuming functions (to be called from value cb). *********************/ diff --git a/upb_table.c b/upb_table.c index 22c0d5a..e572dd1 100644 --- a/upb_table.c +++ b/upb_table.c @@ -15,13 +15,11 @@ static const double MAX_LOAD = 0.85; static uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed); -static uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; } - /* We use 1-based indexes into the table so that 0 can be "NULL". */ -static struct upb_inttable_entry *intent(struct upb_inttable *t, uint32_t i) { +static struct upb_inttable_entry *intent(struct upb_inttable *t, int32_t i) { return UPB_INDEX(t->t.entries, i-1, t->t.entry_size); } -static struct upb_strtable_entry *strent(struct upb_strtable *t, uint32_t i) { +static struct upb_strtable_entry *strent(struct upb_strtable *t, int32_t i) { return UPB_INDEX(t->t.entries, i-1, t->t.entry_size); } @@ -190,7 +188,33 @@ void upb_strtable_insert(struct upb_strtable *t, struct upb_strtable_entry *e) upb_strtable_free(t); *t = new_table; } - strinsert(t->t.entries, e); + strinsert(t, e); +} + +void *upb_inttable_begin(struct upb_inttable *t) { + return upb_inttable_next(t, intent(t, -1)); +} + +void *upb_inttable_next(struct upb_inttable *t, struct upb_inttable_entry *cur) { + struct upb_inttable_entry *end = intent(t, upb_inttable_size(t)); + do { + cur = (void*)((char*)cur + t->t.entry_size); + if(cur == end) return NULL; + } while(cur->key == UPB_EMPTY_ENTRY); + return cur; +} + +void *upb_strtable_begin(struct upb_strtable *t) { + return upb_strtable_next(t, strent(t, -1)); +} + +void *upb_strtable_next(struct upb_strtable *t, struct upb_strtable_entry *cur) { + struct upb_strtable_entry *end = strent(t, upb_strtable_size(t)); + do { + cur = (void*)((char*)cur + t->t.entry_size); + if(cur == end) return NULL; + } while(cur->key.byte_len == 0); + return cur; } #ifdef UPB_UNALIGNED_READS_OK -- cgit v1.2.3