Esempio n. 1
0
/**
 * 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;
}
Esempio n. 2
0
/**
 * 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;
}
Esempio n. 3
0
/**
 * 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;
}
Esempio n. 4
0
/**
 * 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;
}
Esempio n. 5
0
/**
 * 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;
}
Esempio n. 6
0
/**
 * 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;
}
Esempio n. 7
0
/**
 * 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;
}