summaryrefslogtreecommitdiff
path: root/src/upb_def.h
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2011-06-17 10:34:29 -0700
committerJoshua Haberman <jhaberman@gmail.com>2011-06-17 10:34:29 -0700
commit559e23c796f973a65d05c76e211835b126ee8ac8 (patch)
treeec359628f3b93b88718cc34e5ec86ca6e6c6c1e2 /src/upb_def.h
parenta503b8859c37906ab5012db163daca43bfe393bb (diff)
Major refactoring: abandon upb_msg, add upb_accessors.
Next on the chopping block is upb_string.
Diffstat (limited to 'src/upb_def.h')
-rw-r--r--src/upb_def.h371
1 files changed, 228 insertions, 143 deletions
diff --git a/src/upb_def.h b/src/upb_def.h
index 776231a..ca969cb 100644
--- a/src/upb_def.h
+++ b/src/upb_def.h
@@ -4,25 +4,16 @@
* Copyright (c) 2009-2011 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*
- * Provides a mechanism for loading proto definitions from descriptors, and
- * data structures to represent those definitions. These form the protobuf
- * schema, and are used extensively throughout upb:
+ * Provides a mechanism for creating and linking proto definitions.
+ * These form the protobuf schema, and are used extensively throughout upb:
* - upb_msgdef: describes a "message" construct.
* - upb_fielddef: describes a message field.
* - upb_enumdef: describes an enum.
- * (TODO: definitions of extensions and services).
+ * (TODO: definitions of services).
*
- * Defs are obtained from a upb_symtab object. A upb_symtab is empty when
- * constructed, and definitions can be added by supplying descriptors.
- *
- * Defs are immutable and reference-counted. Symbol tables reference any defs
- * that are the "current" definitions. 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 messages (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.
+ * These defs are mutable (and not thread-safe) when first created.
+ * Once they are added to a defbuilder (and later its symtab) they become
+ * immutable.
*/
#ifndef UPB_DEF_H_
@@ -35,51 +26,37 @@
extern "C" {
#endif
-/* upb_def: base class for defs **********************************************/
+struct _upb_symtab;
+typedef struct _upb_symtab upb_symtab;
// All the different kind of defs we support. These correspond 1:1 with
// declarations in a .proto file.
typedef enum {
UPB_DEF_MSG = 0,
UPB_DEF_ENUM,
- UPB_DEF_SVC,
- UPB_DEF_EXT,
- // Internal-only, placeholder for a def that hasn't be resolved yet.
- UPB_DEF_UNRESOLVED,
+ UPB_DEF_SERVICE, // Not yet implemented.
- // For specifying that defs of any type are requsted from getdefs.
- UPB_DEF_ANY = -1
-} upb_deftype;
+ UPB_DEF_ANY = -1, // Wildcard for upb_symtab_get*()
+ UPB_DEF_UNRESOLVED = 99, // Internal-only.
+} upb_deftype_t;
-// This typedef is more space-efficient than declaring an enum var directly.
-typedef int8_t upb_deftype_t;
+
+/* upb_def: base class for defs **********************************************/
typedef struct {
- upb_string *fqname; // Fully qualified.
- upb_atomic_t refcount;
+ upb_string *fqname; // Fully qualified.
+ upb_symtab *symtab; // Def is mutable iff symtab == NULL.
+ upb_atomic_t refcount; // Owns a ref on symtab iff (symtab && refcount > 0).
upb_deftype_t type;
-
- // The is_cyclic flag could go in upb_msgdef instead of here, because only
- // messages can be involved in cycles. However, putting them here is free
- // from a space perspective because structure alignment will otherwise leave
- // three bytes empty after type. It is also makes ref and unref more
- // efficient, because we don't have to downcast to msgdef before checking the
- // is_cyclic flag.
- bool is_cyclic;
- uint16_t search_depth; // Used during initialization dfs.
} upb_def;
-// These must not be called directly!
-void _upb_def_cyclic_ref(upb_def *def);
-void _upb_def_reftozero(upb_def *def);
-
-// Call to ref/deref a def.
-INLINE void upb_def_ref(upb_def *def) {
- if(upb_atomic_ref(&def->refcount) && def->is_cyclic) _upb_def_cyclic_ref(def);
-}
-INLINE void upb_def_unref(upb_def *def) {
- if(def && upb_atomic_unref(&def->refcount)) _upb_def_reftozero(def);
-}
+// Call to ref/unref a def. Can be used at any time, but is not thread-safe
+// until the def is in a symtab. While a def is in a symtab, everything
+// reachable from that def (the symtab and all defs in the symtab) are
+// guaranteed to be alive.
+void upb_def_ref(upb_def *def);
+void upb_def_unref(upb_def *def);
+upb_def *upb_def_dup(upb_def *def);
#define UPB_UPCAST(ptr) (&(ptr)->base)
@@ -88,30 +65,66 @@ INLINE void upb_def_unref(upb_def *def) {
// 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.
-// It is also reference-counted.
+// must be part of a upb_msgdef. It is also reference-counted.
struct _upb_fielddef {
- uint8_t type;
- uint8_t label;
- // True if we own a ref on "def" (above). This is true unless this edge is
- // part of a cycle.
- bool owned;
- uint8_t set_bit_mask;
+ struct _upb_msgdef *msgdef;
+ upb_def *def; // if upb_hasdef(f)
+ upb_atomic_t refcount;
+ bool finalized;
+ // The following fields may be modified until the def is finalized.
+ uint8_t type; // Use UPB_TYPE() constants.
+ uint8_t label; // Use UPB_LABEL() constants.
+ int16_t hasbit;
+ uint16_t offset;
int32_t number;
- int16_t field_index; // Indicates set bit.
+ upb_string *name;
+ upb_value defaultval; // Only meaningful for non-repeated scalars and strings.
+ upb_value fval;
+ struct _upb_accessor_vtbl *accessor;
+};
- uint16_t set_bit_offset;
- uint32_t byte_offset; // Where in a upb_msg to find the data.
+upb_fielddef *upb_fielddef_new();
+void upb_fielddef_ref(upb_fielddef *f);
+void upb_fielddef_unref(upb_fielddef *f);
+upb_fielddef *upb_fielddef_dup(upb_fielddef *f);
+
+// Read accessors. May be called any time.
+INLINE uint8_t upb_fielddef_type(upb_fielddef *f) { return f->type; }
+INLINE uint8_t upb_fielddef_label(upb_fielddef *f) { return f->label; }
+INLINE int32_t upb_fielddef_number(upb_fielddef *f) { return f->number; }
+INLINE upb_string *upb_fielddef_name(upb_fielddef *f) { return f->name; }
+INLINE upb_value upb_fielddef_default(upb_fielddef *f) { return f->defaultval; }
+INLINE upb_value upb_fielddef_fval(upb_fielddef *f) { return f->fval; }
+INLINE bool upb_fielddef_finalized(upb_fielddef *f) { return f->finalized; }
+INLINE struct _upb_msgdef *upb_fielddef_msgdef(upb_fielddef *f) {
+ return f->msgdef;
+}
+INLINE struct _upb_accessor_vtbl *upb_fielddef_accessor(upb_fielddef *f) {
+ return f->accessor;
+}
- upb_value default_value;
- upb_string *name;
- struct _upb_msgdef *msgdef;
+// Only meaningful once the def is in a symtab (returns NULL otherwise, or for
+// a fielddef where !upb_hassubdef(f)).
+upb_def *upb_fielddef_subdef(upb_fielddef *f);
- // For the case of an enum or a submessage, points to the def for that type.
- upb_def *def;
- upb_atomic_t refcount;
-};
+// NULL until the fielddef has been added to a msgdef.
+
+// Write accessors. "Number" and "name" must be set before the fielddef is
+// added to a msgdef. For the moment we do not allow these to be set once
+// the fielddef is added to a msgdef -- this could be relaxed in the future.
+void upb_fielddef_setnumber(upb_fielddef *f, int32_t number);
+void upb_fielddef_setname(upb_fielddef *f, upb_string *name);
+
+// These writers may be called at any time prior to being put in a symtab.
+void upb_fielddef_settype(upb_fielddef *f, uint8_t type);
+void upb_fielddef_setlabel(upb_fielddef *f, uint8_t label);
+void upb_fielddef_setdefault(upb_fielddef *f, upb_value value);
+void upb_fielddef_setfval(upb_fielddef *f, upb_value fval);
+void upb_fielddef_setaccessor(upb_fielddef *f, struct _upb_accessor_vtbl *vtbl);
+// The name of the message or enum this field is referring to. Must be found
+// at name resolution time (when the symtabtxn is committed to the symtab).
+void upb_fielddef_settypename(upb_fielddef *f, upb_string *name);
// A variety of tests about the type of a field.
INLINE bool upb_issubmsgtype(upb_fieldtype_t type) {
@@ -125,58 +138,35 @@ INLINE bool upb_isprimitivetype(upb_fieldtype_t type) {
}
INLINE bool upb_issubmsg(upb_fielddef *f) { return upb_issubmsgtype(f->type); }
INLINE bool upb_isstring(upb_fielddef *f) { return upb_isstringtype(f->type); }
-INLINE bool upb_isarray(upb_fielddef *f) {
- return f->label == UPB_LABEL(REPEATED);
-}
+INLINE bool upb_isseq(upb_fielddef *f) { return f->label == UPB_LABEL(REPEATED); }
+
// Does the type of this field imply that it should contain an associated def?
INLINE bool upb_hasdef(upb_fielddef *f) {
return upb_issubmsg(f) || f->type == UPB_TYPE(ENUM);
}
-INLINE upb_valuetype_t upb_field_valuetype(upb_fielddef *f) {
- if (upb_isarray(f)) {
- return UPB_VALUETYPE_ARRAY;
- } else {
- return f->type;
- }
-}
-
-INLINE upb_valuetype_t upb_elem_valuetype(upb_fielddef *f) {
- assert(upb_isarray(f));
- return f->type;
-}
-
-INLINE bool upb_field_ismm(upb_fielddef *f) {
- return upb_isarray(f) || upb_isstring(f) || upb_issubmsg(f);
-}
-
-INLINE bool upb_elem_ismm(upb_fielddef *f) {
- return upb_isstring(f) || upb_issubmsg(f);
-}
/* upb_msgdef *****************************************************************/
// Structure that describes a single .proto message type.
typedef struct _upb_msgdef {
upb_def base;
- upb_atomic_t cycle_refcount;
- uint32_t size;
- uint32_t set_flags_bytes;
// Tables for looking up fields by number and name.
upb_inttable itof; // int to field
upb_strtable ntof; // name to field
- // Immutable msg instance that has all default values set.
- // TODO: need a way of making this immutable!
- struct _upb_msg *default_message;
+ // The following fields may be modified until finalized.
+ uint16_t size;
+ uint8_t hasbit_bytes;
+ // The range of tag numbers used to store extensions.
+ uint32_t extension_start;
+ uint32_t extension_end;
} upb_msgdef;
// Hash table entries for looking up fields by name or number.
typedef struct {
bool junk;
- uint8_t field_type;
- uint8_t native_wire_type;
upb_fielddef *f;
} upb_itof_ent;
typedef struct {
@@ -184,23 +174,56 @@ typedef struct {
upb_fielddef *f;
} upb_ntof_ent;
-INLINE void upb_msgdef_unref(upb_msgdef *md) {
- upb_def_unref(UPB_UPCAST(md));
+upb_msgdef *upb_msgdef_new();
+INLINE void upb_msgdef_unref(upb_msgdef *md) { upb_def_unref(UPB_UPCAST(md)); }
+INLINE void upb_msgdef_ref(upb_msgdef *md) { upb_def_ref(UPB_UPCAST(md)); }
+
+// Returns a new msgdef that is a copy of the given msgdef (and a copy of all
+// the fields) but with any references to submessages broken and replaced with
+// just the name of the submessage. This can be put back into another symtab
+// and the names will be re-resolved in the new context.
+upb_msgdef *upb_msgdef_dup(upb_msgdef *m);
+
+// Read accessors. May be called at any time.
+INLINE uint16_t upb_msgdef_size(upb_msgdef *m) { return m->size; }
+INLINE uint8_t upb_msgdef_hasbit_bytes(upb_msgdef *m) {
+ return m->hasbit_bytes;
+}
+INLINE uint32_t upb_msgdef_extension_start(upb_msgdef *m) {
+ return m->extension_start;
}
-INLINE void upb_msgdef_ref(upb_msgdef *md) {
- upb_def_ref(UPB_UPCAST(md));
+INLINE uint32_t upb_msgdef_extension_end(upb_msgdef *m) {
+ return m->extension_end;
}
+// Write accessors. May only be called before the msgdef is in a symtab.
+void upb_msgdef_setsize(upb_msgdef *m, uint16_t size);
+void upb_msgdef_sethasbit_bytes(upb_msgdef *m, uint16_t bytes);
+void upb_msgdef_setextension_start(upb_msgdef *m, uint32_t start);
+void upb_msgdef_setextension_end(upb_msgdef *m, uint32_t end);
+
+// Adds a fielddef to a msgdef, and passes a ref on the field to the msgdef.
+// May only be done before the msgdef is in a symtab. The fielddef's name and
+// number must be set, and the message may not already contain any field with
+// this name or number -- if it does, the fielddef is unref'd and false is
+// returned. The fielddef may not already belong to another message.
+bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f);
+
+// Sets the layout of all fields according to default rules:
+// 1. Hasbits for required fields come first, then optional fields.
+// 2. Values are laid out in a way that respects alignment rules.
+// 3. The order is chosen to minimize memory usage.
+// This should only be called once all fielddefs have been added.
+// TODO: will likely want the ability to exclude strings/submessages/arrays.
+// TODO: will likely want the ability to define a header size.
+void upb_msgdef_layout(upb_msgdef *m);
+
// 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 upb_itof_ent *upb_msgdef_itofent(upb_msgdef *m, uint32_t num) {
- return (upb_itof_ent*)upb_inttable_fastlookup(
- &m->itof, num, sizeof(upb_itof_ent));
-}
-
-INLINE upb_fielddef *upb_msgdef_itof(upb_msgdef *m, uint32_t num) {
- upb_itof_ent *e = upb_msgdef_itofent(m, num);
+INLINE upb_fielddef *upb_msgdef_itof(upb_msgdef *m, uint32_t i) {
+ upb_itof_ent *e = (upb_itof_ent*)
+ upb_inttable_fastlookup(&m->itof, i, sizeof(upb_itof_ent));
return e ? e->f : NULL;
}
@@ -214,6 +237,7 @@ INLINE int upb_msgdef_numfields(upb_msgdef *m) {
}
// Iteration over fields. The order is undefined.
+// Iterators are invalidated when a field is added or removed.
// upb_msg_iter i;
// for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
// upb_fielddef *f = upb_msg_iter_field(i);
@@ -225,6 +249,7 @@ upb_msg_iter upb_msg_begin(upb_msgdef *m);
upb_msg_iter upb_msg_next(upb_msgdef *m, upb_msg_iter iter);
INLINE bool upb_msg_done(upb_msg_iter iter) { return upb_inttable_done(iter); }
+// Iterator accessor.
INLINE upb_fielddef *upb_msg_iter_field(upb_msg_iter iter) {
upb_itof_ent *ent = (upb_itof_ent*)upb_inttable_iter_value(iter);
return ent->f;
@@ -233,13 +258,11 @@ INLINE upb_fielddef *upb_msg_iter_field(upb_msg_iter iter) {
/* upb_enumdef ****************************************************************/
-typedef int32_t upb_enumval_t;
-
typedef struct _upb_enumdef {
upb_def base;
upb_strtable ntoi;
upb_inttable iton;
- upb_enumval_t default_value; // The first value listed in the enum.
+ int32_t defaultval;
} upb_enumdef;
typedef struct {
@@ -252,12 +275,28 @@ typedef struct {
upb_string *string;
} upb_iton_ent;
+upb_enumdef *upb_enumdef_new();
+INLINE void upb_enumdef_ref(upb_enumdef *e) { upb_def_ref(UPB_UPCAST(e)); }
+INLINE void upb_enumdef_unref(upb_enumdef *e) { upb_def_unref(UPB_UPCAST(e)); }
+upb_enumdef *upb_enumdef_dup(upb_enumdef *e);
+
+INLINE int32_t upb_enumdef_default(upb_enumdef *e) { return e->defaultval; }
+
+// May only be set before the enumdef is in a symtab.
+void upb_enumdef_setdefault(upb_enumdef *e, int32_t val);
+
+// Adds a value to the enumdef. Requires that no existing val has this
+// name or number (returns false and does not add if there is). May only
+// be called before the enumdef is in a symtab.
+bool upb_enumdef_addval(upb_enumdef *e, upb_string *name, int32_t num);
+
// Lookups from name to integer and vice-versa.
-bool upb_enumdef_ntoi(upb_enumdef *e, upb_string *name, upb_enumval_t *num);
+bool upb_enumdef_ntoi(upb_enumdef *e, upb_string *name, int32_t *num);
// Caller does not own a ref on the returned string.
-upb_string *upb_enumdef_iton(upb_enumdef *e, upb_enumval_t num);
+upb_string *upb_enumdef_iton(upb_enumdef *e, int32_t num);
// Iteration over name/value pairs. The order is undefined.
+// Adding an enum val invalidates any iterators.
// upb_enum_iter i;
// for(i = upb_enum_begin(e); !upb_enum_done(i); i = upb_enum_next(e, i)) {
// // ...
@@ -268,6 +307,7 @@ upb_enum_iter upb_enum_begin(upb_enumdef *e);
upb_enum_iter upb_enum_next(upb_enumdef *e, upb_enum_iter iter);
INLINE bool upb_enum_done(upb_enum_iter iter) { return upb_inttable_done(iter); }
+// Iterator accessors.
INLINE upb_string *upb_enum_iter_name(upb_enum_iter iter) {
upb_iton_ent *e = (upb_iton_ent*)upb_inttable_iter_value(iter);
return e->string;
@@ -277,28 +317,74 @@ INLINE int32_t upb_enum_iter_number(upb_enum_iter iter) {
}
+/* upb_symtabtxn **************************************************************/
+
+// A symbol table transaction is a map of defs that can be added to a symtab
+// in one single atomic operation that either succeeds or fails. Mutable defs
+// can be added to this map (and perhaps removed, in the future).
+//
+// A symtabtxn is not thread-safe.
+
+typedef struct {
+ upb_strtable deftab;
+} upb_symtabtxn;
+
+void upb_symtabtxn_init(upb_symtabtxn *t);
+void upb_symtabtxn_uninit(upb_symtabtxn *t);
+
+// Adds a def to the symtab. Caller passes a ref on the def to the symtabtxn.
+// The def's name must be set and there must not be any existing defs in the
+// symtabtxn with this name, otherwise false will be returned and no operation
+// will be performed (and the ref on the def will be released).
+bool upb_symtabtxn_add(upb_symtabtxn *t, upb_def *def);
+
+// Gets the def (if any) that is associated with this name in the symtab.
+// Caller does *not* inherit a ref on the def.
+upb_def *upb_symtabtxn_get(upb_symtabtxn *t, upb_string *name);
+
+// Iterate over the defs that are part of the transaction.
+// The order is undefined.
+// The iterator is invalidated by upb_symtabtxn_add().
+// upb_symtabtxn_iter i;
+// for(i = upb_symtabtxn_begin(t); !upb_symtabtxn_done(t);
+// i = upb_symtabtxn_next(t, i)) {
+// upb_def *def = upb_symtabtxn_iter_def(i);
+// }
+typedef void* upb_symtabtxn_iter;
+
+upb_symtabtxn_iter upb_symtabtxn_begin(upb_symtabtxn *t);
+upb_symtabtxn_iter upb_symtabtxn_next(upb_symtabtxn *t, upb_symtabtxn_iter i);
+bool upb_symtabtxn_done(upb_symtabtxn_iter i);
+upb_def *upb_symtabtxn_iter_def(upb_symtabtxn_iter iter);
+
+
/* upb_symtab *****************************************************************/
// A SymbolTable is where upb_defs live. It is empty when first constructed.
-// Clients add definitions to the symtab by supplying descriptors (as defined
-// in descriptor.proto) via the upb_stream interface.
+// Clients add definitions to the symtab (or replace existing definitions) by
+// using a upb_symtab_commit() or calling upb_symtab_add().
+
+// upb_deflist: A little dynamic array for storing a growing list of upb_defs.
+typedef struct {
+ upb_def **defs;
+ uint32_t len;
+ uint32_t size;
+} upb_deflist;
+
+void upb_deflist_init(upb_deflist *l);
+void upb_deflist_uninit(upb_deflist *l);
+void upb_deflist_push(upb_deflist *l, upb_def *d);
+
struct _upb_symtab {
upb_atomic_t refcount;
upb_rwlock_t lock; // Protects all members except the refcount.
upb_strtable symtab; // The symbol table.
- upb_msgdef *fds_msgdef; // Msgdef for google.protobuf.FileDescriptorSet.
+ upb_deflist olddefs;
};
-typedef struct _upb_symtab upb_symtab;
-// Initializes a upb_symtab. Symtabs are not freed explicitly, but unref'd
-// when the caller is done with them.
upb_symtab *upb_symtab_new(void);
-void _upb_symtab_free(upb_symtab *s); // Must not be called directly!
-
INLINE void upb_symtab_ref(upb_symtab *s) { upb_atomic_ref(&s->refcount); }
-INLINE void upb_symtab_unref(upb_symtab *s) {
- if(s && upb_atomic_unref(&s->refcount)) _upb_symtab_free(s);
-}
+void upb_symtab_unref(upb_symtab *s);
// Resolves the given symbol using the rules described in descriptor.proto,
// namely:
@@ -310,35 +396,36 @@ INLINE void upb_symtab_unref(upb_symtab *s) {
//
// If a def is found, the caller owns one ref on the returned def. Otherwise
// returns NULL.
+// TODO: make return const
upb_def *upb_symtab_resolve(upb_symtab *s, upb_string *base, upb_string *sym);
// Find an entry in the symbol table with this exact name. If a def is found,
// the caller owns one ref on the returned def. Otherwise returns NULL.
+// TODO: make return const
upb_def *upb_symtab_lookup(upb_symtab *s, upb_string *sym);
// Gets an array of pointers to all currently active defs in this symtab. The
// caller owns the returned array (which is of length *count) as well as a ref
// to each symbol inside. If type is UPB_DEF_ANY then defs of all types are
// returned, otherwise only defs of the required type are returned.
-upb_def **upb_symtab_getdefs(upb_symtab *s, int *count, upb_deftype_t type);
+// TODO: make return const
+upb_def **upb_symtab_getdefs(upb_symtab *s, int *n, upb_deftype_t type);
-// upb_defbuilder: For adding defs to the symtab.
-// You allocate the defbuilder, which can handle a single descriptor.
-// It will be freed automatically when the parse completes.
-struct _upb_defbuilder;
-typedef struct _upb_defbuilder upb_defbuilder;
-struct _upb_handlers;
-struct _upb_handlers;
+// Adds a single upb_def into the symtab. A ref on the def is passed to the
+// symtab. If any references cannot be resolved, false is returned and the
+// symtab is unchanged. The error (if any) is saved to status if non-NULL.
+bool upb_symtab_add(upb_symtab *s, upb_def *d, upb_status *status);
-// Allocates a new defbuilder that will add defs to the given symtab.
-upb_defbuilder *upb_defbuilder_new(upb_symtab *s);
+// Adds the set of defs contained in the transaction to the symtab, clearing
+// the txn. The entire operation either succeeds or fails. If the operation
+// fails, the symtab is unchanged, false is returned, and status indicates
+// the error.
+bool upb_symtab_commit(upb_symtab *s, upb_symtabtxn *t, upb_status *status);
-// Registers handlers that will operate on a defbuilder to add the defs
-// to the defbuilder's symtab. Will free itself when the parse finishes.
-//
-// TODO: should this allow redefinition? Either is possible, but which is
-// more useful? Maybe it should be an option.
-struct _upb_mhandlers *upb_defbuilder_reghandlers(struct _upb_handlers *h);
+// Frees defs that are no longer active in the symtab and are no longer
+// reachable. Such defs are not freed when they are replaced in the symtab
+// if they are still reachable from defs that are still referenced.
+void upb_symtab_gc(upb_symtab *s);
/* upb_def casts **************************************************************/
@@ -352,8 +439,7 @@ struct _upb_mhandlers *upb_defbuilder_reghandlers(struct _upb_handlers *h);
}
UPB_DYNAMIC_CAST_DEF(msgdef, MSG);
UPB_DYNAMIC_CAST_DEF(enumdef, ENUM);
-UPB_DYNAMIC_CAST_DEF(svcdef, SVC);
-UPB_DYNAMIC_CAST_DEF(extdef, EXT);
+UPB_DYNAMIC_CAST_DEF(svcdef, SERVICE);
UPB_DYNAMIC_CAST_DEF(unresolveddef, UNRESOLVED);
#undef UPB_DYNAMIC_CAST_DEF
@@ -367,8 +453,7 @@ UPB_DYNAMIC_CAST_DEF(unresolveddef, UNRESOLVED);
}
UPB_DOWNCAST_DEF(msgdef, MSG);
UPB_DOWNCAST_DEF(enumdef, ENUM);
-UPB_DOWNCAST_DEF(svcdef, SVC);
-UPB_DOWNCAST_DEF(extdef, EXT);
+UPB_DOWNCAST_DEF(svcdef, SERVICE);
UPB_DOWNCAST_DEF(unresolveddef, UNRESOLVED);
#undef UPB_DOWNCAST_DEF
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback