summaryrefslogtreecommitdiff
path: root/upb/def.c
diff options
context:
space:
mode:
Diffstat (limited to 'upb/def.c')
-rw-r--r--upb/def.c86
1 files changed, 26 insertions, 60 deletions
diff --git a/upb/def.c b/upb/def.c
index 000b7f2..889eeea 100644
--- a/upb/def.c
+++ b/upb/def.c
@@ -485,46 +485,12 @@ upb_msg_iter upb_msg_next(upb_msgdef *m, upb_msg_iter iter) {
}
-/* upb_symtabtxn **************************************************************/
+/* upb_symtab *****************************************************************/
typedef struct {
upb_def *def;
} upb_symtab_ent;
-void upb_symtabtxn_init(upb_symtabtxn *t) {
- upb_strtable_init(&t->deftab, 16, sizeof(upb_symtab_ent));
-}
-
-void upb_symtabtxn_uninit(upb_symtabtxn *txn) {
- upb_strtable *t = &txn->deftab;
- upb_strtable_iter i;
- for(upb_strtable_begin(&i, t); !upb_strtable_done(&i); upb_strtable_next(&i)) {
- const upb_symtab_ent *e = upb_strtable_iter_value(&i);
- free(e->def);
- }
- upb_strtable_free(t);
-}
-
-bool upb_symtabtxn_add(upb_symtabtxn *t, upb_def *def) {
- // TODO: check if already present.
- upb_symtab_ent e = {def};
- //fprintf(stderr, "txn Inserting: %p, ent: %p\n", e.def, &e);
- upb_strtable_insert(&t->deftab, def->fqname, &e);
- return true;
-}
-
-#if 0
-err:
- // We need to free all defs from "tmptab."
- upb_rwlock_unlock(&s->lock);
- for(upb_symtab_ent *e = upb_strtable_begin(&tmptab); e;
- e = upb_strtable_next(&tmptab, &e->e)) {
- upb_def_unref(e->def);
- }
- upb_strtable_free(&tmptab);
- return false;
-#endif
-
// Given a symbol and the base symbol inside which it is defined, find the
// symbol's definition in t.
static upb_symtab_ent *upb_resolve(upb_strtable *t,
@@ -543,19 +509,6 @@ static upb_symtab_ent *upb_resolve(upb_strtable *t,
}
}
-void upb_symtabtxn_begin(upb_symtabtxn_iter *i, upb_symtabtxn *t) {
- upb_strtable_begin(i, &t->deftab);
-}
-void upb_symtabtxn_next(upb_symtabtxn_iter *i) { upb_strtable_next(i); }
-bool upb_symtabtxn_done(upb_symtabtxn_iter *i) { return upb_strtable_done(i); }
-upb_def *upb_symtabtxn_iter_def(upb_symtabtxn_iter *i) {
- const upb_symtab_ent *e = upb_strtable_iter_value(i);
- return e->def;
-}
-
-
-/* upb_symtab public interface ************************************************/
-
static void _upb_symtab_free(upb_strtable *t) {
upb_strtable_iter i;
upb_strtable_begin(&i, t);
@@ -641,7 +594,7 @@ upb_def *upb_symtab_resolve(upb_symtab *s, const char *base, const char *sym) {
}
bool upb_symtab_dfs(upb_def *def, upb_def **open_defs, int n,
- upb_symtabtxn *txn) {
+ upb_strtable *addtab) {
// This linear search makes the DFS O(n^2) in the length of the paths.
// Could make this O(n) with a hash table, but n is small.
for (int i = 0; i < n; i++) {
@@ -656,23 +609,37 @@ bool upb_symtab_dfs(upb_def *def, upb_def **open_defs, int n,
for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
upb_fielddef *f = upb_msg_iter_field(i);
if (!upb_hasdef(f)) continue;
- needcopy |= upb_symtab_dfs(f->def, open_defs, n, txn);
+ needcopy |= upb_symtab_dfs(f->def, open_defs, n, addtab);
}
}
- bool replacing = (upb_strtable_lookup(&txn->deftab, m->base.fqname) != NULL);
+ bool replacing = (upb_strtable_lookup(addtab, m->base.fqname) != NULL);
if (needcopy && !replacing) {
upb_symtab_ent e = {upb_def_dup(def)};
//fprintf(stderr, "Replacing def: %p\n", e.def);
- upb_strtable_insert(&txn->deftab, def->fqname, &e);
+ upb_strtable_insert(addtab, def->fqname, &e);
replacing = true;
}
return replacing;
}
-bool upb_symtab_commit(upb_symtab *s, upb_symtabtxn *txn, upb_status *status) {
+bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status) {
upb_rwlock_wrlock(&s->lock);
+ // Add all defs to a table for resolution.
+ upb_strtable addtab;
+ upb_strtable_init(&addtab, n, sizeof(upb_symtab_ent));
+ for (int i = 0; i < n; i++) {
+ upb_def *def = defs[i];
+ if (upb_strtable_lookup(&addtab, def->fqname)) {
+ upb_status_setf(status, UPB_ERROR,
+ "Conflicting defs named '%s'", def->fqname);
+ upb_strtable_free(&addtab);
+ return false;
+ }
+ upb_strtable_insert(&addtab, def->fqname, &def);
+ }
+
// All existing defs that can reach defs that are being replaced must
// themselves be replaced with versions that will point to the new defs.
// Do a DFS -- any path that finds a new def must replace all ancestors.
@@ -682,12 +649,11 @@ bool upb_symtab_commit(upb_symtab *s, upb_symtabtxn *txn, upb_status *status) {
for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
upb_def *open_defs[UPB_MAX_TYPE_DEPTH];
const upb_symtab_ent *e = upb_strtable_iter_value(&i);
- upb_symtab_dfs(e->def, open_defs, 0, txn);
+ upb_symtab_dfs(e->def, open_defs, 0, &addtab);
}
// Resolve all refs.
- upb_strtable *txntab = &txn->deftab;
- upb_strtable_begin(&i, txntab);
+ upb_strtable_begin(&i, &addtab);
for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
const upb_symtab_ent *e = upb_strtable_iter_value(&i);
upb_msgdef *m = upb_dyncast_msgdef(e->def);
@@ -701,11 +667,11 @@ bool upb_symtab_commit(upb_symtab *s, upb_symtabtxn *txn, upb_status *status) {
if(!upb_hasdef(f)) continue; // No resolving necessary.
const char *name = upb_downcast_unresolveddef(f->def)->name;
- // Resolve from either the txntab (pending adds) or symtab (existing
+ // Resolve from either the addtab (pending adds) or symtab (existing
// defs). If both exist, prefer the pending add, because it will be
// overwriting the existing def.
upb_symtab_ent *found;
- if(!(found = upb_resolve(txntab, base, name)) &&
+ if(!(found = upb_resolve(&addtab, base, name)) &&
!(found = upb_resolve(symtab, base, name))) {
upb_status_setf(status, UPB_ERROR, "could not resolve symbol '%s' "
"in context '%s'", name, base);
@@ -727,7 +693,7 @@ bool upb_symtab_commit(upb_symtab *s, upb_symtabtxn *txn, upb_status *status) {
// The defs in the transaction have been vetted, and can be moved to the
// symtab without causing errors.
- upb_strtable_begin(&i, txntab);
+ upb_strtable_begin(&i, &addtab);
for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
const upb_symtab_ent *tmptab_e = upb_strtable_iter_value(&i);
upb_def_movetosymtab(tmptab_e->def, s);
@@ -742,7 +708,7 @@ bool upb_symtab_commit(upb_symtab *s, upb_symtabtxn *txn, upb_status *status) {
}
}
- upb_strtable_clear(txntab);
+ upb_strtable_free(&addtab);
upb_rwlock_unlock(&s->lock);
upb_symtab_gc(s);
return true;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback