Azure IoT common library

Dependents:   STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more

optionhandler.c

Committer:
AzureIoTClient
Date:
2016-07-29
Revision:
7:1af47e3a19b6
Child:
19:2e0811512ceb

File content as of revision 7:1af47e3a19b6:

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "azure_c_shared_utility/optionhandler.h"
#include "azure_c_shared_utility/xlogging.h"
#include "azure_c_shared_utility/gballoc.h"
#include "azure_c_shared_utility/vector.h"

typedef struct OPTION_TAG
{
    const char* name;
    void* storage;
}OPTION;

typedef struct OPTIONHANDLER_HANDLE_DATA_TAG
{
    pfCloneOption cloneOption;
    pfDestroyOption destroyOption;
    pfSetOption setOption;
    VECTOR_HANDLE storage;
}OPTIONHANDLER_HANDLE_DATA;

OPTIONHANDLER_HANDLE OptionHandler_Create(pfCloneOption cloneOption, pfDestroyOption destroyOption, pfSetOption setOption)
{
    /*Codes_SRS_OPTIONHANDLER_02_001: [ OptionHandler_Create shall fail and retun NULL if any parameters are NULL. ]*/
    OPTIONHANDLER_HANDLE_DATA* result;
    if (
        (cloneOption == NULL) ||
        (destroyOption == NULL) ||
        (setOption == NULL)
        )
    {
        LogError("invalid parameter = pfCloneOption cloneOption=%p, pfDestroyOption destroyOption=%p, pfSetOption setOption=%p", cloneOption, destroyOption, setOption);
        result = NULL;
    }
    else
    {
        result = (OPTIONHANDLER_HANDLE_DATA*)malloc(sizeof(OPTIONHANDLER_HANDLE_DATA));
        if (result == NULL)
        {
            /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/
            LogError("unable to malloc");
            /*return as is*/
        }
        else
        {
            /*Codes_SRS_OPTIONHANDLER_02_002: [ OptionHandler_Create shall create an empty VECTOR that will hold pairs of const char* and void*. ]*/
            result->storage = VECTOR_create(sizeof(OPTION));
            if (result->storage == NULL)
            {
                /*Codes_SRS_OPTIONHANDLER_02_004: [ Otherwise, OptionHandler_Create shall fail and return NULL. ]*/
                LogError("unable to VECTOR_create");
                free(result);
                result= NULL;
            }
            else
            {
                /*Codes_SRS_OPTIONHANDLER_02_003: [ If all the operations succeed then OptionHandler_Create shall succeed and return a non-NULL handle. ]*/
                result->cloneOption = cloneOption;
                result->destroyOption = destroyOption;
                result->setOption = setOption;
                /*return as is*/
            }
        }
    }
    return result;

}

OPTIONHANDLER_RESULT OptionHandler_AddOption(OPTIONHANDLER_HANDLE handle, const char* name, const void* value)
{
    OPTIONHANDLER_RESULT result;
    /*Codes_SRS_OPTIONHANDLER_02_001: [ OptionHandler_Create shall fail and retun NULL if any parameters are NULL. ]*/
    if (
        (handle == NULL) ||
        (name == NULL) ||
        (value == NULL)
        )
    {
        LogError("invalid arguments: OPTIONHANDLER_HANDLE handle=%p, const char* name=%p, void* value=%p", handle, name, value);
        result= OPTIONHANDLER_INVALIDARG;
    }
    else
    {
        const char* cloneOfName;
        if (mallocAndStrcpy_s((char**)&cloneOfName, name) != 0)
        {
            /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
            LogError("unable to clone name");
            result = OPTIONHANDLER_ERROR;
        }
        else 
        {
            /*Codes_SRS_OPTIONHANDLER_02_006: [ OptionHandler_AddProperty shall call pfCloneOption passing name and value. ]*/
            void* cloneOfValue = handle->cloneOption(name, value);
            if (cloneOfValue == NULL)
            {
                /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
                LogError("unable to clone value");
                free((void*)cloneOfName);
                result = OPTIONHANDLER_ERROR;
            }
            else
            {
                OPTION temp;
                temp.name = cloneOfName;
                temp.storage = cloneOfValue;
                /*Codes_SRS_OPTIONHANDLER_02_007: [ OptionHandler_AddProperty shall use VECTOR APIs to save the name and the newly created clone of value. ]*/
                if (VECTOR_push_back(handle->storage, &temp, 1) != 0)
                {
                    /*Codes_SRS_OPTIONHANDLER_02_009: [ Otherwise, OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_ERROR. ]*/
                    LogError("unable to VECTOR_push_back");
                    handle->destroyOption(name, cloneOfValue);
                    free((void*)cloneOfName);
                    result = OPTIONHANDLER_ERROR;
                }
                else
                {
                    /*Codes_SRS_OPTIONHANDLER_02_008: [ If all the operations succed then OptionHandler_AddProperty shall succeed and return OPTIONHANDLER_OK. ]*/
                    result = OPTIONHANDLER_OK;
                }
            }
        }
    }
    return result;
}

