summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoerg <joerg@NetBSD.org>2007-08-30 12:23:53 +0000
committerjoerg <joerg@NetBSD.org>2007-08-30 12:23:53 +0000
commit4deb593145a6d95f78a080aefb8cfc760bcddac9 (patch)
tree798627c927bc10e7c4639b8f24a47fcdaf82600a
parentebcc6a8e1aa8ec2e8fd237a3d1512d620918c753 (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.h3
-rw-r--r--common/lib/libprop/prop_array.c77
-rw-r--r--common/lib/libprop/prop_bool.c22
-rw-r--r--common/lib/libprop/prop_data.c31
-rw-r--r--common/lib/libprop/prop_dictionary.c111
-rw-r--r--common/lib/libprop/prop_number.c36
-rw-r--r--common/lib/libprop/prop_object.c64
-rw-r--r--common/lib/libprop/prop_object_impl.h22
-rw-r--r--common/lib/libprop/prop_stack.c40
-rw-r--r--common/lib/libprop/prop_stack.h12
-rw-r--r--common/lib/libprop/prop_string.c29
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);
}
/*