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);