Move upb_array into its own header, upb_context parses fds instead of fd.

pull/13171/head
Joshua Haberman 16 years ago
parent 1e388b0af3
commit 6fe8601713
  1. 11
      descriptor/descriptor.h
  2. 66
      src/upb_array.h
  3. 26
      src/upb_context.c
  4. 7
      src/upb_context.h
  5. 5
      src/upb_enum.h
  6. 21
      src/upb_msg.c
  7. 69
      src/upb_msg.h

@ -3,7 +3,8 @@
#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H_
#define GOOGLE_PROTOBUF_DESCRIPTOR_H_
#include "upb_msg.h"
#include "upb_string.h"
#include "upb_array.h"
/* Enums. */
@ -25,23 +26,23 @@ typedef enum google_protobuf_FieldDescriptorProto_Type {
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32 = 15,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64 = 16,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18
} google_protobuf_FieldDescriptorProto_Type;
typedef enum google_protobuf_FieldDescriptorProto_Label {
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_OPTIONAL = 1,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED = 2,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3
} google_protobuf_FieldDescriptorProto_Label;
typedef enum google_protobuf_FileOptions_OptimizeMode {
GOOGLE_PROTOBUF_FILEOPTIONS_SPEED = 1,
GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2,
GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2
} google_protobuf_FileOptions_OptimizeMode;
typedef enum google_protobuf_FieldOptions_CType {
GOOGLE_PROTOBUF_FIELDOPTIONS_CORD = 1,
GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2,
GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2
} google_protobuf_FieldOptions_CType;
/* Forward declarations of all message types.

@ -0,0 +1,66 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2009 Joshua Haberman. See LICENSE for details.
* Defines an in-memory array type. TODO: more documentation.
*
*/
#ifndef UPB_ARRAY_H_
#define UPB_ARRAY_H_
#ifdef __cplusplus
extern "C" {
#endif
struct upb_string;
#include "upb.h"
/* Represents an array (a repeated field) of any type. The interpretation of
* the data in the array depends on the type. */
struct upb_array {
union upb_value_ptr elements;
uint32_t len; /* Measured in elements. */
};
/* Returns a pointer to an array element. */
INLINE union upb_value_ptr upb_array_getelementptr(
struct upb_array *arr, uint32_t n, upb_field_type_t type)
{
union upb_value_ptr ptr;
ptr._void = (void*)((char*)arr->elements._void + n*upb_type_info[type].size);
return ptr;
}
/* These are all overlays on upb_array, pointers between them can be cast. */
#define UPB_DEFINE_ARRAY_TYPE(name, type) \
struct name ## _array { \
type *elements; \
uint32_t len; \
};
UPB_DEFINE_ARRAY_TYPE(upb_double, double)
UPB_DEFINE_ARRAY_TYPE(upb_float, float)
UPB_DEFINE_ARRAY_TYPE(upb_int32, int32_t)
UPB_DEFINE_ARRAY_TYPE(upb_int64, int64_t)
UPB_DEFINE_ARRAY_TYPE(upb_uint32, uint32_t)
UPB_DEFINE_ARRAY_TYPE(upb_uint64, uint64_t)
UPB_DEFINE_ARRAY_TYPE(upb_bool, bool)
UPB_DEFINE_ARRAY_TYPE(upb_string, struct upb_string*)
UPB_DEFINE_ARRAY_TYPE(upb_msg, void*)
/* Defines an array of a specific message type. */
#define UPB_MSG_ARRAY(msg_type) struct msg_type ## _array
#define UPB_DEFINE_MSG_ARRAY(msg_type) \
UPB_MSG_ARRAY(msg_type) { \
msg_type **elements; \
uint32_t len; \
};
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

