diff options
| author | joerg <joerg@NetBSD.org> | 2007-08-30 12:23:53 +0000 |
|---|---|---|
| committer | joerg <joerg@NetBSD.org> | 2007-08-30 12:23:53 +0000 |
| commit | 4deb593145a6d95f78a080aefb8cfc760bcddac9 (patch) | |
| tree | 798627c927bc10e7c4639b8f24a47fcdaf82600a | |
| parent | ebcc6a8e1aa8ec2e8fd237a3d1512d620918c753 (diff) | |
Avoid using unbound amount of stack frames in prop_object_equal
by using a dynamic stack as well. Reorder arguments for the internalizer
as the iteration is always present and should go before possibly
NULL arguments.
Reviewed by mjf@ and adrianp@
| -rw-r--r-- | common/include/prop/prop_object.h | 3 | ||||
| -rw-r--r-- | common/lib/libprop/prop_array.c | 77 | ||||
| -rw-r--r-- | common/lib/libprop/prop_bool.c | 22 | ||||
| -rw-r--r-- | common/lib/libprop/prop_data.c | 31 | ||||
| -rw-r--r-- | common/lib/libprop/prop_dictionary.c | 111 | ||||
| -rw-r--r-- | common/lib/libprop/prop_number.c | 36 | ||||
| -rw-r--r-- | common/lib/libprop/prop_object.c | 64 | ||||
| -rw-r--r-- | common/lib/libprop/prop_object_impl.h | 22 | ||||
| -rw-r--r-- | common/lib/libprop/prop_stack.c | 40 | ||||
| -rw-r--r-- | common/lib/libprop/prop_stack.h | 12 | ||||
| -rw-r--r-- | common/lib/libprop/prop_string.c | 29 |
11 files changed, 302 insertions, 145 deletions
diff --git a/common/include/prop/prop_object.h b/common/include/prop/prop_object.h index 2874c12f65e..c6b91c4489b 100644 --- a/common/include/prop/prop_object.h +++ b/common/include/prop/prop_object.h @@ -1,4 +1,4 @@ -/* $NetBSD: prop_object.h,v 1.5 2007/08/16 16:28:17 thorpej Exp $ */ +/* $NetBSD: prop_object.h,v 1.6 2007/08/30 12:23:53 joerg Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -65,6 +65,7 @@ void prop_object_release(prop_object_t); prop_type_t prop_object_type(prop_object_t); bool prop_object_equals(prop_object_t, prop_object_t); +bool prop_object_equals_with_error(prop_object_t, prop_object_t, bool *); typedef struct _prop_object_iterator *prop_object_iterator_t; diff --git a/common/lib/libprop/prop_array.c b/common/lib/libprop/prop_array.c index d20d0685b58..cc3a868c8b6 100644 --- a/common/lib/libprop/prop_array.c +++ b/common/lib/libprop/prop_array.c @@ -1,4 +1,4 @@ -/* $NetBSD: prop_array.c,v 1.10 2007/08/16 21:44:07 joerg Exp $ */ +/* $NetBSD: prop_array.c,v 1.11 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc. @@ -65,7 +65,10 @@ static void _prop_array_emergency_free(prop_object_t); static bool _prop_array_externalize( struct _prop_object_externalize_context *, void *); -static bool _prop_array_equals(void *, void *); +static bool _prop_array_equals(prop_object_t, prop_object_t, + void **, void **, + prop_object_t *, prop_object_t *); +static void _prop_array_equals_finish(prop_object_t, prop_object_t); static const struct _prop_object_type _prop_object_type_array = { .pot_type = PROP_TYPE_ARRAY, @@ -73,6 +76,7 @@ static const struct _prop_object_type _prop_object_type_array = { .pot_emergency_free = _prop_array_emergency_free, .pot_extern = _prop_array_externalize, .pot_equals = _prop_array_equals, + .pot_equals_finish = _prop_array_equals_finish, }; #define prop_object_is_array(x) \ @@ -122,7 +126,7 @@ _prop_array_free(prop_stack_t stack, prop_object_t *obj) } /* Otherwise, try to push the current object on the stack. */ - if (!_prop_stack_push(stack, pa, NULL, NULL)) { + if (!_prop_stack_push(stack, pa, NULL, NULL, NULL)) { /* Push failed, entering emergency release mode. */ return (_PROP_OBJECT_FREE_FAILED); } @@ -194,39 +198,49 @@ _prop_array_externalize(struct _prop_object_externalize_context *ctx, return (rv); } +/* ARGSUSED */ static bool -_prop_array_equals(void *v1, void *v2) +_prop_array_equals(prop_object_t v1, prop_object_t v2, + void **stored_pointer1, void **stored_pointer2, + prop_object_t *next_obj1, prop_object_t *next_obj2) { prop_array_t array1 = v1; prop_array_t array2 = v2; - unsigned int idx; - bool rv = false; - - if (! (prop_object_is_array(array1) && - prop_object_is_array(array2))) - return (false); + uintptr_t idx; + bool rv = _PROP_OBJECT_EQUALS_FALSE; if (array1 == array2) - return (true); - - if ((uintptr_t)array1 < (uintptr_t)array2) { - _PROP_RWLOCK_RDLOCK(array1->pa_rwlock); - _PROP_RWLOCK_RDLOCK(array2->pa_rwlock); - } else { - _PROP_RWLOCK_RDLOCK(array2->pa_rwlock); - _PROP_RWLOCK_RDLOCK(array1->pa_rwlock); + return (_PROP_OBJECT_EQUALS_TRUE); + + _PROP_ASSERT(*stored_pointer1 == *stored_pointer2); + idx = (uintptr_t)*stored_pointer1; + + /* For the first iteration, lock the objects. */ + if (idx == 0) { + if ((uintptr_t)array1 < (uintptr_t)array2) { + _PROP_RWLOCK_RDLOCK(array1->pa_rwlock); + _PROP_RWLOCK_RDLOCK(array2->pa_rwlock); + } else { + _PROP_RWLOCK_RDLOCK(array2->pa_rwlock); + _PROP_RWLOCK_RDLOCK(array1->pa_rwlock); + } } if (array1->pa_count != array2->pa_count) goto out; - - for (idx = 0; idx < array1->pa_count; idx++) { - if (prop_object_equals(array1->pa_array[idx], - array2->pa_array[idx]) == false) - goto out; + if (idx == array1->pa_count) { + rv = true; + goto out; } + _PROP_ASSERT(idx < array1->pa_count); - rv = true; + *stored_pointer1 = (void *)(idx + 1); + *stored_pointer2 = (void *)(idx + 1); + + *next_obj1 = array1->pa_array[idx]; + *next_obj2 = array2->pa_array[idx]; + + return (_PROP_OBJECT_EQUALS_RECURSE); out: _PROP_RWLOCK_UNLOCK(array1->pa_rwlock); @@ -234,6 +248,13 @@ _prop_array_equals(void *v1, void *v2) return (rv); } +static void +_prop_array_equals_finish(prop_object_t v1, prop_object_t v2) +{ + _PROP_RWLOCK_UNLOCK(((prop_array_t)v1)->pa_rwlock); + _PROP_RWLOCK_UNLOCK(((prop_array_t)v2)->pa_rwlock); +} + static prop_array_t _prop_array_alloc(unsigned int capacity) { @@ -675,8 +696,10 @@ prop_array_remove(prop_array_t pa, unsigned int idx) bool prop_array_equals(prop_array_t array1, prop_array_t array2) { + if (!prop_object_is_array(array1) || !prop_object_is_array(array2)) + return (false); - return (_prop_array_equals(array1, array2)); + return (prop_object_equals(array1, array2)); } /* @@ -791,8 +814,8 @@ _prop_array_internalize_body(prop_stack_t stack, prop_object_t *obj, return (true); } - if (_prop_stack_push(stack, array, NULL, - _prop_array_internalize_continue)) + if (_prop_stack_push(stack, array, + _prop_array_internalize_continue, NULL, NULL)) return (false); bad: diff --git a/common/lib/libprop/prop_bool.c b/common/lib/libprop/prop_bool.c index cf48c212811..f33ad7e6651 100644 --- a/common/lib/libprop/prop_bool.c +++ b/common/lib/libprop/prop_bool.c @@ -1,4 +1,4 @@ -/* $NetBSD: prop_bool.c,v 1.11 2007/08/16 21:44:07 joerg Exp $ */ +/* $NetBSD: prop_bool.c,v 1.12 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -54,7 +54,9 @@ static int _prop_bool_free(prop_stack_t, prop_object_t *); static bool _prop_bool_externalize( struct _prop_object_externalize_context *, void *); -static bool _prop_bool_equals(void *, void *); +static bool _prop_bool_equals(prop_object_t, prop_object_t, + void **, void **, + prop_object_t *, prop_object_t *); static const struct _prop_object_type _prop_object_type_bool = { .pot_type = PROP_TYPE_BOOL, @@ -89,21 +91,27 @@ _prop_bool_externalize(struct _prop_object_externalize_context *ctx, pb->pb_value ? "true" : "false")); } +/* ARGSUSED */ static bool -_prop_bool_equals(void *v1, void *v2) +_prop_bool_equals(prop_object_t v1, prop_object_t v2, + void **stored_pointer1, void **stored_pointer2, + prop_object_t *next_obj1, prop_object_t *next_obj2) { prop_bool_t b1 = v1; prop_bool_t b2 = v2; if (! (prop_object_is_bool(b1) && prop_object_is_bool(b2))) - return (false); + return (_PROP_OBJECT_EQUALS_FALSE); /* * Since we only ever allocate one true and one false, * save ourselves a couple of memory operations. */ - return (b1 == b2); + if (b1 == b2) + return (_PROP_OBJECT_EQUALS_TRUE); + else + return (_PROP_OBJECT_EQUALS_FALSE); } static prop_bool_t @@ -185,8 +193,10 @@ prop_bool_true(prop_bool_t pb) bool prop_bool_equals(prop_bool_t b1, prop_bool_t b2) { + if (!prop_object_is_bool(b1) || !prop_object_is_bool(b2)) + return (false); - return (_prop_bool_equals(b1, b2)); + return (prop_object_equals(b1, b2)); } /* diff --git a/common/lib/libprop/prop_data.c b/common/lib/libprop/prop_data.c index 0fa62eef91b..a4f96c0f2c8 100644 --- a/common/lib/libprop/prop_data.c +++ b/common/lib/libprop/prop_data.c @@ -1,4 +1,4 @@ -/* $NetBSD: prop_data.c,v 1.8 2007/08/16 21:44:07 joerg Exp $ */ +/* $NetBSD: prop_data.c,v 1.9 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -73,7 +73,9 @@ static int _prop_data_free(prop_stack_t, prop_object_t *); static bool _prop_data_externalize( struct _prop_object_externalize_context *, void *); -static bool _prop_data_equals(void *, void *); +static bool _prop_data_equals(prop_object_t, prop_object_t, + void **, void **, + prop_object_t *, prop_object_t *); static const struct _prop_object_type _prop_object_type_data = { .pot_type = PROP_TYPE_DATA, @@ -177,27 +179,28 @@ _prop_data_externalize(struct _prop_object_externalize_context *ctx, void *v) return (true); } +/* ARGSUSED */ static bool -_prop_data_equals(void *v1, void *v2) +_prop_data_equals(prop_object_t v1, prop_object_t v2, + void **stored_pointer1, void **stored_pointer2, + prop_object_t *next_obj1, prop_object_t *next_obj2) { prop_data_t pd1 = v1; prop_data_t pd2 = v2; - if (! (prop_object_is_data(pd1) && - prop_object_is_data(pd2))) - return (false); - if (pd1 == pd2) - return (true); + return (_PROP_OBJECT_EQUALS_TRUE); if (pd1->pd_size != pd2->pd_size) - return (false); + return (_PROP_OBJECT_EQUALS_FALSE); if (pd1->pd_size == 0) { _PROP_ASSERT(pd1->pd_immutable == NULL); _PROP_ASSERT(pd2->pd_immutable == NULL); - return (true); + return (_PROP_OBJECT_EQUALS_TRUE); } - return (memcmp(pd1->pd_immutable, pd2->pd_immutable, - pd1->pd_size) == 0); + if (memcmp(pd1->pd_immutable, pd2->pd_immutable, pd1->pd_size) == 0) + return _PROP_OBJECT_EQUALS_TRUE; + else + return _PROP_OBJECT_EQUALS_FALSE; } static prop_data_t @@ -359,8 +362,10 @@ prop_data_data_nocopy(prop_data_t pd) bool prop_data_equals(prop_data_t pd1, prop_data_t pd2) { + if (!prop_object_is_data(pd1) || !prop_object_is_data(pd2)) + return (false); - return (_prop_data_equals(pd1, pd2)); + return (prop_object_equals(pd1, pd2)); } /* diff --git a/common/lib/libprop/prop_dictionary.c b/common/lib/libprop/prop_dictionary.c index 6e08d33f357..2afb9d2f743 100644 --- a/common/lib/libprop/prop_dictionary.c +++ b/common/lib/libprop/prop_dictionary.c @@ -1,4 +1,4 @@ -/* $NetBSD: prop_dictionary.c,v 1.19 2007/08/16 21:44:07 joerg Exp $ */ +/* $NetBSD: prop_dictionary.c,v 1.20 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc. @@ -116,7 +116,10 @@ static void _prop_dictionary_emergency_free(prop_object_t); static bool _prop_dictionary_externalize( struct _prop_object_externalize_context *, void *); -static bool _prop_dictionary_equals(void *, void *); +static bool _prop_dictionary_equals(prop_object_t, prop_object_t, + void **, void **, + prop_object_t *, prop_object_t *); +static void _prop_dictionary_equals_finish(prop_object_t, prop_object_t); static const struct _prop_object_type _prop_object_type_dictionary = { .pot_type = PROP_TYPE_DICTIONARY, @@ -124,13 +127,16 @@ static const struct _prop_object_type _prop_object_type_dictionary = { .pot_emergency_free = _prop_dictionary_emergency_free, .pot_extern = _prop_dictionary_externalize, .pot_equals = _prop_dictionary_equals, + .pot_equals_finish = _prop_dictionary_equals_finish, }; static int _prop_dict_keysym_free(prop_stack_t, prop_object_t *); static bool _prop_dict_keysym_externalize( struct _prop_object_externalize_context *, void *); -static bool _prop_dict_keysym_equals(void *, void *); +static bool _prop_dict_keysym_equals(prop_object_t, prop_object_t, + void **, void **, + prop_object_t *, prop_object_t *); static const struct _prop_object_type _prop_object_type_dict_keysym = { .pot_type = PROP_TYPE_DICT_KEYSYM, @@ -236,21 +242,23 @@ _prop_dict_keysym_externalize(struct _prop_object_externalize_context *ctx, return (true); } +/* ARGSUSED */ static bool -_prop_dict_keysym_equals(void *v1, void *v2) +_prop_dict_keysym_equals(prop_object_t v1, prop_object_t v2, + void **stored_pointer1, void **stored_pointer2, + prop_object_t *next_obj1, prop_object_t *next_obj2) { prop_dictionary_keysym_t pdk1 = v1; prop_dictionary_keysym_t pdk2 = v2; - if (! (prop_object_is_dictionary_keysym(pdk1) && - prop_object_is_dictionary_keysym(pdk2))) - return (false); - /* * There is only ever one copy of a keysym at any given time, * so we can reduce this to a simple pointer equality check. */ - return (pdk1 == pdk2); + if (pdk1 == pdk2) + return _PROP_OBJECT_EQUALS_TRUE; + else + return _PROP_OBJECT_EQUALS_FALSE; } static prop_dictionary_keysym_t @@ -359,7 +367,7 @@ _prop_dictionary_free(prop_stack_t stack, prop_object_t *obj) } /* Otherwise, try to push the current object on the stack. */ - if (!_prop_stack_push(stack, pd, NULL, NULL)) { + if (!_prop_stack_push(stack, pd, NULL, NULL, NULL)) { /* Push failed, entering emergency release mode. */ return (_PROP_OBJECT_FREE_FAILED); } @@ -445,46 +453,55 @@ _prop_dictionary_externalize(struct _prop_object_externalize_context *ctx, return (rv); } +/* ARGSUSED */ static bool -_prop_dictionary_equals(void *v1, void *v2) +_prop_dictionary_equals(prop_object_t v1, prop_object_t v2, + void **stored_pointer1, void **stored_pointer2, + prop_object_t *next_obj1, prop_object_t *next_obj2) { prop_dictionary_t dict1 = v1; prop_dictionary_t dict2 = v2; - const struct _prop_dict_entry *pde1, *pde2; - unsigned int idx; - bool rv = false; - - if (! (prop_object_is_dictionary(dict1) && - prop_object_is_dictionary(dict2))) - return (false); + uintptr_t idx; + bool rv = _PROP_OBJECT_EQUALS_FALSE; if (dict1 == dict2) - return (true); + return (_PROP_OBJECT_EQUALS_TRUE); - if ((uintptr_t)dict1 < (uintptr_t)dict2) { - _PROP_RWLOCK_RDLOCK(dict1->pd_rwlock); - _PROP_RWLOCK_RDLOCK(dict2->pd_rwlock); - } else { - _PROP_RWLOCK_RDLOCK(dict2->pd_rwlock); - _PROP_RWLOCK_RDLOCK(dict1->pd_rwlock); + _PROP_ASSERT(*stored_pointer1 == *stored_pointer2); + + idx = (uintptr_t)*stored_pointer1; + + if (idx == 0) { + if ((uintptr_t)dict1 < (uintptr_t)dict2) { + _PROP_RWLOCK_RDLOCK(dict1->pd_rwlock); + _PROP_RWLOCK_RDLOCK(dict2->pd_rwlock); + } else { + _PROP_RWLOCK_RDLOCK(dict2->pd_rwlock); + _PROP_RWLOCK_RDLOCK(dict1->pd_rwlock); + } } if (dict1->pd_count != dict2->pd_count) goto out; - for (idx = 0; idx < dict1->pd_count; idx++) { - pde1 = &dict1->pd_array[idx]; - pde2 = &dict2->pd_array[idx]; - - if (prop_dictionary_keysym_equals(pde1->pde_key, - pde2->pde_key) == false) - goto out; - if (prop_object_equals(pde1->pde_objref, - pde2->pde_objref) == false) - goto out; + if (idx == dict1->pd_count) { + rv = _PROP_OBJECT_EQUALS_TRUE; + goto out; } - rv = true; + _PROP_ASSERT(idx < dict1->pd_count); + + *stored_pointer1 = (void *)(idx + 1); + *stored_pointer2 = (void *)(idx + 1); + + *next_obj1 = &dict1->pd_array[idx].pde_objref; + *next_obj2 = &dict2->pd_array[idx].pde_objref; + + if (!prop_dictionary_keysym_equals(dict1->pd_array[idx].pde_key, + dict2->pd_array[idx].pde_key)) + goto out; + + return (_PROP_OBJECT_EQUALS_RECURSE); out: _PROP_RWLOCK_UNLOCK(dict1->pd_rwlock); @@ -492,6 +509,13 @@ _prop_dictionary_equals(void *v1, void *v2) return (rv); } +static void +_prop_dictionary_equals_finish(prop_object_t v1, prop_object_t v2) +{ + _PROP_RWLOCK_UNLOCK(((prop_dictionary_t)v1)->pd_rwlock); + _PROP_RWLOCK_UNLOCK(((prop_dictionary_t)v2)->pd_rwlock); +} + static prop_dictionary_t _prop_dictionary_alloc(unsigned int capacity) { @@ -1039,8 +1063,11 @@ prop_dictionary_remove_keysym(prop_dictionary_t pd, bool prop_dictionary_equals(prop_dictionary_t dict1, prop_dictionary_t dict2) { + if (!prop_object_is_dictionary(dict1) || + !prop_object_is_dictionary(dict2)) + return (false); - return (_prop_dictionary_equals(dict1, dict2)); + return (prop_object_equals(dict1, dict2)); } /* @@ -1066,8 +1093,11 @@ bool prop_dictionary_keysym_equals(prop_dictionary_keysym_t pdk1, prop_dictionary_keysym_t pdk2) { + if (!prop_object_is_dictionary_keysym(pdk1) || + !prop_object_is_dictionary_keysym(pdk2)) + return (_PROP_OBJECT_EQUALS_FALSE); - return (_prop_dict_keysym_equals(pdk1, pdk2)); + return (prop_object_equals(pdk1, pdk2)); } /* @@ -1223,8 +1253,9 @@ _prop_dictionary_internalize_body(prop_stack_t stack, prop_object_t *obj, /* * Key is found, now wait for value to be parsed. */ - if (_prop_stack_push(stack, *obj, tmpkey, - _prop_dictionary_internalize_continue)) + if (_prop_stack_push(stack, *obj, + _prop_dictionary_internalize_continue, + tmpkey, NULL)) return (false); bad: diff --git a/common/lib/libprop/prop_number.c b/common/lib/libprop/prop_number.c index 427145874cd..1fd82b9b99a 100644 --- a/common/lib/libprop/prop_number.c +++ b/common/lib/libprop/prop_number.c @@ -1,4 +1,4 @@ -/* $NetBSD: prop_number.c,v 1.13 2007/08/16 21:44:07 joerg Exp $ */ +/* $NetBSD: prop_number.c,v 1.14 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -75,7 +75,9 @@ static int _prop_number_free(prop_stack_t, prop_object_t *); static bool _prop_number_externalize( struct _prop_object_externalize_context *, void *); -static bool _prop_number_equals(void *, void *); +static bool _prop_number_equals(prop_object_t, prop_object_t, + void **, void **, + prop_object_t *, prop_object_t *); static const struct _prop_object_type _prop_object_type_number = { .pot_type = PROP_TYPE_NUMBER, @@ -188,30 +190,29 @@ _prop_number_externalize(struct _prop_object_externalize_context *ctx, return (true); } +/* ARGSUSED */ static bool -_prop_number_equals(void *v1, void *v2) +_prop_number_equals(prop_object_t v1, prop_object_t v2, + void **stored_pointer1, void **stored_pointer2, + prop_object_t *next_obj1, prop_object_t *next_obj2) { prop_number_t num1 = v1; prop_number_t num2 = v2; - if (! (prop_object_is_number(num1) && - prop_object_is_number(num2))) - return (false); - /* * There is only ever one copy of a number object at any given * time, so we can reduce this to a simple pointer equality check * in the common case. */ if (num1 == num2) - return (true); + return (_PROP_OBJECT_EQUALS_TRUE); /* * If the numbers are the same signed-ness, then we know they * cannot be equal because they would have had pointer equality. */ if (num1->pn_value.pnv_is_unsigned == num2->pn_value.pnv_is_unsigned) - return (false); + return (_PROP_OBJECT_EQUALS_TRUE); /* * We now have one signed value and one unsigned value. We can @@ -226,20 +227,23 @@ _prop_number_equals(void *v1, void *v2) * num1 is unsigned and num2 is signed. */ if (num1->pn_value.pnv_unsigned > INT64_MAX) - return (false); + return (_PROP_OBJECT_EQUALS_FALSE); if (num2->pn_value.pnv_signed < 0) - return (false); + return (_PROP_OBJECT_EQUALS_FALSE); } else { /* * num1 is signed and num2 is unsigned. */ if (num1->pn_value.pnv_signed < 0) - return (false); + return (_PROP_OBJECT_EQUALS_FALSE); if (num2->pn_value.pnv_unsigned > INT64_MAX) - return (false); + return (_PROP_OBJECT_EQUALS_FALSE); } - return (num1->pn_value.pnv_signed == num2->pn_value.pnv_signed); + if (num1->pn_value.pnv_signed == num2->pn_value.pnv_signed) + return _PROP_OBJECT_EQUALS_TRUE; + else + return _PROP_OBJECT_EQUALS_FALSE; } static prop_number_t @@ -439,8 +443,10 @@ prop_number_unsigned_integer_value(prop_number_t pn) bool prop_number_equals(prop_number_t num1, prop_number_t num2) { + if (!prop_object_is_number(num1) || !prop_object_is_number(num2)) + return (false); - return (_prop_number_equals(num1, num2)); + return (prop_object_equals(num1, num2)); } /* diff --git a/common/lib/libprop/prop_object.c b/common/lib/libprop/prop_object.c index f1244b31bb5..e5e65679320 100644 --- a/common/lib/libprop/prop_object.c +++ b/common/lib/libprop/prop_object.c @@ -1,4 +1,4 @@ -/* $NetBSD: prop_object.c,v 1.15 2007/08/16 21:44:07 joerg Exp $ */ +/* $NetBSD: prop_object.c,v 1.16 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc. @@ -634,7 +634,7 @@ match_start: break; } if (poi == NULL) { - while (_prop_stack_pop(&stack, &obj, &data, &iter)) { + while (_prop_stack_pop(&stack, &obj, &iter, &data, NULL)) { iter_func = (prop_object_internalizer_continue_t)iter; (*iter_func)(&stack, &obj, ctx, data, NULL); } @@ -647,7 +647,7 @@ match_start: goto match_start; parent_obj = obj; - while (_prop_stack_pop(&stack, &parent_obj, &data, &iter)) { + 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; @@ -1071,7 +1071,6 @@ prop_object_release(prop_object_t obj) { struct _prop_object *po; struct _prop_stack stack; - void *dummy1, *dummy2; int ret; uint32_t ocnt; @@ -1103,7 +1102,7 @@ prop_object_release(prop_object_t obj) } while (ret == _PROP_OBJECT_FREE_RECURSE); if (ret == _PROP_OBJECT_FREE_FAILED) prop_object_release_emergency(obj); - } while (_prop_stack_pop(&stack, &obj, &dummy1, &dummy2)); + } while (_prop_stack_pop(&stack, &obj, NULL, NULL, NULL)); } /* @@ -1128,13 +1127,62 @@ prop_object_type(prop_object_t obj) bool prop_object_equals(prop_object_t obj1, prop_object_t obj2) { - struct _prop_object *po1 = obj1; - struct _prop_object *po2 = obj2; + return (prop_object_equals_with_error(obj1, obj2, NULL)); +} + +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; + int 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; + goto continue_subtree; + } + _PROP_ASSERT(ret == _PROP_OBJECT_EQUALS_RECURSE); - return ((*po1->po_type->pot_equals)(obj1, obj2)); + 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); } /* diff --git a/common/lib/libprop/prop_object_impl.h b/common/lib/libprop/prop_object_impl.h index 95fc9d51763..ed2318f34ff 100644 --- a/common/lib/libprop/prop_object_impl.h +++ b/common/lib/libprop/prop_object_impl.h @@ -1,4 +1,4 @@ -/* $NetBSD: prop_object_impl.h,v 1.17 2007/08/16 21:44:08 joerg Exp $ */ +/* $NetBSD: prop_object_impl.h,v 1.18 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -111,6 +111,12 @@ enum { _PROP_OBJECT_FREE_FAILED }; +enum { + _PROP_OBJECT_EQUALS_FALSE, + _PROP_OBJECT_EQUALS_TRUE, + _PROP_OBJECT_EQUALS_RECURSE +}; + #define _PROP_EOF(c) ((c) == '\0') #define _PROP_ISSPACE(c) \ ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' || \ @@ -190,14 +196,24 @@ struct _prop_object_type { /* * func to free the child returned by pot_free with stack == NULL. * - * Must be implemented if pot_free can return non-0. + * Must be implemented if pot_free can return anything other than + * _PROP_OBJECT_FREE_DONE. */ void (*pot_emergency_free)(prop_object_t); /* func to externalize object */ bool (*pot_extern)(struct _prop_object_externalize_context *, void *); /* func to test quality */ - bool (*pot_equals)(void *, void *); + bool (*pot_equals)(prop_object_t, prop_object_t, + void **, void **, + prop_object_t *, prop_object_t *); + /* + * func to finish equality iteration. + * + * Must be implemented if pot_equals can return + * _PROP_OBJECT_EQUALS_RECURSE + */ + void (*pot_equals_finish)(prop_object_t, prop_object_t); }; struct _prop_object { diff --git a/common/lib/libprop/prop_stack.c b/common/lib/libprop/prop_stack.c index 3b6c0c68309..a08118c2a44 100644 --- a/common/lib/libprop/prop_stack.c +++ b/common/lib/libprop/prop_stack.c @@ -1,4 +1,4 @@ -/* $NetBSD: prop_stack.c,v 1.1 2007/08/16 21:44:08 joerg Exp $ */ +/* $NetBSD: prop_stack.c,v 1.2 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. @@ -40,7 +40,8 @@ _prop_stack_init(prop_stack_t stack) } bool -_prop_stack_push(prop_stack_t stack, prop_object_t obj, void *obj_data, void *iter) +_prop_stack_push(prop_stack_t stack, prop_object_t obj, void *data1, + void *data2, void *data3) { struct _prop_stack_extern_elem *eelem; struct _prop_stack_intern_elem *ielem; @@ -52,8 +53,9 @@ _prop_stack_push(prop_stack_t stack, prop_object_t obj, void *obj_data, void *it return false; eelem->object = obj; - eelem->object_data = obj_data; - eelem->iterator = iter; + eelem->object_data[0] = data1; + eelem->object_data[1] = data2; + eelem->object_data[2] = data3; SLIST_INSERT_HEAD(&stack->extern_elems, eelem, stack_link); @@ -65,8 +67,9 @@ _prop_stack_push(prop_stack_t stack, prop_object_t obj, void *obj_data, void *it ielem = &stack->intern_elems[stack->used_intern_elems]; ielem->object = obj; - ielem->object_data = obj_data; - ielem->iterator = iter; + ielem->object_data[0] = data1; + ielem->object_data[1] = data2; + ielem->object_data[2] = data3; ++stack->used_intern_elems; @@ -74,7 +77,8 @@ _prop_stack_push(prop_stack_t stack, prop_object_t obj, void *obj_data, void *it } bool -_prop_stack_pop(prop_stack_t stack, prop_object_t *obj, void **obj_data, void **iter) +_prop_stack_pop(prop_stack_t stack, prop_object_t *obj, void **data1, + void **data2, void **data3) { struct _prop_stack_extern_elem *eelem; struct _prop_stack_intern_elem *ielem; @@ -86,9 +90,14 @@ _prop_stack_pop(prop_stack_t stack, prop_object_t *obj, void **obj_data, void ** _PROP_ASSERT(stack->used_intern_elems == PROP_STACK_INTERN_ELEMS); SLIST_REMOVE_HEAD(&stack->extern_elems, stack_link); - *obj = eelem->object; - *obj_data = eelem->object_data; - *iter = eelem->iterator; + if (obj) + *obj = eelem->object; + if (data1) + *data1 = eelem->object_data[0]; + if (data2) + *data2 = eelem->object_data[1]; + if (data3) + *data3 = eelem->object_data[2]; _PROP_FREE(eelem, M_TEMP); return true; } @@ -96,9 +105,14 @@ _prop_stack_pop(prop_stack_t stack, prop_object_t *obj, void **obj_data, void ** --stack->used_intern_elems; ielem = &stack->intern_elems[stack->used_intern_elems]; - *obj = ielem->object; - *obj_data = ielem->object_data; - *iter = ielem->iterator; + if (obj) + *obj = ielem->object; + if (data1) + *data1 = ielem->object_data[0]; + if (data2) + *data2 = ielem->object_data[1]; + if (data3) + *data3 = ielem->object_data[2]; return true; } diff --git a/common/lib/libprop/prop_stack.h b/common/lib/libprop/prop_stack.h index 4430e001dea..dca99c15279 100644 --- a/common/lib/libprop/prop_stack.h +++ b/common/lib/libprop/prop_stack.h @@ -1,4 +1,4 @@ -/* $NetBSD: prop_stack.h,v 1.1 2007/08/16 21:44:08 joerg Exp $ */ +/* $NetBSD: prop_stack.h,v 1.2 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. @@ -38,15 +38,13 @@ struct _prop_stack_intern_elem { prop_object_t object; - void *object_data; - void *iterator; + void *object_data[3]; }; struct _prop_stack_extern_elem { SLIST_ENTRY(_prop_stack_extern_elem) stack_link; prop_object_t object; - void *object_data; - void *iterator; + void *object_data[3]; }; #define PROP_STACK_INTERN_ELEMS 16 @@ -60,7 +58,7 @@ struct _prop_stack { typedef struct _prop_stack *prop_stack_t; void _prop_stack_init(prop_stack_t); -bool _prop_stack_push(prop_stack_t, prop_object_t, void *, void *); -bool _prop_stack_pop(prop_stack_t, prop_object_t *, void **, void **); +bool _prop_stack_push(prop_stack_t, prop_object_t, void *, void *, void *); +bool _prop_stack_pop(prop_stack_t, prop_object_t *, void **, void **, void **); #endif diff --git a/common/lib/libprop/prop_string.c b/common/lib/libprop/prop_string.c index 2627bd50ee8..2fdf67fbaa3 100644 --- a/common/lib/libprop/prop_string.c +++ b/common/lib/libprop/prop_string.c @@ -1,4 +1,4 @@ -/* $NetBSD: prop_string.c,v 1.8 2007/08/16 21:44:08 joerg Exp $ */ +/* $NetBSD: prop_string.c,v 1.9 2007/08/30 12:23:54 joerg Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -62,7 +62,9 @@ static int _prop_string_free(prop_stack_t, prop_object_t *); static bool _prop_string_externalize( struct _prop_object_externalize_context *, void *); -static bool _prop_string_equals(void *, void *); +static bool _prop_string_equals(prop_object_t, prop_object_t, + void **, void **, + prop_object_t *, prop_object_t *); static const struct _prop_object_type _prop_object_type_string = { .pot_type = PROP_TYPE_STRING, @@ -106,22 +108,23 @@ _prop_string_externalize(struct _prop_object_externalize_context *ctx, return (true); } +/* ARGSUSED */ static bool -_prop_string_equals(void *v1, void *v2) +_prop_string_equals(prop_object_t v1, prop_object_t v2, + void **stored_pointer1, void **stored_pointer2, + prop_object_t *next_obj1, prop_object_t *next_obj2) { prop_string_t str1 = v1; prop_string_t str2 = v2; - if (! (prop_object_is_string(str1) && - prop_object_is_string(str2))) - return (false); - if (str1 == str2) - return (true); + return (_PROP_OBJECT_EQUALS_TRUE); if (str1->ps_size != str2->ps_size) - return (false); - return (strcmp(prop_string_contents(str1), - prop_string_contents(str2)) == 0); + return (_PROP_OBJECT_EQUALS_FALSE); + if (strcmp(prop_string_contents(str1), prop_string_contents(str2))) + return (_PROP_OBJECT_EQUALS_FALSE); + else + return (_PROP_OBJECT_EQUALS_TRUE); } static prop_string_t @@ -392,8 +395,10 @@ prop_string_append_cstring(prop_string_t dst, const char *src) bool prop_string_equals(prop_string_t str1, prop_string_t str2) { + if (!prop_object_is_string(str1) || !prop_object_is_string(str2)) + return (false); - return (_prop_string_equals(str1, str2)); + return prop_object_equals(str1, str2); } /* |
