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 "field.h"
26 #include "types.h"
27 #include "alloc.h"
28 #include "instance.h"
29 #include "return.h"
30 #include "types.h"
31 #include "indent.h"
32 #include "strings.h"
33 #include "io.h"
34 #include "helpers.h"
35
36 #define T MI_T
37 #define _BORROW 0x01
38
39 /*
40 **==============================================================================
41 **
42 ** Local definitions
43 mike 1.1 **
44 **==============================================================================
45 */
46
47 static unsigned char _fieldSizes[] =
48 {
49 sizeof(MI_BooleanField),
50 sizeof(MI_Uint8Field),
51 sizeof(MI_Sint8Field),
52 sizeof(MI_Uint16Field),
53 sizeof(MI_Sint16Field),
54 sizeof(MI_Uint32Field),
55 sizeof(MI_Sint32Field),
56 sizeof(MI_Uint64Field),
57 sizeof(MI_Sint64Field),
58 sizeof(MI_Real32Field),
59 sizeof(MI_Real64Field),
60 sizeof(MI_Char16Field),
61 sizeof(MI_DatetimeField),
62 sizeof(MI_StringField),
63 sizeof(MI_ReferenceField),
64 mike 1.1 sizeof(MI_InstanceField),
65 sizeof(MI_BooleanAField),
66 sizeof(MI_Uint8AField),
67 sizeof(MI_Sint8AField),
68 sizeof(MI_Uint16AField),
69 sizeof(MI_Sint16AField),
70 sizeof(MI_Uint32AField),
71 sizeof(MI_Sint32AField),
72 sizeof(MI_Uint64AField),
73 sizeof(MI_Sint64AField),
74 sizeof(MI_Real32AField),
75 sizeof(MI_Real64AField),
76 sizeof(MI_Char16AField),
77 sizeof(MI_DatetimeAField),
78 sizeof(MI_StringAField),
79 sizeof(MI_ReferenceAField),
80 sizeof(MI_InstanceAField),
81 };
82
|
228 mike 1.1 }
229
230 /*
231 **==============================================================================
232 **
233 ** Public definitions
234 **
235 **==============================================================================
236 */
237
238 MI_Result Field_Construct(
239 Field* self,
240 MI_Type type,
241 const MI_Value* value,
242 MI_Uint32 flags,
243 Batch* batch)
244 {
245 MI_Result r;
246
247 /* Zero out self */
248 _Fill(self, type, 0);
249 mike 1.1
250 /* Handle null case up front */
251 if (flags & MI_FLAG_NULL)
252 MI_RETURN(MI_RESULT_OK);
253
254 /* Reject null values */
255 /* ATTN: Tolerate this for now */
256 if (!value)
257 MI_RETURN(MI_RESULT_OK);
258
259 switch (type)
260 {
261 case MI_BOOLEAN:
262 {
263 self->boolean.value = value->boolean;
264 self->boolean.exists = MI_TRUE;
265 break;
266 }
267 case MI_UINT8:
268 {
269 self->uint8.value = value->uint8;
270 mike 1.1 self->uint8.exists = MI_TRUE;
271 break;
272 }
273 case MI_SINT8:
274 {
275 self->sint8.value = value->sint8;
276 self->sint8.exists = MI_TRUE;
277 break;
278 }
279 case MI_UINT16:
280 {
281 self->uint16.value = value->uint16;
282 self->uint16.exists = MI_TRUE;
283 break;
284 }
285 case MI_SINT16:
286 {
287 self->sint16.value = value->sint16;
288 self->sint16.exists = MI_TRUE;
289 break;
290 }
291 mike 1.1 case MI_UINT32:
292 {
293 self->uint32.value = value->uint32;
294 self->uint32.exists = MI_TRUE;
295 break;
296 }
297 case MI_SINT32:
298 {
299 self->sint32.value = value->sint32;
300 self->sint32.exists = MI_TRUE;
301 break;
302 }
303 case MI_UINT64:
304 {
305 self->uint64.value = value->uint64;
306 self->uint64.exists = MI_TRUE;
307 break;
308 }
309 case MI_SINT64:
310 {
311 self->sint64.value = value->sint64;
312 mike 1.1 self->sint64.exists = MI_TRUE;
313 break;
314 }
315 case MI_REAL32:
316 {
317 self->real32.value = value->real32;
318 self->real32.exists = MI_TRUE;
319 break;
320 }
321 case MI_REAL64:
322 {
323 self->real64.value = value->real64;
324 self->real64.exists = MI_TRUE;
325 break;
326 }
327 case MI_CHAR16:
328 {
329 self->char16.value = value->char16;
330 self->char16.exists = MI_TRUE;
331 break;
332 }
333 mike 1.1 case MI_DATETIME:
334 {
335 self->datetime.value = value->datetime;
336 self->datetime.exists = MI_TRUE;
337 break;
338 }
339 case MI_STRING:
340 {
341 if (value->string)
342 {
343 MI_Char* str;
344
345 if (flags & MI_FLAG_BORROW)
346 {
347 self->string.value = value->string;
348 self->string.exists = MI_TRUE;
349 self->string.flags = _BORROW;
350 break;
351 }
352
353 str = BStrdup(batch, value->string, CALLSITE);
354 mike 1.1 if (!str)
355 MI_RETURN(MI_RESULT_FAILED);
356
357 self->string.value = str;
358 self->string.exists = MI_TRUE;
359 }
360 else
361 {
362 self->string.value = NULL;
363 self->string.exists = MI_FALSE;
364 self->string.flags = 0;
365 }
366 break;
367 }
368 case MI_INSTANCE:
369 case MI_REFERENCE:
370 {
371 if (value->instance)
372 {
373 MI_Instance* instance;
374
375 mike 1.1 if (flags & MI_FLAG_BORROW)
376 {
377 self->instance.value = value->instance;
378 self->instance.exists = MI_TRUE;
379 self->instance.flags = _BORROW;
380 break;
381 }
382
383 r = Instance_Clone(value->instance, &instance, batch);
384 if (r != MI_RESULT_OK)
385 MI_RETURN(r);
386
387 self->instance.value = instance;
388 self->instance.exists = MI_TRUE;
389 }
390 else
391 {
392 self->instance.value = NULL;
393 self->instance.exists = MI_FALSE;
394 self->instance.flags = 0;
395 }
396 mike 1.1 break;
397 }
398 case MI_BOOLEANA:
399 case MI_UINT8A:
400 case MI_SINT8A:
401 case MI_UINT16A:
402 case MI_SINT16A:
403 case MI_UINT32A:
404 case MI_SINT32A:
405 case MI_UINT64A:
406 case MI_SINT64A:
407 case MI_REAL32A:
408 case MI_REAL64A:
409 case MI_CHAR16A:
410 case MI_DATETIMEA:
411 {
412 if (value->array.data)
413 {
414 void* data;
415
416 if (flags & MI_FLAG_BORROW)
417 mike 1.1 {
418 self->array.value = value->array;
419 self->array.exists = MI_TRUE;
420 self->array.flags = _BORROW;;
421 break;
422 }
423
424 data = _CloneSimpleArray(
425 value->array.data, value->array.size, type, batch);
426 if (!data)
427 MI_RETURN(MI_RESULT_FAILED);
428
429 self->array.value.data = data;
430 self->array.value.size = value->array.size;
431 self->array.exists = MI_TRUE;
432 }
433 else
434 {
435 self->array.value.data = NULL;
436 self->array.value.size = 0;
437 self->array.exists = MI_FALSE;
438 mike 1.1 }
439 break;
440 }
441 case MI_STRINGA:
442 {
443 MI_Char** data;
444
445 if (value->array.data)
446 {
447 if (flags & MI_FLAG_BORROW)
448 {
449 self->stringa.value = value->stringa;
450 self->stringa.exists = MI_TRUE;
451 self->stringa.flags = _BORROW;;
452 break;
453 }
454
455 data = _CloneStringArray((const MI_Char**)value->stringa.data,
456 value->stringa.size, batch);
457 if (!data)
458 MI_RETURN(MI_RESULT_FAILED);
459 mike 1.1
460 self->stringa.value.data = data;
461 self->stringa.value.size = value->array.size;
462 self->stringa.exists = MI_TRUE;
463 }
464 else
465 {
466 self->stringa.value.data = NULL;
467 self->stringa.value.size = 0;
468 self->stringa.exists = MI_FALSE;
469 }
470 break;
471 }
472 case MI_INSTANCEA:
473 case MI_REFERENCEA:
474 {
475 if (value->instancea.data)
476 {
477 MI_Instance** data;
478
479 if (flags & MI_FLAG_BORROW)
480 mike 1.1 {
481 self->instancea.value = value->instancea;
482 self->instancea.exists = MI_TRUE;
483 self->instancea.flags = _BORROW;;
484 break;
485 }
486
487 data = _CloneInstanceArray(value->instancea.data,
488 value->instancea.size, batch);
489 if (!data)
490 MI_RETURN(MI_RESULT_FAILED);
491
492 self->instancea.value.data = data;
493 self->instancea.value.size = value->array.size;
494 self->instancea.exists = MI_TRUE;
495 }
496 else
497 {
498 self->instancea.value.data = NULL;
499 self->instancea.value.size = 0;
500 self->instancea.exists = MI_FALSE;
501 mike 1.1 }
502 break;
503 }
504 }
505
506 return MI_RESULT_OK;
507 }
508
509 void Field_Destruct(
510 Field* self,
511 MI_Type type,
512 Batch* batch)
513 {
514 switch (type)
515 {
516 case MI_STRING:
517 {
518 MI_StringField* f = &self->string;
519
520 if (!(f->flags & _BORROW) && f->value)
521 BFree(batch, f->value, CALLSITE);
522 mike 1.1 break;
523 }
524 case MI_BOOLEANA:
525 case MI_SINT8A:
526 case MI_UINT8A:
527 case MI_SINT16A:
528 case MI_UINT16A:
529 case MI_SINT32A:
530 case MI_UINT32A:
531 case MI_SINT64A:
532 case MI_UINT64A:
533 case MI_REAL32A:
534 case MI_REAL64A:
535 case MI_CHAR16A:
536 case MI_DATETIMEA:
537 case MI_STRINGA:
538 {
539 MI_ArrayField* f = &self->array;
540
541 if (!(f->flags & _BORROW) && f->value.data)
542 BFree(batch, f->value.data, CALLSITE);
543 mike 1.1 break;
544 }
545 case MI_INSTANCE:
546 case MI_REFERENCE:
547 {
548 MI_InstanceField* f = &self->instance;
549
550 if (!(f->flags & _BORROW) && f->value)
551 MI_Instance_Delete(f->value);
552 break;
553 }
554 case MI_INSTANCEA:
555 case MI_REFERENCEA:
556 {
557 MI_InstanceAField* f = &self->instancea;
558
559 if (!(f->flags & _BORROW) && f->value.data)
560 {
561 MI_Uint32 j;
562
563 for (j = 0; j < f->value.size; j++ )
564 mike 1.1 MI_Instance_Delete(f->value.data[j]);
565
566 BFree(batch, f->value.data, CALLSITE);
567 }
568 break;
569 }
570 default:
571 break;
572 }
573
574 /* Fill with illegal character */
575 _Fill(self, type, 0xDD);
576 }
577
578 MI_Result Field_Set(
579 Field* self,
580 MI_Type type,
581 const MI_Value* value,
582 MI_Uint32 flags,
583 Batch* batch)
584 {
585 mike 1.1 Field field;
586 MI_Result r;
587
588 /* Initialize new field */
589 r = Field_Construct(&field, type, value, flags, batch);
590 if (r != MI_RESULT_OK)
591 MI_RETURN(r);
592
593 /* Destroy self */
594 Field_Destruct(self, type, batch);
595
596 /* Swap new field with self */
597 _Swap(self, &field, type);
598
599 return MI_RESULT_OK;
600 }
601
602 MI_Result Field_Copy(
603 Field* self,
604 MI_Type type,
605 const Field* field,
606 mike 1.1 Batch* batch)
607 {
608 MI_Value value;
609 MI_Boolean exists;
610 MI_Uint8 flags;
611 MI_Uint32 tflags = 0;
612 MI_Result r;
613
614 Field_Extract(field, type, &value, &exists, &flags);
615
616 if (!exists)
617 tflags |= MI_FLAG_NULL;
618
619 r = Field_Construct(self, type, &value, tflags, batch);
620
621 return r;
622 }
623
624 void Field_Clear(
625 Field* self,
626 MI_Type type,
627 mike 1.1 Batch* batch)
628 {
629 Field_Destruct(self, type, batch);
630 _Fill(self, type, 0);
631 }
632
633 void Field_Extract(
634 const Field* self,
635 MI_Type type,
636 MI_Value* valueOut,
637 MI_Boolean* existsOut,
638 MI_Uint8* flagsOut)
639 {
640 size_t size = Type_SizeOf(type);
641 memcpy(valueOut, self, size);
642 *existsOut = *(MI_Boolean*)((char*)self + size);
643 *flagsOut = *(MI_Uint8*)((char*)self + size + sizeof(MI_Boolean));
644 }
645
646 void Field_Print(
647 const Field* self,
648 mike 1.1 FILE* os,
649 MI_Type type,
650 MI_Uint32 level)
651 {
652 MI_Value v;
653 MI_Boolean e;
654 MI_Uint8 f;
655 Field_Extract(self, type, &v, &e, &f);
656
657 if (!e)
658 {
659 fprintf(os, "NULL");
660 return;
661 }
662 else
663 {
664 switch (type)
665 {
666 case MI_BOOLEAN:
667 {
668 const MI_Boolean* p = (const MI_Boolean*)&v;
669 mike 1.1 fprintf(os, "%s", *p ? "true" : "false");
670 break;
671 }
672 case MI_SINT8:
673 {
674 fprintf(os, "%d", *((const MI_Sint8*)&v));
675 break;
676 }
677 case MI_UINT8:
678 {
679 fprintf(os, "%u", *((const MI_Uint8*)&v));
680 break;
681 }
682 case MI_SINT16:
683 {
684 fprintf(os, "%d", *((const MI_Sint16*)&v));
685 break;
686 }
687 case MI_UINT16:
688 {
689 fprintf(os, "%u", *((const MI_Uint16*)&v));
690 mike 1.1 break;
691 }
692 case MI_SINT32:
693 {
694 fprintf(os, "%d", *((const MI_Sint32*)&v));
695 break;
696 }
697 case MI_UINT32:
698 {
699 fprintf(os, "%u", *((const MI_Uint32*)&v));
700 break;
701 }
702 case MI_SINT64:
703 {
704 fprintf(os, SINT64_FMT, *((const MI_Sint64*)&v));
705 break;
706 }
707 case MI_UINT64:
708 {
709 fprintf(os, UINT64_FMT, *((const MI_Uint64*)&v));
710 break;
711 mike 1.1 }
712 case MI_REAL32:
713 {
714 fprintf(os, "%g", *((const MI_Real32*)&v));
715 break;
716 }
717 case MI_REAL64:
718 {
719 fprintf(os, "%g", *((const MI_Real64*)&v));
720 break;
721 }
722 case MI_CHAR16:
723 {
724 fprintf(os, "%u", *((const MI_Char16*)&v));
725 break;
726 }
727 case MI_DATETIME:
728 {
729 MI_Char buf[26];
730 DatetimeToStr((const MI_Datetime*)&v, buf);
731 Fzprintf(os, T("%s"), buf);
732 mike 1.1 break;
733 }
734 case MI_STRING:
735 {
736 Fzprintf(os, T("%s"), *((MI_Char**)&v));
737 break;
738 }
739 case MI_BOOLEANA:
740 case MI_SINT8A:
741 case MI_UINT8A:
742 case MI_SINT16A:
743 case MI_UINT16A:
744 case MI_SINT32A:
745 case MI_UINT32A:
746 case MI_SINT64A:
747 case MI_UINT64A:
748 case MI_REAL32A:
749 case MI_REAL64A:
750 case MI_CHAR16A:
751 case MI_DATETIMEA:
752 {
753 mike 1.1 MI_BooleanA* arr = (MI_BooleanA*)&v;
754 char* ptr = (char*)arr->data;
755 MI_Uint32 i;
756
757 fprintf(os, "{");
758
759 for (i = 0; i < arr->size; i++)
760 {
761 MI_Type stype = Type_ScalarOf(type);
762 MI_Type ssize = Type_SizeOf(stype);
763 Field field;
764
765 /* Build dummy field */
766 memcpy(&field, ptr, ssize);
767 *(MI_Boolean*)((char*)&field + ssize) = MI_TRUE;
768 *(MI_Uint8*)((char*)&field + ssize + 1) = 0;
769
770 /* Print dummy field */
771 Field_Print(&field, os, stype, level);
772 ptr += ssize;
773
774 mike 1.1 if (i + 1 != arr->size)
775 fprintf(os, ", ");
776 }
777
778 fprintf(os, "}");
779 break;
780 }
781 case MI_STRINGA:
782 {
783 MI_StringA* arr = (MI_StringA*)&v;
784 MI_Uint32 i;
785
786 fprintf(os, "{");
787
788 for (i = 0; i < arr->size; i++)
789 {
790 Fzprintf(os, T("%s"), arr->data[i]);
791
792 if (i + 1 != arr->size)
793 fprintf(os, ", ");
794 }
795 mike 1.1
796 fprintf(os, "}");
797 break;
798 }
799 case MI_INSTANCE:
800 case MI_REFERENCE:
801 {
802 MI_Instance* inst = *((MI_Instance**)&v);
803
804 if ( type == MI_REFERENCE)
805 fprintf(os, " REF ");
806
807 __MI_Instance_Print(inst, os, level);
808 break;
809 }
810 case MI_INSTANCEA:
811 case MI_REFERENCEA:
812 {
813 MI_InstanceA* inst = ((MI_InstanceA*)&v);
814 MI_Uint32 i;
815
816 mike 1.1 if ( type == MI_REFERENCEA)
817 fprintf(os, " REF ");
818
819 #if 0
820 fprintf(os, "[%d]\n", (int)inst->size);
821 #endif
822 fprintf(os, "\n");
823
824 Indent(os, level);
825 fprintf(os, "{\n");
826
827 for (i = 0; i < inst->size; i++)
828 {
829 __MI_Instance_Print(inst->data[i], os, level + 1);
830 }
831
832 Indent(os, level);
833 fprintf(os, "}");
834
835 break;
836 }
837 mike 1.1 default:
838 break;
839 }
840 }
841 }
842
843 static MI_Boolean _MatchDatetime(
844 const MI_Datetime* x,
845 const MI_Datetime* y)
846 {
847 if (x->isTimestamp)
848 {
849 if (!y->isTimestamp)
850 return MI_FALSE;
851
852 return
853 x->u.timestamp.year == y->u.timestamp.year &&
854 x->u.timestamp.month == y->u.timestamp.month &&
855 x->u.timestamp.day == y->u.timestamp.day &&
856 x->u.timestamp.hour == y->u.timestamp.hour &&
857 x->u.timestamp.minute == y->u.timestamp.minute &&
858 mike 1.1 x->u.timestamp.second == y->u.timestamp.second &&
859 x->u.timestamp.microseconds == y->u.timestamp.microseconds &&
860 x->u.timestamp.utc == y->u.timestamp.utc;
861 }
862 else
863 {
864 if (y->isTimestamp)
865 return MI_FALSE;
866
867 return
868 x->u.interval.days == y->u.interval.days &&
869 x->u.interval.hours == y->u.interval.hours &&
870 x->u.interval.minutes == y->u.interval.minutes &&
871 x->u.interval.seconds == y->u.interval.seconds &&
872 x->u.interval.microseconds == y->u.interval.microseconds;
873 }
874 }
875
876 MI_Boolean Field_MatchKey(
877 const Field* f1,
878 const Field* f2,
879 mike 1.1 MI_Type type)
880 {
881 MI_Boolean e1 = Field_GetExists(f1, type);
882 MI_Boolean e2 = Field_GetExists(f2, type);
883 int f = MI_FALSE;
884
885 if ((e1 && !e2) || (e2 && !e1))
886 return MI_FALSE;
887
888 switch (type)
889 {
890 case MI_BOOLEAN:
891 f = f1->boolean.value == f2->boolean.value;
892 break;
893 case MI_UINT8:
894 f = f1->uint8.value == f2->uint8.value;
895 break;
896 case MI_SINT8:
897 f = f1->sint8.value == f2->sint8.value;
898 break;
899 case MI_UINT16:
900 mike 1.1 f = f1->uint16.value == f2->uint16.value;
901 break;
902 case MI_SINT16:
903 f = f1->sint16.value == f2->sint16.value;
904 break;
905 case MI_UINT32:
906 f = f1->uint32.value == f2->uint32.value;
907 break;
908 case MI_SINT32:
909 f = f1->sint32.value == f2->sint32.value;
910 break;
911 case MI_UINT64:
912 f = f1->uint64.value == f2->uint64.value;
913 break;
914 case MI_SINT64:
915 f = f1->sint64.value == f2->sint64.value;
916 break;
917 case MI_REAL32:
918 f = f1->real32.value == f2->real32.value;
919 break;
920 case MI_REAL64:
921 mike 1.1 f = f1->real64.value == f2->real64.value;
922 break;
923 case MI_CHAR16:
924 f = f1->char16.value == f2->char16.value;
925 break;
926 case MI_DATETIME:
927 f = _MatchDatetime(&f1->datetime.value, &f2->datetime.value);
928 break;
929 case MI_STRING:
930 f = Zcmp(f1->string.value, f2->string.value) == 0;
931 break;
932 case MI_REFERENCE:
933 {
934 if (!f1->reference.value && !f2->reference.value)
935 return MI_TRUE;
936
937 f = Instance_MatchKeys(f1->reference.value, f2->reference.value);
938 break;
939 }
940 case MI_INSTANCE:
941 /* Instances cannot be keys */
942 mike 1.1 f = MI_FALSE;
943 break;
944 default:
945 /* Arrays cannot be keys */
946 f = MI_FALSE;
947 break;
948 }
949
950 return f ? MI_TRUE : MI_FALSE;
951 }
|