1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
|
8 krisbash 1.4 ** 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 mike 1.1 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15 krisbash 1.4 ** 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 mike 1.1 **
|
19 krisbash 1.4 ** See the Apache 2 License for the specific language governing permissions
|
20 mike 1.1 ** and limitations under the License.
21 **
22 **==============================================================================
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 krisbash 1.4 #include <pal/strings.h>
32 #include "miextras.h"
33 #include <pal/format.h>
34 #include <pal/file.h>
|
35 mike 1.1 #include "helpers.h"
|
36 krisbash 1.4 #include "strarr.h"
|
37 mike 1.1
38 #define _BORROW 0x01
39
40 /*
41 **==============================================================================
42 **
43 ** Local definitions
44 **
45 **==============================================================================
46 */
47
48 static unsigned char _fieldSizes[] =
49 {
50 sizeof(MI_BooleanField),
51 sizeof(MI_Uint8Field),
52 sizeof(MI_Sint8Field),
53 sizeof(MI_Uint16Field),
54 sizeof(MI_Sint16Field),
55 sizeof(MI_Uint32Field),
56 sizeof(MI_Sint32Field),
57 sizeof(MI_Uint64Field),
58 mike 1.1 sizeof(MI_Sint64Field),
59 sizeof(MI_Real32Field),
60 sizeof(MI_Real64Field),
61 sizeof(MI_Char16Field),
62 sizeof(MI_DatetimeField),
63 sizeof(MI_StringField),
64 sizeof(MI_ReferenceField),
65 sizeof(MI_InstanceField),
66 sizeof(MI_BooleanAField),
67 sizeof(MI_Uint8AField),
68 sizeof(MI_Sint8AField),
69 sizeof(MI_Uint16AField),
70 sizeof(MI_Sint16AField),
71 sizeof(MI_Uint32AField),
72 sizeof(MI_Sint32AField),
73 sizeof(MI_Uint64AField),
74 sizeof(MI_Sint64AField),
75 sizeof(MI_Real32AField),
76 sizeof(MI_Real64AField),
77 sizeof(MI_Char16AField),
78 sizeof(MI_DatetimeAField),
79 mike 1.1 sizeof(MI_StringAField),
80 sizeof(MI_ReferenceAField),
81 sizeof(MI_InstanceAField),
82 };
83
|
84 mike 1.2 MI_INLINE size_t FieldSizeOf(MI_Type type)
85 {
86 return _fieldSizes[(int)type];
87 }
88
|
89 mike 1.1 static void* _CloneSimpleArray(
90 const void* data,
91 MI_Uint32 size,
92 MI_Uint32 type,
93 Batch* batch)
94 {
95 void* array;
96 size_t m;
97
98 /* Handle empty arrays up front */
99 if (!data || size == 0)
100 return NULL;
101
102 /* Get element size in bytes */
103 m = Type_SizeOf(Type_ScalarOf((MI_Type)type));
104
105 /* Allocate memory for array elements */
106 array = BAlloc(batch, size * m, CALLSITE);
107 if (!array)
108 return NULL;
109
110 mike 1.1 /* Copy elements to the new array */
111 memcpy(array, data, m * size);
112
113 return array;
114 }
115
116 static void* _CloneInstanceArray(
117 const void* data_,
118 MI_Uint32 size,
119 Batch* batch)
120 {
121 const MI_Instance** data = (const MI_Instance**)data_;
122 MI_Instance** array;
123 MI_Uint32 i;
124
125 /* Handle empty arrays up front */
126 if (!data || size == 0)
127 return NULL;
128
129 /* validate entries */
130 for (i = 0; i < size; i++ )
131 mike 1.1 {
132 if (!data[i])
133 {
134 /* Null elements are illegal */
135 return NULL;
136 }
137 }
138
139 /* Allocate memory for the new array */
140 array = BCalloc(batch, size * sizeof(MI_Instance*), CALLSITE);
141 if (!array)
142 return NULL;
143
144 /* Clone each reference (or instance) */
145 for (i = 0; i < size; i++)
146 {
147 MI_Result r = Instance_Clone(data[i], &array[i], batch);
148 if (r != MI_RESULT_OK)
149 return NULL;
150 }
151
152 mike 1.1 return array;
153 }
154
155 INLINE void _Copy(
|
156 krisbash 1.4 Field* dest,
|
157 mike 1.1 const Field* src,
158 MI_Type type)
159 {
|
160 mike 1.2 memcpy(dest, src, FieldSizeOf(type));
|
161 mike 1.1 }
162
163 static void _Swap(
|
164 krisbash 1.4 Field* field1,
165 Field* field2,
|
166 mike 1.1 MI_Type type)
167 {
168 Field tmp;
169 _Copy(&tmp, field1, type);
170 _Copy(field1, field2, type);
171 _Copy(field2, &tmp, type);
172 }
173
174 static void _Fill(
|
175 krisbash 1.4 Field* self,
|
176 mike 1.1 MI_Type type,
177 MI_Uint8 x)
178 {
|
179 mike 1.2 memset(self, x, FieldSizeOf(type));
|
180 mike 1.1 }
181
182 /*
183 **==============================================================================
184 **
185 ** Public definitions
186 **
187 **==============================================================================
188 */
189
190 MI_Result Field_Construct(
191 Field* self,
192 MI_Type type,
193 const MI_Value* value,
194 MI_Uint32 flags,
195 Batch* batch)
196 {
197 MI_Result r;
198
199 /* Zero out self */
200 _Fill(self, type, 0);
201 mike 1.1
202 /* Handle null case up front */
203 if (flags & MI_FLAG_NULL)
204 MI_RETURN(MI_RESULT_OK);
205
206 /* Reject null values */
207 /* ATTN: Tolerate this for now */
208 if (!value)
209 MI_RETURN(MI_RESULT_OK);
210
211 switch (type)
212 {
213 case MI_BOOLEAN:
214 {
215 self->boolean.value = value->boolean;
216 self->boolean.exists = MI_TRUE;
217 break;
218 }
219 case MI_UINT8:
220 {
221 self->uint8.value = value->uint8;
222 mike 1.1 self->uint8.exists = MI_TRUE;
223 break;
224 }
225 case MI_SINT8:
226 {
227 self->sint8.value = value->sint8;
228 self->sint8.exists = MI_TRUE;
229 break;
230 }
231 case MI_UINT16:
232 {
233 self->uint16.value = value->uint16;
234 self->uint16.exists = MI_TRUE;
235 break;
236 }
237 case MI_SINT16:
238 {
239 self->sint16.value = value->sint16;
240 self->sint16.exists = MI_TRUE;
241 break;
242 }
243 mike 1.1 case MI_UINT32:
244 {
245 self->uint32.value = value->uint32;
246 self->uint32.exists = MI_TRUE;
247 break;
248 }
249 case MI_SINT32:
250 {
251 self->sint32.value = value->sint32;
252 self->sint32.exists = MI_TRUE;
253 break;
254 }
255 case MI_UINT64:
256 {
257 self->uint64.value = value->uint64;
258 self->uint64.exists = MI_TRUE;
259 break;
260 }
261 case MI_SINT64:
262 {
263 self->sint64.value = value->sint64;
264 mike 1.1 self->sint64.exists = MI_TRUE;
265 break;
266 }
267 case MI_REAL32:
268 {
269 self->real32.value = value->real32;
270 self->real32.exists = MI_TRUE;
271 break;
272 }
273 case MI_REAL64:
274 {
275 self->real64.value = value->real64;
276 self->real64.exists = MI_TRUE;
277 break;
278 }
279 case MI_CHAR16:
280 {
281 self->char16.value = value->char16;
282 self->char16.exists = MI_TRUE;
283 break;
284 }
285 mike 1.1 case MI_DATETIME:
286 {
287 self->datetime.value = value->datetime;
288 self->datetime.exists = MI_TRUE;
289 break;
290 }
291 case MI_STRING:
292 {
293 if (value->string)
294 {
|
295 krisbash 1.4 ZChar* str;
|
296 mike 1.1
297 if (flags & MI_FLAG_BORROW)
298 {
299 self->string.value = value->string;
300 self->string.exists = MI_TRUE;
301 self->string.flags = _BORROW;
302 break;
303 }
304
305 str = BStrdup(batch, value->string, CALLSITE);
306 if (!str)
307 MI_RETURN(MI_RESULT_FAILED);
308
309 self->string.value = str;
310 self->string.exists = MI_TRUE;
311 }
312 else
313 {
314 self->string.value = NULL;
315 self->string.exists = MI_FALSE;
316 self->string.flags = 0;
317 mike 1.1 }
318 break;
319 }
320 case MI_INSTANCE:
321 case MI_REFERENCE:
322 {
323 if (value->instance)
324 {
325 MI_Instance* instance;
326
327 if (flags & MI_FLAG_BORROW)
328 {
329 self->instance.value = value->instance;
330 self->instance.exists = MI_TRUE;
331 self->instance.flags = _BORROW;
332 break;
333 }
334
335 r = Instance_Clone(value->instance, &instance, batch);
336 if (r != MI_RESULT_OK)
337 MI_RETURN(r);
338 mike 1.1
339 self->instance.value = instance;
340 self->instance.exists = MI_TRUE;
341 }
342 else
343 {
344 self->instance.value = NULL;
345 self->instance.exists = MI_FALSE;
346 self->instance.flags = 0;
347 }
348 break;
349 }
350 case MI_BOOLEANA:
351 case MI_UINT8A:
352 case MI_SINT8A:
353 case MI_UINT16A:
354 case MI_SINT16A:
355 case MI_UINT32A:
356 case MI_SINT32A:
357 case MI_UINT64A:
358 case MI_SINT64A:
359 mike 1.1 case MI_REAL32A:
360 case MI_REAL64A:
361 case MI_CHAR16A:
362 case MI_DATETIMEA:
363 {
364 if (value->array.data)
365 {
366 void* data;
367
368 if (flags & MI_FLAG_BORROW)
369 {
370 self->array.value = value->array;
371 self->array.exists = MI_TRUE;
372 self->array.flags = _BORROW;;
373 break;
374 }
375
376 data = _CloneSimpleArray(
377 value->array.data, value->array.size, type, batch);
|
378 krisbash 1.4
379 if ((value->array.size != 0) && !data)
|
380 mike 1.1 MI_RETURN(MI_RESULT_FAILED);
381
382 self->array.value.data = data;
383 self->array.value.size = value->array.size;
384 self->array.exists = MI_TRUE;
385 }
386 else
387 {
388 self->array.value.data = NULL;
389 self->array.value.size = 0;
|
390 krisbash 1.4 self->array.exists = MI_TRUE;
|
391 mike 1.1 }
392 break;
393 }
394 case MI_STRINGA:
395 {
|
396 krisbash 1.4 ZChar** data;
|
397 mike 1.1
398 if (value->array.data)
399 {
400 if (flags & MI_FLAG_BORROW)
401 {
402 self->stringa.value = value->stringa;
403 self->stringa.exists = MI_TRUE;
404 self->stringa.flags = _BORROW;;
405 break;
406 }
407
|
408 krisbash 1.4 data = CloneStringArray((const ZChar**)value->stringa.data,
|
409 mike 1.1 value->stringa.size, batch);
410 if (!data)
411 MI_RETURN(MI_RESULT_FAILED);
412
413 self->stringa.value.data = data;
414 self->stringa.value.size = value->array.size;
415 self->stringa.exists = MI_TRUE;
416 }
417 else
418 {
419 self->stringa.value.data = NULL;
420 self->stringa.value.size = 0;
|
421 krisbash 1.4 self->stringa.exists = MI_TRUE;
|
422 mike 1.1 }
423 break;
424 }
425 case MI_INSTANCEA:
426 case MI_REFERENCEA:
427 {
428 if (value->instancea.data)
429 {
430 MI_Instance** data;
431
432 if (flags & MI_FLAG_BORROW)
433 {
434 self->instancea.value = value->instancea;
435 self->instancea.exists = MI_TRUE;
436 self->instancea.flags = _BORROW;;
437 break;
438 }
439
|
440 krisbash 1.4 data = _CloneInstanceArray(value->instancea.data,
|
441 mike 1.1 value->instancea.size, batch);
442 if (!data)
443 MI_RETURN(MI_RESULT_FAILED);
444
445 self->instancea.value.data = data;
446 self->instancea.value.size = value->array.size;
447 self->instancea.exists = MI_TRUE;
448 }
449 else
450 {
451 self->instancea.value.data = NULL;
452 self->instancea.value.size = 0;
|
453 krisbash 1.4 self->instancea.exists = MI_TRUE;
|
454 mike 1.1 }
455 break;
456 }
457 }
458
459 return MI_RESULT_OK;
460 }
461
462 void Field_Destruct(
463 Field* self,
464 MI_Type type,
465 Batch* batch)
466 {
467 switch (type)
468 {
469 case MI_STRING:
470 {
471 MI_StringField* f = &self->string;
472
473 if (!(f->flags & _BORROW) && f->value)
474 BFree(batch, f->value, CALLSITE);
475 mike 1.1 break;
476 }
477 case MI_BOOLEANA:
478 case MI_SINT8A:
479 case MI_UINT8A:
480 case MI_SINT16A:
481 case MI_UINT16A:
482 case MI_SINT32A:
483 case MI_UINT32A:
484 case MI_SINT64A:
485 case MI_UINT64A:
486 case MI_REAL32A:
487 case MI_REAL64A:
488 case MI_CHAR16A:
489 case MI_DATETIMEA:
490 case MI_STRINGA:
491 {
492 MI_ArrayField* f = &self->array;
493
494 if (!(f->flags & _BORROW) && f->value.data)
495 BFree(batch, f->value.data, CALLSITE);
496 mike 1.1 break;
497 }
498 case MI_INSTANCE:
499 case MI_REFERENCE:
500 {
501 MI_InstanceField* f = &self->instance;
502
503 if (!(f->flags & _BORROW) && f->value)
504 MI_Instance_Delete(f->value);
505 break;
506 }
507 case MI_INSTANCEA:
508 case MI_REFERENCEA:
509 {
510 MI_InstanceAField* f = &self->instancea;
511
512 if (!(f->flags & _BORROW) && f->value.data)
513 {
514 MI_Uint32 j;
515
516 for (j = 0; j < f->value.size; j++ )
517 mike 1.1 MI_Instance_Delete(f->value.data[j]);
518
519 BFree(batch, f->value.data, CALLSITE);
520 }
521 break;
522 }
523 default:
524 break;
525 }
526
527 /* Fill with illegal character */
528 _Fill(self, type, 0xDD);
529 }
530
531 MI_Result Field_Set(
532 Field* self,
533 MI_Type type,
534 const MI_Value* value,
535 MI_Uint32 flags,
536 Batch* batch)
537 {
538 mike 1.1 Field field;
539 MI_Result r;
540
541 /* Initialize new field */
542 r = Field_Construct(&field, type, value, flags, batch);
543 if (r != MI_RESULT_OK)
544 MI_RETURN(r);
545
546 /* Destroy self */
547 Field_Destruct(self, type, batch);
548
549 /* Swap new field with self */
550 _Swap(self, &field, type);
551
552 return MI_RESULT_OK;
553 }
554
555 MI_Result Field_Copy(
556 Field* self,
557 MI_Type type,
558 const Field* field,
559 mike 1.1 Batch* batch)
560 {
561 MI_Value value;
562 MI_Boolean exists;
563 MI_Uint8 flags;
564 MI_Uint32 tflags = 0;
565 MI_Result r;
566
567 Field_Extract(field, type, &value, &exists, &flags);
568
569 if (!exists)
570 tflags |= MI_FLAG_NULL;
571
572 r = Field_Construct(self, type, &value, tflags, batch);
573
574 return r;
575 }
576
577 void Field_Clear(
578 Field* self,
579 MI_Type type,
580 mike 1.1 Batch* batch)
581 {
582 Field_Destruct(self, type, batch);
583 _Fill(self, type, 0);
584 }
585
586 void Field_Extract(
587 const Field* self,
588 MI_Type type,
589 MI_Value* valueOut,
590 MI_Boolean* existsOut,
591 MI_Uint8* flagsOut)
592 {
593 size_t size = Type_SizeOf(type);
594 memcpy(valueOut, self, size);
|
595 krisbash 1.4 *existsOut = *(MI_Boolean*)((const char*)self + size);
596 *flagsOut = *(MI_Uint8*)((const char*)self + size + sizeof(MI_Boolean));
|
597 mike 1.1 }
598
599 static MI_Boolean _MatchDatetime(
600 const MI_Datetime* x,
601 const MI_Datetime* y)
602 {
603 if (x->isTimestamp)
604 {
605 if (!y->isTimestamp)
606 return MI_FALSE;
607
|
608 krisbash 1.4 return
|
609 mike 1.1 x->u.timestamp.year == y->u.timestamp.year &&
610 x->u.timestamp.month == y->u.timestamp.month &&
611 x->u.timestamp.day == y->u.timestamp.day &&
612 x->u.timestamp.hour == y->u.timestamp.hour &&
613 x->u.timestamp.minute == y->u.timestamp.minute &&
614 x->u.timestamp.second == y->u.timestamp.second &&
615 x->u.timestamp.microseconds == y->u.timestamp.microseconds &&
616 x->u.timestamp.utc == y->u.timestamp.utc;
617 }
618 else
619 {
620 if (y->isTimestamp)
621 return MI_FALSE;
622
|
623 krisbash 1.4 return
|
624 mike 1.1 x->u.interval.days == y->u.interval.days &&
625 x->u.interval.hours == y->u.interval.hours &&
626 x->u.interval.minutes == y->u.interval.minutes &&
627 x->u.interval.seconds == y->u.interval.seconds &&
628 x->u.interval.microseconds == y->u.interval.microseconds;
629 }
630 }
631
632 MI_Boolean Field_MatchKey(
633 const Field* f1,
|
634 krisbash 1.4 const Field* f2,
|
635 mike 1.1 MI_Type type)
636 {
637 MI_Boolean e1 = Field_GetExists(f1, type);
638 MI_Boolean e2 = Field_GetExists(f2, type);
639 int f = MI_FALSE;
640
641 if ((e1 && !e2) || (e2 && !e1))
642 return MI_FALSE;
643
644 switch (type)
645 {
646 case MI_BOOLEAN:
647 f = f1->boolean.value == f2->boolean.value;
648 break;
649 case MI_UINT8:
650 f = f1->uint8.value == f2->uint8.value;
651 break;
652 case MI_SINT8:
653 f = f1->sint8.value == f2->sint8.value;
654 break;
655 case MI_UINT16:
656 mike 1.1 f = f1->uint16.value == f2->uint16.value;
657 break;
658 case MI_SINT16:
659 f = f1->sint16.value == f2->sint16.value;
660 break;
661 case MI_UINT32:
662 f = f1->uint32.value == f2->uint32.value;
663 break;
664 case MI_SINT32:
665 f = f1->sint32.value == f2->sint32.value;
666 break;
667 case MI_UINT64:
668 f = f1->uint64.value == f2->uint64.value;
669 break;
670 case MI_SINT64:
671 f = f1->sint64.value == f2->sint64.value;
672 break;
673 case MI_REAL32:
674 f = f1->real32.value == f2->real32.value;
675 break;
676 case MI_REAL64:
677 mike 1.1 f = f1->real64.value == f2->real64.value;
678 break;
679 case MI_CHAR16:
680 f = f1->char16.value == f2->char16.value;
681 break;
682 case MI_DATETIME:
683 f = _MatchDatetime(&f1->datetime.value, &f2->datetime.value);
684 break;
685 case MI_STRING:
|
686 krisbash 1.4 f = Tcscmp(f1->string.value, f2->string.value) == 0;
|
687 mike 1.1 break;
688 case MI_REFERENCE:
689 {
690 if (!f1->reference.value && !f2->reference.value)
691 return MI_TRUE;
692
693 f = Instance_MatchKeys(f1->reference.value, f2->reference.value);
694 break;
695 }
696 case MI_INSTANCE:
697 /* Instances cannot be keys */
698 f = MI_FALSE;
699 break;
700 default:
701 /* Arrays cannot be keys */
702 f = MI_FALSE;
703 break;
704 }
705
706 return f ? MI_TRUE : MI_FALSE;
707 }
|