(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           ** 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           
 83 mike  1.2 MI_INLINE size_t FieldSizeOf(MI_Type type)
 84           {
 85               return _fieldSizes[(int)type];
 86           }
 87           
 88 mike  1.1 static void* _CloneSimpleArray(
 89               const void* data,
 90               MI_Uint32 size,
 91               MI_Uint32 type,
 92               Batch* batch)
 93           {
 94               void* array;
 95               size_t m;
 96           
 97               /* Handle empty arrays up front */
 98               if (!data || size == 0)
 99                   return NULL;
100           
101               /* Get element size in bytes */
102               m = Type_SizeOf(Type_ScalarOf((MI_Type)type));
103           
104               /* Allocate memory for array elements */
105               array = BAlloc(batch, size * m, CALLSITE);
106               if (!array)
107                   return NULL;
108           
109 mike  1.1     /* Copy elements to the new array */
110               memcpy(array, data, m * size);
111           
112               return array;
113           }
114           
115           static MI_Char** _CloneStringArray(
116               const MI_Char** data, 
117               MI_Uint32 size,
118               Batch* batch)
119           {
120               size_t n;
121               MI_Uint32 i;
122               MI_Char* ptr;
123               MI_Char** array;
124           
125               /* Empty arrays are represented by NULL */
126               if (!data || size == 0)
127                   return NULL;
128           
129               /* Calculate space for pointer array */
130 mike  1.1     n = size * sizeof(MI_Char*);
131           
132               /* Calculate space for strings (add space for zero terminators) */
133               for (i = 0; i < size; i++)
134               {
135                   if (!data[i])
136                   {
137                       /* Null elements are illegal */
138                       return NULL;
139                   }
140           
141                   n += (Zlen(data[i]) + 1) * sizeof(MI_Char);
142               }
143           
144               /* Allocate memory */
145               array = (MI_Char**)BAlloc(batch, n, CALLSITE);
146           
147               if (!array)
148                   return NULL;
149           
150               ptr = (MI_Char*)&array[size];
151 mike  1.1 
152               /* Copy the strings */
153               for (i = 0; i < size; i++)
154               {
155                   size_t count = Zlen(data[i]) + 1;
156                   memcpy(ptr, data[i], count * sizeof(MI_Char));
157                   array[i] = ptr;
158                   ptr += count;
159               }
160           
161               return array;
162           }
163           
164           static void* _CloneInstanceArray(
165               const void* data_,
166               MI_Uint32 size,
167               Batch* batch)
168           {
169               const MI_Instance** data = (const MI_Instance**)data_;
170               MI_Instance** array;
171               MI_Uint32 i;
172 mike  1.1 
173               /* Handle empty arrays up front */
174               if (!data || size == 0)
175                   return NULL;
176           
177               /* validate entries */
178               for (i = 0; i < size; i++ )
179               {
180                   if (!data[i])
181                   {
182                       /* Null elements are illegal */
183                       return NULL;
184                   }
185               }
186           
187               /* Allocate memory for the new array */
188               array = BCalloc(batch, size * sizeof(MI_Instance*), CALLSITE);
189               if (!array)
190                   return NULL;
191           
192               /* Clone each reference (or instance) */
193 mike  1.1     for (i = 0; i < size; i++)
194               {
195                   MI_Result r = Instance_Clone(data[i], &array[i], batch);
196                   if (r != MI_RESULT_OK)
197                       return NULL;
198               }
199           
200               return array;
201           }
202           
203           INLINE void _Copy(
204               Field* dest, 
205               const Field* src,
206               MI_Type type)
207           {
208 mike  1.2     memcpy(dest, src, FieldSizeOf(type));
209 mike  1.1 }
210           
211           static void _Swap(
212               Field* field1, 
213               Field* field2, 
214               MI_Type type)
215           {
216               Field tmp;
217               _Copy(&tmp, field1, type);
218               _Copy(field1, field2, type);
219               _Copy(field2, &tmp, type);
220           }
221           
222           static void _Fill(
223               Field* self, 
224               MI_Type type,
225               MI_Uint8 x)
226           {
227 mike  1.2     memset(self, x, FieldSizeOf(type));
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           }

ViewCVS 0.9.2