OPTIONHANDLER_RESULT OptionHandler_FeedOptions(OPTIONHANDLER_HANDLE handle, void* destinationHandle)
{
    OPTIONHANDLER_RESULT result;
    /*Codes_SRS_OPTIONHANDLER_02_010: [ OptionHandler_FeedOptions shall fail and return OPTIONHANDLER_INVALIDARG if any argument is NULL. ]*/
    if (
        (handle == NULL) ||
        (destinationHandle == NULL)
        )
    {
        LogError("invalid arguments OPTIONHANDLER_HANDLE handle=%p, void* destinationHandle=%p", handle, destinationHandle);
        result = OPTIONHANDLER_INVALIDARG;
    }
    else
    {
        /*Codes_SRS_OPTIONHANDLER_02_011: [ Otherwise, OptionHandler_FeedOptions shall use VECTOR's iteration mechanisms to retrieve pairs of name, value (const char* and void*). ]*/
        size_t nOptions = VECTOR_size(handle->storage), i;
        for (i = 0;i < nOptions;i++)
        {
            OPTION* option = (OPTION*)VECTOR_element(handle->storage, i);
            /*Codes_SRS_OPTIONHANDLER_02_012: [ OptionHandler_FeedOptions shall call for every pair of name,value setOption passing destinationHandle, name and value. ]*/
            if (handle->setOption(destinationHandle, option->name, option->storage) != 0)
            {
                LogError("failure while trying to _SetOption");
                break;
            }
        }
            
        if (i == nOptions)
        {
            /*Codes_SRS_OPTIONHANDLER_02_014: [ Otherwise, OptionHandler_FeedOptions shall fail and return OPTIONHANDLER_ERROR. ]*/
            result = OPTIONHANDLER_OK;
        }
        else
        {
            /*Codes_SRS_OPTIONHANDLER_02_013: [ If all the operations succeed then OptionHandler_FeedOptions shall succeed and return OPTIONHANDLER_OK. ]*/
            result = OPTIONHANDLER_ERROR;
        }
    }
    return result;
}

void OptionHandler_Destroy(OPTIONHANDLER_HANDLE handle)
{   
    /*Codes_SRS_OPTIONHANDLER_02_015: [ OptionHandler_Destroy shall do nothing if parameter handle is NULL. ]*/
    if (handle == NULL)
    {
        LogError("invalid argument OPTIONHANDLER_HANDLE handle=%p", handle);
    }
    else
    {
        /*Codes_SRS_OPTIONHANDLER_02_016: [ Otherwise, OptionHandler_Destroy shall free all used resources. ]*/
        size_t nOptions = VECTOR_size(handle->storage), i;
        for (i = 0;i < nOptions;i++)
        {
            OPTION* option = (OPTION*)VECTOR_element(handle->storage, i);
            handle->destroyOption(option->name, option->storage);
            free((void*)option->name);
        }

        VECTOR_destroy(handle->storage);
        free(handle);
    }
}