int amqpvalue_set_map_value()

in src/amqpvalue.c [1548:1651]


int amqpvalue_set_map_value(AMQP_VALUE map, AMQP_VALUE key, AMQP_VALUE value)
{
    int result;

    /* Codes_SRS_AMQPVALUE_01_183: [If any of the arguments are NULL, amqpvalue_set_map_value shall fail and return a non-zero value.] */
    if ((map == NULL) ||
        (key == NULL) ||
        (value == NULL))
    {
        LogError("Bad arguments: map = %p, key = %p, value = %p",
            map, key, value);
        result = MU_FAILURE;
    }
    else
    {
        AMQP_VALUE_DATA* value_data = (AMQP_VALUE_DATA*)map;

        /* Codes_SRS_AMQPVALUE_01_196: [If the map argument is not an AMQP value created with the amqpvalue_create_map function than amqpvalue_set_map_value shall fail and return a non-zero value.] */
        if (value_data->type != AMQP_TYPE_MAP)
        {
            LogError("Value is not of type MAP");
            result = MU_FAILURE;
        }
        else
        {
            AMQP_VALUE cloned_value;

            /* Codes_SRS_AMQPVALUE_01_185: [When storing the key or value, their contents shall be cloned.] */
            cloned_value = amqpvalue_clone(value);
            if (cloned_value == NULL)
            {
                /* Codes_SRS_AMQPVALUE_01_188: [If cloning the value fails, amqpvalue_set_map_value shall fail and return a non-zero value.] */
                LogError("Could not clone value to set in the map");
                result = MU_FAILURE;
            }
            else
            {
                uint32_t i;
                AMQP_VALUE cloned_key;

                for (i = 0; i < value_data->value.map_value.pair_count; i++)
                {
                    if (amqpvalue_are_equal(value_data->value.map_value.pairs[i].key, key))
                    {
                        LogError("Could not allocate NULL value for map entries");
                        break;
                    }
                }

                if (i < value_data->value.map_value.pair_count)
                {
                    /* Codes_SRS_AMQPVALUE_01_184: [If the key already exists in the map, its value shall be replaced with the value provided by the value argument.] */
                    /* Codes_SRS_AMQPVALUE_01_125: [A map in which there exist two identical key values is invalid.] */
                    amqpvalue_destroy(value_data->value.map_value.pairs[i].value);
                    value_data->value.map_value.pairs[i].value = cloned_value;

                    /* Codes_SRS_AMQPVALUE_01_182: [On success amqpvalue_set_map_value shall return 0.] */
                    result = 0;
                }
                else
                {
                    /* Codes_SRS_AMQPVALUE_01_185: [When storing the key or value, their contents shall be cloned.] */
                    cloned_key = amqpvalue_clone(key);
                    if (cloned_key == NULL)
                    {
                        /* Codes_SRS_AMQPVALUE_01_187: [If cloning the key fails, amqpvalue_set_map_value shall fail and return a non-zero value.] */
                        amqpvalue_destroy(cloned_value);
                        LogError("Could not clone key for map");
                        result = MU_FAILURE;
                    }
                    else
                    {
                        AMQP_MAP_KEY_VALUE_PAIR* new_pairs;
                        size_t realloc_size = safe_add_size_t((size_t)value_data->value.map_value.pair_count, 1);
                        realloc_size = safe_multiply_size_t(realloc_size, sizeof(AMQP_MAP_KEY_VALUE_PAIR));
                        if (realloc_size == SIZE_MAX ||
                            (new_pairs = (AMQP_MAP_KEY_VALUE_PAIR*)realloc(value_data->value.map_value.pairs, realloc_size)) == NULL)
                        {
                            /* Codes_SRS_AMQPVALUE_01_186: [If allocating memory to hold a new key/value pair fails, amqpvalue_set_map_value shall fail and return a non-zero value.] */
                            amqpvalue_destroy(cloned_key);
                            amqpvalue_destroy(cloned_value);
                            LogError("Could not reallocate memory for new_pairs map, size:%zu", realloc_size);
                            result = MU_FAILURE;
                        }
                        else
                        {
                            value_data->value.map_value.pairs = new_pairs;

                            /* Codes_SRS_AMQPVALUE_01_181: [amqpvalue_set_map_value shall set the value in the map identified by the map argument for a key/value pair identified by the key argument.] */
                            value_data->value.map_value.pairs[value_data->value.map_value.pair_count].key = cloned_key;
                            value_data->value.map_value.pairs[value_data->value.map_value.pair_count].value = cloned_value;
                            value_data->value.map_value.pair_count++;

                            /* Codes_SRS_AMQPVALUE_01_182: [On success amqpvalue_set_map_value shall return 0.] */
                            result = 0;
                        }
                    }
                }
            }
        }
    }

    return result;
}