summaryrefslogtreecommitdiff
path: root/src/upb_def.h
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2009-11-27 11:59:38 -0800
committerJoshua Haberman <joshua@reverberate.org>2009-11-27 14:21:59 -0800
commit246a36998bc0e6800959ff76c2a8c76ff8de3561 (patch)
tree466504163ea910ed5564a28923a2fc6801a5328c /src/upb_def.h
parentd16038073629b3f89acabfbd2f2d9911b2a771d4 (diff)
WIP of cleaning up defs.
Diffstat (limited to 'src/upb_def.h')
-rw-r--r--src/upb_def.h179
1 files changed, 99 insertions, 80 deletions
diff --git a/src/upb_def.h b/src/upb_def.h
index 1cfbfd2..6a6622a 100644
--- a/src/upb_def.h
+++ b/src/upb_def.h
@@ -10,10 +10,10 @@
* (TODO: descriptions of extensions and services).
*
* Defs are immutable and reference-counted. Contexts reference any defs
- * that are the currently active def for that context, but they can be
- * unref'd if the message is changed by loading extensions. In the case
- * that a def is no longer active in a context, it will still be ref'd by
- * messages (if any) that were constructed with that def.
+ * that are the currently in their symbol table. If an extension is loaded
+ * that adds a field to an existing message, a new msgdef is constructed that
+ * includes the new field and the old msgdef is unref'd. The old msgdef will
+ * still be ref'd by message (if any) that were constructed with that msgdef.
*
* This file contains routines for creating and manipulating the definitions
* themselves. To create and manipulate actual messages, see upb_msg.h.
@@ -29,42 +29,47 @@
extern "C" {
#endif
-/* Message definition. ********************************************************/
-
-struct upb_fielddef;
-struct upb_context;
-struct google_protobuf_EnumDescriptorProto;
-struct google_protobuf_DescriptorProto;
-struct google_protobuf_FieldDescriptorProto;
+/* "Base class" for defs; defines common members and functions. **************/
+
+// All the different kind of defs we support. These correspond 1:1 with
+// declarations in a .proto file.
+enum upb_def_type {
+ UPB_DEF_MESSAGE,
+ UPB_DEF_ENUM,
+ UPB_DEF_SERVICE,
+ UPB_DEF_EXTENSION,
+ // Represented by a string, symbol hasn't been resolved yet.
+ UPB_DEF_UNRESOLVED
+};
-/* Structure that describes a single .proto message type. */
-struct upb_msgdef {
+// Common members.
+struct upb_def {
+ enum upb_def_type type;
upb_atomic_refcount_t refcount;
- struct upb_context *context;
- struct upb_msg *default_msg; /* Message with all default values set. */
- struct upb_string *fqname; /* Fully qualified. */
- size_t size;
- uint32_t num_fields;
- uint32_t set_flags_bytes;
- uint32_t num_required_fields; /* Required fields have the lowest set bytemasks. */
- struct upb_inttable fields_by_num;
- struct upb_strtable fields_by_name;
- struct upb_fielddef *fields;
-};
+ struct upb_string *fqname; /* Fully-qualified. */
+}
-/* Structure that describes a single field in a message. */
-struct upb_fielddef {
- union upb_symbol_ref ref;
- uint32_t byte_offset; /* Where to find the data. */
- uint16_t field_index; /* Indicates set bit. */
+void upb_def_init(struct upb_def *def, enum upb_def_type type,
+ struct upb_string *fqname);
- /* TODO: Performance test whether it's better to move the name and number
- * into an array in upb_msgdef, indexed by field_index. */
- upb_field_number_t number;
- struct upb_string *name;
+/* Field definition. **********************************************************/
+// A upb_fielddef describes a single field in a message. It isn't a full def
+// in the sense that it derives from upb_def. It cannot stand on its own; it
+// is either a field of a upb_msgdef or contained inside a upb_extensiondef.
+struct upb_fielddef {
upb_field_type_t type;
upb_label_t label;
+ upb_field_number_t number;
+ struct upb_string *name;
+
+ // These are set only when this fielddef is part of a msgdef.
+ uint32_t byte_offset; // Where in a upb_msg to find the data.
+ uint16_t field_index; // Indicates set bit.
+
+ // For the case of an enum or a submessage, points to the def for that type.
+ // We own a ref on this def.
+ struct upb_def *def;
};
INLINE bool upb_issubmsg(struct upb_fielddef *f) {
@@ -100,47 +105,72 @@ INLINE upb_mm_ptrtype upb_elem_ptrtype(struct upb_fielddef *f) {
else return -1;
}
-/* Number->field and name->field lookup. *************************************/
+// Interfaces for constructing/destroying fielddefs. These are internal-only.
+struct google_protobuf_FieldDescriptorProto;
+
+// Initializes a upb_fielddef from a FieldDescriptorProto. The caller must
+// have previously allocated the upb_fielddef.
+void upb_fielddef_init(struct google_protobuf_FieldDescriptorProto *fd,
+ struct upb_fielddef *f);
+void upb_fielddef_uninit(struct upb_fielddef *f);
+
+// Sort the given fielddefs in-place, according to what we think is an optimal
+// ordering of fields. This can change from upb release to upb release.
+void upb_fielddef_sort(struct upb_fielddef *defs, size_t num);
+
+/* Message definition. ********************************************************/
+
+struct google_protobuf_EnumDescriptorProto;
+struct google_protobuf_DescriptorProto;
-/* The num->field and name->field maps in upb_msgdef allow fast lookup of fields
- * by number or name. These lookups are in the critical path of parsing and
- * field lookup, so they must be as fast as possible. To make these more
- * cache-friendly, we put the data in the table by value. */
+// Structure that describes a single .proto message type.
+struct upb_msgdef {
+ struct upb_def def;
+ struct upb_msg *default_msg; // Message with all default values set.
+ size_t size;
+ uint32_t num_fields;
+ uint32_t set_flags_bytes;
+ uint32_t num_required_fields; // Required fields have the lowest set bytemasks.
+ struct upb_fielddef *fields; // We have exclusive ownership of these.
+ // Tables for looking up fields by number and name.
+ struct upb_inttable fields_by_num;
+ struct upb_strtable fields_by_name;
+};
+
+// The num->field and name->field maps in upb_msgdef allow fast lookup of fields
+// by number or name. These lookups are in the critical path of parsing and
+// field lookup, so they must be as fast as possible.
struct upb_fieldsbynum_entry {
struct upb_inttable_entry e;
struct upb_fielddef f;
};
-
struct upb_fieldsbyname_entry {
struct upb_strtable_entry e;
struct upb_fielddef f;
};
-/* Looks up a field by name or number. While these are written to be as fast
- * as possible, it will still be faster to cache the results of this lookup if
- * possible. These return NULL if no such field is found. */
+// Looks up a field by name or number. While these are written to be as fast
+// as possible, it will still be faster to cache the results of this lookup if
+// possible. These return NULL if no such field is found.
INLINE struct upb_fielddef *upb_msg_fieldbynum(struct upb_msgdef *m,
- uint32_t number) {
- struct upb_fieldsbynum_entry *e =
- (struct upb_fieldsbynum_entry*)upb_inttable_fast_lookup(
- &m->fields_by_num, number, sizeof(struct upb_fieldsbynum_entry));
+ uint32_t number) {
+ struct upb_fieldsbynum_entry *e = upb_inttable_fast_lookup(
+ &m->fields_by_num, number, sizeof(struct upb_fieldsbynum_entry));
return e ? &e->f : NULL;
}
INLINE struct upb_fielddef *upb_msg_fieldbyname(struct upb_msgdef *m,
- struct upb_string *name) {
- struct upb_fieldsbyname_entry *e =
- (struct upb_fieldsbyname_entry*)upb_strtable_lookup(
- &m->fields_by_name, name);
+ struct upb_string *name) {
+ struct upb_fieldsbyname_entry *e = upb_strtable_lookup(
+ &m->fields_by_name, name);
return e ? &e->f : NULL;
}
-/* Enums. *********************************************************************/
+/* Enum defintion. ************************************************************/
struct upb_enumdef {
upb_atomic_refcount_t refcount;
- struct upb_context *context;
struct upb_strtable nametoint;
struct upb_inttable inttoname;
};
@@ -172,7 +202,7 @@ struct upb_enumdef_iton_entry {
void upb_msgdef_init(struct upb_msgdef *m,
struct google_protobuf_DescriptorProto *d,
struct upb_string *fqname, bool sort,
- struct upb_context *c, struct upb_status *status);
+ struct upb_status *status);
void _upb_msgdef_free(struct upb_msgdef *m);
INLINE void upb_msgdef_ref(struct upb_msgdef *m) {
upb_atomic_ref(&m->refcount);
@@ -181,12 +211,6 @@ INLINE void upb_msgdef_unref(struct upb_msgdef *m) {
if(upb_atomic_unref(&m->refcount)) _upb_msgdef_free(m);
}
-/* Sort the given field descriptors in-place, according to what we think is an
- * optimal ordering of fields. This can change from upb release to upb
- * release. */
-void upb_msgdef_sortfds(struct google_protobuf_FieldDescriptorProto **fds,
- size_t num);
-
/* Clients use this function on a previously initialized upb_msgdef to resolve
* the "ref" field in the upb_fielddef. Since messages can refer to each
* other in mutually-recursive ways, this step must be separated from
@@ -197,8 +221,7 @@ void upb_msgdef_setref(struct upb_msgdef *m, struct upb_fielddef *f,
/* Initializes and frees an enum, respectively. Caller retains ownership of
* ed. The enumdef is initialized with one ref. */
void upb_enumdef_init(struct upb_enumdef *e,
- struct google_protobuf_EnumDescriptorProto *ed,
- struct upb_context *c);
+ struct google_protobuf_EnumDescriptorProto *ed);
void _upb_enumdef_free(struct upb_enumdef *e);
INLINE void upb_enumdef_ref(struct upb_enumdef *e) {
upb_atomic_ref(&e->refcount);
@@ -207,28 +230,24 @@ INLINE void upb_enumdef_unref(struct upb_enumdef *e) {
if(upb_atomic_unref(&e->refcount)) _upb_enumdef_free(e);
}
-INLINE void upb_def_ref(union upb_symbol_ref ref, upb_field_type_t type) {
- switch(type) {
- case UPB_TYPENUM(MESSAGE):
- case UPB_TYPENUM(GROUP):
- upb_msgdef_ref(ref.msg);
+INLINE void upb_def_ref(struct upb_def *def) { upb_atomic_ref(&def->refcount); }
+INLINE void upb_def_unref(struct upb_def *def) {
+ if(upb_atomic_unref(&def->refcount)) {
+ switch(def->type) {
+ case UPB_DEF_MESSAGE:
+ _upb_msgdef_free((struct upb_msgdef*)def);
break;
- case UPB_TYPENUM(ENUM):
- upb_enumdef_ref(ref._enum);
+ case UPB_DEF_ENUM:
+ _upb_emumdef_free((struct upb_enumdef*)def);
break;
- default:
- assert(false);
- }
-}
-
-INLINE void upb_def_unref(union upb_symbol_ref ref, upb_field_type_t type) {
- switch(type) {
- case UPB_TYPENUM(MESSAGE):
- case UPB_TYPENUM(GROUP):
- upb_msgdef_unref(ref.msg);
+ case UPB_DEF_SERVICE:
+ assert(false); /* Unimplemented. */
+ break;
+ case UPB_DEF_EXTENSION,
+ _upb_extensiondef_free((struct upb_extensiondef*)def);
break;
- case UPB_TYPENUM(ENUM):
- upb_enumdef_unref(ref._enum);
+ case UPB_DEF_UNRESOLVED
+ upb_string_unref((struct upb_string*)def);
break;
default:
assert(false);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback