void CAParseURI(const char* uriInfo, coap_list_t **optlist)
{
    OIC_LOG(DEBUG, TAG, "parse URI");

    unsigned char portbuf[2];
    unsigned char _buf[CA_BUFSIZE];
    unsigned char *buf = _buf;
    coap_uri_t uri;
    size_t buflen;
    uint32_t res;

    OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);

    /* split arg into Uri-* options */
    coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);

    if (uri.port != COAP_DEFAULT_PORT)
    {
        coap_insert(optlist,
                CACreateNewOptionNode(COAP_OPTION_URI_PORT,
                        coap_encode_var_bytes(portbuf, uri.port), portbuf), CAOrderOpts);
    }

    if (uri.path.length)
    {
        buflen = CA_BUFSIZE;
        res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);

        while (res--)
        {
            coap_insert(optlist,
                    CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf),
                            COAP_OPT_VALUE(buf)), CAOrderOpts);
            buf += COAP_OPT_SIZE(buf);
        }
    }

    if (uri.query.length)
    {
        buflen = CA_BUFSIZE;
        buf = _buf;
        res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);

        while (res--)
        {
            coap_insert(optlist,
                    CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf),
                            COAP_OPT_VALUE(buf)), CAOrderOpts);

            buf += COAP_OPT_SIZE(buf);
        }
    }

}
CAResult_t CAParseUriPartial(const unsigned char *str, size_t length, int target,
                             coap_list_t **optlist)
{
    if (!optlist)
    {
        OIC_LOG(ERROR, TAG, "optlist is null");
        return CA_STATUS_INVALID_PARAM;
    }

    if ((target != COAP_OPTION_URI_PATH) && (target != COAP_OPTION_URI_QUERY))
    {
        // should never occur. Log just in case.
        OIC_LOG(DEBUG, TAG, "Unexpected URI component.");
        return CA_NOT_SUPPORTED;
    }
    else if (str && length)
    {
        unsigned char uriBuffer[CA_BUFSIZE] = { 0 };
        unsigned char *pBuf = uriBuffer;
        size_t buflen = sizeof(uriBuffer);
        int res = (target == COAP_OPTION_URI_PATH) ? coap_split_path(str, length, pBuf, &buflen) :
                  coap_split_query(str, length, pBuf, &buflen);

        if (res > 0)
        {
            size_t prevIdx = 0;
            while (res--)
            {
                int ret = coap_insert(optlist,
                                      CACreateNewOptionNode(target, COAP_OPT_LENGTH(pBuf),
                                              (char *)COAP_OPT_VALUE(pBuf)),
                                      CAOrderOpts);
                if (ret <= 0)
                {
                    return CA_STATUS_INVALID_PARAM;
                }

                size_t optSize = COAP_OPT_SIZE(pBuf);
                if ((prevIdx + optSize) < buflen)
                {
                    pBuf += optSize;
                    prevIdx += optSize;
                }
            }
        }
        else
        {
            OIC_LOG_V(ERROR, TAG, "Problem parsing URI : %d for %d", res, target);
            return CA_STATUS_FAILED;
        }
    }
    else
    {
        OIC_LOG(ERROR, TAG, "str or length is not available");
        return CA_STATUS_FAILED;
    }

    return CA_STATUS_OK;
}
void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)
{
    OIC_LOG_V(DEBUG, TAG, "start parse Head Option : %d", info.numOptions);

    uint32_t i;
    for (i = 0; i < info.numOptions; i++)
    {
        coap_insert(optlist,
                CACreateNewOptionNode(info.options->optionID, info.options->optionLength,
                        info.options->optionData), CAOrderOpts);
    }
}
CAResult_t CAParseHeadOption(uint32_t code, const CAInfo_t *info, coap_list_t **optlist)
{
    (void)code;
    OIC_LOG(DEBUG, TAG, "IN");
    VERIFY_NON_NULL_RET(info, TAG, "info is NULL", CA_STATUS_INVALID_PARAM);

    OIC_LOG_V(DEBUG, TAG, "parse Head Opt: %d", info->numOptions);

    if (!optlist)
    {
        OIC_LOG(ERROR, TAG, "optlist is null");
        return CA_STATUS_INVALID_PARAM;
    }

    for (uint32_t i = 0; i < info->numOptions; i++)
    {
        if(!(info->options + i))
        {
            OIC_LOG(ERROR, TAG, "options is not available");
            return CA_STATUS_FAILED;
        }

        uint32_t id = (info->options + i)->optionID;
        if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id)
        {
            OIC_LOG_V(DEBUG, TAG, "not Header Opt: %d", id);
        }
        else
        {
            if ((info->options + i)->optionData && (info->options + i)->optionLength > 0)
            {
                OIC_LOG_V(DEBUG, TAG, "Head opt ID: %d", id);
                OIC_LOG_V(DEBUG, TAG, "Head opt data: %s", (info->options + i)->optionData);
                OIC_LOG_V(DEBUG, TAG, "Head opt length: %d", (info->options + i)->optionLength);
                int ret = coap_insert(optlist,
                                      CACreateNewOptionNode(id, (info->options + i)->optionLength,
                                              (info->options + i)->optionData),
                                      CAOrderOpts);
                if (ret <= 0)
                {
                    return CA_STATUS_INVALID_PARAM;
                }
            }
        }
    }

    // insert one extra header with the payload format if applicable.
    if (CA_FORMAT_UNDEFINED != info->payloadFormat)
    {
        coap_list_t* node = NULL;
        uint8_t buf[3] = {0};
        switch (info->payloadFormat) {
        case CA_FORMAT_CBOR:
            node = CACreateNewOptionNode(
                       COAP_OPTION_CONTENT_FORMAT,
                       coap_encode_var_bytes(buf, (uint16_t)COAP_MEDIATYPE_APPLICATION_CBOR),
                       (char *)buf);
            break;
        default:
            OIC_LOG_V(ERROR, TAG, "format option:[%d] not supported", info->payloadFormat);
        }
        if (!node)
        {
            OIC_LOG(ERROR, TAG, "format option not created");
            return CA_STATUS_INVALID_PARAM;
        }
        int ret = coap_insert(optlist, node, CAOrderOpts);
        if (ret <= 0)
        {
            coap_delete(node);
            OIC_LOG(ERROR, TAG, "format option not inserted in header");
            return CA_STATUS_INVALID_PARAM;
        }
    }

    OIC_LOG(DEBUG, TAG, "OUT");
    return CA_STATUS_OK;
}
CAResult_t CAParseURI(const char *uriInfo, coap_list_t **optlist)
{
    OIC_LOG(DEBUG, TAG, "IN");

    if (NULL == uriInfo)
    {
        OIC_LOG(ERROR, TAG, "uriInfo is null");
        return CA_STATUS_INVALID_PARAM;
    }

    OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo);

    if (NULL == optlist)
    {
        OIC_LOG(ERROR, TAG, "optlist is null");
        return CA_STATUS_INVALID_PARAM;
    }

    /* split arg into Uri-* options */
    coap_uri_t uri;
    coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);

    if (uri.port != COAP_DEFAULT_PORT)
    {
        unsigned char portbuf[CA_PORT_BUFFER_SIZE] = { 0 };
        int ret = coap_insert(optlist,
                              CACreateNewOptionNode(COAP_OPTION_URI_PORT,
                                      coap_encode_var_bytes(portbuf, uri.port),
                                      (char *)portbuf),
                              CAOrderOpts);
        if (ret <= 0)
        {
            return CA_STATUS_INVALID_PARAM;
        }
    }

    if (uri.path.s && uri.path.length)
    {
        CAResult_t ret = CAParseUriPartial(uri.path.s, uri.path.length,
                                           COAP_OPTION_URI_PATH, optlist);
        if (CA_STATUS_OK != ret)
        {
            OIC_LOG(ERROR, TAG, "CAParseUriPartial failed(uri path)");
            return ret;
        }
    }

    if (uri.query.s && uri.query.length)
    {
        CAResult_t ret = CAParseUriPartial(uri.query.s, uri.query.length, COAP_OPTION_URI_QUERY,
                                           optlist);
        if (CA_STATUS_OK != ret)
        {
            OIC_LOG(ERROR, TAG, "CAParseUriPartial failed(uri query)");
            return ret;
        }
    }

    OIC_LOG(DEBUG, TAG, "OUT");
    return CA_STATUS_OK;
}