From 43c9497feb5cc3404953c8f0b637196cb392c8f9 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Thu, 13 Nov 2014 15:18:21 +0100 Subject: [PATCH] Introduce xbps_array_add_first() to insert obj at the head of array. The behaviour of this routine mimics the existing xbps_array_add() with the difference that stored objects are moved to the right to insert our object as the first element on the array. Use this to add replaced packages in the transaction array at the head rather than at the end, to preserve the proper sorting order. --- include/xbps.h.in | 2 +- include/xbps/xbps_array.h | 1 + lib/portableproplib/prop/prop_array.h | 1 + lib/portableproplib/prop_array.c | 59 +++++++++++++++++++++++++++ lib/proplib_wrapper.c | 6 +++ lib/transaction_package_replace.c | 3 +- 6 files changed, 70 insertions(+), 2 deletions(-) diff --git a/include/xbps.h.in b/include/xbps.h.in index a2544b44..aa10a95e 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -48,7 +48,7 @@ * * This header documents the full API for the XBPS Library. */ -#define XBPS_API_VERSION "20141107" +#define XBPS_API_VERSION "20141113" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" diff --git a/include/xbps/xbps_array.h b/include/xbps/xbps_array.h index 0c5c8b54..1d404baa 100644 --- a/include/xbps/xbps_array.h +++ b/include/xbps/xbps_array.h @@ -59,6 +59,7 @@ xbps_object_iterator_t xbps_array_iterator(xbps_array_t); xbps_object_t xbps_array_get(xbps_array_t, unsigned int); bool xbps_array_set(xbps_array_t, unsigned int, xbps_object_t); bool xbps_array_add(xbps_array_t, xbps_object_t); +bool xbps_array_add_first(xbps_array_t, xbps_object_t); void xbps_array_remove(xbps_array_t, unsigned int); bool xbps_array_equals(xbps_array_t, xbps_array_t); diff --git a/lib/portableproplib/prop/prop_array.h b/lib/portableproplib/prop/prop_array.h index 513299fc..684c68f6 100644 --- a/lib/portableproplib/prop/prop_array.h +++ b/lib/portableproplib/prop/prop_array.h @@ -59,6 +59,7 @@ prop_object_iterator_t prop_array_iterator(prop_array_t); prop_object_t prop_array_get(prop_array_t, unsigned int); bool prop_array_set(prop_array_t, unsigned int, prop_object_t); bool prop_array_add(prop_array_t, prop_object_t); +bool prop_array_add_first(prop_array_t, prop_object_t); void prop_array_remove(prop_array_t, unsigned int); bool prop_array_equals(prop_array_t, prop_array_t); diff --git a/lib/portableproplib/prop_array.c b/lib/portableproplib/prop_array.c index 5a4d82e0..5500dd9a 100644 --- a/lib/portableproplib/prop_array.c +++ b/lib/portableproplib/prop_array.c @@ -615,6 +615,45 @@ _prop_array_add(prop_array_t pa, prop_object_t po) return (true); } +static bool +_prop_array_add_first(prop_array_t pa, prop_object_t po) +{ + unsigned int cnt; + /* + * Array must be WRITE-LOCKED. + */ + + _PROP_ASSERT(pa->pa_count <= pa->pa_capacity); + + if (prop_array_is_immutable(pa) || + (pa->pa_count == pa->pa_capacity && + _prop_array_expand(pa, pa->pa_capacity + EXPAND_STEP) == false)) + return false; + + prop_object_retain(po); + if (pa->pa_count) { + cnt = pa->pa_count+1; + /* move all stored elements to the right */ + while (--cnt) { + prop_object_t opo = pa->pa_array[cnt-1]; + _PROP_ASSERT(opo != NULL); + prop_object_retain(opo); + pa->pa_array[cnt] = opo; + prop_object_release(opo); + printf("%s: po %p\n", __func__, pa->pa_array[cnt]); + } + /* passed in object is now the first element */ + pa->pa_array[0] = po; + pa->pa_version++; + pa->pa_count++; + printf("%s: po %p\n", __func__, pa->pa_array[0]); + } else { + pa->pa_array[pa->pa_count++] = po; + pa->pa_version++; + } + return true; +} + /* * prop_array_set -- * Store a reference to an object at the specified array index. @@ -679,6 +718,26 @@ prop_array_add(prop_array_t pa, prop_object_t po) return (rv); } +/* + * prop_array_add_first -- + * Add a reference to an object to the specified array, inserting it + * as first element, moving all objects to the right and growing the + * array's capacity, if necessary. + */ +bool +prop_array_add_first(prop_array_t pa, prop_object_t po) +{ + bool rv; + + if (! prop_object_is_array(pa)) + return (false); + + _PROP_RWLOCK_WRLOCK(pa->pa_rwlock); + rv = _prop_array_add_first(pa, po); + _PROP_RWLOCK_UNLOCK(pa->pa_rwlock); + + return (rv); +} /* * prop_array_remove -- * Remove the reference to an object from an array at the specified diff --git a/lib/proplib_wrapper.c b/lib/proplib_wrapper.c index dfbdfd62..3a8a8966 100644 --- a/lib/proplib_wrapper.c +++ b/lib/proplib_wrapper.c @@ -112,6 +112,12 @@ xbps_array_add(xbps_array_t a, xbps_object_t obj) return prop_array_add(a, obj); } +bool +xbps_array_add_first(xbps_array_t a, xbps_object_t obj) +{ + return prop_array_add_first(a, obj); +} + void xbps_array_remove(xbps_array_t a, unsigned int i) { diff --git a/lib/transaction_package_replace.c b/lib/transaction_package_replace.c index f8e6ceca..031f19a5 100644 --- a/lib/transaction_package_replace.c +++ b/lib/transaction_package_replace.c @@ -123,7 +123,8 @@ xbps_transaction_package_replace(struct xbps_handle *xhp, xbps_array_t pkgs) */ xbps_dictionary_set_cstring_nocopy(instd, "transaction", "remove"); - xbps_array_add(pkgs, instd); + if (!xbps_array_add_first(pkgs, instd)) + return EINVAL; free(curpkgname); } xbps_object_iterator_release(iter);