bool prop_object_equals_with_error(prop_object_t obj1, prop_object_t obj2, bool *error_flag) { struct _prop_object *po1; struct _prop_object *po2; void *stored_pointer1, *stored_pointer2; prop_object_t next_obj1, next_obj2; struct _prop_stack stack; _prop_object_equals_rv_t ret; _prop_stack_init(&stack); if (error_flag) *error_flag = false; start_subtree: stored_pointer1 = NULL; stored_pointer2 = NULL; po1 = obj1; po2 = obj2; if (po1->po_type != po2->po_type) return (false); continue_subtree: ret = (*po1->po_type->pot_equals)(obj1, obj2, &stored_pointer1, &stored_pointer2, &next_obj1, &next_obj2); if (ret == _PROP_OBJECT_EQUALS_FALSE) goto finish; if (ret == _PROP_OBJECT_EQUALS_TRUE) { if (!_prop_stack_pop(&stack, &obj1, &obj2, &stored_pointer1, &stored_pointer2)) return true; po1 = obj1; po2 = obj2; goto continue_subtree; } _PROP_ASSERT(ret == _PROP_OBJECT_EQUALS_RECURSE); if (!_prop_stack_push(&stack, obj1, obj2, stored_pointer1, stored_pointer2)) { if (error_flag) *error_flag = true; goto finish; } obj1 = next_obj1; obj2 = next_obj2; goto start_subtree; finish: while (_prop_stack_pop(&stack, &obj1, &obj2, NULL, NULL)) { po1 = obj1; (*po1->po_type->pot_equals_finish)(obj1, obj2); } return (false); }
/* * prop_object_release -- * Decrement the reference count on an object. * * Free the object if we are releasing the final * reference. */ void prop_object_release(prop_object_t obj) { struct _prop_object *po; struct _prop_stack stack; void (*unlock)(void); int ret; uint32_t ocnt; _prop_stack_init(&stack); do { do { po = obj; _PROP_ASSERT(obj); if (po->po_type->pot_lock != NULL) po->po_type->pot_lock(); /* Save pointer to object unlock function */ unlock = po->po_type->pot_unlock; _PROP_REFCNT_LOCK(); ocnt = po->po_refcnt--; _PROP_REFCNT_UNLOCK(); _PROP_ASSERT(ocnt != 0); if (ocnt != 1) { ret = 0; if (unlock != NULL) unlock(); break; } ret = (po->po_type->pot_free)(&stack, &obj); if (unlock != NULL) unlock(); if (ret == _PROP_OBJECT_FREE_DONE) break; _PROP_REFCNT_LOCK(); ++po->po_refcnt; _PROP_REFCNT_UNLOCK(); } while (ret == _PROP_OBJECT_FREE_RECURSE); if (ret == _PROP_OBJECT_FREE_FAILED) prop_object_release_emergency(obj); } while (_prop_stack_pop(&stack, &obj, NULL, NULL, NULL)); }
/* * _prop_object_internalize_by_tag -- * Determine the object type from the tag in the context and * internalize it. */ prop_object_t _prop_object_internalize_by_tag(struct _prop_object_internalize_context *ctx) { const struct _prop_object_internalizer *poi; prop_object_t obj, parent_obj; void *data, *iter; prop_object_internalizer_continue_t iter_func; struct _prop_stack stack; _prop_stack_init(&stack); match_start: for (poi = _prop_object_internalizer_table; poi->poi_tag != NULL; poi++) { if (_prop_object_internalize_match(ctx->poic_tagname, ctx->poic_tagname_len, poi->poi_tag, poi->poi_taglen)) break; } if (poi == NULL) { while (_prop_stack_pop(&stack, &obj, &iter, &data, NULL)) { iter_func = (prop_object_internalizer_continue_t)iter; (*iter_func)(&stack, &obj, ctx, data, NULL); } return (NULL); } obj = NULL; if (!(*poi->poi_intern)(&stack, &obj, ctx)) goto match_start; parent_obj = obj; while (_prop_stack_pop(&stack, &parent_obj, &iter, &data, NULL)) { iter_func = (prop_object_internalizer_continue_t)iter; if (!(*iter_func)(&stack, &parent_obj, ctx, data, obj)) goto match_start; obj = parent_obj; } return (parent_obj); }