int amqpvalue_set_list_item()

in src/amqpvalue.c [1386:1487]


int amqpvalue_set_list_item(AMQP_VALUE value, uint32_t index, AMQP_VALUE list_item_value)
{
    int result;

    /* Codes_SRS_AMQPVALUE_01_165: [If value or list_item_value is NULL, amqpvalue_set_list_item shall fail and return a non-zero value.] */
    if (value == NULL)
    {
        LogError("NULL list value");
        result = MU_FAILURE;
    }
    else
    {
        AMQP_VALUE_DATA* value_data = (AMQP_VALUE_DATA*)value;
        if (value_data->type != AMQP_TYPE_LIST)
        {
            LogError("Value is not of type LIST");
            result = MU_FAILURE;
        }
        else
        {
            /* Codes_SRS_AMQPVALUE_01_168: [The item stored at the index-th position in the list shall be a clone of list_item_value.] */
            AMQP_VALUE cloned_item = amqpvalue_clone(list_item_value);
            if (cloned_item == NULL)
            {
                /* Codes_SRS_AMQPVALUE_01_170: [When amqpvalue_set_list_item fails due to not being able to clone the item or grow the list, the list shall not be altered.] */
                /* Codes_SRS_AMQPVALUE_01_169: [If cloning the item fails, amqpvalue_set_list_item shall fail and return a non-zero value.] */
                LogError("Could not clone list item");
                result = MU_FAILURE;
            }
            else
            {
                if (index >= value_data->value.list_value.count)
                {
                    AMQP_VALUE* new_list;
                    size_t realloc_size = safe_add_size_t((size_t)index, 1);
                    realloc_size = safe_multiply_size_t(realloc_size, sizeof(AMQP_VALUE));
                    if (realloc_size == SIZE_MAX ||
                        (new_list = (AMQP_VALUE*)realloc(value_data->value.list_value.items, realloc_size)) == NULL)
                    {
                        /* Codes_SRS_AMQPVALUE_01_170: [When amqpvalue_set_list_item fails due to not being able to clone the item or grow the list, the list shall not be altered.] */
                        LogError("Could not reallocate list storage, size:%zu", realloc_size);
                        amqpvalue_destroy(cloned_item);
                        result = MU_FAILURE;
                    }
                    else
                    {
                        uint32_t i;

                        value_data->value.list_value.items = new_list;

                        for (i = value_data->value.list_value.count; i < index; i++)
                        {
                            new_list[i] = amqpvalue_create_null();
                            if (new_list[i] == NULL)
                            {
                                LogError("Could not allocate NULL value for list entries");
                                break;
                            }
                        }

                        if (i < index)
                        {
                            /* Codes_SRS_AMQPVALUE_01_170: [When amqpvalue_set_list_item fails due to not being able to clone the item or grow the list, the list shall not be altered.] */
                            uint32_t j;

                            for (j = value_data->value.list_value.count; j < i; j++)
                            {
                                amqpvalue_destroy(new_list[j]);
                            }

                            amqpvalue_destroy(cloned_item);

                            /* Codes_SRS_AMQPVALUE_01_172: [If growing the list fails, then amqpvalue_set_list_item shall fail and return a non-zero value.] */
                            result = MU_FAILURE;
                        }
                        else
                        {
                            value_data->value.list_value.count = index + 1;
                            value_data->value.list_value.items[index] = cloned_item;

                            /* Codes_SRS_AMQPVALUE_01_164: [On success amqpvalue_set_list_item shall return 0.] */
                            result = 0;
                        }
                    }
                }
                else
                {
                    /* Codes_SRS_AMQPVALUE_01_167: [Any previous value stored at the position index in the list shall be freed by using amqpvalue_destroy.] */
                    amqpvalue_destroy(value_data->value.list_value.items[index]);

                    /* Codes_SRS_AMQPVALUE_01_163: [amqpvalue_set_list_item shall replace the item at the 0 based index-th position in the list identified by the value argument with the AMQP_VALUE specified by list_item_value.] */
                    value_data->value.list_value.items[index] = cloned_item;

                    /* Codes_SRS_AMQPVALUE_01_164: [On success amqpvalue_set_list_item shall return 0.] */
                    result = 0;
                }
            }
        }
    }

    return result;
}