/** * Adds a new element to the array at a specified position by shifting all * subsequent elements by one. The specified index must be within the bounds * of the array. This function may also fail if the memory allocation for * the new element was unsuccessful. * * @param[in] ar the array to which the element is being added * @param[in] element the element that is being added * @param[in] index the position in the array at which the element is being * added * * @return CC_OK if the element was successfully added, CC_ERR_OUT_OF_RANGE if * the specified index was not in range, CC_ERR_ALLOC if the memory * allocation for the new element failed, or CC_ERR_MAX_CAPACITY if the * array is already at maximum capacity. */ enum cc_stat array_add_at(Array *ar, void *element, size_t index) { if (index == ar->size) return array_add(ar, element); if ((ar->size == 0 && index != 0) || index > (ar->size - 1)) return CC_ERR_OUT_OF_RANGE; if (ar->size >= ar->capacity) { enum cc_stat status = expand_capacity(ar); if (status != CC_OK) return status; } size_t shift = (ar->size - index) * sizeof(void*); memmove(&(ar->buffer[index + 1]), &(ar->buffer[index]), shift); ar->buffer[index] = element; ar->size++; return CC_OK; }
/** * Adds a new element pair to the arrays after the last returned element pair by * <code>array_zip_iter_next()</code> and immediately before an element pair * that would be returned by a subsequent call to <code>array_zip_iter_next()</code> * without invalidating the iterator. * * @param[in] iter iterator on which this operation is being performed * @param[in] e1 element added to the first array * @param[in] e2 element added to the second array * * @return CC_OK if the element pair was successfully added to the arrays, or * CC_ERR_ALLOC if the memory allocation for the new elements failed. */ enum cc_stat array_zip_iter_add(ArrayZipIter *iter, void *e1, void *e2) { size_t index = iter->index++; Array *ar1 = iter->ar1; Array *ar2 = iter->ar2; /* Make sure both array buffers have room */ if ((ar1->size == ar1->capacity && (expand_capacity(ar1) != CC_OK)) || (ar2->size == ar2->capacity && (expand_capacity(ar2) != CC_OK))) return CC_ERR_ALLOC; array_add_at(ar1, e1, index); array_add_at(ar2, e2, index); return CC_OK; }
/** * Adds a new element to the back of the Deque. * * @param[in] deque the Deque to which the element is being added * @param[in] element the element that is being added * * @return CC_OK if the element was successfully added, or CC_ERR_ALLOC if the * memory allocation for the new element has failed. */ enum cc_stat deque_add_last(Deque *deque, void *element) { if (deque->capacity == deque->size && expand_capacity(deque) != CC_OK) return CC_ERR_ALLOC; deque->buffer[deque->last] = element; deque->last = (deque->last + 1) & (deque->capacity - 1); deque->size++; return CC_OK; }
/** * Adds a new element pair to the deques after the last returned element pair by * <code>deque_zip_iter_next()</code> and immediately before an element pair * that would be returned by a subsequent call to <code>deque_zip_iter_next()</code> * without invalidating the iterator. * * @param[in] iter Iterator on which this operation is being performed * @param[in] e1 element added to the first deque * @param[in] e2 element added to the second deque * * @return CC_OK if the element pair was successfully added to the deques, or * CC_ERR_ALLOC if the memory allocation for the new elements failed. */ enum cc_stat deque_zip_iter_add(DequeZipIter *iter, void *e1, void *e2) { if (iter->index >= iter->d1->size || iter->index >= iter->d2->size) return CC_ERR_OUT_OF_RANGE; /* While this check is performed by a call to deque_add_at, it is necessary to know in advance whether both deque buffers have enough room before inserting new elements because this operation must insert either both elements, or none.*/ if ((iter->d1->capacity == iter->d1->size && expand_capacity(iter->d1) != CC_OK) && (iter->d2->capacity == iter->d2->size && expand_capacity(iter->d2) != CC_OK)) { return CC_ERR_ALLOC; } /* The retun status can be ignored since the checks have already been made. */ deque_add_at(iter->d1, e1, iter->index); deque_add_at(iter->d2, e2, iter->index); iter->index++; return CC_OK; }
/** * Adds a new element to the back of the deque. This function returns a * <code>bool</code> based on whether the memory allocation for the new element * was successful or not. * * @param[in] deque the deque to which the element is being added * @param[in] element the element that is being added * * @return true if the operation was successful */ bool deque_add_last(Deque *deque, void *element) { if (deque->capacity == deque->size && !expand_capacity(deque)) return false; deque->buffer[deque->last] = element; deque->last = (deque->last + 1) & (deque->capacity - 1); deque->size++; return true; }
/** * Adds a new element to the Array. The element is appended to the array making * it the last element (the one with the highest index) of the Array. * * @param[in] ar the array to which the element is being added * @param[in] element the element that is being added * * @return CC_OK if the element was successfully added, CC_ERR_ALLOC if the * memory allocation for the new element failed, or CC_ERR_MAX_CAPACITY if the * array is already at maximum capacity. */ enum cc_stat array_add(Array *ar, void *element) { if (ar->size >= ar->capacity) { enum cc_stat status = expand_capacity(ar); if (status != CC_OK) return status; } ar->buffer[ar->size] = element; ar->size++; return CC_OK; }
/** * Inserts a new element at the specified index within the deque. The index * must be within the range of the Deque. * * @param[in] deque Deque to which this new element is being added * @param[in] element element that is being added * @param[in] index position within the Deque at which this new element is * is being added * * @return CC_OK if the element was successfully added, CC_ERR_OUT_OF_RANGE if * the specified index was not in range, or CC_ERR_ALLOC if the memory * allocation for the new element failed. */ enum cc_stat deque_add_at(Deque *deque, void *element, size_t index) { if (index >= deque->size) return CC_ERR_OUT_OF_RANGE; if (deque->capacity == deque->size && expand_capacity(deque) != CC_OK) return CC_ERR_ALLOC; const size_t c = deque->capacity - 1; const size_t l = deque->last & c; const size_t f = deque->first & c; const size_t p = (deque->first + index) & c; if (index == 0) return deque_add_first(deque, element); if (index == c) return deque_add_last(deque, element); if (index <= (deque->size / 2) - 1) { if (p < f || f == 0) { /* _________________________________ * | 1 | 2 | 3 | 4 | 5 | . | . | 6 | * --------------------------------- * (p) <-- L F * * Left circular shift from (p) */ const size_t r_move = (f != 0) ? c - f + 1 : 0; const size_t l_move = p; void *e_first = deque->buffer[0]; if (f != 0) { memmove(&(deque->buffer[f - 1]), &(deque->buffer[f]), r_move * sizeof(void*)); } if (p != 0) { memmove(&(deque->buffer[0]), &(deque->buffer[1]), l_move * sizeof(void*)); } deque->buffer[c] = e_first; } else { memmove(&(deque->buffer[f - 1]), &(deque->buffer[f]), index * sizeof(void*)); } deque->first = (deque->first - 1) & c; } else { if (p > l || l == c) { /* _________________________________ * | 1 | . | . | 6 | 5 | 4 | 3 | 2 | * --------------------------------- * L F (p) --> * * Circular right shift from (p) */ void* e_last = deque->buffer[c]; if (p != c) { memmove(&(deque->buffer[p + 1]), &(deque->buffer[p]), (c - p) * sizeof(void*)); } if (l != c) { memmove(&(deque->buffer[1]), &(deque->buffer[0]), (l + 1) * sizeof(void*)); } deque->buffer[0] = e_last; } else { memmove(&(deque->buffer[p + 1]), &(deque->buffer[p]), (deque->size - index) * sizeof(void*)); } deque->last = (deque->last + 1) & c; } deque->buffer[p] = element; deque->size++; return CC_OK; }