(file) Return to field.c CVS log (file) (dir) Up to [OMI] / omi / base

  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              }

ViewCVS 0.9.2