static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj, void *closure) { check_state *s = closure; assert(obj == s->obj); assert(subobj); upb_inttable *ref2 = &s->ref2; upb_value v; bool removed = upb_inttable_removeptr(ref2, subobj, &v); // The following assertion will fail if the visit() function visits a subobj // that it did not have a ref2 on, or visits the same subobj too many times. assert(removed); int32_t newcount = upb_value_getint32(v) - 1; if (newcount > 0) { upb_inttable_insert(ref2, (uintptr_t)subobj, upb_value_int32(newcount)); } }
// Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that // originate from the given owner. static void getref2s(const upb_refcounted *owner, upb_inttable *tab) { upb_lock(); upb_inttable_iter i; upb_inttable_begin(&i, owner->ref2s); for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i); // To get the count we need to look in the target's table. upb_value v; bool found = upb_inttable_lookupptr(to->refs, owner, &v); assert(found); trackedref *ref = upb_value_getptr(v); upb_value count = upb_value_int32(ref->count); bool ok = upb_inttable_insertptr(tab, to, count); CHECK_OOM(ok); } upb_unlock(); }
bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, upb_status *status) { if (!upb_isident(name, strlen(name), false, status)) { return false; } if (upb_enumdef_ntoi(e, name, NULL)) { upb_status_seterrf(status, "name '%s' is already defined", name); return false; } if (!upb_strtable_insert(&e->ntoi, name, upb_value_int32(num))) { upb_status_seterrliteral(status, "out of memory"); return false; } if (!upb_inttable_lookup(&e->iton, num, NULL) && !upb_inttable_insert(&e->iton, num, upb_value_cstr(upb_strdup(name)))) { upb_status_seterrliteral(status, "out of memory"); upb_strtable_remove(&e->ntoi, name, NULL); return false; } return true; }