summaryrefslogtreecommitdiffstats
path: root/common/refarray/ref_array.c
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2010-04-21 21:10:10 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-04-30 07:51:19 -0400
commitd91d82d86a01e4fec91ab4c06b1d7687bd0a8b33 (patch)
treecfa680319da2cd32782a685e09adead759805979 /common/refarray/ref_array.c
parentcd13aab316d57c353df99962eba2fbaf13f5430f (diff)
downloadsssd-d91d82d86a01e4fec91ab4c06b1d7687bd0a8b33.tar.gz
sssd-d91d82d86a01e4fec91ab4c06b1d7687bd0a8b33.tar.xz
sssd-d91d82d86a01e4fec91ab4c06b1d7687bd0a8b33.zip
Extending refarray interface
Added functions to inert, delete, replace swap the array elements. Unit test and docs have been updated accordingly. Fixing review comments for refarray.
Diffstat (limited to 'common/refarray/ref_array.c')
-rw-r--r--common/refarray/ref_array.c197
1 files changed, 196 insertions, 1 deletions
diff --git a/common/refarray/ref_array.c b/common/refarray/ref_array.c
index d33a16b4f..d02f9aed8 100644
--- a/common/refarray/ref_array.c
+++ b/common/refarray/ref_array.c
@@ -194,7 +194,7 @@ int ref_array_append(struct ref_array *ra, void *element)
error = ref_array_grow(ra);
if (error) {
TRACE_ERROR_NUMBER("Failed to grow array.", error);
- return EINVAL;
+ return error;
}
}
@@ -272,6 +272,201 @@ uint32_t ref_array_len(struct ref_array *ra)
}
+/* Insert a new element into the array */
+int ref_array_insert(struct ref_array *ra,
+ uint32_t idx,
+ void *element)
+{
+ int error = EOK;
+ uint32_t i;
+
+ TRACE_FLOW_STRING("ref_array_insert", "Entry");
+
+ if ((!ra) || (!element)) {
+ TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
+ return EINVAL;
+ }
+
+ if (idx > ra->len) {
+ TRACE_ERROR_NUMBER("Index is out of range", ERANGE);
+ return ERANGE;
+ }
+
+ /* Do we have enough room for a new element? */
+ if (ra->size == ra->len) {
+ error = ref_array_grow(ra);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to grow array.", error);
+ return error;
+ }
+ }
+
+ /* Shift elements right */
+ for (i = ra->len; i >= (idx + 1); i--) {
+ memcpy((unsigned char *)(ra->storage) + i * ra->elsize,
+ (unsigned char *)(ra->storage) + (i - 1) * ra->elsize,
+ ra->elsize);
+ }
+
+ /* Overwrite element */
+ memcpy((unsigned char *)(ra->storage) + idx * ra->elsize,
+ element,
+ ra->elsize);
+
+ ra->len++;
+
+ TRACE_FLOW_STRING("ref_array_insert", "Exit");
+ return error;
+
+}
+
+
+/* Replace element in the array */
+int ref_array_replace(struct ref_array *ra,
+ uint32_t idx,
+ void *element)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("ref_array_replace", "Entry");
+
+ if ((!ra) || (!element)) {
+ TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
+ return EINVAL;
+ }
+
+ if (idx > ra->len) {
+ TRACE_ERROR_NUMBER("Index is out of range", ERANGE);
+ return ERANGE;
+ }
+
+ /* Clear old element */
+ ra->cb((unsigned char *)(ra->storage) + idx * ra->elsize,
+ REF_ARRAY_DELETE, ra->cb_data);
+
+ /* Overwrite element */
+ memcpy((unsigned char *)(ra->storage) + idx * ra->elsize,
+ element,
+ ra->elsize);
+
+
+ TRACE_FLOW_STRING("ref_array_replace", "Exit");
+ return error;
+}
+
+
+/* Remove element from the array */
+int ref_array_remove(struct ref_array *ra,
+ uint32_t idx)
+{
+ int error = EOK;
+ uint32_t i;
+
+ TRACE_FLOW_STRING("ref_array_remove", "Entry");
+
+ if (!ra) {
+ TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
+ return EINVAL;
+ }
+
+ if (idx >= ra->len) {
+ TRACE_ERROR_NUMBER("Index is out of range", ERANGE);
+ return ERANGE;
+ }
+
+ /* Clear old element */
+ ra->cb((unsigned char *)(ra->storage) + idx * ra->elsize,
+ REF_ARRAY_DELETE, ra->cb_data);
+
+ /* Shift elements left */
+ for (i = idx + 1; i < ra->len; i++) {
+ memcpy((unsigned char *)(ra->storage) + (i - 1) * ra->elsize,
+ (unsigned char *)(ra->storage) + i * ra->elsize,
+ ra->elsize);
+ }
+
+ ra->len--;
+
+ TRACE_FLOW_STRING("ref_array_remove", "Exit");
+ return error;
+}
+
+/* Reset array */
+void ref_array_reset(struct ref_array *ra)
+{
+ int idx;
+
+ TRACE_FLOW_STRING("ref_array_reset", "Entry");
+
+ /* Check if array is not NULL */
+ if (!ra) {
+ TRACE_ERROR_STRING("Uninitialized array.", "Coding error???");
+ return;
+ }
+
+ if (ra->cb) {
+ for (idx = 0; idx < ra->len; idx++) {
+ ra->cb((unsigned char *)(ra->storage) + idx * ra->elsize,
+ REF_ARRAY_DESTROY, ra->cb_data);
+ }
+ }
+
+ free(ra->storage);
+ ra->storage = NULL;
+ ra->size = 0;
+ ra->len = 0;
+
+ TRACE_FLOW_STRING("ref_array_reset", "Exit");
+}
+
+/* Swap two elements in the array */
+int ref_array_swap(struct ref_array *ra,
+ uint32_t idx1,
+ uint32_t idx2)
+{
+ int error = EOK;
+ void *temp = NULL;
+
+ TRACE_FLOW_STRING("ref_array_swap", "Entry");
+
+ if (!ra) {
+ TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL);
+ return EINVAL;
+ }
+
+ if ((idx1 >= ra->len) ||
+ (idx2 >= ra->len)) {
+ TRACE_ERROR_NUMBER("Index is out of range", ERANGE);
+ return ERANGE;
+ }
+
+ if (idx1 == idx2) {
+ TRACE_FLOW_STRING("ref_array_swap", "Noop return");
+ return EOK;
+ }
+
+ temp = malloc(ra->elsize);
+ if (!temp) {
+ TRACE_FLOW_STRING("Failed to allocate memory for temp storage.", "");
+ return ENOMEM;
+ }
+
+ memcpy(temp,
+ (unsigned char *)(ra->storage) + idx2 * ra->elsize,
+ ra->elsize);
+ memcpy((unsigned char *)(ra->storage) + idx2 * ra->elsize,
+ (unsigned char *)(ra->storage) + idx1 * ra->elsize,
+ ra->elsize);
+ memcpy((unsigned char *)(ra->storage) + idx1 * ra->elsize,
+ temp,
+ ra->elsize);
+
+ free(temp);
+
+ TRACE_FLOW_STRING("ref_array_swap", "Exit");
+ return error;
+}
+
/* Debug function */
void ref_array_debug(struct ref_array *ra)
{