@ -258,23 +258,9 @@ bool addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs,
return true;
}
bool upb_context_addfd(struct upb_context *c,
google_protobuf_FileDescriptorProto *fd)
bool upb_context_addfds(struct upb_context *c,
google_protobuf_FileDescriptorSet *fds)
{
struct upb_strtable tmp;
if(!addfd(&tmp, &c->symtab, fd, false)) {
free_symtab(&tmp);
return false;
}
upb_strtable_free(&tmp);
return true;
}
bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds_str) {
google_protobuf_FileDescriptorSet *fds =
upb_alloc_and_parse(c->fds_msg, fds_str, false);
if(!fds) return false;
if(fds->set_flags.has.file) {
/* Insert new symbols into a temporary table until we have verified that
* the descriptor is valid. */
@ -293,6 +279,14 @@ bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds_str) {
upb_strtable_insert(&c->symtab, &e->e);
upb_strtable_free(&tmp);
}
return true;
}
bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds_str) {
google_protobuf_FileDescriptorSet *fds =
upb_alloc_and_parse(c->fds_msg, fds_str, false);
if(!fds) return false;
if(!upb_context_addfds(c, fds)) return false;
/* We own fds now, need to keep a ref so we can free it later. */
if(c->fds_size == c->fds_len) {

@ -94,8 +94,11 @@ INLINE struct upb_symtab_entry *upb_context_symnext(
* 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,
struct google_protobuf_FileDescriptorProto *fd);
bool upb_context_addfds(struct upb_context *c,
struct google_protobuf_FileDescriptorSet *fds);
bool upb_context_addfds(struct upb_context *c,
struct google_protobuf_FileDescriptorSet *fds);
bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds);

@ -11,10 +11,7 @@
#include <stdint.h>
#include "upb_table.h"
/* Forward declaration from descriptor.h. */
struct google_protobuf_EnumDescriptorProto;
struct google_protobuf_EnumValueDescriptorProto;
#include "descriptor.h"
struct upb_enum {
struct google_protobuf_EnumDescriptorProto *descriptor;

@ -17,16 +17,6 @@ static int div_round_up(int numerator, int denominator) {
return numerator > 0 ? (numerator - 1) / denominator + 1 : 0;
}
static bool issubmsgtype(upb_field_type_t type) {
return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP ||
type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE;
}
static bool isstringtype(upb_field_type_t type) {
return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING ||
type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES;
}
/* Callback for sorting fields. */
static int compare_fields(const void *e1, const void *e2) {
const google_protobuf_FieldDescriptorProto *fd1 = *(void**)e1;
@ -272,7 +262,7 @@ static upb_field_type_t tag_cb(void *udata, struct upb_tag tag,
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(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) {
if(upb_isarray(f)) {
size_t len = upb_msg_is_set(data, f) ? (*p.arr)->len : 0;
upb_msg_reuse_array(p.arr, len+1, f->type);
(*p.arr)->len = len + 1;
@ -411,13 +401,13 @@ bool upb_array_eql(struct upb_array *arr1, struct upb_array *arr2,
struct upb_msg_field *f, bool recursive)
{
if(arr1->len != arr2->len) return false;
if(issubmsgtype(f->type)) {
if(upb_issubmsg(f)) {
if(!recursive) return true;
for(uint32_t i = 0; i < arr1->len; i++)
if(!upb_msg_eql(arr1->elements.msg[i], arr2->elements.msg[i],
f->ref.msg, recursive))
return false;
} else if(isstringtype(f->type)) {
} else if(upb_isstring(f)) {
for(uint32_t i = 0; i < arr1->len; i++)
if(!upb_streql(arr1->elements.str[i], arr2->elements.str[i]))
return false;
@ -431,7 +421,8 @@ bool upb_array_eql(struct upb_array *arr1, struct upb_array *arr2,
bool upb_msg_eql(void *data1, void *data2, struct upb_msg *m, bool recursive)
{
/* Must have the same fields set. */
/* Must have the same fields set. TODO: is this wrong? Should we also
* consider absent defaults equal to explicitly set defaults? */
if(memcmp(data1, data2, m->set_flags_bytes) != 0)
return false;
@ -447,7 +438,7 @@ bool upb_msg_eql(void *data1, void *data2, struct upb_msg *m, bool recursive)
if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) {
if(!upb_array_eql(*p1.arr, *p2.arr, f, recursive)) return false;
} else {
if(issubmsgtype(f->type)) {
if(upb_issubmsg(f)) {
if(recursive && !upb_msg_eql(p1.msg, p2.msg, f->ref.msg, recursive))
return false;
} else if(!upb_value_eql(p1, p2, f->type)) {

@ -101,15 +101,12 @@
#include "upb.h"
#include "upb_table.h"
#include "upb_parse.h"
#include "descriptor.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations from descriptor.h. */
struct google_protobuf_DescriptorProto;
struct google_protobuf_FieldDescriptorProto;
/* Message definition. ********************************************************/
/* Structure that describes a single field in a message. This structure is very
@ -128,6 +125,7 @@ struct upb_msg_field {
/* Structure that describes a single .proto message type. */
struct upb_msg {
struct google_protobuf_DescriptorProto *descriptor;
struct upb_string fqname; /* Fully qualified. */
size_t size;
uint32_t num_fields;
uint32_t set_flags_bytes;
@ -197,6 +195,26 @@ INLINE struct upb_msg_field *upb_msg_fieldbyname(struct upb_msg *m,
return e ? &e->f : NULL;
}
INLINE bool upb_issubmsgtype(upb_field_type_t type) {
return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP ||
type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE;
}
INLINE bool upb_isstringtype(upb_field_type_t type) {
return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING ||
type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES;
}
INLINE bool upb_issubmsg(struct upb_msg_field *f) {
return upb_issubmsgtype(f->type);
}
INLINE bool upb_isstring(struct upb_msg_field *f) {
return upb_isstringtype(f->type);
}
INLINE bool upb_isarray(struct upb_msg_field *f) {
return f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED;
}
/* "Set" flag reading and writing. *******************************************/
INLINE size_t upb_isset_offset(uint32_t field_index) {
@ -251,49 +269,6 @@ INLINE union upb_value_ptr upb_msg_getptr(void *data, struct upb_msg_field *f) {
return p;
}
/* Arrays. ********************************************************************/
/* Represents an array (a repeated field) of any type. The interpretation of
* the data in the array depends on the type. */
struct upb_array {
union upb_value_ptr elements;
uint32_t len; /* Measured in elements. */
};
/* Returns a pointer to an array element. */
INLINE union upb_value_ptr upb_array_getelementptr(
struct upb_array *arr, uint32_t n, upb_field_type_t type)
{
union upb_value_ptr ptr;
ptr._void = (void*)((char*)arr->elements._void + n*upb_type_info[type].size);
return ptr;
}
/* These are all overlays on upb_array, pointers between them can be cast. */
#define UPB_DEFINE_ARRAY_TYPE(name, type) \
struct name ## _array { \
type *elements; \
uint32_t len; \
};
UPB_DEFINE_ARRAY_TYPE(upb_double, double)
UPB_DEFINE_ARRAY_TYPE(upb_float, float)
UPB_DEFINE_ARRAY_TYPE(upb_int32, int32_t)
UPB_DEFINE_ARRAY_TYPE(upb_int64, int64_t)
UPB_DEFINE_ARRAY_TYPE(upb_uint32, uint32_t)
UPB_DEFINE_ARRAY_TYPE(upb_uint64, uint64_t)
UPB_DEFINE_ARRAY_TYPE(upb_bool, bool)
UPB_DEFINE_ARRAY_TYPE(upb_string, struct upb_string*)
UPB_DEFINE_ARRAY_TYPE(upb_msg, void*)
/* Defines an array of a specific message type. */
#define UPB_MSG_ARRAY(msg_type) struct msg_type ## _array
#define UPB_DEFINE_MSG_ARRAY(msg_type) \
UPB_MSG_ARRAY(msg_type) { \
msg_type **elements; \
uint32_t len; \
};
/* Memory management *********************************************************/
/* One important note about these memory management routines: they must be used

Loading…
Cancel
Save