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;
}