AGENT_DATA_TYPES_RESULT AgentDataTypes_ToString()

in serializer/src/agenttypesystem.c [1240:2247]


AGENT_DATA_TYPES_RESULT AgentDataTypes_ToString(STRING_HANDLE destination, const AGENT_DATA_TYPE* value)
{
    AGENT_DATA_TYPES_RESULT result;

    if(destination == NULL)
    {
        result = AGENT_DATA_TYPES_INVALID_ARG;
        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
    }
    else if (value == NULL)
    {
        result = AGENT_DATA_TYPES_INVALID_ARG;
        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
    }
    else
    {
        switch(value->type)
        {
            default:
            {
                result = AGENT_DATA_TYPES_INVALID_ARG;
                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                break;
            }
        case(EDM_NULL_TYPE) :
            {
                /*SRS_AGENT_TYPE_SYSTEM_99_101:[ EDM_NULL_TYPE shall return the unquoted string null.]*/
                if (STRING_concat(destination, "null") != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
        case(EDM_BOOLEAN_TYPE) :
            {
                if (value->value.edmBoolean.value == EDM_TRUE)
                {
                    /*SRS_AGENT_TYPE_SYSTEM_99_030:[If v is different than 0 then the AGENT_DATA_TYPE shall have the value "true".]*/
                    if (STRING_concat(destination, "true") != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                }
                else if (value->value.edmBoolean.value == EDM_FALSE)
                {
                    if (STRING_concat(destination, "false") != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                }
                else
                {
                    result = AGENT_DATA_TYPES_INVALID_ARG;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }

                break;
            }
            case(EDM_BYTE_TYPE) :
            {
                char tempbuffer2[4]; /*because bytes can at most be 255 and that is 3 characters + 1 for '\0'*/
                size_t pos = 0;
                if (value->value.edmByte.value >= 100) tempbuffer2[pos++] = '0' + (value->value.edmByte.value / 100);
                if (value->value.edmByte.value >= 10) tempbuffer2[pos++] = '0' + (value->value.edmByte.value % 100) / 10;
                tempbuffer2[pos++] = '0' + (value->value.edmByte.value % 10);
                tempbuffer2[pos++] = '\0';

                if (STRING_concat(destination, tempbuffer2) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
            case(EDM_DATE_TYPE) :
            {
                size_t pos = 0;
                char tempBuffer2[1 + 5 + 1 + 2 + 1 + 2 + 1+1];
                int16_t year = value->value.edmDate.year;
                tempBuffer2[pos++] = '\"';
                if (year < 0)
                {
                    tempBuffer2[pos++] = '-';
                    year = -year;
                }

                tempBuffer2[pos++] = '0' + (char)(year / 1000);
                tempBuffer2[pos++] = '0' + (char)((year % 1000) / 100);
                tempBuffer2[pos++] = '0' + (char)((year % 100) / 10);
                tempBuffer2[pos++] = '0' + (char)(year % 10);
                tempBuffer2[pos++] = '-';
                tempBuffer2[pos++] = '0' + value->value.edmDate.month / 10;
                tempBuffer2[pos++] = '0' + value->value.edmDate.month % 10;
                tempBuffer2[pos++] = '-';
                tempBuffer2[pos++] = '0' + value->value.edmDate.day / 10;
                tempBuffer2[pos++] = '0' + value->value.edmDate.day % 10;
                tempBuffer2[pos++] = '\"';
                tempBuffer2[pos++] = '\0';

                if (STRING_concat(destination, tempBuffer2) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
            case (EDM_DATE_TIME_OFFSET_TYPE):
            {
                /*from ABNF seems like these numbers HAVE to be padded with zeroes*/
                if (value->value.edmDateTimeOffset.hasTimeZone)
                {
                    if (value->value.edmDateTimeOffset.hasFractionalSecond)
                    {
                        size_t tempBufferSize = 1 + // \"
                            MAX_LONG_STRING_LENGTH + // %.4d
                            1 + // -
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // -
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // T
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // .
                            MAX_ULONG_LONG_STRING_LENGTH + // %.12llu
                            1 + MAX_LONG_STRING_LENGTH + // %+.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + //\"
                            1;  // " (terminating NULL);

                        char* tempBuffer = (char*)malloc(tempBufferSize);
                        if (tempBuffer == NULL)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else
                        {
                            if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.12llu%+.2d:%.2d\"", /*+ in printf forces the sign to appear*/
                                value->value.edmDateTimeOffset.dateTime.tm_year+1900,
                                value->value.edmDateTimeOffset.dateTime.tm_mon+1,
                                value->value.edmDateTimeOffset.dateTime.tm_mday,
                                value->value.edmDateTimeOffset.dateTime.tm_hour,
                                value->value.edmDateTimeOffset.dateTime.tm_min,
                                value->value.edmDateTimeOffset.dateTime.tm_sec,
                                value->value.edmDateTimeOffset.fractionalSecond,
                                value->value.edmDateTimeOffset.timeZoneHour,
                                value->value.edmDateTimeOffset.timeZoneMinute) < 0)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else if (STRING_concat(destination, tempBuffer) != 0)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else
                            {
                                result = AGENT_DATA_TYPES_OK;
                            }

                            // Clean up temp buffer if allocated
                            free(tempBuffer);
                        }
                    }
                    else
                    {
                        size_t tempBufferSize = 1 + // \"
                            MAX_LONG_STRING_LENGTH + // %.4d
                            1 + // -
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // -
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // T
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + MAX_LONG_STRING_LENGTH + // %+.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // \"
                            1; // " terminating NULL
                        char* tempBuffer = (char*)malloc(tempBufferSize);

                        if (tempBuffer == NULL)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else
                        {
                            if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d%+.2d:%.2d\"", /*+ in printf forces the sign to appear*/
                                value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
                                value->value.edmDateTimeOffset.dateTime.tm_mon+1,
                                value->value.edmDateTimeOffset.dateTime.tm_mday,
                                value->value.edmDateTimeOffset.dateTime.tm_hour,
                                value->value.edmDateTimeOffset.dateTime.tm_min,
                                value->value.edmDateTimeOffset.dateTime.tm_sec,
                                value->value.edmDateTimeOffset.timeZoneHour,
                                value->value.edmDateTimeOffset.timeZoneMinute) < 0)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else if (STRING_concat(destination, tempBuffer) != 0)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else
                            {
                                result = AGENT_DATA_TYPES_OK;
                            }

                            // Clean up temp buffer if allocated
                            free(tempBuffer);
                        }
                    }
                }
                else
                {
                    if (value->value.edmDateTimeOffset.hasFractionalSecond)
                    {
                        size_t tempBufferSize = 1 + //\"
                            MAX_LONG_STRING_LENGTH + // %.4d
                            1 + // -
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // -
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // T
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // .
                            MAX_ULONG_LONG_STRING_LENGTH + // %.12llu
                            1 + // Z
                            1 + // \"
                            1; // " (terminating NULL)
                        char* tempBuffer = (char*)malloc(tempBufferSize);

                        if (tempBuffer == NULL)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else
                        {
                            if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.12lluZ\"", /*+ in printf forces the sign to appear*/
                                value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
                                value->value.edmDateTimeOffset.dateTime.tm_mon+1,
                                value->value.edmDateTimeOffset.dateTime.tm_mday,
                                value->value.edmDateTimeOffset.dateTime.tm_hour,
                                value->value.edmDateTimeOffset.dateTime.tm_min,
                                value->value.edmDateTimeOffset.dateTime.tm_sec,
                                value->value.edmDateTimeOffset.fractionalSecond) < 0)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else if (STRING_concat(destination, tempBuffer) != 0)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else
                            {
                                result = AGENT_DATA_TYPES_OK;
                            }

                            free(tempBuffer);
                        }
                    }
                    else
                    {
                        size_t tempBufferSize = 1 + // \"
                            MAX_LONG_STRING_LENGTH + // %.4d
                            1 + // -
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // -
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // T
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // :
                            MAX_LONG_STRING_LENGTH + // %.2d
                            1 + // Z
                            1 + // \"
                            1; // " (terminating null);

                        char* tempBuffer = (char*)malloc(tempBufferSize);

                        if (tempBuffer == NULL)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else
                        {
                            if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ\"",
                                value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
                                value->value.edmDateTimeOffset.dateTime.tm_mon+1,
                                value->value.edmDateTimeOffset.dateTime.tm_mday,
                                value->value.edmDateTimeOffset.dateTime.tm_hour,
                                value->value.edmDateTimeOffset.dateTime.tm_min,
                                value->value.edmDateTimeOffset.dateTime.tm_sec) < 0)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else if (STRING_concat(destination, tempBuffer) != 0)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else
                            {
                                result = AGENT_DATA_TYPES_OK;
                            }

                            free(tempBuffer);
                        }
                    }
                }
                break;
            }
            case(EDM_DECIMAL_TYPE) :
            {
                if (STRING_concat_with_STRING(destination, value->value.edmDecimal.value) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
            case (EDM_INT16_TYPE) :
            {
                /*-32768 to +32767*/
                char buffertemp2[7]; /*because 5 digits and sign and '\0'*/
                uint16_t positiveValue;
                size_t pos = 0;
                uint16_t rank = (uint16_t)10000;
                bool foundFirstDigit = false;

                if (value->value.edmInt16.value < 0)
                {
                    buffertemp2[pos++] = '-';
                    positiveValue = -value->value.edmInt16.value;
                }
                else
                {
                    positiveValue = value->value.edmInt16.value;
                }

                while (rank >= 10)
                {
                    if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
                    {
                        buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
                        foundFirstDigit = true;
                    }
                    positiveValue %= rank;
                    rank /= 10;
                }
                buffertemp2[pos++] = '0' + (char)(positiveValue);
                buffertemp2[pos++] = '\0';

                if (STRING_concat(destination, buffertemp2) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
            case (EDM_INT32_TYPE) :
            {
                /*-2147483648 to +2147483647*/
                char buffertemp2[12]; /*because 10 digits and sign and '\0'*/
                uint32_t positiveValue;
                size_t pos = 0;
                uint32_t rank = 1000000000UL;
                bool foundFirstDigit = false;

                if (value->value.edmInt32.value < 0)
                {
                    buffertemp2[pos++] = '-';
                    positiveValue = - value->value.edmInt32.value;
                }
                else
                {
                    positiveValue = value->value.edmInt32.value;
                }

                while (rank >= 10)
                {
                    if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
                    {
                        buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
                        foundFirstDigit = true;
                    }
                    positiveValue %= rank;
                    rank /= 10;
                }
                buffertemp2[pos++] = '0' + (char)(positiveValue);
                buffertemp2[pos++] = '\0';

                if (STRING_concat(destination, buffertemp2) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
            case (EDM_INT64_TYPE):
            {
                char buffertemp2[21]; /*because 19 digits and sign and '\0'*/
                uint64_t positiveValue;
                size_t pos = 0;
                uint64_t rank = 10000000000000000000ULL;
                bool foundFirstDigit = false;

                if (value->value.edmInt64.value < 0)
                {
                    buffertemp2[pos++] = '-';
                    positiveValue = -value->value.edmInt64.value;
                }
                else
                {
                    positiveValue = value->value.edmInt64.value;
                }

                while (rank >= 10)
                {
                    if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
                    {
                        buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
                        foundFirstDigit = true;
                    }
                    positiveValue %= rank;
                    rank /= 10;
                }
                buffertemp2[pos++] = '0' + (char)(positiveValue);
                buffertemp2[pos++] = '\0';

                if (STRING_concat(destination, buffertemp2) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
            case (EDM_SBYTE_TYPE) :
            {
                char tempbuffer2[5]; /* because '-' and 3 characters for 127 let's say and '\0'*/
                int absValue = value->value.edmSbyte.value;
                size_t pos=0;

                if (value->value.edmSbyte.value < 0)
                {
                    tempbuffer2[pos++] = '-';
                    absValue = -absValue;
                }

                if (absValue >= 100 ) tempbuffer2[pos++] = '0' + (char)(absValue / 100);
                if (absValue >=10) tempbuffer2[pos++] = '0' + (absValue % 100) / 10;
                tempbuffer2[pos++] = '0' + (absValue % 10);
                tempbuffer2[pos++] = '\0';


                if (STRING_concat(destination, tempbuffer2) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
            case (EDM_STRING_TYPE):
            {
                size_t i;
                size_t nControlCharacters = 0; /*counts how many characters are to be expanded from 1 character to \uxxxx (6 characters)*/
                size_t nEscapeCharacters = 0;
                size_t vlen = value->value.edmString.length;
                char* v = value->value.edmString.chars;

                for (i = 0; i < vlen; i++)
                {
                    if ((unsigned char)v[i] >= 128) /*this be a UNICODE character begin*/
                    {
                        break;
                    }
                    else
                    {
                        if (v[i] <= 0x1F)
                        {
                            nControlCharacters++;
                        }
                        else if (
                            (v[i] == '"') ||
                            (v[i] == '\\') ||
                            (v[i] == '/')
                            )
                        {
                            nEscapeCharacters++;
                        }
                    }
                }

                if (i < vlen)
                {
                    result = AGENT_DATA_TYPES_INVALID_ARG; /*don't handle those who do not copy bit by bit to UTF8*/
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    /*forward parse the string to scan for " and for \ that in JSON are \" respectively \\*/
                    size_t tempBufferSize = vlen + 5 * nControlCharacters + nEscapeCharacters + 3 + 1;
                    char* tempBuffer = (char*)malloc(tempBufferSize);
                    if (tempBuffer == NULL)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        size_t w = 0;
                        tempBuffer[w++] = '"';
                        for (i = 0; i < vlen; i++)
                        {
                            if (v[i] <= 0x1F)
                            {
                                tempBuffer[w++] = '\\';
                                tempBuffer[w++] = 'u';
                                tempBuffer[w++] = '0';
                                tempBuffer[w++] = '0';
                                tempBuffer[w++] = hexToASCII[(v[i] & 0xF0) >> 4]; /*high nibble*/
#ifdef _MSC_VER
#pragma warning(disable:6386) // warning C6386: Buffer overrun while writing to 'tempBuffer'. This if statement will only enter if v[i] is a control character, which means that the buffer will not be overrun.
#endif
                                tempBuffer[w++] = hexToASCII[v[i] & 0x0F]; /*lowNibble nibble*/
#ifdef _MSC_VER
#pragma warning (default:6386)
#endif
                            }
                            else if (v[i] == '"')
                            {
                                tempBuffer[w++] = '\\';
                                tempBuffer[w++] = '"';
                            }
                            else if (v[i] == '\\')
                            {
                                tempBuffer[w++] = '\\';
                                tempBuffer[w++] = '\\';
                            }
                            else if (v[i] == '/')
                            {
                                tempBuffer[w++] = '\\';
                                tempBuffer[w++] = '/';
                            }
                            else
                            {
                                tempBuffer[w++] = v[i];
                            }
                        }

#ifdef _MSC_VER
#pragma warning(suppress: 6386) /* The test Create_AGENT_DATA_TYPE_from_charz_With_2_Slashes_Succeeds verifies that Code Analysis is wrong here */
#endif
                        tempBuffer[w] = '"';
                        /*zero terminating it*/
                        tempBuffer[vlen + 5 * nControlCharacters + nEscapeCharacters + 3 - 1] = '\0';

                        if (STRING_concat(destination, tempBuffer) != 0)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else
                        {
                            result = AGENT_DATA_TYPES_OK;
                        }

                        free(tempBuffer);
                    }
                }

                break;
            }

            case (EDM_STRING_NO_QUOTES_TYPE) :
            {
                /* this is a special case where we just want to copy/paste the contents, no encoding, no quotes */
                if (STRING_concat(destination, value->value.edmStringNoQuotes.chars) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }

                break;
            }

#ifndef NO_FLOATS
            case(EDM_SINGLE_TYPE):
            {
                /*C89 standard says: When a float is promoted to double or long double, or a double is promoted to long double, its value is unchanged*/
                /*I read that as : when a float is NaN or Inf, it will stay NaN or INF in double representation*/

                /*The sprintf function returns the number of characters written in the array, not counting the terminating null character.*/

                if(ISNAN(value->value.edmSingle.value))
                {
                    if (STRING_concat(destination, NaN_STRING) != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                }
                else if (ISNEGATIVEINFINITY(value->value.edmSingle.value))
                {
                    if (STRING_concat(destination, MINUSINF_STRING) != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                }
                else if (ISPOSITIVEINFINITY(value->value.edmSingle.value))
                {
                    if (STRING_concat(destination, PLUSINF_STRING) != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                }
                else
                {
                    size_t tempBufferSize = MAX_FLOATING_POINT_STRING_LENGTH;
                    char* tempBuffer = (char*)malloc(tempBufferSize);
                    if (tempBuffer == NULL)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        if (sprintf_s(tempBuffer, tempBufferSize, "%.*f", FLT_DIG, (double)(value->value.edmSingle.value)) < 0)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else if (STRING_concat(destination, tempBuffer) != 0)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else
                        {
                            result = AGENT_DATA_TYPES_OK;
                        }

                        free(tempBuffer);
                    }
                }
                break;
            }
            case(EDM_DOUBLE_TYPE):
            {
                /*The sprintf function returns the number of characters written in the array, not counting the terminating null character.*/
                /*OData-ABNF says these can be used: nanInfinity = 'NaN' / '-INF' / 'INF'*/
                /*C90 doesn't declare a NaN or Inf in the standard, however, values might be NaN or Inf...*/
                /*C99 ... does*/
                /*C11 is same as C99*/
                if(ISNAN(value->value.edmDouble.value))
                {
                    if (STRING_concat(destination, NaN_STRING) != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                }
                else if (ISNEGATIVEINFINITY(value->value.edmDouble.value))
                {
                    if (STRING_concat(destination, MINUSINF_STRING) != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                }
                else if (ISPOSITIVEINFINITY(value->value.edmDouble.value))
                {
                    if (STRING_concat(destination, PLUSINF_STRING) != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                }
                else
                {
                    size_t tempBufferSize = DECIMAL_DIG * 2;
                    char* tempBuffer = (char*)malloc(tempBufferSize);
                    if (tempBuffer == NULL)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        if (sprintf_s(tempBuffer, tempBufferSize, "%.*f", DBL_DIG, value->value.edmDouble.value) < 0)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else if (STRING_concat(destination, tempBuffer) != 0)
                        {
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                        }
                        else
                        {
                            result = AGENT_DATA_TYPES_OK;
                        }

                        free(tempBuffer);
                    }
                }
                break;
            }
#endif

            case(EDM_COMPLEX_TYPE_TYPE) :
            {
                /*to produce an EDM_COMPLEX_TYPE is a recursive process*/
                /*uses JSON encoder*/
                MULTITREE_HANDLE treeHandle;
                result = AGENT_DATA_TYPES_OK;
                /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
                treeHandle = MultiTree_Create(NoCloneFunction, NoFreeFunction);
                if (treeHandle == NULL)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    size_t i;
                    for (i = 0; i < value->value.edmComplexType.nMembers; i++)
                    {
                        if (MultiTree_AddLeaf(treeHandle, value->value.edmComplexType.fields[i].fieldName, value->value.edmComplexType.fields[i].value) != MULTITREE_OK)
                        {
                            /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
                            result = AGENT_DATA_TYPES_ERROR;
                            LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            break;
                        }
                        else
                        {
                            /*all is fine*/
                        }
                    }

                    if (result == AGENT_DATA_TYPES_OK)
                    {
                            /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
                            if (JSONEncoder_EncodeTree(treeHandle, destination, (JSON_ENCODER_TOSTRING_FUNC)AgentDataTypes_ToString) != JSON_ENCODER_OK)
                            {
                                result = AGENT_DATA_TYPES_ERROR;
                                LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                            }
                            else
                            {
                                /*all is fine*/
                            }

                    }

                    MultiTree_Destroy(treeHandle);
                }
                break;
            }
            case EDM_GUID_TYPE:
            {
                char tempBuffer2[1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1+ 1];
                tempBuffer2[0] = '\"';
                tempBuffer2[1] = hexDigitToChar(value->value.edmGuid.GUID[0] / 16);
                tempBuffer2[2] = hexDigitToChar(value->value.edmGuid.GUID[0] % 16);
                tempBuffer2[3] = hexDigitToChar(value->value.edmGuid.GUID[1] / 16);
                tempBuffer2[4] = hexDigitToChar(value->value.edmGuid.GUID[1] % 16);
                tempBuffer2[5] = hexDigitToChar(value->value.edmGuid.GUID[2] / 16);
                tempBuffer2[6] = hexDigitToChar(value->value.edmGuid.GUID[2] % 16);
                tempBuffer2[7] = hexDigitToChar(value->value.edmGuid.GUID[3] / 16);
                tempBuffer2[8] = hexDigitToChar(value->value.edmGuid.GUID[3] % 16);

                tempBuffer2[9] = '-';
                tempBuffer2[10] = hexDigitToChar(value->value.edmGuid.GUID[4] / 16);
                tempBuffer2[11] = hexDigitToChar(value->value.edmGuid.GUID[4] % 16);
                tempBuffer2[12] = hexDigitToChar(value->value.edmGuid.GUID[5] / 16);
                tempBuffer2[13] = hexDigitToChar(value->value.edmGuid.GUID[5] % 16);

                tempBuffer2[14] = '-';
                tempBuffer2[15] = hexDigitToChar(value->value.edmGuid.GUID[6] / 16);
                tempBuffer2[16] = hexDigitToChar(value->value.edmGuid.GUID[6] % 16);
                tempBuffer2[17] = hexDigitToChar(value->value.edmGuid.GUID[7] / 16);
                tempBuffer2[18] = hexDigitToChar(value->value.edmGuid.GUID[7] % 16);

                tempBuffer2[19] = '-';
                tempBuffer2[20] = hexDigitToChar(value->value.edmGuid.GUID[8] / 16);
                tempBuffer2[21] = hexDigitToChar(value->value.edmGuid.GUID[8] % 16);
                tempBuffer2[22] = hexDigitToChar(value->value.edmGuid.GUID[9] / 16);
                tempBuffer2[23] = hexDigitToChar(value->value.edmGuid.GUID[9] % 16);

                tempBuffer2[24] = '-';
                tempBuffer2[25] = hexDigitToChar(value->value.edmGuid.GUID[10] / 16);
                tempBuffer2[26] = hexDigitToChar(value->value.edmGuid.GUID[10] % 16);
                tempBuffer2[27] = hexDigitToChar(value->value.edmGuid.GUID[11] / 16);
                tempBuffer2[28] = hexDigitToChar(value->value.edmGuid.GUID[11] % 16);
                tempBuffer2[29] = hexDigitToChar(value->value.edmGuid.GUID[12] / 16);
                tempBuffer2[30] = hexDigitToChar(value->value.edmGuid.GUID[12] % 16);
                tempBuffer2[31] = hexDigitToChar(value->value.edmGuid.GUID[13] / 16);
                tempBuffer2[32] = hexDigitToChar(value->value.edmGuid.GUID[13] % 16);
                tempBuffer2[33] = hexDigitToChar(value->value.edmGuid.GUID[14] / 16);
                tempBuffer2[34] = hexDigitToChar(value->value.edmGuid.GUID[14] % 16);
                tempBuffer2[35] = hexDigitToChar(value->value.edmGuid.GUID[15] / 16);
                tempBuffer2[36] = hexDigitToChar(value->value.edmGuid.GUID[15] % 16);

                tempBuffer2[37] = '\"';
                tempBuffer2[38] = '\0';

                if (STRING_concat(destination, tempBuffer2) != 0)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                    LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                }
                else
                {
                    result = AGENT_DATA_TYPES_OK;
                }
                break;
            }
            case EDM_BINARY_TYPE:
            {
                size_t currentPosition = 0;
                char* temp;
                /*binary types */
                /*the following will happen*/
                /*1. the "data" of the binary shall be "eaten" 3 characters at a time and produce 4 base64 encoded characters for as long as there are more than 3 characters still to process*/
                /*2. the remaining characters (1 or 2) shall be encoded.*/
                /*there's a level of assumption that 'a' corresponds to 0b000000 and that '_' corresponds to 0b111111*/
                /*the encoding will use the optional [=] or [==] at the end of the encoded string, so that other less standard aware libraries can do their work*/
                /*these are the bits of the 3 normal bytes to be encoded*/
                size_t neededSize = 2; /*2 because starting and ending quotes */
                neededSize += (value->value.edmBinary.size == 0) ? (0) : ((((value->value.edmBinary.size-1) / 3) + 1) * 4);
                neededSize += 1; /*+1 because \0 at the end of the string*/
                if ((temp = (char*)malloc(neededSize))==NULL)
                {
                    result = AGENT_DATA_TYPES_ERROR;
                }
                else
                {
                    /*b0            b1(+1)          b2(+2)
                      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
                      |----c1---| |----c2---| |----c3---| |----c4---|
                    */

                    size_t destinationPointer = 0;
                    temp[destinationPointer++] = '"';
                    while (value->value.edmBinary.size - currentPosition >= 3)
                    {
                        char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
                        char c2 = base64char(
                            ((value->value.edmBinary.data[currentPosition] & 3) << 4) |
                                (value->value.edmBinary.data[currentPosition + 1] >> 4)
                        );
                        char c3 = base64char(
                            ((value->value.edmBinary.data[currentPosition + 1] & 0x0F) << 2) |
                                ((value->value.edmBinary.data[currentPosition + 2] >> 6) & 3)
                        );
                        char c4 = base64char(
                            value->value.edmBinary.data[currentPosition + 2] & 0x3F
                        );
                        currentPosition += 3;
                        temp[destinationPointer++] = c1;
                        temp[destinationPointer++] = c2;
                        temp[destinationPointer++] = c3;
                        temp[destinationPointer++] = c4;

                    }
                    if (value->value.edmBinary.size - currentPosition == 2)
                    {
                        char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
                        char c2 = base64char(
                            ((value->value.edmBinary.data[currentPosition] & 0x03) << 4) |
                                (value->value.edmBinary.data[currentPosition + 1] >> 4)
                        );
                        char c3 = base64b16(value->value.edmBinary.data[currentPosition + 1] & 0x0F);
                        temp[destinationPointer++] = c1;
                        temp[destinationPointer++] = c2;
                        temp[destinationPointer++] = c3;
                        temp[destinationPointer++] = '=';
                    }
                    else if (value->value.edmBinary.size - currentPosition == 1)
                    {
                        char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
                        char c2 = base64b8(value->value.edmBinary.data[currentPosition] & 0x03);
                        temp[destinationPointer++] = c1;
                        temp[destinationPointer++] = c2;
                        temp[destinationPointer++] = '=';
                        temp[destinationPointer++] = '=';
                    }

                    /*closing quote*/
                    temp[destinationPointer++] = '"';
                    /*null terminating the string*/
                    temp[destinationPointer] = '\0';

                    if (STRING_concat(destination, temp) != 0)
                    {
                        result = AGENT_DATA_TYPES_ERROR;
                        LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
                    }
                    else
                    {
                        result = AGENT_DATA_TYPES_OK;
                    }
                    free(temp);
                }
                break;
            }
        }
    }
    return result;
}