summaryrefslogtreecommitdiff
path: root/src/upb_def.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/upb_def.c')
-rw-r--r--src/upb_def.c87
1 files changed, 54 insertions, 33 deletions
diff --git a/src/upb_def.c b/src/upb_def.c
index 6a1e543..0382610 100644
--- a/src/upb_def.c
+++ b/src/upb_def.c
@@ -859,6 +859,7 @@ static upb_symtab_ent *upb_resolve(upb_strtable *t,
// TODO: This branch is totally broken, but currently not used.
upb_string *sym_str = upb_string_new();
int baselen = upb_string_len(base);
+ upb_symtab_ent *ret = NULL;
while(1) {
// sym_str = base[0...base_len] + UPB_SYMBOL_SEPARATOR + sym
upb_strlen_t len = baselen + upb_string_len(sym) + 1;
@@ -868,11 +869,18 @@ static upb_symtab_ent *upb_resolve(upb_strtable *t,
memcpy(buf + baselen + 1, upb_string_getrobuf(sym), upb_string_len(sym));
upb_symtab_ent *e = upb_strtable_lookup(t, sym_str);
- if (e) return e;
- else if(baselen == 0) return NULL; // No more scopes to try.
-
+ if (e) {
+ ret = e;
+ break;
+ } else if(baselen == 0) {
+ // No more scopes to try.
+ ret = NULL;
+ break;
+ }
baselen = my_memrchr(buf, UPB_SYMBOL_SEPARATOR, baselen);
}
+ upb_string_unref(sym_str);
+ return ret;
}
}
@@ -1307,38 +1315,51 @@ static upb_src *upb_baredecoder_src(upb_baredecoder *d) {
return &d->src;
}
-void upb_symtab_add_descriptorproto(upb_symtab *symtab) {
- // For the moment we silently decline to perform the operation if the symbols
- // already exist in the symtab. Revisit this when we have a better story
- // about whether syms in a table can be replaced.
- if(symtab->fds_msgdef) return;
-
- static upb_string descriptor_str =
- UPB_STATIC_STRING_ARRAY(descriptor_pb);
- upb_baredecoder *decoder = upb_baredecoder_new(&descriptor_str);
- upb_status status = UPB_STATUS_INIT;
- upb_symtab_addfds(symtab, upb_baredecoder_src(decoder), &status);
- upb_baredecoder_free(decoder);
-
- if(!upb_ok(&status)) {
- // upb itself is corrupt.
- upb_printerr(&status);
- upb_clearerr(&status);
- upb_symtab_unref(symtab);
- abort();
+static upb_symtab *descriptor_symtab = NULL;
+
+static void upb_free_descriptor_symtab() {
+ if (descriptor_symtab) {
+ // There should be no way for anyone to acquire a ref on this symtab.
+ assert(upb_atomic_only(&descriptor_symtab->refcount));
+ _upb_symtab_free(descriptor_symtab);
+ descriptor_symtab = NULL;
}
- upb_def *def = upb_symtab_lookup(
- symtab, UPB_STRLIT("google.protobuf.FileDescriptorSet"));
- if (!def || (symtab->fds_msgdef = upb_dyncast_msgdef(def)) == NULL) {
- // upb itself is corrupt.
- abort();
+}
+
+upb_def *upb_getdescriptordef(upb_string *str) {
+ // TODO: add locking.
+ if (descriptor_symtab == NULL) {
+ descriptor_symtab = upb_symtab_new();
+
+ static upb_string descriptor_str =
+ UPB_STATIC_STRING_ARRAY(descriptor_pb);
+ upb_baredecoder *decoder = upb_baredecoder_new(&descriptor_str);
+ upb_status status = UPB_STATUS_INIT;
+ upb_symtab_addfds(descriptor_symtab, upb_baredecoder_src(decoder), &status);
+ upb_baredecoder_free(decoder);
+
+ if(!upb_ok(&status)) {
+ // upb itself is corrupt.
+ upb_printerr(&status);
+ upb_clearerr(&status);
+ abort();
+ }
+ upb_status_uninit(&status);
+
+ // As a sanity check, make sure that FileDescriptorSet was loaded.
+ upb_msgdef *def = upb_getfdsdef();
+ if (!def) {
+ // upb itself is corrupt.
+ abort();
+ }
+ upb_def_unref(UPB_UPCAST(def)); // The symtab already holds a ref on it.
+ atexit(upb_free_descriptor_symtab);
}
- upb_def_unref(def); // The symtab already holds a ref on it.
- upb_status_uninit(&status);
+ return upb_symtab_resolve(
+ descriptor_symtab, UPB_STRLIT("google.protobuf"), str);
}
-upb_msgdef *upb_symtab_fds_def(upb_symtab *s) {
- assert(s->fds_msgdef != NULL);
- upb_def_ref(UPB_UPCAST(s->fds_msgdef));
- return s->fds_msgdef;
+upb_msgdef *upb_getfdsdef() {
+ return upb_downcast_msgdef(
+ upb_getdescriptordef(UPB_STRLIT("FileDescriptorSet")));
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback