From ee1ed1ccb87effa403dc91603d452d4c98ed716f Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 22 Jul 2009 19:49:53 -0700 Subject: Compiler finally works (except string arrays). Untested. Holy crap that was a lot of work. --- src/upb.h | 23 +++++++++++++++-------- src/upb_array.h | 6 ++++++ src/upb_msg.c | 4 ++-- src/upb_msg.h | 7 ++++++- src/upb_parse.c | 37 +++++++++++++++++++------------------ src/upb_string.c | 1 + src/upb_string.h | 10 +++++++++- src/upb_text.c | 8 ++++---- src/upb_text.h | 4 ++-- 9 files changed, 64 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/upb.h b/src/upb.h index 113e6e8..f8cbba3 100644 --- a/src/upb.h +++ b/src/upb.h @@ -12,6 +12,7 @@ #include #include #include /* for size_t. */ +#include "upb_string.h" #ifdef __cplusplus extern "C" { @@ -35,7 +36,6 @@ extern "C" { #define UPB_INDEX(base, i, m) (void*)((char*)(base) + ((i)*(m))) INLINE uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; } -INLINE uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; } /* Value type as defined in a .proto file. The values of this are defined by * google_protobuf_FieldDescriptorProto_Type (from descriptor.proto). @@ -43,20 +43,21 @@ INLINE uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; } * represent exceptional circumstances. */ typedef uint8_t upb_field_type_t; -/* Label (optional, repeated, required) as defined in a .proto file. The values - * of this are defined by google.protobuf.FieldDescriptorProto.Label (from - * descriptor.proto). */ -typedef uint8_t upb_label_t; - struct upb_type_info { uint8_t align; uint8_t size; uint8_t expected_wire_type; + struct upb_string ctype; }; /* Contains information for all .proto types. Indexed by upb_field_type_t. */ extern struct upb_type_info upb_type_info[]; +/* Label (optional, repeated, required) as defined in a .proto file. The values + * of this are defined by google.protobuf.FieldDescriptorProto.Label (from + * descriptor.proto). */ +typedef uint8_t upb_label_t; + /* A pointer to a .proto value. The owner must have an out-of-band way of * knowing the type, so it knows which union member to use. */ union upb_value { @@ -67,8 +68,8 @@ union upb_value { uint32_t uint32; uint64_t uint64; bool _bool; - struct upb_string **string; - struct upb_array **array; + struct upb_string *str; + struct upb_array *arr; void *msg; }; @@ -86,6 +87,12 @@ union upb_value_ptr { void *_void; }; +INLINE union upb_value upb_deref(union upb_value_ptr ptr, upb_field_type_t t) { + union upb_value val; + memcpy(&val, ptr._void, upb_type_info[t].size); + return val; +} + union upb_symbol_ref { struct upb_msg *msg; struct upb_enum *_enum; diff --git a/src/upb_array.h b/src/upb_array.h index 4282a7f..0e5178f 100644 --- a/src/upb_array.h +++ b/src/upb_array.h @@ -34,6 +34,12 @@ INLINE union upb_value_ptr upb_array_getelementptr( return ptr; } +INLINE union upb_value upb_array_getelement( + struct upb_array *arr, uint32_t n, upb_field_type_t type) +{ + return upb_deref(upb_array_getelementptr(arr, n, type), type); +} + /* These are all overlays on upb_array, pointers between them can be cast. */ #define UPB_DEFINE_ARRAY_TYPE(name, type) \ struct name ## _array { \ diff --git a/src/upb_msg.c b/src/upb_msg.c index d44649e..19edba8 100644 --- a/src/upb_msg.c +++ b/src/upb_msg.c @@ -265,7 +265,7 @@ static union upb_value_ptr get_value_ptr(void *data, struct upb_msg_field *f) { union upb_value_ptr p = upb_msg_getptr(data, f); if(upb_isarray(f)) { - size_t len = upb_msg_is_set(data, f) ? (*p.arr)->len : 0; + size_t len = upb_msg_isset(data, f) ? (*p.arr)->len : 0; upb_msg_reuse_array(p.arr, len+1, f->type); (*p.arr)->len = len + 1; assert(p._void); @@ -448,7 +448,7 @@ bool upb_msg_eql(void *data1, void *data2, struct upb_msg *m, bool recursive) for(uint32_t i = 0; i < m->num_fields; i++) { struct upb_msg_field *f = &m->fields[i]; - if(!upb_msg_is_set(data1, f)) continue; + if(!upb_msg_isset(data1, f)) continue; union upb_value_ptr p1 = upb_msg_getptr(data1, f); union upb_value_ptr p2 = upb_msg_getptr(data2, f); if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { diff --git a/src/upb_msg.h b/src/upb_msg.h index 6be9405..233e604 100644 --- a/src/upb_msg.h +++ b/src/upb_msg.h @@ -231,7 +231,7 @@ INLINE void upb_msg_unset(void *s, struct upb_msg_field *f) ((char*)s)[upb_isset_offset(f->field_index)] &= ~upb_isset_mask(f->field_index); } -INLINE bool upb_msg_is_set(void *s, struct upb_msg_field *f) +INLINE bool upb_msg_isset(void *s, struct upb_msg_field *f) { return ((char*)s)[upb_isset_offset(f->field_index)] & upb_isset_mask(f->field_index); } @@ -262,6 +262,11 @@ INLINE union upb_value_ptr upb_msg_getptr(void *data, struct upb_msg_field *f) { return p; } +/* Returns a a specific field in a message. */ +INLINE union upb_value upb_msg_get(void *data, struct upb_msg_field *f) { + return upb_deref(upb_msg_getptr(data, f), f->type); +} + /* Memory management *********************************************************/ /* One important note about these memory management routines: they must be used diff --git a/src/upb_parse.c b/src/upb_parse.c index 60533b4..96b7647 100644 --- a/src/upb_parse.c +++ b/src/upb_parse.c @@ -11,25 +11,26 @@ /* May want to move this to upb.c if enough other things warrant it. */ #define alignof(t) offsetof(struct { char c; t x; }, x) +#define TYPE_INFO(proto_type, wire_type, ctype) [proto_type] = {alignof(ctype), sizeof(ctype), wire_type, UPB_STRLIT(#ctype)}, struct upb_type_info upb_type_info[] = { - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE] = {alignof(double), sizeof(double), UPB_WIRE_TYPE_64BIT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT] = {alignof(float), sizeof(float), UPB_WIRE_TYPE_32BIT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64] = {alignof(int64_t), sizeof(int64_t), UPB_WIRE_TYPE_VARINT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64] = {alignof(uint64_t), sizeof(uint64_t), UPB_WIRE_TYPE_VARINT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32] = {alignof(int32_t), sizeof(int32_t), UPB_WIRE_TYPE_VARINT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64] = {alignof(uint64_t), sizeof(uint64_t), UPB_WIRE_TYPE_64BIT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32] = {alignof(uint32_t), sizeof(uint32_t), UPB_WIRE_TYPE_32BIT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL] = {alignof(bool), sizeof(bool), UPB_WIRE_TYPE_VARINT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE] = {alignof(void*), sizeof(void*), UPB_WIRE_TYPE_DELIMITED}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP] = {alignof(void*), sizeof(void*), UPB_WIRE_TYPE_START_GROUP}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32] = {alignof(uint32_t), sizeof(uint32_t), UPB_WIRE_TYPE_VARINT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM] = {alignof(uint32_t), sizeof(uint32_t), UPB_WIRE_TYPE_VARINT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32]= {alignof(int32_t), sizeof(int32_t), UPB_WIRE_TYPE_32BIT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64]= {alignof(int64_t), sizeof(int64_t), UPB_WIRE_TYPE_64BIT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32] = {alignof(int32_t), sizeof(int32_t), UPB_WIRE_TYPE_VARINT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64] = {alignof(int64_t), sizeof(int64_t), UPB_WIRE_TYPE_VARINT}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING] = {alignof(struct upb_string*), sizeof(struct upb_string*), UPB_WIRE_TYPE_DELIMITED}, - [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES] = {alignof(struct upb_string*), sizeof(struct upb_string*), UPB_WIRE_TYPE_DELIMITED}, + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE, UPB_WIRE_TYPE_64BIT, double) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT, UPB_WIRE_TYPE_32BIT, float) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64, UPB_WIRE_TYPE_VARINT, int64_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64, UPB_WIRE_TYPE_VARINT, uint64_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32, UPB_WIRE_TYPE_VARINT, int32_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64, UPB_WIRE_TYPE_64BIT, uint64_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32, UPB_WIRE_TYPE_32BIT, uint32_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL, UPB_WIRE_TYPE_VARINT, bool) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE, UPB_WIRE_TYPE_DELIMITED, void*) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP, UPB_WIRE_TYPE_START_GROUP, void*) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32, UPB_WIRE_TYPE_VARINT, uint32_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM, UPB_WIRE_TYPE_VARINT, uint32_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32, UPB_WIRE_TYPE_32BIT, int32_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64, UPB_WIRE_TYPE_64BIT, int64_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32, UPB_WIRE_TYPE_VARINT, int32_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64, UPB_WIRE_TYPE_VARINT, int64_t) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING, UPB_WIRE_TYPE_DELIMITED, struct upb_string*) + TYPE_INFO(GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES, UPB_WIRE_TYPE_DELIMITED, struct upb_string*) }; /* Lowest-level functions -- these read integers from the input buffer. */ diff --git a/src/upb_string.c b/src/upb_string.c index 733bafe..bb40a62 100644 --- a/src/upb_string.c +++ b/src/upb_string.c @@ -4,6 +4,7 @@ * Copyright (c) 2009 Joshua Haberman. See LICENSE for details. */ +#include #include "upb_string.h" bool upb_strreadfile(const char *filename, struct upb_string *data) { diff --git a/src/upb_string.h b/src/upb_string.h index de2384d..8e56daa 100644 --- a/src/upb_string.h +++ b/src/upb_string.h @@ -27,9 +27,15 @@ extern "C" { #endif +#include +#include #include #include -#include "upb.h" + +/* inline if possible, emit standalone code if required. */ +#ifndef INLINE +#define INLINE static inline +#endif struct upb_string { /* We expect the data to be 8-bit clean (uint8_t), but char* is such an @@ -38,6 +44,8 @@ struct upb_string { uint32_t byte_len; }; +INLINE uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; } + INLINE bool upb_streql(struct upb_string *s1, struct upb_string *s2) { return s1->byte_len == s2->byte_len && memcmp(s1->ptr, s2->ptr, s1->byte_len) == 0; diff --git a/src/upb_text.c b/src/upb_text.c index d51db06..7ca17cc 100644 --- a/src/upb_text.c +++ b/src/upb_text.c @@ -8,9 +8,9 @@ #include "upb_text.h" #include "descriptor.h" -void upb_text_printval(upb_field_type_t type, union upb_value_ptr p, FILE *file) +void upb_text_printval(upb_field_type_t type, union upb_value val, FILE *file) { -#define CASE(fmtstr, member) fprintf(file, fmtstr, *p.member); break; +#define CASE(fmtstr, member) fprintf(file, fmtstr, val.member); break; switch(type) { case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: CASE("%0.f", _double); @@ -36,7 +36,7 @@ void upb_text_printval(upb_field_type_t type, union upb_value_ptr p, FILE *file) case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: /* TODO: escaping. */ - fprintf(file, "\"" UPB_STRFMT "\"", UPB_STRARG(**p.str)); break; + fprintf(file, "\"" UPB_STRFMT "\"", UPB_STRARG(*val.str)); break; } } @@ -49,7 +49,7 @@ static void print_indent(struct upb_text_printer *p, FILE *stream) void upb_text_printfield(struct upb_text_printer *p, struct upb_string name, - upb_field_type_t valtype, union upb_value_ptr val, + upb_field_type_t valtype, union upb_value val, FILE *stream) { print_indent(p, stream); diff --git a/src/upb_text.h b/src/upb_text.h index b1dbf59..f35f8d8 100644 --- a/src/upb_text.h +++ b/src/upb_text.h @@ -22,9 +22,9 @@ INLINE void upb_text_printer_init(struct upb_text_printer *p, bool single_line) p->indent_depth = 0; p->single_line = single_line; } -void upb_text_printval(upb_field_type_t type, union upb_value_ptr p, FILE *file); +void upb_text_printval(upb_field_type_t type, union upb_value p, FILE *file); void upb_text_printfield(struct upb_text_printer *p, struct upb_string name, - upb_field_type_t valtype, union upb_value_ptr val, + upb_field_type_t valtype, union upb_value val, FILE *stream); void upb_text_push(struct upb_text_printer *p, struct upb_string submsg_type, FILE *stream); -- cgit v1.2.3