1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include <ctype.h>
26 #include "helpers.h"
27 #include "types.h"
28 #include "strings.h"
29 #include "alloc.h"
30 #include "io.h"
31
32 #define T MI_T
33
34 static const MI_Char* _ParseNumber(const MI_Char* p, unsigned long* n)
35 {
36 MI_Char* end;
37
38 *n = Ztoul(p, &end, 10);
39
40 if (end == p)
41 return NULL;
42
43 mike 1.1 return end;
44 }
45
46 static const MI_Char* _ParseDecimalPart(
47 const MI_Char* p,
48 unsigned long* n)
49 {
50 MI_Char* end;
51 int i;
52 MI_Char buf[7];
53 unsigned long x;
54
55 x = Ztoul(p, &end, 10);
56
57 if (end == p)
58 {
59 /* Zero decimal part */
60 *n = 0;
61 return p;
62 }
63
64 mike 1.1 for (i = 0; i < 6 && p != end; i++, p++)
65 buf[i] = *p;
66
67 for (; i < 6; i++)
68 buf[i] = '0';
69
70 buf[6] = '\0';
71
72 *n = Ztoul(buf, NULL, 10);
73
74 return end;
75 }
76
77 static int _ParseWSManDuration(const MI_Char* str, MI_Datetime* x)
78 {
79 const MI_Char* p = str;
80 int foundT = 0;
81 unsigned long years = 0;
82 unsigned long months = 0;
83 unsigned long days = 0;
84 unsigned long hours = 0;
85 mike 1.1 unsigned long minutes = 0;
86 unsigned long seconds = 0;
87 unsigned long microseconds = 0;
88
89 /* xs:duration: PnYnMnDTnHnMnS */
90 if (*p != 'P')
91 return -1;
92
93 /* [xs:duration]
94 *
95 * Format: "PnYnMnDTnHnMnS", where
96 * P - period (required)
97 * nY - number of years
98 * nM - number of month
99 * nD - number of days
100 * T - start of time section (required for the following)
101 * nH - number of hours
102 * nM - number of minutes
103 * nS - number of seconds
104 *
105 * Examples:
106 mike 1.1 * -P10D (rejected)
107 * -P1347M (rejected)
108 * P5Y
109 * P5Y2M10D
110 * P5Y2M10DT15H
111 * PT15H
112 * P1347Y
113 * P1347M
114 * P1Y2MT2H
115 * P0Y1347M
116 * P0Y1347M0D
117 * P1Y2M3DT10H30M
118 *
119 * Illegal:
120 * P-1347M (rejected)
121 * P1Y2MT (tolerated)
122 */
123
124 p++;
125
126 while (*p)
127 mike 1.1 {
128 unsigned long n = 0;
129
130 if (*p == 'T')
131 {
132 foundT = 1;
133 p++;
134 }
135 else if (foundT)
136 {
137 p = _ParseNumber(p, &n);
138
139 if (!p)
140 break;
141
142 switch (*p)
143 {
144 case 'H':
145 hours = n;
146 break;
147 case 'M':
148 mike 1.1 minutes = n;
149 break;
150 case 'S':
151 seconds = n;
152 break;
153 case '.':
154 {
155 p++;
156 p = _ParseDecimalPart(p, µseconds);
157
158 if (*p != 'S')
159 return -1;
160
161 seconds = n;
162 break;
163 }
164 default:
165 return -1;
166 }
167
168 p++;
169 mike 1.1 }
170 else
171 {
172 p = _ParseNumber(p, &n);
173
174 if (!p)
175 break;
176
177 switch (*p)
178 {
179 case 'Y':
180 years = n;
181 break;
182 case 'M':
183 months = n;
184 break;
185 case 'D':
186 days = n;
187 break;
188 default:
189 return -1;
190 mike 1.1 }
191
192 p++;
193 }
194 }
195
196 /* ATTN: check for overflow */
197
198 /* Normalize seconds (possibly increasing minutes) */
199 minutes += seconds / 60;
200 seconds = seconds % 60;
201
202 /* Normalize minutes (possibly increasing hours) */
203 hours += minutes / 60;
204 minutes = minutes % 60;
205
206 /* Normalize hours (possibly increasing days) */
207 days += hours / 24;
208 hours = hours % 24;
209
210 /* Approximate days from years-months-days */
211 mike 1.1 days += years * 365;
212 days += years / 4;
213 days += months * 30;
214 days += months / 2;
215
216 /* Set CIM datetime fields */
217 x->isTimestamp = MI_FALSE;
218 x->u.interval.days = (unsigned int)days;
219 x->u.interval.hours = (unsigned int)hours;
220 x->u.interval.minutes = (unsigned int)minutes;
221 x->u.interval.seconds = (unsigned int)seconds;
222 x->u.interval.microseconds = microseconds;
223
224 return (p && *p == '\0') ? 0 : -1;
225 }
226
227 static const MI_Char* _ParseWSManUTC(const MI_Char* str, MI_Datetime* x)
228 {
229 const MI_Char* p = str;
230 unsigned long utcHours = 0;
231 unsigned long utcMinutes = 0;
232 mike 1.1 long utcSign = 0; /* '1' is positive, '-1' is negative */
233
234 if (*p == 'Z')
235 {
236 p++;
237 return p;
238 }
239 else if (*p == '+' || *p == '-')
240 {
241 /* Parse UTC "HH:SS" */
242 const MI_Char* end;
243
244 utcSign = (*p == '-') ? -1 : 1;
245
246 p++;
247 end = _ParseNumber(p, &utcHours);
248
249 if (!end || (end - p) != 2)
250 return NULL;
251
252 p = end;
253 mike 1.1
254 if (*p != ':')
255 return NULL;
256
257 p++;
258 end = _ParseNumber(p, &utcMinutes);
259
260 if (!end || (end - p) != 2)
261 return NULL;
262
263 p = end;
264 }
265 else
266 {
267 return NULL;
268 }
269
270 /* Set CIM datetime fields */
271 x->u.timestamp.utc = utcSign * ((utcHours * 60) + utcMinutes);
272
273 return p;
274 mike 1.1 }
275
276 static const MI_Char* _ParseWSManDate(const MI_Char* str, MI_Datetime* x)
277 {
278 const MI_Char* p = str;
279 unsigned long year = 0;
280 unsigned long month = 0;
281 unsigned long day = 0;
282
283 /* Parse YYYY */
284 {
285 const MI_Char* end = _ParseNumber(p, &year);
286
287 if (!end || (end - p) != 4)
288 return NULL;
289
290 p = end;
291 }
292
293 /* Expect '-' */
294 if (*p++ != '-')
295 mike 1.1 return NULL;
296
297 /* Parse MM */
298 {
299 const MI_Char* end = _ParseNumber(p, &month);
300
301 if (!end || (end - p) != 2)
302 return NULL;
303
304 p = end;
305 }
306
307 /* Expect '-' */
308 if (*p++ != '-')
309 return NULL;
310
311 /* Parse DD */
312 {
313 const MI_Char* end = _ParseNumber(p, &day);
314
315 if (!end || (end - p) != 2)
316 mike 1.1 return NULL;
317
318 p = end;
319 }
320
321 /* Set CIM datetime fields */
322 memset(x, 0, sizeof(MI_Datetime));
323 x->isTimestamp = MI_TRUE;
324 x->u.timestamp.year = (unsigned int)year;
325 x->u.timestamp.month = (unsigned int)month;
326 x->u.timestamp.day = (unsigned int)day;
327
328 /* Parse UTC part */
329 if (*p == 'Z' || *p == '+' || *p == '-')
330 {
331 p = _ParseWSManUTC(p, x);
332
333 if (!p)
334 return NULL;
335 }
336
337 mike 1.1 return p;
338 }
339
340 static const MI_Char* _ParseWSManTime(const MI_Char* str, MI_Datetime* x)
341 {
342 const MI_Char* p = str;
343 unsigned long hour = 0;
344 unsigned long minute = 0;
345 unsigned long second = 0;
346 unsigned long microseconds = 0;
347
348 /* Parse "HH" */
349 {
350 const MI_Char* end = _ParseNumber(p, &hour);
351
352 if (!end || (end - p) != 2)
353 return NULL;
354
355 p = end;
356 }
357
358 mike 1.1 /* Expect ':' */
359 if (*p++ != ':')
360 return NULL;
361
362 /* Parse "MM" */
363 {
364 const MI_Char* end = _ParseNumber(p, &minute);
365
366 if (!end || (end - p) != 2)
367 return NULL;
368
369 p = end;
370 }
371
372 /* Expect ":" */
373 if (*p++ != ':')
374 return NULL;
375
376 /* Parse "SS" */
377 {
378 const MI_Char* end = _ParseNumber(p, &second);
379 mike 1.1
380 if (!end || (end - p) != 2)
381 return NULL;
382
383 p = end;
384 }
385
386 /* Parse decimal part */
387 if (*p == '.')
388 {
389 p++;
390 p = _ParseDecimalPart(p, µseconds);
391
392 if (!p)
393 return NULL;
394 }
395
396 /* Set CIM datetime fields */
397 x->isTimestamp = MI_TRUE;
398 x->u.timestamp.hour = (unsigned int)hour;
399 x->u.timestamp.minute = (unsigned int)minute;
400 mike 1.1 x->u.timestamp.second = (unsigned int)second;
401 x->u.timestamp.microseconds = (unsigned int)microseconds;
402
403 /* Parse UTC part */
404 if (*p == 'Z' || *p == '+' || *p == '-')
405 {
406 p = _ParseWSManUTC(p, x);
407
408 if (!p)
409 return NULL;
410 }
411
412 return p;
413 }
414
415 int ParseWSManDatetime(const MI_Char* str, MI_Datetime* x)
416 {
417 const MI_Char* p = str;
418
419 /* Clear datetime */
420 memset(x, 0, sizeof(MI_Datetime));
421 mike 1.1
422 /* negative xs:duration */
423 if (*p == '-')
424 {
425 /* Negative intervals not supported by CIM */
426 return -1;
427 }
428
429 /* xs:duration: "PnYnMnDTnHnMnS" */
430 if (*p == 'P')
431 {
432 return _ParseWSManDuration(str, x);
433 }
434
435 /* xs:date: "YYYY-MM-DD" plus UTC */
436 if (isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]))
437 {
438 p = _ParseWSManDate(str, x);
439
440 if (!p)
441 return -1;
442 mike 1.1
443 if (*p == '\0')
444 return 0;
445
446 /* xs:time "HH:MM:SS" plus UTC */
447 if (*p == 'T')
448 {
449 p++;
450 p = _ParseWSManTime(p, x);
451
452 if (!p)
453 return -1;
454
455 if (*p == '\0')
456 return 0;
457 }
458 }
459
460 /* xs:time: "HH:MM:SS" plus UTC */
461 if (isdigit(p[0]) && isdigit(p[1]) && p[2] == ':')
462 {
463 mike 1.1 p = _ParseWSManTime(str, x);
464
465 if (!p)
466 return -1;
467
468 if (*p == '\0')
469 return 0;
470 }
471
472 /* Failed */
473 return -1;
474 }
475
476 void FormatWSManDatetime(const MI_Datetime* x, MI_Char buffer[64])
477 {
478 int n = 64;
479
480 *buffer = '\0';
481
482 if (x->isTimestamp)
483 {
484 mike 1.1 /* Example output: "2010-12-31T12:30:03.123456+06:00" */
485 int haveDate;
486 int haveTime;
487 MI_Char tmpbuf[64];
488
489 haveDate = x->u.timestamp.year || x->u.timestamp.month ||
490 x->u.timestamp.day;
491
492 haveTime = x->u.timestamp.hour || x->u.timestamp.minute ||
493 x->u.timestamp.second || x->u.timestamp.microseconds;
494
495 if (haveDate)
496 {
497 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%04u-%02u-%02u"),
498 x->u.timestamp.year,
499 x->u.timestamp.month,
500 x->u.timestamp.day);
501 Zlcat(buffer, tmpbuf, n);
502 }
503
504 if (haveTime || !haveDate)
505 mike 1.1 {
506 if (haveDate)
507 Zlcat(buffer, T("T"), n);
508
509 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%02u:%02u:%02u"),
510 x->u.timestamp.hour,
511 x->u.timestamp.minute,
512 x->u.timestamp.second);
513 Zlcat(buffer, tmpbuf, n);
514
515 if (x->u.timestamp.microseconds)
516 {
517 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T(".%06u"),
518 x->u.timestamp.microseconds);
519 Zlcat(buffer, tmpbuf, n);
520 }
521
522 }
523
524 if (x->u.timestamp.utc > 0)
525 {
526 mike 1.1 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("+%02u:%02u"),
527 x->u.timestamp.utc / 60, x->u.timestamp.utc % 60);
528 Zlcat(buffer, tmpbuf, n);
529 }
530 else if (x->u.timestamp.utc < 0)
531 {
532 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("-%02u:%02u"),
533 -x->u.timestamp.utc / 60, -x->u.timestamp.utc % 60);
534 Zlcat(buffer, tmpbuf, n);
535 }
536 }
537 else
538 {
539 MI_Char tmpbuf[64];
540
541 /* Example: "P1Y1M22DT10H11M12S" */
542
543 Zlcat(buffer, T("P"), n);
544
545 if (x->u.interval.days)
546 {
547 mike 1.1 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uD"), x->u.interval.days);
548 Zlcat(buffer, tmpbuf, n);
549 }
550
551 if (x->u.interval.hours || x->u.interval.minutes ||
552 x->u.interval.seconds || x->u.interval.microseconds)
553 {
554 Zlcat(buffer, T("T"), n);
555 }
556
557 if (x->u.interval.hours)
558 {
559 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uH"), x->u.interval.hours);
560 Zlcat(buffer, tmpbuf, n);
561 }
562
563 if (x->u.interval.minutes)
564 {
565 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uM"), x->u.interval.minutes);
566 Zlcat(buffer, tmpbuf, n);
567 }
568 mike 1.1
569 if (x->u.interval.seconds && x->u.interval.microseconds)
570 {
571 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%u.%06uS"),
572 x->u.interval.seconds, x->u.interval.microseconds);
573 Zlcat(buffer, tmpbuf, n);
574 }
575 else if (x->u.interval.seconds && !x->u.interval.microseconds)
576 {
577 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("%uS"), x->u.interval.seconds);
578 Zlcat(buffer, tmpbuf, n);
579 }
580 else if (!x->u.interval.seconds && x->u.interval.microseconds)
581 {
582 Szprintf(tmpbuf, MI_COUNT(tmpbuf), T("0.%06uS"),
583 x->u.interval.microseconds);
584 Zlcat(buffer, tmpbuf, n);
585 }
586 }
587 }
588
589 mike 1.1 static int _StrToU32(const MI_Char* s, size_t offset, size_t size, MI_Uint32* x)
590 {
591 MI_Char buf[64];
592 MI_Char* end;
593
594 if (size >= MI_COUNT(buf))
595 return -1;
596
597 memcpy(buf, &s[offset], size * sizeof(MI_Char));
598 buf[size] = '\0';
599
600 *x = (MI_Uint32)Ztoul(buf, &end, 10);
601
602 if (*end != '\0')
603 return -1;
604
605 /* Success */
606 return 0;
607 }
608
609 int StrToChar16(const MI_Char* str, MI_Char16* x)
610 mike 1.1 {
611 MI_Char* end;
612 *x = (MI_Char16)Ztoul(str, &end, 0);
613
614 if (*end != '\0')
615 return -1;
616
617 return 0;
618 }
619
620 int StrToDatetime(const MI_Char* s, MI_Datetime* x)
621 {
622 if (Zlen(s) != 25)
623 return -1;
624
625 memset(x, 0, sizeof(MI_Datetime));
626
627 if (s[21] == '+' || s[21] == '-')
628 {
629 MI_Uint32 utc;
630
631 mike 1.1 /* It must be a timestamp (YYYYMMDDHHMMSS.MMMMMMSUTC) */
632 if (_StrToU32(s, 0, 4, &x->u.timestamp.year) != 0 ||
633 _StrToU32(s, 4, 2, &x->u.timestamp.month) != 0 ||
634 _StrToU32(s, 6, 2, &x->u.timestamp.day) != 0 ||
635 _StrToU32(s, 8, 2, &x->u.timestamp.hour) != 0 ||
636 _StrToU32(s, 10, 2, &x->u.timestamp.minute) != 0 ||
637 _StrToU32(s, 12, 2, &x->u.timestamp.second) != 0 ||
638 s[14] != '.' ||
639 _StrToU32(s, 15, 6, &x->u.timestamp.microseconds) != 0 ||
640 _StrToU32(s, 22, 3, &utc) != 0)
641 {
642 return -1;
643 }
644
645 if (s[21] == '+')
646 x->u.timestamp.utc = (MI_Sint32)utc;
647 else
648 x->u.timestamp.utc = -(MI_Sint32)utc;
649
650 x->isTimestamp = 1;
651 }
652 mike 1.1 else if (s[21] == ':')
653 {
654 /* It must be an interval (DDDDDDDDHHMMSS.MMMMMM:000) */
655 if (_StrToU32(s, 0, 8, &x->u.interval.days) != 0 ||
656 _StrToU32(s, 8, 2, &x->u.interval.hours) != 0 ||
657 _StrToU32(s, 10, 2, &x->u.interval.minutes) != 0 ||
658 _StrToU32(s, 12, 2, &x->u.interval.seconds) != 0 ||
659 s[14] != '.' ||
660 _StrToU32(s, 15, 6, &x->u.interval.microseconds) != 0 ||
661 s[22] != '0' || s[23] != '0' || s[24] != '0')
662 {
663 return -1;
664 }
665
666 x->isTimestamp = 0;
667 }
668 else
669 return -1;
670
671 return 0;
672 }
673 mike 1.1
674 static int _ParseDatetime(const MI_Char* str, MI_Datetime* x)
675 {
676 if (StrToDatetime(str, x) == 0)
677 return 0;
678
679 if (ParseWSManDatetime(str, x) == 0)
680 return 0;
681
682 return -1;
683 }
684
685 int StrToBoolean(const MI_Char* str, MI_Boolean* x)
686 {
687 if (Zcasecmp(str, T("true")) == 0)
688 *x = MI_TRUE;
689 else if (Zcasecmp(str, T("false")) == 0)
690 *x = MI_FALSE;
691 else
692 return -1;
693
694 mike 1.1 return 0;
695 }
696
697 int StrToUint8(const MI_Char* str, MI_Uint8* x)
698 {
699 MI_Char* end;
700 *x = (MI_Uint8)Ztoul(str, &end, 0);
701
702 if (*end != '\0')
703 return -1;
704
705 return 0;
706 }
707
708 int StrToSint8(const MI_Char* str, MI_Sint8* x)
709 {
710 MI_Char* end;
711 *x = (MI_Sint8)Ztol(str, &end, 0);
712
713 if (*end != '\0')
714 return -1;
715 mike 1.1
716 return 0;
717 }
718
719 int StrToUint16(const MI_Char* str, MI_Uint16* x)
720 {
721 MI_Char* end;
722 *x = (MI_Uint16)Ztoul(str, &end, 0);
723
724 if (*end != '\0')
725 return -1;
726
727 return 0;
728 }
729
730 int StrToSint16(const MI_Char* str, MI_Sint16* x)
731 {
732 MI_Char* end;
733 *x = (MI_Sint16)Ztol(str, &end, 0);
734
735 if (*end != '\0')
736 mike 1.1 return -1;
737
738 return 0;
739 }
740
741 int StrToUint32(const MI_Char* str, MI_Uint32* x)
742 {
743 MI_Char* end;
744 *x = (MI_Uint32)Ztoul(str, &end, 0);
745
746 if (*end != '\0')
747 return -1;
748
749 return 0;
750 }
751
752 int StrToSint32(const MI_Char* str, MI_Sint32* x)
753 {
754 MI_Char* end;
755 *x = (MI_Sint32)Ztol(str, &end, 0);
756
757 mike 1.1 if (*end != '\0')
758 return -1;
759
760 return 0;
761 }
762
763 int StrToUint64(const MI_Char* str, MI_Uint64* x)
764 {
765 MI_Char* end;
766 *x = (MI_Uint64)Ztoull(str, &end, 0);
767
768 if (*end != '\0')
769 return -1;
770
771 return 0;
772 }
773
774 int StrToSint64(const MI_Char* str, MI_Sint64* x)
775 {
776 MI_Char* end;
777 *x = (MI_Sint64)Ztoll(str, &end, 0);
778 mike 1.1
779 if (*end != '\0')
780 return -1;
781
782 return 0;
783 }
784
785 int StrToReal32(const MI_Char* str, MI_Real32* x)
786 {
787 MI_Char* end;
788 *x = (MI_Real32)Ztod(str, &end);
789
790 if (*end != '\0')
791 return -1;
792
793 return 0;
794 }
795
796 int StrToReal64(const MI_Char* str, MI_Real64* x)
797 {
798 MI_Char* end;
799 mike 1.1 *x = (MI_Real64)Ztod(str, &end);
800
801 if (*end != '\0')
802 return -1;
803
804 return 0;
805 }
806
807 MI_Result MI_CALL Instance_SetElementFromString(
808 MI_Instance* self,
809 const MI_Char* name,
810 const MI_Char* str)
811 {
812 /* ATTN: check for integer value truncation (see use of Ztol) */
813 /* ATTN: implement array types! */
814 /* ATTN: implement instance and reference types! */
815 MI_Type type;
816 MI_Value value;
817
818 /* Check arguments */
819 if (!self || !name || !str)
820 mike 1.1 MI_RETURN(MI_RESULT_INVALID_PARAMETER);
821
822 /* Obtain type of named property */
823 {
824 MI_Result r = MI_Instance_GetElement(self, name, NULL, &type,
825 NULL, NULL);
826
827 if (r != MI_RESULT_OK)
828 return r;
829 }
830
831 /* If type is array and value is string,
832 try to create a single item array from this string
833 */
834 if (0 != (MI_ARRAY_BIT & type))
835 return Instance_SetElementFromStringA(
836 self, name, &str, 1);
837
838
839 /* Convert string to value */
840 switch (type)
841 mike 1.1 {
842 case MI_BOOLEAN:
843 {
844 if (StrToBoolean(str, &value.boolean) != 0)
845 MI_RETURN(MI_RESULT_FAILED);
846 break;
847 }
848 case MI_UINT8:
849 {
850 if (StrToUint8(str, &value.uint8) != 0)
851 MI_RETURN(MI_RESULT_FAILED);
852 break;
853 }
854 case MI_SINT8:
855 {
856 if (StrToSint8(str, &value.sint8) != 0)
857 MI_RETURN(MI_RESULT_FAILED);
858 break;
859 }
860 case MI_UINT16:
861 {
862 mike 1.1 if (StrToUint16(str, &value.uint16) != 0)
863 MI_RETURN(MI_RESULT_FAILED);
864 break;
865 }
866 case MI_SINT16:
867 {
868 if (StrToSint16(str, &value.sint16) != 0)
869 MI_RETURN(MI_RESULT_FAILED);
870 break;
871 }
872 case MI_UINT32:
873 {
874 if (StrToUint32(str, &value.uint32) != 0)
875 MI_RETURN(MI_RESULT_FAILED);
876 break;
877 }
878 case MI_SINT32:
879 {
880 if (StrToSint32(str, &value.sint32) != 0)
881 MI_RETURN(MI_RESULT_FAILED);
882 break;
883 mike 1.1 }
884 case MI_UINT64:
885 {
886 if (StrToUint64(str, &value.uint64) != 0)
887 MI_RETURN(MI_RESULT_FAILED);
888 break;
889 }
890 case MI_SINT64:
891 {
892 if (StrToSint64(str, &value.sint64) != 0)
893 MI_RETURN(MI_RESULT_FAILED);
894 break;
895 }
896 case MI_REAL32:
897 {
898 if (StrToReal32(str, &value.real32) != 0)
899 MI_RETURN(MI_RESULT_FAILED);
900 break;
901 }
902 case MI_REAL64:
903 {
904 mike 1.1 if (StrToReal64(str, &value.real64) != 0)
905 MI_RETURN(MI_RESULT_FAILED);
906 break;
907 }
908 case MI_CHAR16:
909 {
910 if (StrToUint16(str, &value.char16) != 0)
911 MI_RETURN(MI_RESULT_FAILED);
912 break;
913 }
914 case MI_DATETIME:
915 {
916 if (_ParseDatetime(str, &value.datetime) != 0)
917 MI_RETURN(MI_RESULT_FAILED);
918 break;
919 }
920 case MI_STRING:
921 {
922 value.string = (MI_Char*)str;
923 break;
924 }
925 mike 1.1 default:
926 {
927 MI_RETURN(MI_RESULT_FAILED);
928 }
929 }
930
931 MI_RETURN(MI_Instance_SetElement(self, name, &value, type, 0));
932 }
933
934 MI_Result MI_CALL Instance_SetElementFromStringA(
935 MI_Instance* self_,
936 const MI_Char* name,
937 const MI_Char** data,
938 MI_Uint32 size)
939 {
940 Instance* self = (Instance*)self_;
941 MI_Type type = MI_BOOLEAN;
942 MI_Value v;
943 MI_Uint32 i;
944 MI_Result result = MI_RESULT_OK;
945 MI_Uint32 flags = 0;
946 mike 1.1
947 /* Clear value first */
948 memset(&v, 0, sizeof(v));
949
950 /* Check arguments */
951 if (!self || !name || !data)
952 {
953 /* return instead of goto failed: 'v' is not initialized yet */
954 return MI_RESULT_INVALID_PARAMETER;
955 }
956
957 /* Obtain type of named property */
958 if (MI_Instance_GetElement(self_, name, NULL, &type, NULL, NULL))
959 {
960 /* return instead of goto failed: 'v' is not initialized yet */
961 return MI_RESULT_FAILED;
962 }
963
964 /* Allocate array (allocate extra element for possible empty array) */
965 if (type == MI_STRINGA)
966 {
967 mike 1.1 v.array.data = (MI_Char**)data;
968 v.array.size = size;
969 }
970 else
971 {
972 MI_Uint32 esize = (MI_Uint32)Type_SizeOf(Type_ScalarOf(type));
973 v.array.data = BAlloc(self->batch, (size + 1) * esize, CALLSITE);
974
975 if (!v.array.data)
976 {
977 result = MI_RESULT_FAILED;
978 goto done;
979 }
980
981 v.array.size = size;
982 flags |= MI_FLAG_ADOPT;
983 }
984
985 /* Convert string to v */
986 switch (type)
987 {
988 mike 1.1 case MI_BOOLEANA:
989 {
990 for (i = 0; i < size; i++)
991 {
992 if (StrToBoolean(data[i], &v.booleana.data[i]) != 0)
993 {
994 result = MI_RESULT_FAILED;
995 goto done;
996 }
997 }
998 break;
999 }
1000 case MI_UINT8A:
1001 {
1002 for (i = 0; i < size; i++)
1003 {
1004 if (StrToUint8(data[i], &v.uint8a.data[i]) != 0)
1005 {
1006 result = MI_RESULT_FAILED;
1007 goto done;
1008 }
1009 mike 1.1 }
1010 break;
1011 }
1012 case MI_SINT8A:
1013 {
1014 for (i = 0; i < size; i++)
1015 {
1016 if (StrToSint8(data[i], &v.sint8a.data[i]) != 0)
1017 {
1018 result = MI_RESULT_FAILED;
1019 goto done;
1020 }
1021 }
1022 break;
1023 }
1024 case MI_UINT16A:
1025 {
1026 for (i = 0; i < size; i++)
1027 {
1028 if (StrToUint16(data[i], &v.uint16a.data[i]) != 0)
1029 {
1030 mike 1.1 result = MI_RESULT_FAILED;
1031 goto done;
1032 }
1033 }
1034 break;
1035 }
1036 case MI_SINT16A:
1037 {
1038 for (i = 0; i < size; i++)
1039 {
1040 if (StrToSint16(data[i], &v.sint16a.data[i]) != 0)
1041 {
1042 result = MI_RESULT_FAILED;
1043 goto done;
1044 }
1045 }
1046 break;
1047 }
1048 case MI_UINT32A:
1049 {
1050 for (i = 0; i < size; i++)
1051 mike 1.1 {
1052 if (StrToUint32(data[i], &v.uint32a.data[i]) != 0)
1053 {
1054 result = MI_RESULT_FAILED;
1055 goto done;
1056 }
1057 }
1058 break;
1059 }
1060 case MI_SINT32A:
1061 {
1062 for (i = 0; i < size; i++)
1063 {
1064 if (StrToSint32(data[i], &v.sint32a.data[i]) != 0)
1065 {
1066 result = MI_RESULT_FAILED;
1067 goto done;
1068 }
1069 }
1070 break;
1071 }
1072 mike 1.1 case MI_UINT64A:
1073 {
1074 for (i = 0; i < size; i++)
1075 {
1076 if (StrToUint64(data[i], &v.uint64a.data[i]) != 0)
1077 {
1078 result = MI_RESULT_FAILED;
1079 goto done;
1080 }
1081 }
1082 break;
1083 }
1084 case MI_SINT64A:
1085 {
1086 for (i = 0; i < size; i++)
1087 {
1088 if (StrToSint64(data[i], &v.sint64a.data[i]) != 0)
1089 {
1090 result = MI_RESULT_FAILED;
1091 goto done;
1092 }
1093 mike 1.1 }
1094 break;
1095 }
1096 case MI_REAL32A:
1097 {
1098 for (i = 0; i < size; i++)
1099 {
1100 if (StrToReal32(data[i], &v.real32a.data[i]) != 0)
1101 {
1102 result = MI_RESULT_FAILED;
1103 goto done;
1104 }
1105 }
1106 break;
1107 }
1108 case MI_REAL64A:
1109 {
1110 for (i = 0; i < size; i++)
1111 {
1112 if (StrToReal64(data[i], &v.real64a.data[i]) != 0)
1113 {
1114 mike 1.1 result = MI_RESULT_FAILED;
1115 goto done;
1116 }
1117 }
1118 break;
1119 }
1120 case MI_CHAR16A:
1121 {
1122 for (i = 0; i < size; i++)
1123 {
1124 if (StrToChar16(data[i], &v.char16a.data[i]) != 0)
1125 {
1126 result = MI_RESULT_FAILED;
1127 goto done;
1128 }
1129 }
1130 break;
1131 }
1132 case MI_DATETIMEA:
1133 {
1134 for (i = 0; i < size; i++)
1135 mike 1.1 {
1136 if (_ParseDatetime(data[i], &v.datetimea.data[i]) != 0)
1137 {
1138 result = MI_RESULT_FAILED;
1139 goto done;
1140 }
1141 }
1142 break;
1143 }
1144 case MI_STRINGA:
1145 {
1146 // Handled above.
1147 break;
1148 }
1149 default:
1150 {
1151 result = MI_RESULT_FAILED;
1152 goto done;
1153 }
1154 }
1155
1156 mike 1.1 if (MI_Instance_SetElement(self_, name, &v, type, flags))
1157 {
1158 result = MI_RESULT_FAILED;
1159 goto done;
1160 }
1161
1162 done:
1163
1164 if (result && v.array.data && type != MI_STRINGA)
1165 BFree(self->batch, v.array.data, CALLSITE);
1166
1167 return result;
1168 }
1169
1170 MI_Result MI_CALL Instance_GetValue(
1171 MI_Instance* self,
1172 const MI_Char* name,
1173 void* value,
1174 MI_Type type)
1175 {
1176 MI_Result r;
1177 mike 1.1 MI_Value v;
1178 MI_Type t;
1179 MI_Uint32 f;
1180
1181 r = MI_Instance_GetElement(self, name, &v, &t, &f, NULL);
1182
1183 if (r != MI_RESULT_OK)
1184 MI_RETURN(r);
1185
1186 if (t != type)
1187 MI_RETURN(MI_RESULT_TYPE_MISMATCH);
1188
1189 if (f & MI_FLAG_NULL)
1190 MI_RETURN(MI_RESULT_NOT_FOUND);
1191
1192 if (!value)
1193 MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1194
1195 memcpy(value, &v, Type_SizeOf(type));
1196
1197 MI_RETURN(MI_RESULT_OK);
1198 mike 1.1 }
1199
1200 void DatetimeToStr(const MI_Datetime* x, MI_Char buf[26])
1201 {
1202 if (x->isTimestamp)
1203 {
1204 const MI_Char FMT[] = MI_T("%04d%02d%02d%02d%02d%02d.%06d%c%03d");
1205 MI_Sint32 utc = x->u.timestamp.utc;
1206 Szprintf(buf, 26, FMT,
1207 x->u.timestamp.year,
1208 x->u.timestamp.month,
1209 x->u.timestamp.day,
1210 x->u.timestamp.hour,
1211 x->u.timestamp.minute,
1212 x->u.timestamp.second,
1213 x->u.timestamp.microseconds,
1214 utc < 0 ? '-' : '+',
1215 utc < 0 ? -utc : utc);
1216 }
1217 else
1218 {
1219 mike 1.1 const MI_Char FMT[] = MI_T("%08u%02u%02u%02u.%06u:000");
1220 Szprintf(buf, 26, FMT,
1221 x->u.interval.days,
1222 x->u.interval.hours,
1223 x->u.interval.minutes,
1224 x->u.interval.seconds,
1225 x->u.interval.microseconds);
1226 }
1227 }
|