source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/serializer/src/agenttypesystem.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 160.7 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#include <stdlib.h>
5#include "azure_c_shared_utility/gballoc.h"
6
7#include "agenttypesystem.h"
8#include <inttypes.h>
9
10#ifdef _MSC_VER
11#pragma warning(disable: 4756) /* Known warning for INFINITY */
12#endif
13
14#include <stddef.h>
15
16#include <float.h>
17#include <math.h>
18#include <limits.h>
19#include <errno.h>
20
21/*if ULLONG_MAX is defined by limits.h for whatever reasons... */
22#ifndef ULLONG_MAX
23#define ULLONG_MAX 18446744073709551615
24#endif
25
26#include "azure_c_shared_utility/crt_abstractions.h"
27
28#include "jsonencoder.h"
29#include "multitree.h"
30
31#include "azure_c_shared_utility/xlogging.h"
32
33#define NaN_STRING "NaN"
34#define MINUSINF_STRING "-INF"
35#define PLUSINF_STRING "INF"
36
37#ifndef _HUGE_ENUF
38#define _HUGE_ENUF 1e+300 /* _HUGE_ENUF*_HUGE_ENUF must overflow */
39#endif /* _HUGE_ENUF */
40
41#ifndef INFINITY
42#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) /* causes warning C4756: overflow in constant arithmetic (by design) */
43#endif /* INFINITY */
44
45#ifndef NAN
46#define NAN ((float)(INFINITY * 0.0F))
47#endif /* NAN */
48
49#define GUID_STRING_LENGTH 38
50
51// This is an artificial upper limit on floating point string length
52// (e.g. the size of the string when printing %f). It is set to twice the
53// maximum decimal precision plus 2. 1 for the decimal point and 1 for a
54// sign (+/-)
55// Unfortunately it is quite possible to print a float larger than this.
56// An example of this would be printf("%.*f", MAX_FLOATING_POINT_STRING_LENGTH, 1.3);
57// But currently no explicit requests for this exist in the file nor are
58// any expected to reasonably occur when being used (numbers that hit
59// this limit would be experiencing significant precision loss in storage anyway.
60#define MAX_FLOATING_POINT_STRING_LENGTH (DECIMAL_DIG *2 + 2)
61
62// This maximum length is 11 for 32 bit integers (including the sign)
63// optionally increase to 21 if longs are 64 bit
64#define MAX_LONG_STRING_LENGTH ( 11 + (10 * (sizeof(long)/ 8)))
65
66// This is the maximum length for the largest 64 bit number (signed)
67#define MAX_ULONG_LONG_STRING_LENGTH 20
68
69MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_RESULT_VALUES);
70
71static int ValidateDate(int year, int month, int day);
72
73static int NoCloneFunction(void** destination, const void* source)
74{
75 *destination = (void*)source;
76 return 0;
77}
78
79static void NoFreeFunction(void* value)
80{
81 (void)value;
82}
83
84
85#define IS_DIGIT(a) (('0'<=(a)) &&((a)<='9'))
86#define splitInt(intVal, bytePos) (char)((intVal >> (bytePos << 3)) & 0xFF)
87#define joinChars(a, b, c, d) (uint32_t)( (uint32_t)a + ((uint32_t)b << 8) + ((uint32_t)c << 16) + ((uint32_t)d << 24))
88
89static char base64char(unsigned char val)
90{
91 char result;
92
93 if (val < 26)
94 {
95 result = 'A' + (char)val;
96 }
97 else if (val < 52)
98 {
99 result = 'a' + ((char)val - 26);
100 }
101 else if (val < 62)
102 {
103 result = '0' + ((char)val - 52);
104 }
105 else if (val == 62)
106 {
107 result = '-';
108 }
109 else
110 {
111 result = '_';
112 }
113
114 return result;
115}
116
117static char base64b16(unsigned char val)
118{
119 const uint32_t base64b16values[4] = {
120 joinChars('A', 'E', 'I', 'M'),
121 joinChars('Q', 'U', 'Y', 'c'),
122 joinChars('g', 'k', 'o', 's'),
123 joinChars('w', '0', '4', '8')
124 };
125 return splitInt(base64b16values[val >> 2], (val & 0x03));
126}
127
128static char base64b8(unsigned char val)
129{
130 const uint32_t base64b8values = joinChars('A', 'Q', 'g', 'w');
131 return splitInt(base64b8values, val);
132};
133
134/*creates an AGENT_DATA_TYPE containing a EDM_BOOLEAN from a int*/
135AGENT_DATA_TYPES_RESULT Create_EDM_BOOLEAN_from_int(AGENT_DATA_TYPE* agentData, int v)
136{
137 AGENT_DATA_TYPES_RESULT result;
138 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[All the Create_... functions shall check their parameters for validity.When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned]*/
139 if(agentData==NULL)
140 {
141 result = AGENT_DATA_TYPES_INVALID_ARG;
142 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
143 }
144 else
145 {
146 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_031:[ Creates a AGENT_DATA_TYPE representing an EDM_BOOLEAN.]*/
147 agentData->type = EDM_BOOLEAN_TYPE;
148 agentData->value.edmBoolean.value = (v)?(EDM_TRUE):(EDM_FALSE);
149 result = AGENT_DATA_TYPES_OK;
150 }
151 return result;
152}
153
154/*creates an AGENT_DATA_TYPE containing a UINT8*/
155AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_UINT8(AGENT_DATA_TYPE* agentData, uint8_t v)
156{
157 AGENT_DATA_TYPES_RESULT result;
158 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
159 if (agentData == NULL)
160 {
161 result = AGENT_DATA_TYPES_INVALID_ARG;
162 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
163 }
164 else
165 {
166 agentData->type = EDM_BYTE_TYPE;
167 agentData->value.edmByte.value = v;
168 result = AGENT_DATA_TYPES_OK;
169 }
170 return result;
171}
172
173/*Codes_SRS_AGENT_TYPE_SYSTEM_99_091:[Creates an AGENT_DATA_TYPE containing an Edm.DateTimeOffset from an EDM_DATE_TIME_OFFSET.]*/
174AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_EDM_DATE_TIME_OFFSET(AGENT_DATA_TYPE* agentData, EDM_DATE_TIME_OFFSET v)
175{
176 AGENT_DATA_TYPES_RESULT result;
177 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ]*/
178 if (agentData == NULL)
179 {
180 result = AGENT_DATA_TYPES_INVALID_ARG;
181 }
182 else if (ValidateDate(v.dateTime.tm_year+1900, v.dateTime.tm_mon +1 , v.dateTime.tm_mday) != 0)
183 {
184 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_092:[ The structure shall be validated to be conforming to OData specifications (odata-abnf-construction-rules, 2013), and if found invalid, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
185 result = AGENT_DATA_TYPES_INVALID_ARG;
186 }
187 else if (
188 (v.dateTime.tm_hour > 23) ||
189 (v.dateTime.tm_hour < 0) ||
190 (v.dateTime.tm_min > 59) ||
191 (v.dateTime.tm_min < 0) ||
192 (v.dateTime.tm_sec > 59) ||
193 (v.dateTime.tm_sec < 0)
194 )
195 {
196 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_092:[ The structure shall be validated, and if found invalid, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
197 result = AGENT_DATA_TYPES_INVALID_ARG;
198 }
199 else if ((v.hasFractionalSecond) && (v.fractionalSecond > 999999999999))
200 {
201 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_092:[ The structure shall be validated to be conforming to OData specifications (odata-abnf-construction-rules, 2013), and if found invalid, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
202 result = AGENT_DATA_TYPES_INVALID_ARG;
203 }
204 else if (
205 (v.hasTimeZone) &&
206 (
207 (v.timeZoneHour<-23) ||
208 (v.timeZoneHour>23) ||
209 (v.timeZoneMinute>59)
210 )
211 )
212 {
213 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_092:[ The structure shall be validated to be conforming to OData specifications (odata-abnf-construction-rules, 2013), and if found invalid, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
214 result = AGENT_DATA_TYPES_INVALID_ARG;
215 }
216 else
217 {
218 agentData->type = EDM_DATE_TIME_OFFSET_TYPE;
219 agentData->value.edmDateTimeOffset = v;
220 result = AGENT_DATA_TYPES_OK;
221 }
222 return result;
223}
224
225/*Codes_SRS_AGENT_TYPE_SYSTEM_99_094:[ Creates and AGENT_DATA_TYPE containing a EDM_GUID from an EDM_GUID]*/
226AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_EDM_GUID(AGENT_DATA_TYPE* agentData, EDM_GUID v)
227{
228 AGENT_DATA_TYPES_RESULT result;
229 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the functions shall check their parameters for validity. When an invalid parameter is detected, the value AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
230 if (agentData == NULL)
231 {
232 result = AGENT_DATA_TYPES_INVALID_ARG;
233 LogError("result = %s ", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
234 }
235 else
236 {
237 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_094:[ Creates and AGENT_DATA_TYPE containing a EDM_GUID from an EDM_GUID]*/
238 agentData->type = EDM_GUID_TYPE;
239 memmove(agentData->value.edmGuid.GUID, v.GUID, 16);
240 result = AGENT_DATA_TYPES_OK;
241 }
242 return result;
243}
244
245/*Codes_SRS_AGENT_TYPE_SYSTEM_99_098:[ Creates an AGENT_DATA_TYPE containing a EDM_BINARY from a EDM_BINARY.]*/
246AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_EDM_BINARY(AGENT_DATA_TYPE* agentData, EDM_BINARY v)
247{
248 AGENT_DATA_TYPES_RESULT result;
249 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the functions shall check their parameters for validity. When an invalid parameter is detected, the value AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
250 if (agentData == NULL)
251 {
252 result = AGENT_DATA_TYPES_INVALID_ARG;
253 LogError("result = %s", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
254 }
255 else
256 {
257 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_098:[ Creates an AGENT_DATA_TYPE containing a EDM_BINARY from a EDM_BINARY.]*/
258 if (v.data == NULL)
259 {
260 if (v.size != 0)
261 {
262 result = AGENT_DATA_TYPES_INVALID_ARG;
263 LogError("result = %s ", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
264 }
265 else
266 {
267 agentData->type = EDM_BINARY_TYPE;
268 agentData->value.edmBinary.size = 0;
269 agentData->value.edmBinary.data = NULL;
270 result = AGENT_DATA_TYPES_OK;
271 }
272 }
273 else
274 {
275 if (v.size != 0)
276 {
277 /*make a copy*/
278 if ((agentData->value.edmBinary.data = (unsigned char*)malloc(v.size)) == NULL)
279 {
280 result = AGENT_DATA_TYPES_ERROR;
281 LogError("result = %s", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
282 }
283 else
284 {
285 (void)memcpy(agentData->value.edmBinary.data, v.data, v.size);
286 agentData->type = EDM_BINARY_TYPE;
287 agentData->value.edmBinary.size = v.size;
288 result = AGENT_DATA_TYPES_OK;
289 }
290 }
291 else
292 {
293 result = AGENT_DATA_TYPES_INVALID_ARG;
294 LogError("result = %s", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
295 }
296 }
297 }
298 return result;
299}
300
301/*scans sign, if any*/
302/*if no sign, then it will set *sign to = +1*/
303/*if sign, then it will set *sign to = +/-1*/
304static void scanOptionalSign(const char* source, size_t sourceSize, size_t* position, int* sign)
305{
306 if (*position < sourceSize)
307 {
308 if (source[*position] == '-')
309 {
310
311 *sign = -1;
312 (*position)++;
313 }
314 else if (source[*position] == '+')
315 {
316 *sign = +1;
317 (*position)++;
318 }
319 else
320 {
321 *sign = +1;
322 }
323 }
324}
325
326/*scans a minus sign, if any*/
327/*if no sign, then it will set *sign to = +1*/
328/*if sign, then it will set *sign to = +/-1*/
329static void scanOptionalMinusSign(const char* source, size_t sourceSize, size_t* position, int* sign)
330{
331 if (*position < sourceSize)
332 {
333 if (source[*position] == '-')
334 {
335
336 *sign = -1;
337 (*position)++;
338 }
339 else
340 {
341 *sign = +1;
342 }
343 }
344}
345
346/*this function alawys returns 0 if it processed 1 digit*/
347/*return 1 when error (such as wrong parameters)*/
348static int scanMandatoryOneDigit(const char* source, size_t sourceSize, size_t* position)
349{
350 int result;
351 if (*position < sourceSize)
352 {
353 if (IS_DIGIT(source[*position]))
354 {
355 (*position)++;
356 result = 0;
357 }
358 else
359 {
360 result = 1;
361 }
362 }
363 else
364 {
365 result = 1;
366 }
367 return result;
368}
369
370/*scans digits, if any*/
371static void scanOptionalNDigits(const char* source, size_t sourceSize, size_t* position)
372{
373 while (*position < sourceSize)
374 {
375 if (IS_DIGIT(source[*position]))
376 {
377 (*position)++;
378 }
379 else
380 {
381 break;
382 }
383 }
384}
385
386/*from the string pointed to by source, having the size sourceSize, starting at initial position *position*/
387/*this function will attempt to read a decimal number having an optional sign(+/-) followed by precisely N digits */
388/*will return 0 if in the string there was a number and that number has been read in the *value parameter*/
389/*will update position parameter to reflect the first character not belonging to the number*/
390static int scanAndReadNDigitsInt(const char* source, size_t* position, int *value, size_t N)
391{
392 N++;
393 *value = 0;
394 while ((IS_DIGIT(source[*position])) &&
395 (N > 0))
396 {
397 *value *= 10;
398 *value += (source[*position] - '0');
399 (*position)++;
400 N--;
401 }
402
403 return N != 1;
404}
405
406/*this function alawys returns 0 if it found a dot followed by at least digit*/
407/*return 1 when error (such as wrong parameters)*/
408static int scanOptionalDotAndDigits(const char* source, size_t sourceSize, size_t* position)
409{
410 int result = 0;
411 if (*position < sourceSize)
412 {
413 if (source[*position] == '.')
414 {
415 (*position)++;
416 if (scanMandatoryOneDigit(source, sourceSize, position) != 0)
417 {
418 /* not a digit following the dot... */
419 result = 1;
420 }
421 else
422 {
423 scanOptionalNDigits(source, sourceSize, position);
424 }
425 }
426 else
427 {
428 /*not a dot, don't care*/
429 }
430 }
431 return result;
432}
433
434
435static int scanMandatory1CapitalHexDigit(const char* source, uint8_t* value)
436{
437 int result = 0;
438 if (('0' <= source[0]) && (source[0] <= '9'))
439 {
440 *value = (source[0] - '0');
441 }
442 else if (('A' <= source[0]) && (source[0] <= 'F'))
443 {
444 *value = (source[0] - 'A'+10);
445 }
446 else
447 {
448 result = 1;
449 }
450 return result;
451}
452
453/*this function alawys returns 0 if it found 2 hex digits, also updates the *value parameter*/
454/*return 1 when error (such as wrong parameters)*/
455static int scanMandatory2CapitalHexDigits(const char* source, uint8_t* value)
456{
457 int result;
458 uint8_t temp;
459 if (scanMandatory1CapitalHexDigit(source, &temp) == 0)
460 {
461 *value = temp*16;
462 if (scanMandatory1CapitalHexDigit(source + 1, &temp) == 0)
463 {
464 *value += temp;
465 result = 0;
466 }
467 else
468 {
469 result = 1;
470 }
471 }
472 else
473 {
474 result = 2;
475 }
476
477 return result;
478}
479
480static int ValidateDecimal(const char* v, size_t vlen)
481{
482 int result;
483 int sign = 0;
484 size_t validatePosition = 0;
485 scanOptionalSign(v, vlen, &validatePosition, &sign);
486 if (scanMandatoryOneDigit(v, vlen, &validatePosition) != 0)
487 {
488 result = 1;
489 }
490 else
491 {
492 scanOptionalNDigits(v, vlen, &validatePosition);
493 if (scanOptionalDotAndDigits(v, vlen, &validatePosition) != 0)
494 {
495 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_067:[ If the string indicated by the parameter v does not match exactly an ODATA string representation, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
496 result = 1;
497 }
498 else if (validatePosition != vlen) /*Trailing wrong characters*/
499 {
500 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_067:[ If the string indicated by the parameter v does not match exactly an ODATA string representation, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
501 result = 1;
502 }
503 else
504 {
505 result = 0;
506 }
507 }
508
509 return result;
510}
511
512/*return 0 if everything went ok*/
513/*takes 1 base64char and returns its value*/
514static int base64toValue(char base64charSource, unsigned char* value)
515{
516 int result;
517 if (('A' <= base64charSource) && (base64charSource <= 'Z'))
518 {
519 *value = base64charSource - 'A';
520 result = 0;
521 }
522 else if (('a' <= base64charSource) && (base64charSource <= 'z'))
523 {
524 *value = ('Z' - 'A') +1+ (base64charSource - 'a');
525 result = 0;
526 }
527 else if (('0' <= base64charSource) && (base64charSource <= '9'))
528 {
529 *value = ('Z' - 'A') +1+('z'-'a')+1 +(base64charSource - '0');
530 result = 0;
531 }
532 else if ('-' == base64charSource)
533 {
534 *value = 62;
535 result = 0;
536 }
537 else if ('_' == base64charSource)
538 {
539 *value = 63;
540 result = 0;
541 }
542 else
543 {
544 result = 1;
545 }
546 return result;
547}
548
549/*returns 0 if everything went ok*/
550/*scans 4 base64 characters and returns 3 usual bytes*/
551static int scan4base64char(const char* source, size_t sourceSize, unsigned char *destination0, unsigned char* destination1, unsigned char* destination2)
552{
553 int result;
554 if (sourceSize < 4)
555 {
556 result = 1;
557 }
558 else
559 {
560 unsigned char b0, b1, b2, b3;
561 if (
562 (base64toValue(source[0], &b0) == 0) &&
563 (base64toValue(source[1], &b1) == 0) &&
564 (base64toValue(source[2], &b2) == 0) &&
565 (base64toValue(source[3], &b3) == 0)
566 )
567 {
568 *destination0 = (b0 << 2) | ((b1 & 0x30) >> 4);
569 *destination1 = ((b1 & 0x0F)<<4) | ((b2 & 0x3C) >>2 );
570 *destination2 = ((b2 & 0x03) << 6) | (b3);
571 result = 0;
572 }
573 else
574 {
575 result = 2;
576 }
577 }
578 return result;
579}
580
581/*return 0 if the character is one of ( 'A' / 'E' / 'I' / 'M' / 'Q' / 'U' / 'Y' / 'c' / 'g' / 'k' / 'o' / 's' / 'w' / '0' / '4' / '8' )*/
582static int base64b16toValue(unsigned char source, unsigned char* destination)
583{
584 unsigned char i;
585 for (i = 0; i <= 15; i++)
586 {
587 if (base64b16(i) == source)
588 {
589 *destination = i;
590 return 0;
591 }
592 }
593 return 1;
594}
595
596/*return 0 if the character is one of ( 'A' / 'Q' / 'g' / 'w' )*/
597static int base64b8toValue(unsigned char source, unsigned char* destination)
598{
599 unsigned char i;
600 for (i = 0; i <= 3; i++)
601 {
602 if (base64b8(i) == source)
603 {
604 *destination = i;
605 return 0;
606 }
607 }
608 return 1;
609}
610
611
612/*returns 0 if everything went ok*/
613/*scans 2 base64 characters + 1 special + 1 optional = and returns 2 usual bytes*/
614int scanbase64b16(const char* source, size_t sourceSize, size_t *consumed, unsigned char* destination0, unsigned char* destination1)
615{
616 int result;
617 if (sourceSize < 3)
618 {
619 result = 1;
620 }
621 else
622 {
623 unsigned char c0, c1, c2;
624 *consumed = 0;
625 if (
626 (base64toValue(source[0], &c0) == 0) &&
627 (base64toValue(source[1], &c1) == 0) &&
628 (base64b16toValue(source[2], &c2) == 0)
629 )
630 {
631 *consumed = 3 + ((sourceSize>=3)&&(source[3] == '=')); /*== produce 1 or 0 ( in C )*/
632 *destination0 = (c0 << 2) | ((c1 & 0x30) >> 4);
633 *destination1 = ((c1 &0x0F) <<4) | c2;
634 result = 0;
635 }
636 else
637 {
638 result = 2;
639 }
640 }
641 return result;
642}
643
644/*return 0 if everything is ok*/
645/*Reads base64b8 = base64char ( 'A' / 'Q' / 'g' / 'w' ) [ "==" ]*/
646int scanbase64b8(const char* source, size_t sourceSize, size_t *consumed, unsigned char* destination0)
647{
648 int result;
649 if (sourceSize < 2)
650 {
651 result = 1;
652 }
653 else
654 {
655 unsigned char c0, c1;
656 if (
657 (base64toValue(source[0], &c0) == 0) &&
658 (base64b8toValue(source[1], &c1) == 0)
659 )
660 {
661 *consumed = 2 + (((sourceSize>=4) && (source[2] == '=') && (source[3] == '='))?2:0); /*== produce 1 or 0 ( in C )*/
662 *destination0 = (c0 << 2) | (c1 & 3);
663 result = 0;
664 }
665 else
666 {
667 result = 2;
668 }
669 }
670 return result;
671}
672
673/*Codes_SRS_AGENT_TYPE_SYSTEM_99_039:[ Creates an AGENT_DATA_TYPE containing an EDM_DECIMAL from a null-terminated string.]*/
674AGENT_DATA_TYPES_RESULT Create_EDM_DECIMAL_from_charz(AGENT_DATA_TYPE* agentData, const char* v)
675{
676 AGENT_DATA_TYPES_RESULT result;
677 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
678 if (agentData == NULL)
679 {
680 result = AGENT_DATA_TYPES_INVALID_ARG;
681 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
682 }
683 else if (v == NULL)
684 {
685 result = AGENT_DATA_TYPES_INVALID_ARG;
686 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
687 }
688 else
689 {
690 size_t vlen = strlen(v);
691 /*validate that v has the form [SIGN] 1*DIGIT ["." 1*DIGIT]*/
692 if (vlen == 0)
693 {
694 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_067:[ If the string indicated by the parameter v does not match exactly an ODATA string representation, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
695 result = AGENT_DATA_TYPES_INVALID_ARG;
696 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
697 }
698 else
699 {
700 if (ValidateDecimal(v, vlen) != 0)
701 {
702 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_067:[ If the string indicated by the parameter v does not match exactly an ODATA string representation, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
703 result = AGENT_DATA_TYPES_INVALID_ARG;
704 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
705 }
706 else if ((agentData->value.edmDecimal.value = STRING_construct(v)) == NULL)
707 {
708 result = AGENT_DATA_TYPES_ERROR;
709 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
710 }
711 else
712 {
713 agentData->type = EDM_DECIMAL_TYPE;
714 result = AGENT_DATA_TYPES_OK;
715 }
716 }
717 }
718 return result;
719}
720
721/*create an AGENT_DATA_TYPE containing an EDM_DOUBLE from a double*/
722AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_DOUBLE(AGENT_DATA_TYPE* agentData, double v)
723{
724 AGENT_DATA_TYPES_RESULT result;
725 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[All the Create_... functions shall check their parameters for validity.When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned]*/
726 if(agentData==NULL)
727 {
728 result = AGENT_DATA_TYPES_INVALID_ARG;
729 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
730 }
731 else
732 {
733 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_041:[Creates an AGENT_DATA_TYPE containing an EDM_DOUBLE from double]*/
734 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_042:[Values of NaN, -INF, +INF are accepted]*/
735 agentData->type = EDM_DOUBLE_TYPE;
736 agentData->value.edmDouble.value = v;
737 result = AGENT_DATA_TYPES_OK;
738 }
739 return result;
740}
741
742/*create an AGENT_DATA_TYPE from INT16_T*/
743/*Codes_SRS_AGENT_TYPE_SYSTEM_99_043:[ Creates an AGENT_DATA_TYPE containing an EDM_INT16 from int16_t]*/
744AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_SINT16(AGENT_DATA_TYPE* agentData, int16_t v)
745{
746 AGENT_DATA_TYPES_RESULT result;
747 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
748 if (agentData == NULL)
749 {
750 result = AGENT_DATA_TYPES_INVALID_ARG;
751 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
752 }
753 else
754 {
755 agentData->type = EDM_INT16_TYPE;
756 agentData->value.edmInt16.value = v;
757 result = AGENT_DATA_TYPES_OK;
758 }
759 return result;
760}
761
762/*create an AGENT_DATA_TYPE from INT32_T*/
763AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_SINT32(AGENT_DATA_TYPE* agentData, int32_t v)
764{
765 AGENT_DATA_TYPES_RESULT result;
766 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
767 if (agentData == NULL)
768 {
769 result = AGENT_DATA_TYPES_INVALID_ARG;
770 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
771 }
772 else
773 {
774 agentData->type = EDM_INT32_TYPE;
775 agentData->value.edmInt32.value = v;
776 result = AGENT_DATA_TYPES_OK;
777 }
778 return result;
779}
780
781/*create an AGENT_DATA_TYPE from INT64_T*/
782/*Codes_SRS_AGENT_TYPE_SYSTEM_99_045:[ Creates an AGENT_DATA_TYPE containing an EDM_INT64 from int64_t]*/
783AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_SINT64(AGENT_DATA_TYPE* agentData, int64_t v)
784{
785 AGENT_DATA_TYPES_RESULT result;
786 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
787 if (agentData == NULL)
788 {
789 result = AGENT_DATA_TYPES_INVALID_ARG;
790 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
791
792 }
793 else
794 {
795 agentData->type = EDM_INT64_TYPE;
796 agentData->value.edmInt64.value = v;
797 result = AGENT_DATA_TYPES_OK;
798 }
799 return result;
800}
801
802/*create an AGENT_DATA_TYPE from int8_t*/
803AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_SINT8(AGENT_DATA_TYPE* agentData, int8_t v)
804{
805 AGENT_DATA_TYPES_RESULT result;
806 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
807 if (agentData == NULL)
808 {
809 result = AGENT_DATA_TYPES_INVALID_ARG;
810 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
811
812 }
813 else
814 {
815 agentData->type = EDM_SBYTE_TYPE;
816 agentData->value.edmSbyte.value = v;
817 result = AGENT_DATA_TYPES_OK;
818 }
819 return result;
820}
821
822static int ValidateDate(int year, int month, int day)
823{
824 int result;
825
826 if ((year <= -10000) || (year >= 10000))
827 {
828 result = 1;
829 }
830 else
831 {
832 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[ If year-month-date does not indicate a valid day (for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
833 if (day <= 0)
834 {
835 result = 1;
836 }
837 else
838 {
839 /*the following data will be validated...*/
840 /*leap years are those that can be divided by 4. But if the year can be divided by 100, it is not leap. But if they year can be divided by 400 it is leap*/
841 if (
842 (month == 1) || /*these months have always 31 days*/
843 (month == 3) ||
844 (month == 5) ||
845 (month == 7) ||
846 (month == 8) ||
847 (month == 10) ||
848 (month == 12)
849 )
850 {
851 if (day <= 31)
852 {
853 result = 0;
854 }
855 else
856 {
857 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
858 result = 1;
859 }
860 }
861 else if (
862 (month == 4) ||
863 (month == 6) ||
864 (month == 9) ||
865 (month == 11)
866 )
867 {
868 if (day <= 30)
869 {
870 result = 0;
871 }
872 else
873 {
874 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
875 result = -1;
876 }
877 }
878 else if (month == 2)/*february*/
879 {
880 if ((year % 400) == 0)
881 {
882 /*these are leap years, suchs as 2000*/
883 if (day <= 29)
884 {
885 result = 0;
886 }
887 else
888 {
889 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
890 result = 1;
891 }
892 }
893 else if ((year % 100) == 0)
894 {
895 /*non-leap year, such as 1900*/
896 if (day <= 28)
897 {
898 result = 0;
899 }
900 else
901 {
902 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
903 result = 1;
904 }
905 }
906 else if ((year % 4) == 0)
907 {
908 /*these are leap years, such as 2104*/
909 if (day <= 29)
910 {
911 result = 0;
912 }
913 else
914 {
915 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
916 result = 1;
917 }
918 }
919 else
920 {
921 /*certainly not a leap year*/
922 if (day <= 28)
923 {
924 result = 0;
925 }
926 else
927 {
928 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
929 result = 1;
930 }
931 }
932 }
933 else
934 {
935 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_070:[If year - month - date does not indicate a valid day(for example 31 Feb 2013), then AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
936 result = 1;
937 }
938 }
939 }
940
941 return result;
942}
943
944/*Codes_SRS_AGENT_TYPE_SYSTEM_99_069:[ Creates an AGENT_DATA_TYPE containing an EDM_DATE from a year, a month and a day of the month.]*/
945AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_date(AGENT_DATA_TYPE* agentData, int16_t year, uint8_t month, uint8_t day)
946{
947 AGENT_DATA_TYPES_RESULT result;
948 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
949 if (agentData == NULL)
950 {
951 result = AGENT_DATA_TYPES_INVALID_ARG;
952 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
953 }
954 /*ODATA-ABNF: year = [ "-" ] ( "0" 3DIGIT / oneToNine 3*DIGIT )*/
955 else if (ValidateDate(year, month, day) != 0)
956 {
957 result = AGENT_DATA_TYPES_INVALID_ARG;
958 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
959 }
960 else
961 {
962 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_069:[ Creates an AGENT_DATA_TYPE containing an EDM_DATE from a year, a month and a day of the month.]*/
963 agentData->type = EDM_DATE_TYPE;
964 agentData->value.edmDate.year = year;
965 agentData->value.edmDate.month = month;
966 agentData->value.edmDate.day = day;
967 result = AGENT_DATA_TYPES_OK;
968 }
969
970 return result;
971}
972
973
974/*create an AGENT_DATA_TYPE from SINGLE*/
975AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_FLOAT(AGENT_DATA_TYPE* agentData, float v)
976{
977 AGENT_DATA_TYPES_RESULT result;
978 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[All the Create_... functions shall check their parameters for validity.When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned]*/
979 if(agentData==NULL)
980 {
981 result = AGENT_DATA_TYPES_INVALID_ARG;
982 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
983 }
984 else
985 {
986 agentData->type = EDM_SINGLE_TYPE;
987 agentData->value.edmSingle.value = v;
988 result = AGENT_DATA_TYPES_OK;
989 }
990 return result;
991}
992
993const char hexToASCII[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
994
995/*create an AGENT_DATA_TYPE from ANSI zero terminated string*/
996AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_charz(AGENT_DATA_TYPE* agentData, const char* v)
997{
998 AGENT_DATA_TYPES_RESULT result = AGENT_DATA_TYPES_OK;
999 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
1000 if (agentData == NULL)
1001 {
1002 result = AGENT_DATA_TYPES_INVALID_ARG;
1003 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1004 }
1005 else if (v == NULL)
1006 {
1007 result = AGENT_DATA_TYPES_INVALID_ARG;
1008 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1009 }
1010 else
1011 {
1012 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_049:[ Creates an AGENT_DATA_TYPE containing an EDM_STRING from an ASCII zero terminated string.]*/
1013 agentData->type = EDM_STRING_TYPE;
1014 if (mallocAndStrcpy_s(&agentData->value.edmString.chars, v) != 0)
1015 {
1016 result = AGENT_DATA_TYPES_ERROR;
1017 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1018 }
1019 else
1020 {
1021 agentData->value.edmString.length = strlen(agentData->value.edmString.chars);
1022 result = AGENT_DATA_TYPES_OK;
1023 }
1024 }
1025 return result;
1026}
1027
1028/*create an AGENT_DATA_TYPE from ANSI zero terminated string (without quotes) */
1029AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_charz_no_quotes(AGENT_DATA_TYPE* agentData, const char* v)
1030{
1031 AGENT_DATA_TYPES_RESULT result = AGENT_DATA_TYPES_OK;
1032 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the Create_... functions shall check their parameters for validity. When an invalid parameter is detected, a code of AGENT_DATA_TYPES_INVALID_ARG shall be returned ].*/
1033 if (agentData == NULL)
1034 {
1035 result = AGENT_DATA_TYPES_INVALID_ARG;
1036 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1037 }
1038 else if (v == NULL)
1039 {
1040 result = AGENT_DATA_TYPES_INVALID_ARG;
1041 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1042 }
1043 else
1044 {
1045 /* Codes_SRS_AGENT_TYPE_SYSTEM_01_001: [Creates an AGENT_DATA_TYPE containing an EDM_STRING from an ASCII zero terminated string.] */
1046 agentData->type = EDM_STRING_NO_QUOTES_TYPE;
1047 if (mallocAndStrcpy_s(&agentData->value.edmStringNoQuotes.chars, v) != 0)
1048 {
1049 result = AGENT_DATA_TYPES_ERROR;
1050 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1051 }
1052 else
1053 {
1054 agentData->value.edmStringNoQuotes.length = strlen(agentData->value.edmStringNoQuotes.chars);
1055 result = AGENT_DATA_TYPES_OK;
1056 }
1057 }
1058 return result;
1059}
1060
1061void Destroy_AGENT_DATA_TYPE(AGENT_DATA_TYPE* agentData)
1062{
1063 if(agentData==NULL)
1064 {
1065 LogError("agentData was NULL.");
1066 }
1067 else
1068 {
1069 switch(agentData->type)
1070 {
1071 default:
1072 {
1073 LogError("invalid agentData");
1074 break;
1075 }
1076 case(EDM_NO_TYPE):
1077 {
1078 LogError("invalid agentData");
1079 break;
1080 }
1081 case(EDM_BINARY_TYPE):
1082 {
1083 /*destroying means maybe deallocating some memory*/
1084 free(agentData->value.edmBinary.data); /* If ptr is a null pointer, no action occurs*/
1085 agentData->value.edmBinary.data = NULL;
1086 break;
1087 }
1088 case(EDM_BOOLEAN_TYPE):
1089 {
1090 /*nothing to do*/
1091 break;
1092 }
1093 case(EDM_BYTE_TYPE):
1094 {
1095 /*nothing to do*/
1096 break;
1097 }
1098 case(EDM_DATE_TYPE):
1099 {
1100 /*nothing to do*/
1101 break;
1102 }
1103 case(EDM_DATE_TIME_OFFSET_TYPE):
1104 {
1105 /*nothing to do*/
1106 break;
1107 }
1108 case(EDM_DECIMAL_TYPE):
1109 {
1110 STRING_delete(agentData->value.edmDecimal.value);
1111 agentData->value.edmDecimal.value = NULL;
1112 break;
1113 }
1114 case(EDM_DURATION_TYPE):
1115 {
1116 LogError("EDM_DURATION_TYPE not implemented");
1117 break;
1118 }
1119 case(EDM_GUID_TYPE):
1120 {
1121 /*nothing to do*/
1122 break;
1123 }
1124 case(EDM_INT16_TYPE):
1125 {
1126 /*nothing to do*/
1127 break;
1128 }
1129 case(EDM_INT32_TYPE):
1130 {
1131 /*nothing to do*/
1132 break;
1133 }
1134 case(EDM_INT64_TYPE):
1135 {
1136 /*nothing to do*/
1137 break;
1138 }
1139 case(EDM_SBYTE_TYPE):
1140 {
1141 /*nothing to do*/
1142 break;
1143 }
1144 case(EDM_STREAM):
1145 {
1146 LogError("EDM_STREAM not implemented");
1147 break;
1148 }
1149 case(EDM_STRING_TYPE):
1150 {
1151 if (agentData->value.edmString.chars != NULL)
1152 {
1153 free(agentData->value.edmString.chars);
1154 agentData->value.edmString.chars = NULL;
1155 }
1156 break;
1157 }
1158 case(EDM_STRING_NO_QUOTES_TYPE) :
1159 {
1160 if (agentData->value.edmStringNoQuotes.chars != NULL)
1161 {
1162 free(agentData->value.edmStringNoQuotes.chars);
1163 agentData->value.edmStringNoQuotes.chars = NULL;
1164 }
1165 break;
1166 }
1167 case(EDM_TIME_OF_DAY_TYPE) :
1168 {
1169 LogError("EDM_TIME_OF_DAY_TYPE not implemented");
1170 break;
1171 }
1172 case(EDM_GEOGRAPHY_TYPE):
1173 {
1174 LogError("EDM_GEOGRAPHY_TYPE not implemented");
1175 break;
1176 }
1177 case(EDM_GEOGRAPHY_POINT_TYPE):
1178 {
1179 LogError("EDM_GEOGRAPHY_POINT_TYPE not implemented");
1180 break;
1181 }
1182 case(EDM_GEOGRAPHY_LINE_STRING_TYPE):
1183 {
1184 LogError("EDM_GEOGRAPHY_LINE_STRING_TYPE not implemented");
1185 break;
1186 }
1187 case(EDM_GEOGRAPHY_POLYGON_TYPE):
1188 {
1189 LogError("EDM_GEOGRAPHY_POLYGON_TYPE not implemented");
1190 break;
1191 }
1192 case(EDM_GEOGRAPHY_MULTI_POINT_TYPE):
1193 {
1194 LogError("EDM_GEOGRAPHY_MULTI_POINT_TYPE not implemented");
1195 break;
1196 }
1197 case(EDM_GEOGRAPHY_MULTI_LINE_STRING_TYPE):
1198 {
1199 LogError("EDM_GEOGRAPHY_MULTI_LINE_STRING_TYPE not implemented");
1200 break;
1201 }
1202 case(EDM_GEOGRAPHY_MULTI_POLYGON_TYPE):
1203 {
1204 LogError("EDM_GEOGRAPHY_MULTI_POLYGON_TYPE");
1205 break;
1206 }
1207 case(EDM_GEOGRAPHY_COLLECTION_TYPE):
1208 {
1209 LogError("EDM_GEOGRAPHY_COLLECTION_TYPE not implemented");
1210 break;
1211 }
1212 case(EDM_GEOMETRY_TYPE):
1213 {
1214 LogError("EDM_GEOMETRY_TYPE not implemented");
1215 break;
1216 }
1217 case(EDM_GEOMETRY_POINT_TYPE):
1218 {
1219 LogError("EDM_GEOMETRY_POINT_TYPE not implemented");
1220 break;
1221 }
1222 case(EDM_GEOMETRY_LINE_STRING_TYPE):
1223 {
1224 LogError("EDM_GEOMETRY_LINE_STRING_TYPE not implemented");
1225 break;
1226 }
1227 case(EDM_GEOMETRY_POLYGON_TYPE):
1228 {
1229 LogError("EDM_GEOMETRY_POLYGON_TYPE not implemented");
1230 break;
1231 }
1232 case(EDM_GEOMETRY_MULTI_POINT_TYPE):
1233 {
1234 LogError("EDM_GEOMETRY_MULTI_POINT_TYPE not implemented");
1235 break;
1236 }
1237 case(EDM_GEOMETRY_MULTI_LINE_STRING_TYPE):
1238 {
1239 LogError("EDM_GEOMETRY_MULTI_LINE_STRING_TYPE not implemented");
1240 break;
1241 }
1242 case(EDM_GEOMETRY_MULTI_POLYGON_TYPE):
1243 {
1244 LogError("EDM_GEOMETRY_MULTI_POLYGON_TYPE not implemented");
1245 break;
1246 }
1247 case(EDM_GEOMETRY_COLLECTION_TYPE):
1248 {
1249 LogError("EDM_GEOMETRY_COLLECTION_TYPE not implemented");
1250 break;
1251 }
1252 case(EDM_SINGLE_TYPE):
1253 {
1254 break;
1255 }
1256 case(EDM_DOUBLE_TYPE):
1257 {
1258 break;
1259 }
1260 case (EDM_COMPLEX_TYPE_TYPE):
1261 {
1262 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_050:[Destroy_AGENT_DATA_TYPE shall deallocate all allocated resources used to represent the type.]*/
1263 size_t i;
1264 for (i = 0; i < agentData->value.edmComplexType.nMembers; i++)
1265 {
1266 free((void*)(agentData->value.edmComplexType.fields[i].fieldName));
1267 agentData->value.edmComplexType.fields[i].fieldName = NULL;
1268 Destroy_AGENT_DATA_TYPE(agentData->value.edmComplexType.fields[i].value);
1269 free(agentData->value.edmComplexType.fields[i].value);
1270 agentData->value.edmComplexType.fields[i].value = NULL;
1271 }
1272 free(agentData->value.edmComplexType.fields);
1273 break;
1274 }
1275 }
1276 agentData->type = EDM_NO_TYPE; /*mark as detroyed*/
1277 }
1278}
1279
1280static char hexDigitToChar(uint8_t hexDigit)
1281{
1282 if (hexDigit < 10) return '0' + hexDigit;
1283 else return ('A' - 10) + hexDigit;
1284}
1285
1286AGENT_DATA_TYPES_RESULT AgentDataTypes_ToString(STRING_HANDLE destination, const AGENT_DATA_TYPE* value)
1287{
1288 AGENT_DATA_TYPES_RESULT result;
1289
1290 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_015:[If destination parameter is NULL, AgentDataTypes_ToString shall return AGENT_DATA_TYPES_INVALID_ARG.]*/
1291 if(destination == NULL)
1292 {
1293 result = AGENT_DATA_TYPES_INVALID_ARG;
1294 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1295 }
1296 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_053:[ If value is NULL or has been destroyed or otherwise doesn't contain valid data, AGENT_DATA_TYPES_INVALID_ARG shall be returned.]*/
1297 else if (value == NULL)
1298 {
1299 result = AGENT_DATA_TYPES_INVALID_ARG;
1300 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1301 }
1302 else
1303 {
1304 switch(value->type)
1305 {
1306 default:
1307 {
1308 result = AGENT_DATA_TYPES_INVALID_ARG;
1309 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1310 break;
1311 }
1312 case(EDM_NULL_TYPE) :
1313 {
1314 /*SRS_AGENT_TYPE_SYSTEM_99_101:[ EDM_NULL_TYPE shall return the unquoted string null.]*/
1315 if (STRING_concat(destination, "null") != 0)
1316 {
1317 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
1318 result = AGENT_DATA_TYPES_ERROR;
1319 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1320 }
1321 else
1322 {
1323 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_014:[ All functions shall return AGENT_DATA_TYPES_OK when the processing is successful.]*/
1324 result = AGENT_DATA_TYPES_OK;
1325 }
1326 break;
1327 }
1328 case(EDM_BOOLEAN_TYPE) :
1329 {
1330 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_017:[EDM_BOOLEAN:as in(odata - abnf - construction - rules, 2013), booleanValue = "true" / "false"]*/
1331 if (value->value.edmBoolean.value == EDM_TRUE)
1332 {
1333 /*SRS_AGENT_TYPE_SYSTEM_99_030:[If v is different than 0 then the AGENT_DATA_TYPE shall have the value "true".]*/
1334 if (STRING_concat(destination, "true") != 0)
1335 {
1336 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
1337 result = AGENT_DATA_TYPES_ERROR;
1338 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1339 }
1340 else
1341 {
1342 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_014:[ All functions shall return AGENT_DATA_TYPES_OK when the processing is successful.]*/
1343 result = AGENT_DATA_TYPES_OK;
1344 }
1345 }
1346 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_017:[EDM_BOOLEAN:as in(odata - abnf - construction - rules, 2013), booleanValue = "true" / "false"]*/
1347 else if (value->value.edmBoolean.value == EDM_FALSE)
1348 {
1349 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_029:[ If v 0 then the AGENT_DATA_TYPE shall have the value "false" Boolean.]*/
1350 if (STRING_concat(destination, "false") != 0)
1351 {
1352 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
1353 result = AGENT_DATA_TYPES_ERROR;
1354 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1355 }
1356 else
1357 {
1358 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_014:[ All functions shall return AGENT_DATA_TYPES_OK when the processing is successful.]*/
1359 result = AGENT_DATA_TYPES_OK;
1360 }
1361 }
1362 else
1363 {
1364 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_053:[ If value contains invalid data, AgentDataTypes_ToString shall return AGENT_DATA_TYPES_INVALID_ARG.]*/
1365 result = AGENT_DATA_TYPES_INVALID_ARG;
1366 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1367 }
1368
1369 break;
1370 }
1371 case(EDM_BYTE_TYPE) :
1372 {
1373 char tempbuffer2[4]; /*because bytes can at most be 255 and that is 3 characters + 1 for '\0'*/
1374 size_t pos = 0;
1375 if (value->value.edmByte.value >= 100) tempbuffer2[pos++] = '0' + (value->value.edmByte.value / 100);
1376 if (value->value.edmByte.value >= 10) tempbuffer2[pos++] = '0' + (value->value.edmByte.value % 100) / 10;
1377 tempbuffer2[pos++] = '0' + (value->value.edmByte.value % 10);
1378 tempbuffer2[pos++] = '\0';
1379
1380 if (STRING_concat(destination, tempbuffer2) != 0)
1381 {
1382 result = AGENT_DATA_TYPES_ERROR;
1383 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1384 }
1385 else
1386 {
1387 result = AGENT_DATA_TYPES_OK;
1388 }
1389 break;
1390 }
1391 case(EDM_DATE_TYPE) :
1392 {
1393 size_t pos = 0;
1394 char tempBuffer2[1 + 5 + 1 + 2 + 1 + 2 + 1+1];
1395 int16_t year = value->value.edmDate.year;
1396 tempBuffer2[pos++] = '\"';
1397 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_068:[ EDM_DATE: dateValue = year "-" month "-" day.]*/
1398 if (year < 0)
1399 {
1400 tempBuffer2[pos++] = '-';
1401 year = -year;
1402 }
1403
1404 tempBuffer2[pos++] = '0' + (char)(year / 1000);
1405 tempBuffer2[pos++] = '0' + (char)((year % 1000) / 100);
1406 tempBuffer2[pos++] = '0' + (char)((year % 100) / 10);
1407 tempBuffer2[pos++] = '0' + (char)(year % 10);
1408 tempBuffer2[pos++] = '-';
1409 tempBuffer2[pos++] = '0' + value->value.edmDate.month / 10;
1410 tempBuffer2[pos++] = '0' + value->value.edmDate.month % 10;
1411 tempBuffer2[pos++] = '-';
1412 tempBuffer2[pos++] = '0' + value->value.edmDate.day / 10;
1413 tempBuffer2[pos++] = '0' + value->value.edmDate.day % 10;
1414 tempBuffer2[pos++] = '\"';
1415 tempBuffer2[pos++] = '\0';
1416
1417 if (STRING_concat(destination, tempBuffer2) != 0)
1418 {
1419 result = AGENT_DATA_TYPES_ERROR;
1420 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1421 }
1422 else
1423 {
1424 result = AGENT_DATA_TYPES_OK;
1425 }
1426 break;
1427 }
1428 case (EDM_DATE_TIME_OFFSET_TYPE):
1429 {
1430 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_019:[ EDM_DATETIMEOFFSET: dateTimeOffsetValue = year "-" month "-" day "T" hour ":" minute [ ":" second [ "." fractionalSeconds ] ] ( "Z" / sign hour ":" minute )]*/
1431 /*from ABNF seems like these numbers HAVE to be padded with zeroes*/
1432 if (value->value.edmDateTimeOffset.hasTimeZone)
1433 {
1434 if (value->value.edmDateTimeOffset.hasFractionalSecond)
1435 {
1436 size_t tempBufferSize = 1 + // \"
1437 MAX_LONG_STRING_LENGTH + // %.4d
1438 1 + // -
1439 MAX_LONG_STRING_LENGTH + // %.2d
1440 1 + // -
1441 MAX_LONG_STRING_LENGTH + // %.2d
1442 1 + // T
1443 MAX_LONG_STRING_LENGTH + // %.2d
1444 1 + // :
1445 MAX_LONG_STRING_LENGTH + // %.2d
1446 1 + // :
1447 MAX_LONG_STRING_LENGTH + // %.2d
1448 1 + // .
1449 MAX_ULONG_LONG_STRING_LENGTH + // %.12llu
1450 1 + MAX_LONG_STRING_LENGTH + // %+.2d
1451 1 + // :
1452 MAX_LONG_STRING_LENGTH + // %.2d
1453 1 + //\"
1454 1; // " (terminating NULL);
1455
1456 char* tempBuffer = (char*)malloc(tempBufferSize);
1457 if (tempBuffer == NULL)
1458 {
1459 result = AGENT_DATA_TYPES_ERROR;
1460 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1461 }
1462 else
1463 {
1464 if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.12llu%+.2d:%.2d\"", /*+ in printf forces the sign to appear*/
1465 value->value.edmDateTimeOffset.dateTime.tm_year+1900,
1466 value->value.edmDateTimeOffset.dateTime.tm_mon+1,
1467 value->value.edmDateTimeOffset.dateTime.tm_mday,
1468 value->value.edmDateTimeOffset.dateTime.tm_hour,
1469 value->value.edmDateTimeOffset.dateTime.tm_min,
1470 value->value.edmDateTimeOffset.dateTime.tm_sec,
1471 value->value.edmDateTimeOffset.fractionalSecond,
1472 value->value.edmDateTimeOffset.timeZoneHour,
1473 value->value.edmDateTimeOffset.timeZoneMinute) < 0)
1474 {
1475 result = AGENT_DATA_TYPES_ERROR;
1476 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1477 }
1478 else if (STRING_concat(destination, tempBuffer) != 0)
1479 {
1480 result = AGENT_DATA_TYPES_ERROR;
1481 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1482 }
1483 else
1484 {
1485 result = AGENT_DATA_TYPES_OK;
1486 }
1487
1488 // Clean up temp buffer if allocated
1489 free(tempBuffer);
1490 }
1491 }
1492 else
1493 {
1494 size_t tempBufferSize = 1 + // \"
1495 MAX_LONG_STRING_LENGTH + // %.4d
1496 1 + // -
1497 MAX_LONG_STRING_LENGTH + // %.2d
1498 1 + // -
1499 MAX_LONG_STRING_LENGTH + // %.2d
1500 1 + // T
1501 MAX_LONG_STRING_LENGTH + // %.2d
1502 1 + // :
1503 MAX_LONG_STRING_LENGTH + // %.2d
1504 1 + // :
1505 MAX_LONG_STRING_LENGTH + // %.2d
1506 1 + MAX_LONG_STRING_LENGTH + // %+.2d
1507 1 + // :
1508 MAX_LONG_STRING_LENGTH + // %.2d
1509 1 + // \"
1510 1; // " terminating NULL
1511 char* tempBuffer = (char*)malloc(tempBufferSize);
1512
1513 if (tempBuffer == NULL)
1514 {
1515 result = AGENT_DATA_TYPES_ERROR;
1516 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1517 }
1518 else
1519 {
1520 if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d%+.2d:%.2d\"", /*+ in printf forces the sign to appear*/
1521 value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
1522 value->value.edmDateTimeOffset.dateTime.tm_mon+1,
1523 value->value.edmDateTimeOffset.dateTime.tm_mday,
1524 value->value.edmDateTimeOffset.dateTime.tm_hour,
1525 value->value.edmDateTimeOffset.dateTime.tm_min,
1526 value->value.edmDateTimeOffset.dateTime.tm_sec,
1527 value->value.edmDateTimeOffset.timeZoneHour,
1528 value->value.edmDateTimeOffset.timeZoneMinute) < 0)
1529 {
1530 result = AGENT_DATA_TYPES_ERROR;
1531 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1532 }
1533 else if (STRING_concat(destination, tempBuffer) != 0)
1534 {
1535 result = AGENT_DATA_TYPES_ERROR;
1536 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1537 }
1538 else
1539 {
1540 result = AGENT_DATA_TYPES_OK;
1541 }
1542
1543 // Clean up temp buffer if allocated
1544 free(tempBuffer);
1545 }
1546 }
1547 }
1548 else
1549 {
1550 if (value->value.edmDateTimeOffset.hasFractionalSecond)
1551 {
1552 size_t tempBufferSize = 1 + //\"
1553 MAX_LONG_STRING_LENGTH + // %.4d
1554 1 + // -
1555 MAX_LONG_STRING_LENGTH + // %.2d
1556 1 + // -
1557 MAX_LONG_STRING_LENGTH + // %.2d
1558 1 + // T
1559 MAX_LONG_STRING_LENGTH + // %.2d
1560 1 + // :
1561 MAX_LONG_STRING_LENGTH + // %.2d
1562 1 + // :
1563 MAX_LONG_STRING_LENGTH + // %.2d
1564 1 + // .
1565 MAX_ULONG_LONG_STRING_LENGTH + // %.12llu
1566 1 + // Z
1567 1 + // \"
1568 1; // " (terminating NULL)
1569 char* tempBuffer = (char*)malloc(tempBufferSize);
1570
1571 if (tempBuffer == NULL)
1572 {
1573 result = AGENT_DATA_TYPES_ERROR;
1574 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1575 }
1576 else
1577 {
1578 if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.12lluZ\"", /*+ in printf forces the sign to appear*/
1579 value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
1580 value->value.edmDateTimeOffset.dateTime.tm_mon+1,
1581 value->value.edmDateTimeOffset.dateTime.tm_mday,
1582 value->value.edmDateTimeOffset.dateTime.tm_hour,
1583 value->value.edmDateTimeOffset.dateTime.tm_min,
1584 value->value.edmDateTimeOffset.dateTime.tm_sec,
1585 value->value.edmDateTimeOffset.fractionalSecond) < 0)
1586 {
1587 result = AGENT_DATA_TYPES_ERROR;
1588 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1589 }
1590 else if (STRING_concat(destination, tempBuffer) != 0)
1591 {
1592 result = AGENT_DATA_TYPES_ERROR;
1593 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1594 }
1595 else
1596 {
1597 result = AGENT_DATA_TYPES_OK;
1598 }
1599
1600 free(tempBuffer);
1601 }
1602 }
1603 else
1604 {
1605 size_t tempBufferSize = 1 + // \"
1606 MAX_LONG_STRING_LENGTH + // %.4d
1607 1 + // -
1608 MAX_LONG_STRING_LENGTH + // %.2d
1609 1 + // -
1610 MAX_LONG_STRING_LENGTH + // %.2d
1611 1 + // T
1612 MAX_LONG_STRING_LENGTH + // %.2d
1613 1 + // :
1614 MAX_LONG_STRING_LENGTH + // %.2d
1615 1 + // :
1616 MAX_LONG_STRING_LENGTH + // %.2d
1617 1 + // Z
1618 1 + // \"
1619 1; // " (terminating null);
1620
1621 char* tempBuffer = (char*)malloc(tempBufferSize);
1622
1623 if (tempBuffer == NULL)
1624 {
1625 result = AGENT_DATA_TYPES_ERROR;
1626 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1627 }
1628 else
1629 {
1630 if (sprintf_s(tempBuffer, tempBufferSize, "\"%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ\"",
1631 value->value.edmDateTimeOffset.dateTime.tm_year + 1900,
1632 value->value.edmDateTimeOffset.dateTime.tm_mon+1,
1633 value->value.edmDateTimeOffset.dateTime.tm_mday,
1634 value->value.edmDateTimeOffset.dateTime.tm_hour,
1635 value->value.edmDateTimeOffset.dateTime.tm_min,
1636 value->value.edmDateTimeOffset.dateTime.tm_sec) < 0)
1637 {
1638 result = AGENT_DATA_TYPES_ERROR;
1639 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1640 }
1641 else if (STRING_concat(destination, tempBuffer) != 0)
1642 {
1643 result = AGENT_DATA_TYPES_ERROR;
1644 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1645 }
1646 else
1647 {
1648 result = AGENT_DATA_TYPES_OK;
1649 }
1650
1651 free(tempBuffer);
1652 }
1653 }
1654 }
1655 break;
1656 }
1657 case(EDM_DECIMAL_TYPE) :
1658 {
1659 if (STRING_concat_with_STRING(destination, value->value.edmDecimal.value) != 0)
1660 {
1661 result = AGENT_DATA_TYPES_ERROR;
1662 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1663 }
1664 else
1665 {
1666 result = AGENT_DATA_TYPES_OK;
1667 }
1668 break;
1669 }
1670 case (EDM_INT16_TYPE) :
1671 {
1672 /*-32768 to +32767*/
1673 char buffertemp2[7]; /*because 5 digits and sign and '\0'*/
1674 uint16_t positiveValue;
1675 size_t pos = 0;
1676 uint16_t rank = (uint16_t)10000;
1677 bool foundFirstDigit = false;
1678
1679 if (value->value.edmInt16.value < 0)
1680 {
1681 buffertemp2[pos++] = '-';
1682 positiveValue = -value->value.edmInt16.value;
1683 }
1684 else
1685 {
1686 positiveValue = value->value.edmInt16.value;
1687 }
1688
1689 while (rank >= 10)
1690 {
1691 if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
1692 {
1693 buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
1694 foundFirstDigit = true;
1695 }
1696 positiveValue %= rank;
1697 rank /= 10;
1698 }
1699 buffertemp2[pos++] = '0' + (char)(positiveValue);
1700 buffertemp2[pos++] = '\0';
1701
1702 if (STRING_concat(destination, buffertemp2) != 0)
1703 {
1704 result = AGENT_DATA_TYPES_ERROR;
1705 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1706 }
1707 else
1708 {
1709 result = AGENT_DATA_TYPES_OK;
1710 }
1711 break;
1712 }
1713 case (EDM_INT32_TYPE) :
1714 {
1715 /*-2147483648 to +2147483647*/
1716 char buffertemp2[12]; /*because 10 digits and sign and '\0'*/
1717 uint32_t positiveValue;
1718 size_t pos = 0;
1719 uint32_t rank = 1000000000UL;
1720 bool foundFirstDigit = false;
1721
1722 if (value->value.edmInt32.value < 0)
1723 {
1724 buffertemp2[pos++] = '-';
1725 positiveValue = - value->value.edmInt32.value;
1726 }
1727 else
1728 {
1729 positiveValue = value->value.edmInt32.value;
1730 }
1731
1732 while (rank >= 10)
1733 {
1734 if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
1735 {
1736 buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
1737 foundFirstDigit = true;
1738 }
1739 positiveValue %= rank;
1740 rank /= 10;
1741 }
1742 buffertemp2[pos++] = '0' + (char)(positiveValue);
1743 buffertemp2[pos++] = '\0';
1744
1745 if (STRING_concat(destination, buffertemp2) != 0)
1746 {
1747 result = AGENT_DATA_TYPES_ERROR;
1748 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1749 }
1750 else
1751 {
1752 result = AGENT_DATA_TYPES_OK;
1753 }
1754 break;
1755 }
1756 case (EDM_INT64_TYPE):
1757 {
1758 char buffertemp2[21]; /*because 19 digits and sign and '\0'*/
1759 uint64_t positiveValue;
1760 size_t pos = 0;
1761 uint64_t rank = 10000000000000000000ULL;
1762 bool foundFirstDigit = false;
1763
1764 if (value->value.edmInt64.value < 0)
1765 {
1766 buffertemp2[pos++] = '-';
1767 positiveValue = -value->value.edmInt64.value;
1768 }
1769 else
1770 {
1771 positiveValue = value->value.edmInt64.value;
1772 }
1773
1774 while (rank >= 10)
1775 {
1776 if ((foundFirstDigit == true) || (positiveValue / rank) > 0)
1777 {
1778 buffertemp2[pos++] = '0' + (char)(positiveValue / rank);
1779 foundFirstDigit = true;
1780 }
1781 positiveValue %= rank;
1782 rank /= 10;
1783 }
1784 buffertemp2[pos++] = '0' + (char)(positiveValue);
1785 buffertemp2[pos++] = '\0';
1786
1787 if (STRING_concat(destination, buffertemp2) != 0)
1788 {
1789 result = AGENT_DATA_TYPES_ERROR;
1790 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1791 }
1792 else
1793 {
1794 result = AGENT_DATA_TYPES_OK;
1795 }
1796 break;
1797 }
1798 case (EDM_SBYTE_TYPE) :
1799 {
1800 char tempbuffer2[5]; /* because '-' and 3 characters for 127 let's say and '\0'*/
1801 int absValue = value->value.edmSbyte.value;
1802 size_t pos=0;
1803 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_026:[ EDM_SBYTE: sbyteValue = [ sign ] 1*3DIGIT ; numbers in the range from -128 to 127]*/
1804
1805 if (value->value.edmSbyte.value < 0)
1806 {
1807 tempbuffer2[pos++] = '-';
1808 absValue = -absValue;
1809 }
1810
1811 if (absValue >= 100 ) tempbuffer2[pos++] = '0' + (char)(absValue / 100);
1812 if (absValue >=10) tempbuffer2[pos++] = '0' + (absValue % 100) / 10;
1813 tempbuffer2[pos++] = '0' + (absValue % 10);
1814 tempbuffer2[pos++] = '\0';
1815
1816
1817 if (STRING_concat(destination, tempbuffer2) != 0)
1818 {
1819 result = AGENT_DATA_TYPES_ERROR;
1820 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1821 }
1822 else
1823 {
1824 result = AGENT_DATA_TYPES_OK;
1825 }
1826 break;
1827 }
1828 case (EDM_STRING_TYPE):
1829 {
1830 size_t i;
1831 size_t nControlCharacters = 0; /*counts how many characters are to be expanded from 1 character to \uxxxx (6 characters)*/
1832 size_t nEscapeCharacters = 0;
1833 size_t vlen = value->value.edmString.length;
1834 char* v = value->value.edmString.chars;
1835
1836 for (i = 0; i < vlen; i++)
1837 {
1838 if ((unsigned char)v[i] >= 128) /*this be a UNICODE character begin*/
1839 {
1840 break;
1841 }
1842 else
1843 {
1844 if (v[i] <= 0x1F)
1845 {
1846 nControlCharacters++;
1847 }
1848 else if (
1849 (v[i] == '"') ||
1850 (v[i] == '\\') ||
1851 (v[i] == '/')
1852 )
1853 {
1854 nEscapeCharacters++;
1855 }
1856 }
1857 }
1858
1859 if (i < vlen)
1860 {
1861 result = AGENT_DATA_TYPES_INVALID_ARG; /*don't handle those who do not copy bit by bit to UTF8*/
1862 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1863 }
1864 else
1865 {
1866 /*forward parse the string to scan for " and for \ that in JSON are \" respectively \\*/
1867 size_t tempBufferSize = vlen + 5 * nControlCharacters + nEscapeCharacters + 3 + 1;
1868 char* tempBuffer = (char*)malloc(tempBufferSize);
1869 if (tempBuffer == NULL)
1870 {
1871 result = AGENT_DATA_TYPES_ERROR;
1872 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1873 }
1874 else
1875 {
1876 size_t w = 0;
1877 tempBuffer[w++] = '"';
1878 for (i = 0; i < vlen; i++)
1879 {
1880 if (v[i] <= 0x1F)
1881 {
1882 tempBuffer[w++] = '\\';
1883 tempBuffer[w++] = 'u';
1884 tempBuffer[w++] = '0';
1885 tempBuffer[w++] = '0';
1886 tempBuffer[w++] = hexToASCII[(v[i] & 0xF0) >> 4]; /*high nibble*/
1887 tempBuffer[w++] = hexToASCII[v[i] & 0x0F]; /*lowNibble nibble*/
1888 }
1889 else if (v[i] == '"')
1890 {
1891 tempBuffer[w++] = '\\';
1892 tempBuffer[w++] = '"';
1893 }
1894 else if (v[i] == '\\')
1895 {
1896 tempBuffer[w++] = '\\';
1897 tempBuffer[w++] = '\\';
1898 }
1899 else if (v[i] == '/')
1900 {
1901 tempBuffer[w++] = '\\';
1902 tempBuffer[w++] = '/';
1903 }
1904 else
1905 {
1906 tempBuffer[w++] = v[i];
1907 }
1908 }
1909
1910#ifdef _MSC_VER
1911#pragma warning(suppress: 6386) /* The test Create_AGENT_DATA_TYPE_from_charz_With_2_Slashes_Succeeds verifies that Code Analysis is wrong here */
1912#endif
1913 tempBuffer[w] = '"';
1914 /*zero terminating it*/
1915 tempBuffer[vlen + 5 * nControlCharacters + nEscapeCharacters + 3 - 1] = '\0';
1916
1917 if (STRING_concat(destination, tempBuffer) != 0)
1918 {
1919 result = AGENT_DATA_TYPES_ERROR;
1920 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1921 }
1922 else
1923 {
1924 result = AGENT_DATA_TYPES_OK;
1925 }
1926
1927 free(tempBuffer);
1928 }
1929 }
1930
1931 break;
1932 }
1933
1934 /* Codes_SRS_AGENT_TYPE_SYSTEM_01_003: [EDM_STRING_no_quotes: the string is copied as given when the AGENT_DATA_TYPE was created.] */
1935 case (EDM_STRING_NO_QUOTES_TYPE) :
1936 {
1937 /* this is a special case where we just want to copy/paste the contents, no encoding, no quotes */
1938 /* Codes_SRS_AGENT_TYPE_SYSTEM_01_002: [When serialized, this type is not enclosed with quotes.] */
1939 if (STRING_concat(destination, value->value.edmStringNoQuotes.chars) != 0)
1940 {
1941 result = AGENT_DATA_TYPES_ERROR;
1942 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1943 }
1944 else
1945 {
1946 result = AGENT_DATA_TYPES_OK;
1947 }
1948
1949 break;
1950 }
1951
1952#ifndef NO_FLOATS
1953 case(EDM_SINGLE_TYPE):
1954 {
1955 /*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*/
1956 /*I read that as : when a float is NaN or Inf, it will stay NaN or INF in double representation*/
1957
1958 /*The sprintf function returns the number of characters written in the array, not counting the terminating null character.*/
1959
1960 if(ISNAN(value->value.edmSingle.value))
1961 {
1962 if (STRING_concat(destination, NaN_STRING) != 0)
1963 {
1964 result = AGENT_DATA_TYPES_ERROR;
1965 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1966 }
1967 else
1968 {
1969 result = AGENT_DATA_TYPES_OK;
1970 }
1971 }
1972 else if (ISNEGATIVEINFINITY(value->value.edmSingle.value))
1973 {
1974 if (STRING_concat(destination, MINUSINF_STRING) != 0)
1975 {
1976 result = AGENT_DATA_TYPES_ERROR;
1977 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1978 }
1979 else
1980 {
1981 result = AGENT_DATA_TYPES_OK;
1982 }
1983 }
1984 else if (ISPOSITIVEINFINITY(value->value.edmSingle.value))
1985 {
1986 if (STRING_concat(destination, PLUSINF_STRING) != 0)
1987 {
1988 result = AGENT_DATA_TYPES_ERROR;
1989 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
1990 }
1991 else
1992 {
1993 result = AGENT_DATA_TYPES_OK;
1994 }
1995 }
1996 else
1997 {
1998 size_t tempBufferSize = MAX_FLOATING_POINT_STRING_LENGTH;
1999 char* tempBuffer = (char*)malloc(tempBufferSize);
2000 if (tempBuffer == NULL)
2001 {
2002 result = AGENT_DATA_TYPES_ERROR;
2003 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2004 }
2005 else
2006 {
2007 if (sprintf_s(tempBuffer, tempBufferSize, "%.*f", FLT_DIG, (double)(value->value.edmSingle.value)) < 0)
2008 {
2009 result = AGENT_DATA_TYPES_ERROR;
2010 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2011 }
2012 else if (STRING_concat(destination, tempBuffer) != 0)
2013 {
2014 result = AGENT_DATA_TYPES_ERROR;
2015 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2016 }
2017 else
2018 {
2019 result = AGENT_DATA_TYPES_OK;
2020 }
2021
2022 free(tempBuffer);
2023 }
2024 }
2025 break;
2026 }
2027 case(EDM_DOUBLE_TYPE):
2028 {
2029 /*The sprintf function returns the number of characters written in the array, not counting the terminating null character.*/
2030 /*OData-ABNF says these can be used: nanInfinity = 'NaN' / '-INF' / 'INF'*/
2031 /*C90 doesn't declare a NaN or Inf in the standard, however, values might be NaN or Inf...*/
2032 /*C99 ... does*/
2033 /*C11 is same as C99*/
2034 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_022:[ EDM_DOUBLE: doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits). The representation shall use DBL_DIG C #define*/
2035 if(ISNAN(value->value.edmDouble.value))
2036 {
2037 if (STRING_concat(destination, NaN_STRING) != 0)
2038 {
2039 result = AGENT_DATA_TYPES_ERROR;
2040 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2041 }
2042 else
2043 {
2044 result = AGENT_DATA_TYPES_OK;
2045 }
2046 }
2047 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_022:[ EDM_DOUBLE: doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits). The representation shall use DBL_DIG C #define*/
2048 else if (ISNEGATIVEINFINITY(value->value.edmDouble.value))
2049 {
2050 if (STRING_concat(destination, MINUSINF_STRING) != 0)
2051 {
2052 result = AGENT_DATA_TYPES_ERROR;
2053 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2054 }
2055 else
2056 {
2057 result = AGENT_DATA_TYPES_OK;
2058 }
2059 }
2060 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_022:[ EDM_DOUBLE: doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits). The representation shall use DBL_DIG C #define*/
2061 else if (ISPOSITIVEINFINITY(value->value.edmDouble.value))
2062 {
2063 if (STRING_concat(destination, PLUSINF_STRING) != 0)
2064 {
2065 result = AGENT_DATA_TYPES_ERROR;
2066 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2067 }
2068 else
2069 {
2070 result = AGENT_DATA_TYPES_OK;
2071 }
2072 }
2073 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_022:[ EDM_DOUBLE: doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits). The representation shall use DBL_DIG C #define*/
2074 else
2075 {
2076 size_t tempBufferSize = DECIMAL_DIG * 2;
2077 char* tempBuffer = (char*)malloc(tempBufferSize);
2078 if (tempBuffer == NULL)
2079 {
2080 result = AGENT_DATA_TYPES_ERROR;
2081 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2082 }
2083 else
2084 {
2085 if (sprintf_s(tempBuffer, tempBufferSize, "%.*f", DBL_DIG, value->value.edmDouble.value) < 0)
2086 {
2087 result = AGENT_DATA_TYPES_ERROR;
2088 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2089 }
2090 else if (STRING_concat(destination, tempBuffer) != 0)
2091 {
2092 result = AGENT_DATA_TYPES_ERROR;
2093 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2094 }
2095 else
2096 {
2097 result = AGENT_DATA_TYPES_OK;
2098 }
2099
2100 free(tempBuffer);
2101 }
2102 }
2103 break;
2104 }
2105#endif
2106
2107 case(EDM_COMPLEX_TYPE_TYPE) :
2108 {
2109 /*to produce an EDM_COMPLEX_TYPE is a recursive process*/
2110 /*uses JSON encoder*/
2111 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_062:[ If the AGENT_DATA_TYPE represents a "complex type", then the JSON marshaller shall produce the following JSON value:[...]*/
2112 MULTITREE_HANDLE treeHandle;
2113 result = AGENT_DATA_TYPES_OK;
2114 /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
2115 treeHandle = MultiTree_Create(NoCloneFunction, NoFreeFunction);
2116 if (treeHandle == NULL)
2117 {
2118 result = AGENT_DATA_TYPES_ERROR;
2119 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2120 }
2121 else
2122 {
2123 size_t i;
2124 for (i = 0; i < value->value.edmComplexType.nMembers; i++)
2125 {
2126 if (MultiTree_AddLeaf(treeHandle, value->value.edmComplexType.fields[i].fieldName, value->value.edmComplexType.fields[i].value) != MULTITREE_OK)
2127 {
2128 /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
2129 result = AGENT_DATA_TYPES_ERROR;
2130 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2131 break;
2132 }
2133 else
2134 {
2135 /*all is fine*/
2136 }
2137 }
2138
2139 if (result == AGENT_DATA_TYPES_OK)
2140 {
2141 /*SRS_AGENT_TYPE_SYSTEM_99_016:[ When the value cannot be converted to a string AgentDataTypes_ToString shall return AGENT_DATA_TYPES_ERROR.]*/
2142 if (JSONEncoder_EncodeTree(treeHandle, destination, (JSON_ENCODER_TOSTRING_FUNC)AgentDataTypes_ToString) != JSON_ENCODER_OK)
2143 {
2144 result = AGENT_DATA_TYPES_ERROR;
2145 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2146 }
2147 else
2148 {
2149 /*all is fine*/
2150 }
2151
2152 }
2153
2154 MultiTree_Destroy(treeHandle);
2155 }
2156 break;
2157 }
2158 case EDM_GUID_TYPE:
2159 {
2160 char tempBuffer2[1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1+ 1];
2161 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_093:[ EDM_GUID: 8HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 12HEXDIG]*/
2162 tempBuffer2[0] = '\"';
2163 tempBuffer2[1] = hexDigitToChar(value->value.edmGuid.GUID[0] / 16);
2164 tempBuffer2[2] = hexDigitToChar(value->value.edmGuid.GUID[0] % 16);
2165 tempBuffer2[3] = hexDigitToChar(value->value.edmGuid.GUID[1] / 16);
2166 tempBuffer2[4] = hexDigitToChar(value->value.edmGuid.GUID[1] % 16);
2167 tempBuffer2[5] = hexDigitToChar(value->value.edmGuid.GUID[2] / 16);
2168 tempBuffer2[6] = hexDigitToChar(value->value.edmGuid.GUID[2] % 16);
2169 tempBuffer2[7] = hexDigitToChar(value->value.edmGuid.GUID[3] / 16);
2170 tempBuffer2[8] = hexDigitToChar(value->value.edmGuid.GUID[3] % 16);
2171
2172 tempBuffer2[9] = '-';
2173 tempBuffer2[10] = hexDigitToChar(value->value.edmGuid.GUID[4] / 16);
2174 tempBuffer2[11] = hexDigitToChar(value->value.edmGuid.GUID[4] % 16);
2175 tempBuffer2[12] = hexDigitToChar(value->value.edmGuid.GUID[5] / 16);
2176 tempBuffer2[13] = hexDigitToChar(value->value.edmGuid.GUID[5] % 16);
2177
2178 tempBuffer2[14] = '-';
2179 tempBuffer2[15] = hexDigitToChar(value->value.edmGuid.GUID[6] / 16);
2180 tempBuffer2[16] = hexDigitToChar(value->value.edmGuid.GUID[6] % 16);
2181 tempBuffer2[17] = hexDigitToChar(value->value.edmGuid.GUID[7] / 16);
2182 tempBuffer2[18] = hexDigitToChar(value->value.edmGuid.GUID[7] % 16);
2183
2184 tempBuffer2[19] = '-';
2185 tempBuffer2[20] = hexDigitToChar(value->value.edmGuid.GUID[8] / 16);
2186 tempBuffer2[21] = hexDigitToChar(value->value.edmGuid.GUID[8] % 16);
2187 tempBuffer2[22] = hexDigitToChar(value->value.edmGuid.GUID[9] / 16);
2188 tempBuffer2[23] = hexDigitToChar(value->value.edmGuid.GUID[9] % 16);
2189
2190 tempBuffer2[24] = '-';
2191 tempBuffer2[25] = hexDigitToChar(value->value.edmGuid.GUID[10] / 16);
2192 tempBuffer2[26] = hexDigitToChar(value->value.edmGuid.GUID[10] % 16);
2193 tempBuffer2[27] = hexDigitToChar(value->value.edmGuid.GUID[11] / 16);
2194 tempBuffer2[28] = hexDigitToChar(value->value.edmGuid.GUID[11] % 16);
2195 tempBuffer2[29] = hexDigitToChar(value->value.edmGuid.GUID[12] / 16);
2196 tempBuffer2[30] = hexDigitToChar(value->value.edmGuid.GUID[12] % 16);
2197 tempBuffer2[31] = hexDigitToChar(value->value.edmGuid.GUID[13] / 16);
2198 tempBuffer2[32] = hexDigitToChar(value->value.edmGuid.GUID[13] % 16);
2199 tempBuffer2[33] = hexDigitToChar(value->value.edmGuid.GUID[14] / 16);
2200 tempBuffer2[34] = hexDigitToChar(value->value.edmGuid.GUID[14] % 16);
2201 tempBuffer2[35] = hexDigitToChar(value->value.edmGuid.GUID[15] / 16);
2202 tempBuffer2[36] = hexDigitToChar(value->value.edmGuid.GUID[15] % 16);
2203
2204 tempBuffer2[37] = '\"';
2205 tempBuffer2[38] = '\0';
2206
2207 if (STRING_concat(destination, tempBuffer2) != 0)
2208 {
2209 result = AGENT_DATA_TYPES_ERROR;
2210 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2211 }
2212 else
2213 {
2214 result = AGENT_DATA_TYPES_OK;
2215 }
2216 break;
2217 }
2218 case EDM_BINARY_TYPE:
2219 {
2220 size_t currentPosition = 0;
2221 char* temp;
2222 /*binary types */
2223 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_099:[EDM_BINARY:= *(4base64char)[base64b16 / base64b8]]*/
2224 /*the following will happen*/
2225 /*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*/
2226 /*2. the remaining characters (1 or 2) shall be encoded.*/
2227 /*there's a level of assumption that 'a' corresponds to 0b000000 and that '_' corresponds to 0b111111*/
2228 /*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*/
2229 /*these are the bits of the 3 normal bytes to be encoded*/
2230 size_t neededSize = 2; /*2 because starting and ending quotes */
2231 neededSize += (value->value.edmBinary.size == 0) ? (0) : ((((value->value.edmBinary.size-1) / 3) + 1) * 4);
2232 neededSize += 1; /*+1 because \0 at the end of the string*/
2233 if ((temp = (char*)malloc(neededSize))==NULL)
2234 {
2235 result = AGENT_DATA_TYPES_ERROR;
2236 }
2237 else
2238 {
2239 /*b0 b1(+1) b2(+2)
2240 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
2241 |----c1---| |----c2---| |----c3---| |----c4---|
2242 */
2243
2244 size_t destinationPointer = 0;
2245 temp[destinationPointer++] = '"';
2246 while (value->value.edmBinary.size - currentPosition >= 3)
2247 {
2248 char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
2249 char c2 = base64char(
2250 ((value->value.edmBinary.data[currentPosition] & 3) << 4) |
2251 (value->value.edmBinary.data[currentPosition + 1] >> 4)
2252 );
2253 char c3 = base64char(
2254 ((value->value.edmBinary.data[currentPosition + 1] & 0x0F) << 2) |
2255 ((value->value.edmBinary.data[currentPosition + 2] >> 6) & 3)
2256 );
2257 char c4 = base64char(
2258 value->value.edmBinary.data[currentPosition + 2] & 0x3F
2259 );
2260 currentPosition += 3;
2261 temp[destinationPointer++] = c1;
2262 temp[destinationPointer++] = c2;
2263 temp[destinationPointer++] = c3;
2264 temp[destinationPointer++] = c4;
2265
2266 }
2267 if (value->value.edmBinary.size - currentPosition == 2)
2268 {
2269 char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
2270 char c2 = base64char(
2271 ((value->value.edmBinary.data[currentPosition] & 0x03) << 4) |
2272 (value->value.edmBinary.data[currentPosition + 1] >> 4)
2273 );
2274 char c3 = base64b16(value->value.edmBinary.data[currentPosition + 1] & 0x0F);
2275 temp[destinationPointer++] = c1;
2276 temp[destinationPointer++] = c2;
2277 temp[destinationPointer++] = c3;
2278 temp[destinationPointer++] = '=';
2279 }
2280 else if (value->value.edmBinary.size - currentPosition == 1)
2281 {
2282 char c1 = base64char(value->value.edmBinary.data[currentPosition] >> 2);
2283 char c2 = base64b8(value->value.edmBinary.data[currentPosition] & 0x03);
2284 temp[destinationPointer++] = c1;
2285 temp[destinationPointer++] = c2;
2286 temp[destinationPointer++] = '=';
2287 temp[destinationPointer++] = '=';
2288 }
2289
2290 /*closing quote*/
2291 temp[destinationPointer++] = '"';
2292 /*null terminating the string*/
2293 temp[destinationPointer] = '\0';
2294
2295 if (STRING_concat(destination, temp) != 0)
2296 {
2297 result = AGENT_DATA_TYPES_ERROR;
2298 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2299 }
2300 else
2301 {
2302 result = AGENT_DATA_TYPES_OK;
2303 }
2304 free(temp);
2305 }
2306 break;
2307 }
2308 }
2309 }
2310 return result;
2311}
2312
2313/*return 0 if all names are different than NULL*/
2314static int isOneNameNULL(size_t nMemberNames, const char* const * memberNames)
2315{
2316 size_t i;
2317 int result = 0;
2318 for (i = 0; i < nMemberNames; i++)
2319 {
2320 if (memberNames[i] == NULL)
2321 {
2322 result = 1;
2323 break;
2324 }
2325 }
2326 return result;
2327}
2328
2329/*return 0 if all names are different than NULL*/
2330static int areThereTwoSameNames(size_t nMemberNames, const char* const * memberNames)
2331{
2332 size_t i, j;
2333 int result = 0;
2334 for (i = 0; i < nMemberNames-1; i++)
2335 {
2336 for (j = i + 1; j < nMemberNames; j++)
2337 {
2338 if (strcmp(memberNames[i], memberNames[j]) == 0)
2339 {
2340 result = 1;
2341 goto out;
2342 }
2343 }
2344 }
2345out:
2346 return result;
2347}
2348
2349static void DestroyHalfBakedComplexType(AGENT_DATA_TYPE* agentData)
2350{
2351 size_t i;
2352 if (agentData != NULL)
2353 {
2354 if (agentData->type == EDM_COMPLEX_TYPE_TYPE)
2355 {
2356 if (agentData->value.edmComplexType.fields != NULL)
2357 {
2358 for (i = 0; i < agentData->value.edmComplexType.nMembers; i++)
2359 {
2360 if (agentData->value.edmComplexType.fields[i].fieldName != NULL)
2361 {
2362 free((void*)(agentData->value.edmComplexType.fields[i].fieldName));
2363 agentData->value.edmComplexType.fields[i].fieldName = NULL;
2364 }
2365 if (agentData->value.edmComplexType.fields[i].value != NULL)
2366 {
2367 Destroy_AGENT_DATA_TYPE(agentData->value.edmComplexType.fields[i].value);
2368 free(agentData->value.edmComplexType.fields[i].value);
2369 agentData->value.edmComplexType.fields[i].value = NULL;
2370 }
2371 }
2372 free(agentData->value.edmComplexType.fields);
2373 agentData->value.edmComplexType.fields = NULL;
2374 }
2375 agentData->type = EDM_NO_TYPE;
2376 }
2377 }
2378}
2379
2380/* Creates an object of AGENT_DATA_TYPE_TYPE EDM_NULL_TYPE*/
2381AGENT_DATA_TYPES_RESULT Create_NULL_AGENT_DATA_TYPE(AGENT_DATA_TYPE* agentData)
2382{
2383 AGENT_DATA_TYPES_RESULT result;
2384 if (agentData == NULL)
2385 {
2386 result = AGENT_DATA_TYPES_INVALID_ARG;
2387 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2388 }
2389 else
2390 {
2391 agentData->type = EDM_NULL_TYPE;
2392 result = AGENT_DATA_TYPES_OK;
2393 }
2394 return result;
2395}
2396/*creates a copy of the AGENT_DATA_TYPE*/
2397AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(AGENT_DATA_TYPE* dest, const AGENT_DATA_TYPE* src)
2398{
2399 AGENT_DATA_TYPES_RESULT result;
2400 size_t i;
2401 if ((dest == NULL) || (src == NULL))
2402 {
2403 result = AGENT_DATA_TYPES_INVALID_ARG;
2404 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2405 }
2406 else
2407 {
2408 switch (src->type)
2409 {
2410 default:
2411 {
2412 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2413 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2414 break;
2415 }
2416 case(EDM_NO_TYPE) :
2417 case(EDM_NULL_TYPE) :
2418 {
2419 dest->type = src->type;
2420 result = AGENT_DATA_TYPES_OK;
2421 break;
2422 }
2423 case(EDM_BOOLEAN_TYPE) :
2424 {
2425 dest->type = src->type;
2426 dest->value.edmBoolean= src->value.edmBoolean;
2427 result = AGENT_DATA_TYPES_OK;
2428 break;
2429 }
2430 case(EDM_BYTE_TYPE) :
2431 {
2432 dest->type = src->type;
2433 dest->value.edmByte= src->value.edmByte;
2434 result = AGENT_DATA_TYPES_OK;
2435 break;
2436 }
2437 case(EDM_DATE_TYPE) :
2438 {
2439 dest->type = src->type;
2440 dest->value.edmDate = src->value.edmDate;
2441 result = AGENT_DATA_TYPES_OK;
2442 break;
2443 }
2444 case(EDM_DATE_TIME_OFFSET_TYPE) :
2445 {
2446 dest->type = src->type;
2447 dest->value.edmDateTimeOffset = src->value.edmDateTimeOffset;
2448 result = AGENT_DATA_TYPES_OK;
2449 break;
2450 }
2451 case(EDM_DECIMAL_TYPE) :
2452 {
2453 if ((dest->value.edmDecimal.value = STRING_clone(src->value.edmDecimal.value)) == NULL)
2454 {
2455 result = AGENT_DATA_TYPES_ERROR;
2456 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2457 }
2458 else
2459 {
2460 dest->type = src->type;
2461 result = AGENT_DATA_TYPES_OK;
2462 /*all is fine*/
2463 }
2464 break;
2465 }
2466 case(EDM_DOUBLE_TYPE) :
2467 {
2468 dest->type = src->type;
2469 dest->value.edmDouble = src->value.edmDouble;
2470 result = AGENT_DATA_TYPES_OK;
2471 break;
2472 }
2473 case(EDM_DURATION_TYPE) :
2474 {
2475 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2476 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2477 break;
2478 }
2479 case(EDM_GUID_TYPE) :
2480 {
2481 dest->type = src->type;
2482 dest->value.edmGuid = src->value.edmGuid;
2483 result = AGENT_DATA_TYPES_OK;
2484 break;
2485 }
2486 case EDM_BINARY_TYPE:
2487 {
2488 if (src->value.edmBinary.size == 0)
2489 {
2490 dest->value.edmBinary.size = 0;
2491 dest->value.edmBinary.data = NULL;
2492 dest->type = EDM_BINARY_TYPE;
2493 result = AGENT_DATA_TYPES_OK;
2494 }
2495 else
2496 {
2497 if ((dest->value.edmBinary.data = (unsigned char*)malloc(src->value.edmBinary.size)) == NULL)
2498 {
2499 result = AGENT_DATA_TYPES_ERROR;
2500 }
2501 else
2502 {
2503 dest->value.edmBinary.size = src->value.edmBinary.size;
2504 (void)memcpy(dest->value.edmBinary.data, src->value.edmBinary.data, src->value.edmBinary.size);
2505 dest->type = EDM_BINARY_TYPE;
2506 result = AGENT_DATA_TYPES_OK;
2507 }
2508 }
2509 break;
2510 }
2511 case(EDM_INT16_TYPE) :
2512 {
2513 dest->type = src->type;
2514 dest->value.edmInt16 = src->value.edmInt16;
2515 result = AGENT_DATA_TYPES_OK;
2516 break;
2517 }
2518 case(EDM_INT32_TYPE) :
2519 {
2520 dest->type = src->type;
2521 dest->value.edmInt32 = src->value.edmInt32;
2522 result = AGENT_DATA_TYPES_OK;
2523 break;
2524 }
2525 case(EDM_INT64_TYPE) :
2526 {
2527 dest->type = src->type;
2528 dest->value.edmInt64 = src->value.edmInt64;
2529 result = AGENT_DATA_TYPES_OK;
2530 break;
2531 }
2532 case(EDM_SBYTE_TYPE) :
2533 {
2534 dest->type = src->type;
2535 dest->value.edmSbyte = src->value.edmSbyte;
2536 result = AGENT_DATA_TYPES_OK;
2537 break;
2538 }
2539 case(EDM_SINGLE_TYPE) :
2540 {
2541 dest->type = src->type;
2542 dest->value.edmSingle = src->value.edmSingle;
2543 result = AGENT_DATA_TYPES_OK;
2544 break;
2545 }
2546 case(EDM_STREAM) :
2547 {
2548 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2549 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2550 break;
2551 } /*not supported, because what is stream?*/
2552 case(EDM_STRING_TYPE) :
2553 {
2554 dest->type = src->type;
2555 dest->value.edmString.length = src->value.edmString.length;
2556 if (mallocAndStrcpy_s((char**)&(dest->value.edmString.chars), (char*)src->value.edmString.chars) != 0)
2557 {
2558 result = AGENT_DATA_TYPES_ERROR;
2559 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2560 }
2561 else
2562 {
2563 result = AGENT_DATA_TYPES_OK;
2564 /*all is fine*/
2565 }
2566 break;
2567 }
2568 case(EDM_STRING_NO_QUOTES_TYPE) :
2569 {
2570 dest->type = src->type;
2571 dest->value.edmStringNoQuotes.length = src->value.edmStringNoQuotes.length;
2572 if (mallocAndStrcpy_s((char**)&(dest->value.edmStringNoQuotes.chars), (char*)src->value.edmStringNoQuotes.chars) != 0)
2573 {
2574 result = AGENT_DATA_TYPES_ERROR;
2575 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2576 }
2577 else
2578 {
2579 result = AGENT_DATA_TYPES_OK;
2580 /*all is fine*/
2581 }
2582 break;
2583 }
2584 case(EDM_TIME_OF_DAY_TYPE) :
2585 {
2586 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2587 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2588 break;
2589 }
2590 case(EDM_GEOGRAPHY_TYPE) :
2591 {
2592 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2593 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2594 break;
2595 } /*not supported because what is "abstract base type"*/
2596 case(EDM_GEOGRAPHY_POINT_TYPE) :
2597 {
2598 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2599 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2600 break;
2601 }
2602 case(EDM_GEOGRAPHY_LINE_STRING_TYPE) :
2603 {
2604 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2605 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2606 break;
2607 }
2608 case(EDM_GEOGRAPHY_POLYGON_TYPE) :
2609 {
2610 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2611 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2612 break;
2613 }
2614 case(EDM_GEOGRAPHY_MULTI_POINT_TYPE) :
2615 {
2616 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2617 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2618 break;
2619 }
2620 case(EDM_GEOGRAPHY_MULTI_LINE_STRING_TYPE) :
2621 {
2622 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2623 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2624 break;
2625 }
2626 case(EDM_GEOGRAPHY_MULTI_POLYGON_TYPE) :
2627 {
2628 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2629 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2630 break;
2631 }
2632 case(EDM_GEOGRAPHY_COLLECTION_TYPE) :
2633 {
2634 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2635 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2636 break;
2637 }
2638 case(EDM_GEOMETRY_TYPE) :
2639 {
2640 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2641 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2642 break;
2643 } /*not supported because what is "abstract base type"*/
2644 case(EDM_GEOMETRY_POINT_TYPE) :
2645 {
2646 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2647 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2648 break;
2649 }
2650 case(EDM_GEOMETRY_LINE_STRING_TYPE) :
2651 {
2652 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2653 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2654 break;
2655 }
2656 case(EDM_GEOMETRY_POLYGON_TYPE) :
2657 {
2658 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2659 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2660 break;
2661 }
2662 case(EDM_GEOMETRY_MULTI_POINT_TYPE) :
2663 {
2664 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2665 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2666 break;
2667 }
2668 case(EDM_GEOMETRY_MULTI_LINE_STRING_TYPE) :
2669 {
2670 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2671 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2672 break;
2673 }
2674 case(EDM_GEOMETRY_MULTI_POLYGON_TYPE) :
2675 {
2676 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2677 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2678 break;
2679 }
2680 case(EDM_GEOMETRY_COLLECTION_TYPE) :
2681 {
2682 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
2683 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2684 break;
2685 }
2686 case(EDM_COMPLEX_TYPE_TYPE) :
2687 {
2688 result = AGENT_DATA_TYPES_OK;
2689 /*copying a COMPLEX_TYPE means to copy all its member names and all its fields*/
2690 dest->type = src->type;
2691 if (src->value.edmComplexType.nMembers == 0)
2692 {
2693 /*error*/
2694 result = AGENT_DATA_TYPES_INVALID_ARG;
2695 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2696 }
2697 else
2698 {
2699 dest->value.edmComplexType.nMembers = src->value.edmComplexType.nMembers;
2700 dest->value.edmComplexType.fields = (COMPLEX_TYPE_FIELD_TYPE*)malloc(dest->value.edmComplexType.nMembers * sizeof(COMPLEX_TYPE_FIELD_TYPE));
2701 if (dest->value.edmComplexType.fields == NULL)
2702 {
2703 result = AGENT_DATA_TYPES_ERROR;
2704 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2705 }
2706 else
2707 {
2708 for (i = 0; i < dest->value.edmComplexType.nMembers; i++)
2709 {
2710 dest->value.edmComplexType.fields[i].fieldName = NULL;
2711 dest->value.edmComplexType.fields[i].value = NULL;
2712 }
2713
2714 for (i = 0; i < dest->value.edmComplexType.nMembers; i++)
2715 {
2716 /*copy the name of this field*/
2717 if (mallocAndStrcpy_s((char**)(&(dest->value.edmComplexType.fields[i].fieldName)), src->value.edmComplexType.fields[i].fieldName) != 0)
2718 {
2719 result = AGENT_DATA_TYPES_ERROR;
2720 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2721 break;
2722 }
2723 else
2724 {
2725 /*field name copied success*/
2726 /*field value copy follows*/
2727 dest->value.edmComplexType.fields[i].value = (AGENT_DATA_TYPE*)calloc(1, sizeof(AGENT_DATA_TYPE));
2728 if (dest->value.edmComplexType.fields[i].value == NULL)
2729 {
2730 result = AGENT_DATA_TYPES_ERROR;
2731 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2732 break;
2733 }
2734 else
2735 {
2736 if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(dest->value.edmComplexType.fields[i].value, src->value.edmComplexType.fields[i].value) != AGENT_DATA_TYPES_OK)
2737 {
2738 result = AGENT_DATA_TYPES_ERROR;
2739 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2740 break;
2741 }
2742 else
2743 {
2744 /*all is fine*/
2745 }
2746 }
2747 }
2748 }
2749
2750 if (result != AGENT_DATA_TYPES_OK)
2751 {
2752 /*unbuild*/
2753 DestroyHalfBakedComplexType(dest);
2754 }
2755 }
2756 }
2757 break;
2758 } /*ANY CHANGE (?!) here must be reflected in the tool providing the binary file (XML2BINARY) */
2759 }
2760
2761 if (result != AGENT_DATA_TYPES_OK)
2762 {
2763 dest->type = EDM_NO_TYPE;
2764 }
2765 }
2766
2767 return result;
2768}
2769
2770AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_MemberPointers(AGENT_DATA_TYPE* agentData, const char* typeName, size_t nMembers, const char* const * memberNames, const AGENT_DATA_TYPE** memberPointerValues)
2771{
2772 AGENT_DATA_TYPES_RESULT result;
2773
2774 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_109:[ AGENT_DATA_TYPES_INVALID_ARG shall be returned if memberPointerValues parameter is NULL.] */
2775 if (memberPointerValues == NULL)
2776 {
2777 result = AGENT_DATA_TYPES_INVALID_ARG;
2778 LogError("(result: AGENT_DATA_TYPES_INVALID_ARG)");
2779 }
2780 else
2781 {
2782 AGENT_DATA_TYPE* values = (AGENT_DATA_TYPE*)calloc(1, (nMembers* sizeof(AGENT_DATA_TYPE)));
2783 if (values == NULL)
2784 {
2785 result = AGENT_DATA_TYPES_ERROR;
2786 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2787 }
2788 else
2789 {
2790 size_t i;
2791 for (i = 0; i < nMembers; i++)
2792 {
2793 if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(values + i, memberPointerValues[i]) != AGENT_DATA_TYPES_OK)
2794 {
2795 size_t j;
2796 for (j = 0; j < i; j++)
2797 {
2798 Destroy_AGENT_DATA_TYPE(values + j);
2799 }
2800 break;
2801 }
2802 }
2803
2804 if (i != nMembers)
2805 {
2806 result = AGENT_DATA_TYPES_ERROR;
2807 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2808 }
2809 else
2810 {
2811 /* SRS_AGENT_TYPE_SYSTEM_99_111:[ AGENT_DATA_TYPES_OK shall be returned upon success.] */
2812 result = Create_AGENT_DATA_TYPE_from_Members(agentData, typeName, nMembers, memberNames, values);
2813 if (result != AGENT_DATA_TYPES_OK)
2814 {
2815 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2816 }
2817 for (i = 0; i < nMembers; i++)
2818 {
2819 Destroy_AGENT_DATA_TYPE(&values[i]);
2820 }
2821 }
2822 free(values);
2823 }
2824 }
2825 return result;
2826}
2827
2828AGENT_DATA_TYPES_RESULT Create_AGENT_DATA_TYPE_from_Members(AGENT_DATA_TYPE* agentData, const char* typeName, size_t nMembers, const char* const * memberNames, const AGENT_DATA_TYPE* memberValues)
2829{
2830 AGENT_DATA_TYPES_RESULT result;
2831 size_t i;
2832 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_013:[ All the functions shall check their parameters for validity. When an invalid parameter is detected, the value AGENT_DATA_TYPES_INVALID_ARG shall be returned ]*/
2833 if (agentData == NULL)
2834 {
2835 result = AGENT_DATA_TYPES_INVALID_ARG;
2836 LogError("(result: AGENT_DATA_TYPES_INVALID_ARG)");
2837 }
2838 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_055:[ If typeName is NULL, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
2839 else if (typeName==NULL)
2840 {
2841 result = AGENT_DATA_TYPES_INVALID_ARG;
2842 LogError("(result: AGENT_DATA_TYPES_INVALID_ARG)");
2843 }
2844 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_056:[If nMembers is 0, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
2845 else if (nMembers == 0)
2846 {
2847 result = AGENT_DATA_TYPES_INVALID_ARG;
2848 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2849 }
2850 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_057:[ If memberNames is NULL, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
2851 else if (memberNames == NULL)
2852 {
2853 result = AGENT_DATA_TYPES_INVALID_ARG;
2854 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2855 }
2856 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_058:[ If any of the memberNames[i] is NULL, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
2857 else if (isOneNameNULL(nMembers, memberNames)!=0)
2858 {
2859 result = AGENT_DATA_TYPES_INVALID_ARG;
2860 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2861 }
2862 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_059:[ If memberValues is NULL, the function shall return AGENT_DATA_TYPES_INVALID_ARG .]*/
2863 else if (memberValues == NULL)
2864 {
2865 result = AGENT_DATA_TYPES_INVALID_ARG;
2866 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2867 }
2868 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_063:[ If there are two memberNames with the same name, then the function shall return AGENT_DATA_TYPES_INVALID_ARG.]*/
2869 else if (areThereTwoSameNames(nMembers, memberNames) != 0)
2870 {
2871 result = AGENT_DATA_TYPES_INVALID_ARG;
2872 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2873 }
2874 else
2875 {
2876 agentData->value.edmComplexType.nMembers = nMembers;
2877 agentData->value.edmComplexType.fields = (COMPLEX_TYPE_FIELD_TYPE*)malloc(nMembers *sizeof(COMPLEX_TYPE_FIELD_TYPE));
2878 if (agentData->value.edmComplexType.fields == NULL)
2879 {
2880 result = AGENT_DATA_TYPES_ERROR;
2881 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2882 }
2883 else
2884 {
2885 result = AGENT_DATA_TYPES_OK; /*not liking this, solution might be to use a temp variable*/
2886
2887 /*initialize the fields*/
2888 for (i = 0; i < nMembers; i++)
2889 {
2890 agentData->value.edmComplexType.fields[i].fieldName = NULL;
2891 agentData->value.edmComplexType.fields[i].value = NULL;
2892 }
2893
2894 for (i = 0; i < nMembers; i++)
2895 {
2896 /*copy the name*/
2897 if (mallocAndStrcpy_s((char**)(&(agentData->value.edmComplexType.fields[i].fieldName)), memberNames[i]) != 0)
2898 {
2899 result = AGENT_DATA_TYPES_ERROR;
2900 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2901 break;
2902 }
2903 else
2904 {
2905 /*field name was transferred successfully*/
2906 /*copy the rest*/
2907 agentData->value.edmComplexType.fields[i].value = (AGENT_DATA_TYPE*)calloc(1, sizeof(AGENT_DATA_TYPE));
2908 if (agentData->value.edmComplexType.fields[i].value == NULL)
2909 {
2910 /*deallocate the name*/
2911 free((void*)(agentData->value.edmComplexType.fields[i].fieldName));
2912 agentData->value.edmComplexType.fields[i].fieldName = NULL;
2913 result = AGENT_DATA_TYPES_ERROR;
2914 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2915 break;
2916 }
2917 else
2918 {
2919 /*copy the values*/
2920 if (Create_AGENT_DATA_TYPE_from_AGENT_DATA_TYPE(agentData->value.edmComplexType.fields[i].value, &(memberValues[i])) != AGENT_DATA_TYPES_OK)
2921 {
2922 result = AGENT_DATA_TYPES_ERROR;
2923 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
2924 break;
2925 }
2926 else
2927 {
2928 /*all is fine*/
2929 }
2930 }
2931 }
2932
2933 }
2934 }
2935
2936 if (result != AGENT_DATA_TYPES_OK)
2937 {
2938 /*dealloc, something went bad*/
2939 DestroyHalfBakedComplexType(agentData);
2940 }
2941 else
2942 {
2943 agentData->type = EDM_COMPLEX_TYPE_TYPE;
2944 }
2945 }
2946 return result;
2947}
2948
2949#define isLeapYear(y) ((((y) % 400) == 0) || (((y)%4==0)&&(!((y)%100==0))))
2950
2951static int daysInAllPreviousMonths(int month)
2952{
2953 int result = 0;
2954 for (int i = 0; i < month; i++)
2955 {
2956 switch (i)
2957 {
2958 case 0:
2959 case 2:
2960 case 4:
2961 case 6:
2962 case 7:
2963 case 9:
2964 result += 31;
2965 break;
2966 case 1:
2967 result += 28;
2968 break;
2969 default:
2970 result += 30;
2971 }
2972 }
2973 return result;
2974}
2975
2976/*this function assumes a correctly filled in tm_year, tm_mon and tm_mday and will fill in tm_yday and tm_wday*/
2977static void fill_tm_yday_and_tm_wday(struct tm* source)
2978{
2979 /*to fill in tm_yday the function shall add the number of days in every month, not including the current one*/
2980 /*and then it will add the number of days in the current month*/
2981 /*1st of Jan is day "0" in a year*/
2982 int year = source->tm_year + 1900 + 10000;
2983 int nLeapYearsSinceYearMinus9999 = ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400);
2984 source->tm_yday = (daysInAllPreviousMonths(source->tm_mon)) + (source->tm_mday - 1) + ((source->tm_mon > 1 /*1 is Feb*/) && isLeapYear(year));
2985 source->tm_wday = ((365 * year + nLeapYearsSinceYearMinus9999) + source->tm_yday) % 7;
2986 /*day "0" is 1st jan -9999 (this is how much odata can span*/
2987 /*the function shall count days */
2988}
2989
2990/*the following function does the same as sscanf(pos2, ":%02d", &sec)*/
2991/*this function only exists because of optimizing valgrind time, otherwise sscanf would be just as good*/
2992static int sscanf2d(const char *pos2, int* sec)
2993{
2994 int result;
2995 size_t position = 1;
2996 if (
2997 (pos2[0] == ':') &&
2998 (scanAndReadNDigitsInt(pos2, &position, sec, 2) == 0)
2999 )
3000 {
3001 result = 1;
3002 }
3003 else
3004 {
3005 result = EOF;
3006 }
3007
3008 return result;
3009
3010}
3011
3012/*the following function does the same as sscanf(pos2, "%d", &sec)*/
3013/*this function only exists because of optimizing valgrind time, otherwise sscanf would be just as good*/
3014static int sscanfd(const char *src, int* dst)
3015{
3016 int result;
3017 char* next;
3018 long int temp = strtol(src, &next, 10);
3019 if ((src == next) || (((temp == LONG_MAX) || (temp == LONG_MIN)) && (errno != 0)))
3020 {
3021 result = EOF;
3022 }
3023 else
3024 {
3025 (*dst) = (int)temp;
3026 result = 1;
3027 }
3028 return result;
3029}
3030
3031/*the following function does the same as sscanf(src, "%llu", &dst), but, it changes the src pointer.*/
3032static int sscanfllu(const char** src, unsigned long long* dst)
3033{
3034 int result = 1;
3035 char* next;
3036 (*dst) = strtoull((*src), &next, 10);
3037 if (((*src) == (const char*)next) || (((*dst) == ULLONG_MAX) && (errno != 0)))
3038 {
3039 result = EOF;
3040 }
3041 (*src) = (const char*)next;
3042 return result;
3043}
3044
3045/*the following function does the same as sscanf(src, ".%llu", &dst)*/
3046static int sscanfdotllu(const char*src, unsigned long long* dst)
3047{
3048 int result;
3049
3050 if ((*src) != '.')
3051 {
3052 /*doesn't start with '.' error out*/
3053 result = EOF;
3054 }
3055 else
3056 {
3057 src++;
3058 result = sscanfllu(&src, dst);
3059 }
3060
3061 return result;
3062}
3063
3064/*the following function does the same as sscanf(src, "%u", &dst)*/
3065static int sscanfu(const char* src, uint32_t* dst)
3066{
3067 int result;
3068 char* next;
3069 unsigned long int temp = strtoul(src, &next, 10);
3070 if ((src == next) || ((temp == ULONG_MAX) && (errno != 0)))
3071 {
3072 result = EOF;
3073 }
3074 else
3075 {
3076 result = 1;
3077 (*dst) = (uint32_t)temp;
3078 }
3079 return result;
3080}
3081
3082/*the following function does the same as sscanf(src, "%f", &dst)*/
3083static int sscanff(const char*src, float* dst)
3084{
3085 int result = 1;
3086 char* next;
3087 (*dst) = strtof(src, &next);
3088 if ((src == next) || (((*dst) == HUGE_VALF) && (errno != 0)))
3089 {
3090 result = EOF;
3091 }
3092 return result;
3093}
3094
3095/*the following function does the same as sscanf(src, "%lf", &dst)*/
3096static int sscanflf(const char*src, double* dst)
3097{
3098 int result = 1;
3099 char* next;
3100 (*dst) = strtod(src, &next);
3101 if ((src == next) || (((*dst) == HUGE_VALL) && (errno != 0)))
3102 {
3103 result = EOF;
3104 }
3105 return result;
3106}
3107
3108
3109/*the below function replaces sscanf(src, "%03d:%02d\"", &hourOffset, &minOffset)*/
3110/*return 2 if success*/
3111
3112static int sscanf3d2d(const char* src, int* hourOffset, int* minOffset)
3113{
3114 size_t position = 0;
3115 int result = EOF;
3116 bool isNegative = false;
3117
3118 if (*src == '+')
3119 {
3120 position++;
3121 }
3122 else if (*src == '-')
3123 {
3124 isNegative = true;
3125 position++;
3126 }
3127
3128 if (
3129 (scanAndReadNDigitsInt(src, &position, hourOffset, (3-position)) == 0) &&
3130 (src[position++] == ':') &&
3131 (scanAndReadNDigitsInt(src, &position, minOffset, 2) == 0)
3132 )
3133 {
3134 result = 2;
3135 }
3136 else
3137 {
3138 result = 0;
3139 }
3140 if (isNegative)
3141 *hourOffset *= -1;
3142
3143 return result;
3144}
3145
3146AGENT_DATA_TYPES_RESULT CreateAgentDataType_From_String(const char* source, AGENT_DATA_TYPE_TYPE type, AGENT_DATA_TYPE* agentData)
3147{
3148
3149 AGENT_DATA_TYPES_RESULT result;
3150
3151 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_073:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is NULL.] */
3152 if ((source == NULL) ||
3153 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_074:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if agentData is NULL.] */
3154 (agentData == NULL))
3155 {
3156 result = AGENT_DATA_TYPES_INVALID_ARG;
3157 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3158 }
3159 else
3160 {
3161 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_071:[ CreateAgentDataType_From_String shall create an AGENT_DATA_TYPE from a char* representation of the type indicated by type parameter.] */
3162 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_072:[ The implementation for the transformation of the char* source into AGENT_DATA_TYPE shall be type specific.] */
3163 switch (type)
3164 {
3165 default:
3166 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_075:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_NOT_IMPLEMENTED if type is not a supported type.] */
3167 result = AGENT_DATA_TYPES_NOT_IMPLEMENTED;
3168 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3169 break;
3170
3171 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_086:[ EDM_STRING] */
3172 case EDM_BOOLEAN_TYPE:
3173 {
3174 if (strcmp(source, "true") == 0)
3175 {
3176 agentData->type = EDM_BOOLEAN_TYPE;
3177 agentData->value.edmBoolean.value = EDM_TRUE;
3178 result = AGENT_DATA_TYPES_OK;
3179 }
3180 else if (strcmp(source, "false") == 0)
3181 {
3182 agentData->type = EDM_BOOLEAN_TYPE;
3183 agentData->value.edmBoolean.value = EDM_FALSE;
3184 result = AGENT_DATA_TYPES_OK;
3185 }
3186 else
3187 {
3188 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3189 result = AGENT_DATA_TYPES_INVALID_ARG;
3190 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3191 }
3192
3193 break;
3194 }
3195 case EDM_NULL_TYPE:
3196 {
3197 if (strcmp(source, "null") == 0)
3198 {
3199 agentData->type = EDM_NULL_TYPE;
3200 result = AGENT_DATA_TYPES_OK;
3201 }
3202 else
3203 {
3204 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3205 result = AGENT_DATA_TYPES_INVALID_ARG;
3206 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3207 }
3208
3209 break;
3210 }
3211
3212 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_084:[ EDM_SBYTE] */
3213 case EDM_SBYTE_TYPE:
3214 {
3215 int sByteValue;
3216 if ((sscanfd(source, &sByteValue) != 1) ||
3217 (sByteValue < -128) ||
3218 (sByteValue > 127))
3219 {
3220 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3221 result = AGENT_DATA_TYPES_INVALID_ARG;
3222 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3223 }
3224 else
3225 {
3226 agentData->type = EDM_SBYTE_TYPE;
3227 agentData->value.edmSbyte.value = (int8_t)sByteValue;
3228 result = AGENT_DATA_TYPES_OK;
3229 }
3230
3231 break;
3232 }
3233
3234 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_077:[ EDM_BYTE] */
3235 case EDM_BYTE_TYPE:
3236 {
3237 int byteValue;
3238 if ((sscanfd(source, &byteValue) != 1) ||
3239 (byteValue < 0) ||
3240 (byteValue > 255))
3241 {
3242 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3243 result = AGENT_DATA_TYPES_INVALID_ARG;
3244 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3245 }
3246 else
3247 {
3248 agentData->type = EDM_BYTE_TYPE;
3249 agentData->value.edmByte.value = (uint8_t)byteValue;
3250 result = AGENT_DATA_TYPES_OK;
3251 }
3252
3253 break;
3254 }
3255
3256 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_081:[ EDM_INT16] */
3257 case EDM_INT16_TYPE:
3258 {
3259 int int16Value;
3260 if ((sscanfd(source, &int16Value) != 1) ||
3261 (int16Value < -32768) ||
3262 (int16Value > 32767))
3263 {
3264 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3265 result = AGENT_DATA_TYPES_INVALID_ARG;
3266 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3267 }
3268 else
3269 {
3270 agentData->type = EDM_INT16_TYPE;
3271 agentData->value.edmInt16.value = (int16_t)int16Value;
3272 result = AGENT_DATA_TYPES_OK;
3273 }
3274
3275 break;
3276 }
3277
3278 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_082:[ EDM_INT32] */
3279 case EDM_INT32_TYPE:
3280 {
3281 int32_t int32Value;
3282 unsigned char isNegative;
3283 uint32_t uint32Value;
3284 const char* pos;
3285 size_t strLength;
3286
3287 if (source[0] == '-')
3288 {
3289 isNegative = 1;
3290 pos = &source[1];
3291 }
3292 else
3293 {
3294 isNegative = 0;
3295 pos = &source[0];
3296 }
3297
3298 strLength = strlen(source);
3299
3300 if ((sscanfu(pos, &uint32Value) != 1) ||
3301 (strLength > 11) ||
3302 ((uint32Value > 2147483648UL) && isNegative) ||
3303 ((uint32Value > 2147483647UL) && (!isNegative)))
3304 {
3305 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3306 result = AGENT_DATA_TYPES_INVALID_ARG;
3307 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3308 }
3309 else
3310 {
3311 if (isNegative)
3312 {
3313 if (uint32Value == 2147483648UL)
3314 {
3315 int32Value = -2147483647L - 1L;
3316 }
3317 else
3318 {
3319 int32Value = -(int32_t)uint32Value;
3320 }
3321 }
3322 else
3323 {
3324 int32Value = uint32Value;
3325 }
3326
3327 agentData->type = EDM_INT32_TYPE;
3328 agentData->value.edmInt32.value = (int32_t)int32Value;
3329 result = AGENT_DATA_TYPES_OK;
3330 }
3331
3332 break;
3333 }
3334
3335 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_083:[ EDM_INT64] */
3336 case EDM_INT64_TYPE:
3337 {
3338 long long int64Value;
3339 unsigned char isNegative;
3340 unsigned long long ullValue;
3341 const char* pos;
3342 size_t strLength;
3343
3344 if (source[0] == '-')
3345 {
3346 isNegative = 1;
3347 pos = &source[1];
3348 }
3349 else
3350 {
3351 isNegative = 0;
3352 pos = &source[0];
3353 }
3354
3355 strLength = strlen(source);
3356
3357 if ((sscanfllu(&pos, &ullValue) != 1) ||
3358 (strLength > 20) ||
3359 ((ullValue > 9223372036854775808ULL) && isNegative) ||
3360 ((ullValue > 9223372036854775807ULL) && (!isNegative)))
3361 {
3362 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3363 result = AGENT_DATA_TYPES_INVALID_ARG;
3364 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3365 }
3366 else
3367 {
3368 if (isNegative)
3369 {
3370 if (ullValue == 9223372036854775808ULL)
3371 {
3372 int64Value = -9223372036854775807LL - 1LL;
3373 }
3374 else
3375 {
3376 int64Value = -(long long)ullValue;
3377 }
3378 }
3379 else
3380 {
3381 int64Value = ullValue;
3382 }
3383 agentData->type = EDM_INT64_TYPE;
3384 agentData->value.edmInt64.value = (int64_t)int64Value;
3385 result = AGENT_DATA_TYPES_OK;
3386 }
3387
3388 break;
3389 }
3390
3391 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_085:[ EDM_DATE] */
3392 case EDM_DATE_TYPE:
3393 {
3394 int year;
3395 int month;
3396 int day;
3397 size_t strLength = strlen(source);
3398
3399 if ((strLength < 2) ||
3400 (source[0] != '"') ||
3401 (source[strLength - 1] != '"'))
3402 {
3403 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3404 result = AGENT_DATA_TYPES_INVALID_ARG;
3405 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3406 }
3407 else
3408 {
3409 size_t pos = 1;
3410 int sign;
3411 scanOptionalMinusSign(source, 2, &pos, &sign);
3412
3413 if ((scanAndReadNDigitsInt(source, &pos, &year, 4) != 0) ||
3414 (source[pos++] != '-') ||
3415 (scanAndReadNDigitsInt(source, &pos, &month, 2) != 0) ||
3416 (source[pos++] != '-') ||
3417 (scanAndReadNDigitsInt(source, &pos, &day, 2) != 0) ||
3418 (Create_AGENT_DATA_TYPE_from_date(agentData, (int16_t)(sign*year), (uint8_t)month, (uint8_t)day) != AGENT_DATA_TYPES_OK))
3419 {
3420 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3421 result = AGENT_DATA_TYPES_INVALID_ARG;
3422 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3423 }
3424 else
3425 {
3426 result = AGENT_DATA_TYPES_OK;
3427 }
3428 }
3429
3430 break;
3431 }
3432
3433 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_078:[ EDM_DATETIMEOFFSET] */
3434 case EDM_DATE_TIME_OFFSET_TYPE:
3435 {
3436 int year;
3437 int month;
3438 int day;
3439 int hour;
3440 int min;
3441 int sec = 0;
3442 int hourOffset;
3443 int minOffset;
3444 unsigned long long fractionalSeconds = 0;
3445 size_t strLength = strlen(source);
3446
3447 agentData->value.edmDateTimeOffset.hasFractionalSecond = 0;
3448 agentData->value.edmDateTimeOffset.hasTimeZone = 0;
3449 /* The value of tm_isdst is positive if Daylight Saving Time is in effect, zero if Daylight
3450 Saving Time is not in effect, and negative if the information is not available.*/
3451 agentData->value.edmDateTimeOffset.dateTime.tm_isdst = -1;
3452
3453 if ((strLength < 2) ||
3454 (source[0] != '"') ||
3455 (source[strLength - 1] != '"'))
3456 {
3457 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3458 result = AGENT_DATA_TYPES_INVALID_ARG;
3459 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3460 }
3461 else
3462 {
3463 size_t pos = 1;
3464 int sign;
3465 scanOptionalMinusSign(source, 2, &pos, &sign);
3466
3467 if ((scanAndReadNDigitsInt(source, &pos, &year, 4) != 0) ||
3468 (source[pos++] != '-') ||
3469 (scanAndReadNDigitsInt(source, &pos, &month, 2) != 0) ||
3470 (source[pos++] != '-') ||
3471 (scanAndReadNDigitsInt(source, &pos, &day, 2) != 0) ||
3472 (source[pos++] != 'T') ||
3473 (scanAndReadNDigitsInt(source, &pos, &hour, 2) != 0) ||
3474 (source[pos++] != ':') ||
3475 (scanAndReadNDigitsInt(source, &pos, &min, 2) != 0))
3476 {
3477 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3478 result = AGENT_DATA_TYPES_INVALID_ARG;
3479 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3480 }
3481 else
3482 {
3483 const char* pos2;
3484 year = year*sign;
3485 if ((pos2 = strchr(source, ':')) == NULL)
3486 {
3487 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3488 result = AGENT_DATA_TYPES_INVALID_ARG;
3489 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3490 }
3491 else
3492 {
3493 pos2 += 3;
3494 if (*pos2 == ':')
3495 {
3496 if (sscanf2d(pos2, &sec) != 1)
3497 {
3498 pos2 = NULL;
3499 }
3500 else
3501 {
3502 pos2 += 3;
3503 }
3504 }
3505
3506 if ((pos2 != NULL) &&
3507 (*pos2 == '.'))
3508 {
3509 if (sscanfdotllu(pos2, &fractionalSeconds) != 1)
3510 {
3511 pos2 = NULL;
3512 }
3513 else
3514 {
3515 pos2++;
3516
3517 agentData->value.edmDateTimeOffset.hasFractionalSecond = 1;
3518
3519 while ((*pos2 != '\0') &&
3520 (IS_DIGIT(*pos2)))
3521 {
3522 pos2++;
3523 }
3524
3525 if (*pos2 == '\0')
3526 {
3527 pos2 = NULL;
3528 }
3529 }
3530 }
3531
3532 if (pos2 == NULL)
3533 {
3534 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3535 result = AGENT_DATA_TYPES_INVALID_ARG;
3536 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3537 }
3538 else
3539 {
3540 hourOffset = 0;
3541 minOffset = 0;
3542
3543 if (sscanf3d2d(pos2, &hourOffset, &minOffset) == 2)
3544 {
3545 agentData->value.edmDateTimeOffset.hasTimeZone = 1;
3546 }
3547
3548 if ((strcmp(pos2, "Z\"") == 0) ||
3549 agentData->value.edmDateTimeOffset.hasTimeZone)
3550 {
3551 if ((ValidateDate(year, month, day) != 0) ||
3552 (hour < 0) ||
3553 (hour > 23) ||
3554 (min < 0) ||
3555 (min > 59) ||
3556 (sec < 0) ||
3557 (sec > 59) ||
3558 (fractionalSeconds > 999999999999) ||
3559 (hourOffset < -23) ||
3560 (hourOffset > 23) ||
3561 (minOffset < 0) ||
3562 (minOffset > 59))
3563 {
3564 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3565 result = AGENT_DATA_TYPES_INVALID_ARG;
3566 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3567 }
3568 else
3569 {
3570 agentData->type = EDM_DATE_TIME_OFFSET_TYPE;
3571 agentData->value.edmDateTimeOffset.dateTime.tm_year= year-1900;
3572 agentData->value.edmDateTimeOffset.dateTime.tm_mon = month-1;
3573 agentData->value.edmDateTimeOffset.dateTime.tm_mday = day;
3574 agentData->value.edmDateTimeOffset.dateTime.tm_hour = hour;
3575 agentData->value.edmDateTimeOffset.dateTime.tm_min = min;
3576 agentData->value.edmDateTimeOffset.dateTime.tm_sec = sec;
3577 /*fill in tm_wday and tm_yday*/
3578 fill_tm_yday_and_tm_wday(&agentData->value.edmDateTimeOffset.dateTime);
3579 agentData->value.edmDateTimeOffset.fractionalSecond = (uint64_t)fractionalSeconds;
3580 agentData->value.edmDateTimeOffset.timeZoneHour = (int8_t)hourOffset;
3581 agentData->value.edmDateTimeOffset.timeZoneMinute = (uint8_t)minOffset;
3582 result = AGENT_DATA_TYPES_OK;
3583 }
3584 }
3585 else
3586 {
3587 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3588 result = AGENT_DATA_TYPES_INVALID_ARG;
3589 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3590 }
3591 }
3592 }
3593 }
3594 }
3595
3596 break;
3597 }
3598
3599 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_080:[ EDM_DOUBLE] */
3600 case EDM_DOUBLE_TYPE:
3601 {
3602 if (strcmp(source, "\"NaN\"") == 0)
3603 {
3604 agentData->type = EDM_DOUBLE_TYPE;
3605 agentData->value.edmDouble.value = NAN;
3606 result = AGENT_DATA_TYPES_OK;
3607 }
3608 else if (strcmp(source, "\"INF\"") == 0)
3609 {
3610 agentData->type = EDM_DOUBLE_TYPE;
3611 agentData->value.edmDouble.value = INFINITY;
3612 result = AGENT_DATA_TYPES_OK;
3613 }
3614 else if (strcmp(source, "\"-INF\"") == 0)
3615 {
3616 agentData->type = EDM_DOUBLE_TYPE;
3617#ifdef _MSC_VER
3618#pragma warning(push)
3619#pragma warning(disable: 4056) /* Known warning for INIFNITY */
3620#endif
3621 agentData->value.edmDouble.value = -INFINITY;
3622#ifdef _MSC_VER
3623#pragma warning(pop)
3624#endif
3625 result = AGENT_DATA_TYPES_OK;
3626 }
3627 else if (sscanflf(source, &(agentData->value.edmDouble.value)) != 1)
3628 {
3629 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3630 result = AGENT_DATA_TYPES_INVALID_ARG;
3631 }
3632 else
3633 {
3634 agentData->type = EDM_DOUBLE_TYPE;
3635 result = AGENT_DATA_TYPES_OK;
3636 }
3637 break;
3638 }
3639
3640 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_089:[EDM_SINGLE] */
3641 case EDM_SINGLE_TYPE:
3642 {
3643 if (strcmp(source, "\"NaN\"") == 0)
3644 {
3645 agentData->type = EDM_SINGLE_TYPE;
3646 agentData->value.edmSingle.value = NAN;
3647 result = AGENT_DATA_TYPES_OK;
3648 }
3649 else if (strcmp(source, "\"INF\"") == 0)
3650 {
3651 agentData->type = EDM_SINGLE_TYPE;
3652 agentData->value.edmSingle.value = INFINITY;
3653 result = AGENT_DATA_TYPES_OK;
3654 }
3655 else if (strcmp(source, "\"-INF\"") == 0)
3656 {
3657 agentData->type = EDM_SINGLE_TYPE;
3658#ifdef _MSC_VER
3659#pragma warning(push)
3660#pragma warning(disable: 4056) /* Known warning for INIFNITY */
3661#endif
3662 agentData->value.edmSingle.value = -INFINITY;
3663#ifdef _MSC_VER
3664#pragma warning(pop)
3665#endif
3666result = AGENT_DATA_TYPES_OK;
3667 }
3668 else if (sscanff(source, &agentData->value.edmSingle.value) != 1)
3669 {
3670 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3671 result = AGENT_DATA_TYPES_INVALID_ARG;
3672 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3673 }
3674 else
3675 {
3676 agentData->type = EDM_SINGLE_TYPE;
3677 result = AGENT_DATA_TYPES_OK;
3678 }
3679 break;
3680 }
3681
3682 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_079:[ EDM_DECIMAL] */
3683 case EDM_DECIMAL_TYPE:
3684 {
3685 size_t strLength = strlen(source);
3686 if ((strLength < 2) ||
3687 (source[0] != '"') ||
3688 (source[strLength - 1] != '"') ||
3689 (ValidateDecimal(source + 1, strLength - 2) != 0))
3690 {
3691 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3692 result = AGENT_DATA_TYPES_INVALID_ARG;
3693 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3694 }
3695 else
3696 {
3697 agentData->type = EDM_DECIMAL_TYPE;
3698 agentData->value.edmDecimal.value = STRING_construct_n(source + 1, strLength-2);
3699 if (agentData->value.edmDecimal.value == NULL)
3700 {
3701 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_088:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_ERROR if any other error occurs.] */
3702 result = AGENT_DATA_TYPES_ERROR;
3703 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3704 }
3705 else
3706 {
3707 result = AGENT_DATA_TYPES_OK;
3708 }
3709 }
3710 break;
3711 }
3712
3713 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_086:[ EDM_STRING] */
3714 case EDM_STRING_TYPE:
3715 {
3716 size_t strLength = strlen(source);
3717 if ((strLength < 2) ||
3718 (source[0] != '"') ||
3719 (source[strLength - 1] != '"'))
3720 {
3721 /* Codes_SRS_AGENT_TYPE_SYSTEM_99_087:[ CreateAgentDataType_From_String shall return AGENT_DATA_TYPES_INVALID_ARG if source is not a valid string for a value of type type.] */
3722 result = AGENT_DATA_TYPES_INVALID_ARG;
3723 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3724 }
3725 else
3726 {
3727 char* temp;
3728 if ((temp = (char*)malloc(strLength - 1)) == NULL)
3729 {
3730 result = AGENT_DATA_TYPES_ERROR;
3731 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3732 }
3733 else if (memcpy(temp, source + 1, strLength - 2) == NULL)
3734 {
3735 free(temp);
3736
3737 result = AGENT_DATA_TYPES_ERROR;
3738 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3739 }
3740 else
3741 {
3742 // Removes the "
3743 temp[strLength - 2] = 0;
3744 agentData->type = EDM_STRING_TYPE;
3745 agentData->value.edmString.chars = temp;
3746 agentData->value.edmString.length = strLength - 2;
3747 result = AGENT_DATA_TYPES_OK;
3748 }
3749 }
3750 break;
3751 }
3752 /* Codes_SRS_AGENT_TYPE_SYSTEM_01_004: [EDM_STRING_NO_QUOTES] */
3753 case EDM_STRING_NO_QUOTES_TYPE:
3754 {
3755 char* temp;
3756 size_t strLength = strlen(source);
3757 if (mallocAndStrcpy_s(&temp, source) != 0)
3758 {
3759 result = AGENT_DATA_TYPES_ERROR;
3760 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, result));
3761 }
3762 else
3763 {
3764 agentData->type = EDM_STRING_NO_QUOTES_TYPE;
3765 agentData->value.edmStringNoQuotes.chars = temp;
3766 agentData->value.edmStringNoQuotes.length = strLength;
3767 result = AGENT_DATA_TYPES_OK;
3768 }
3769 break;
3770 }
3771 /*Codes_SRS_AGENT_TYPE_SYSTEM_99_097:[ EDM_GUID]*/
3772 case EDM_GUID_TYPE:
3773 {
3774 if (strlen(source) != GUID_STRING_LENGTH)
3775 {
3776 result = AGENT_DATA_TYPES_INVALID_ARG;
3777 }
3778 else
3779 {
3780 if (source[0] != '"')
3781 {
3782 result = AGENT_DATA_TYPES_INVALID_ARG;
3783 }
3784 else if (scanMandatory2CapitalHexDigits(source + 1, &(agentData->value.edmGuid.GUID[0])) != 0)
3785 {
3786 result = AGENT_DATA_TYPES_INVALID_ARG;
3787 }
3788 else if (scanMandatory2CapitalHexDigits(source + 3, &(agentData->value.edmGuid.GUID[1])) != 0)
3789 {
3790 result = AGENT_DATA_TYPES_INVALID_ARG;
3791 }
3792 else if (scanMandatory2CapitalHexDigits(source + 5, &(agentData->value.edmGuid.GUID[2])) != 0)
3793 {
3794 result = AGENT_DATA_TYPES_INVALID_ARG;
3795 }
3796 else if (scanMandatory2CapitalHexDigits(source + 7, &(agentData->value.edmGuid.GUID[3])) != 0)
3797 {
3798 result = AGENT_DATA_TYPES_INVALID_ARG;
3799 }
3800 else if (source[9] != '-')
3801 {
3802 result = AGENT_DATA_TYPES_INVALID_ARG;
3803 }
3804 else if (scanMandatory2CapitalHexDigits(source + 10, &(agentData->value.edmGuid.GUID[4])) != 0)
3805 {
3806 result = AGENT_DATA_TYPES_INVALID_ARG;
3807 }
3808 else if (scanMandatory2CapitalHexDigits(source + 12, &(agentData->value.edmGuid.GUID[5])) != 0)
3809 {
3810 result = AGENT_DATA_TYPES_INVALID_ARG;
3811 }
3812 else if (source[14] != '-')
3813 {
3814 result = AGENT_DATA_TYPES_INVALID_ARG;
3815 }
3816 else if (scanMandatory2CapitalHexDigits(source + 15, &(agentData->value.edmGuid.GUID[6])) != 0)
3817 {
3818 result = AGENT_DATA_TYPES_INVALID_ARG;
3819 }
3820 else if (scanMandatory2CapitalHexDigits(source + 17, &(agentData->value.edmGuid.GUID[7])) != 0)
3821 {
3822 result = AGENT_DATA_TYPES_INVALID_ARG;
3823 }
3824 else if (source[19] != '-')
3825 {
3826 result = AGENT_DATA_TYPES_INVALID_ARG;
3827 }
3828 else if (scanMandatory2CapitalHexDigits(source + 20, &(agentData->value.edmGuid.GUID[8])) != 0)
3829 {
3830 result = AGENT_DATA_TYPES_INVALID_ARG;
3831 }
3832 else if (scanMandatory2CapitalHexDigits(source + 22, &(agentData->value.edmGuid.GUID[9])) != 0)
3833 {
3834 result = AGENT_DATA_TYPES_INVALID_ARG;
3835 }
3836 else if (source[24] != '-')
3837 {
3838 result = AGENT_DATA_TYPES_INVALID_ARG;
3839 }
3840 else if (scanMandatory2CapitalHexDigits(source + 25, &(agentData->value.edmGuid.GUID[10])) != 0)
3841 {
3842 result = AGENT_DATA_TYPES_INVALID_ARG;
3843 }
3844 else if (scanMandatory2CapitalHexDigits(source + 27, &(agentData->value.edmGuid.GUID[11])) != 0)
3845 {
3846 result = AGENT_DATA_TYPES_INVALID_ARG;
3847 }
3848 else if (scanMandatory2CapitalHexDigits(source + 29, &(agentData->value.edmGuid.GUID[12])) != 0)
3849 {
3850 result = AGENT_DATA_TYPES_INVALID_ARG;
3851 }
3852 else if (scanMandatory2CapitalHexDigits(source + 31, &(agentData->value.edmGuid.GUID[13])) != 0)
3853 {
3854 result = AGENT_DATA_TYPES_INVALID_ARG;
3855 }
3856 else if (scanMandatory2CapitalHexDigits(source + 33, &(agentData->value.edmGuid.GUID[14])) != 0)
3857 {
3858 result = AGENT_DATA_TYPES_INVALID_ARG;
3859 }
3860 else if (scanMandatory2CapitalHexDigits(source + 35, &(agentData->value.edmGuid.GUID[15])) != 0)
3861 {
3862 result = AGENT_DATA_TYPES_INVALID_ARG;
3863 }
3864 else if (source[37] != '"')
3865 {
3866 result = AGENT_DATA_TYPES_INVALID_ARG;
3867 }
3868 else
3869 {
3870 agentData->type = EDM_GUID_TYPE;
3871 result = AGENT_DATA_TYPES_OK;
3872 }
3873 }
3874 break;
3875 }
3876 case EDM_BINARY_TYPE:
3877 {
3878 size_t sourceLength = strlen(source);
3879 if (sourceLength < 2)
3880 {
3881 result = AGENT_DATA_TYPES_INVALID_ARG;
3882 }
3883 else if (sourceLength == 2)
3884 {
3885 agentData->type = EDM_BINARY_TYPE;
3886 agentData->value.edmBinary.data = NULL;
3887 agentData->value.edmBinary.size = 0;
3888 result = AGENT_DATA_TYPES_OK;
3889 }
3890 else
3891 {
3892 size_t sourcePosition = 0;
3893 if (source[sourcePosition++] != '"') /*if it doesn't start with a quote then... */
3894 {
3895 result = AGENT_DATA_TYPES_INVALID_ARG;
3896 }
3897 else
3898 {
3899 /*1. read groups of 4 base64 character and transfer those into groups of 3 "normal" characters.
3900 2. read the end of the string and produce from that the ending characters*/
3901
3902 /*compute the amount of memory to allocate*/
3903 agentData->value.edmBinary.size = (((sourceLength - 2) + 4) / 4) * 3; /*this is overallocation, shall be trimmed later*/
3904 agentData->value.edmBinary.data = (unsigned char*)malloc(agentData->value.edmBinary.size); /*this is overallocation, shall be trimmed later*/
3905 if (agentData->value.edmBinary.data == NULL)
3906 {
3907 result = AGENT_DATA_TYPES_ERROR;
3908 }
3909 else
3910 {
3911
3912 size_t destinationPosition = 0;
3913 size_t consumed;
3914 /*read and store "solid" groups of 4 base64 chars*/
3915 while (scan4base64char(source + sourcePosition, sourceLength - sourcePosition, agentData->value.edmBinary.data + destinationPosition, agentData->value.edmBinary.data + destinationPosition + 1, agentData->value.edmBinary.data + destinationPosition + 2) == 0)
3916 {
3917 sourcePosition += 4;
3918 destinationPosition += 3;
3919 }
3920
3921 if (scanbase64b16(source + sourcePosition, sourceLength - sourcePosition, &consumed, agentData->value.edmBinary.data + destinationPosition, agentData->value.edmBinary.data + destinationPosition + 1) == 0)
3922 {
3923 sourcePosition += consumed;
3924 destinationPosition += 2;
3925
3926 }
3927 else if (scanbase64b8(source + sourcePosition, sourceLength - sourcePosition, &consumed, agentData->value.edmBinary.data + destinationPosition) == 0)
3928 {
3929 sourcePosition += consumed;
3930 destinationPosition += 1;
3931 }
3932
3933 if (source[sourcePosition++] != '"') /*if it doesn't end with " then bail out*/
3934 {
3935 free(agentData->value.edmBinary.data);
3936 agentData->value.edmBinary.data = NULL;
3937 result = AGENT_DATA_TYPES_INVALID_ARG;
3938 }
3939 else if (sourcePosition != sourceLength)
3940 {
3941 free(agentData->value.edmBinary.data);
3942 agentData->value.edmBinary.data = NULL;
3943 result = AGENT_DATA_TYPES_INVALID_ARG;
3944 }
3945 else
3946 {
3947 /*trim the result*/
3948 void* temp = realloc(agentData->value.edmBinary.data, destinationPosition);
3949 if (temp == NULL) /*this is extremely unlikely to happen, but whatever*/
3950 {
3951 free(agentData->value.edmBinary.data);
3952 agentData->value.edmBinary.data = NULL;
3953 result = AGENT_DATA_TYPES_ERROR;
3954 }
3955 else
3956 {
3957 agentData->type = EDM_BINARY_TYPE;
3958 agentData->value.edmBinary.data = (unsigned char*)temp;
3959 agentData->value.edmBinary.size = destinationPosition;
3960 result = AGENT_DATA_TYPES_OK;
3961 }
3962 }
3963 }
3964 }
3965 }
3966 break;
3967 }
3968 }
3969 }
3970
3971 return result;
3972}
3973
3974// extern AGENT_DATA_TYPES_RESULT AgentDataType_GetComplexTypeField(AGENT_DATA_TYPE* agentData, size_t index, COMPLEX_TYPE_FIELD_TYPE* complexField);
3975COMPLEX_TYPE_FIELD_TYPE* AgentDataType_GetComplexTypeField(AGENT_DATA_TYPE* agentData, size_t index)
3976{
3977 COMPLEX_TYPE_FIELD_TYPE* complexField = NULL;
3978 if (agentData == NULL)
3979 {
3980 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_INVALID_ARG));
3981 }
3982 else
3983 {
3984 if (agentData->type != EDM_COMPLEX_TYPE_TYPE)
3985 {
3986 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_INVALID_ARG));
3987 }
3988
3989 else
3990 {
3991 if (index >= agentData->value.edmComplexType.nMembers)
3992 {
3993 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_INVALID_ARG));
3994 }
3995 else
3996 {
3997 complexField = (COMPLEX_TYPE_FIELD_TYPE*)malloc(sizeof(COMPLEX_TYPE_FIELD_TYPE));
3998 if (complexField == NULL)
3999 {
4000 LogError("(result = %s)", MU_ENUM_TO_STRING(AGENT_DATA_TYPES_RESULT, AGENT_DATA_TYPES_ERROR));
4001 }
4002 else
4003 {
4004 *complexField = agentData->value.edmComplexType.fields[index];
4005 }
4006 }
4007 }
4008 }
4009 return complexField;
4010}
4011
Note: See TracBrowser for help on using the repository browser.