(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           static void* _CloneSimpleArray(
 84               const void* data,
 85 mike  1.1     MI_Uint32 size,
 86               MI_Uint32 type,
 87               Batch* batch)
 88           {
 89               void* array;
 90               size_t m;
 91           
 92               /* Handle empty arrays up front */
 93               if (!data || size == 0)
 94                   return NULL;
 95           
 96               /* Get element size in bytes */
 97               m = Type_SizeOf(Type_ScalarOf((MI_Type)type));
 98           
 99               /* Allocate memory for array elements */
100               array = BAlloc(batch, size * m, CALLSITE);
101               if (!array)
102                   return NULL;
103           
104               /* Copy elements to the new array */
105               memcpy(array, data, m * size);
106 mike  1.1 
107               return array;
108           }
109           
110           static MI_Char** _CloneStringArray(
111               const MI_Char** data, 
112               MI_Uint32 size,
113               Batch* batch)
114           {
115               size_t n;
116               MI_Uint32 i;
117               MI_Char* ptr;
118               MI_Char** array;
119           
120               /* Empty arrays are represented by NULL */
121               if (!data || size == 0)
122                   return NULL;
123           
124               /* Calculate space for pointer array */
125               n = size * sizeof(MI_Char*);
126           
127 mike  1.1     /* Calculate space for strings (add space for zero terminators) */
128               for (i = 0; i < size; i++)
129               {
130                   if (!data[i])
131                   {
132                       /* Null elements are illegal */
133                       return NULL;
134                   }
135           
136                   n += (Zlen(data[i]) + 1) * sizeof(MI_Char);
137               }
138           
139               /* Allocate memory */
140               array = (MI_Char**)BAlloc(batch, n, CALLSITE);
141           
142               if (!array)
143                   return NULL;
144           
145               ptr = (MI_Char*)&array[size];
146           
147               /* Copy the strings */
148 mike  1.1     for (i = 0; i < size; i++)
149               {
150                   size_t count = Zlen(data[i]) + 1;
151                   memcpy(ptr, data[i], count * sizeof(MI_Char));
152                   array[i] = ptr;
153                   ptr += count;
154               }
155           
156               return array;
157           }
158           
159           static void* _CloneInstanceArray(
160               const void* data_,
161               MI_Uint32 size,
162               Batch* batch)
163           {
164               const MI_Instance** data = (const MI_Instance**)data_;
165               MI_Instance** array;
166               MI_Uint32 i;
167           
168               /* Handle empty arrays up front */
169 mike  1.1     if (!data || size == 0)
170                   return NULL;
171           
172               /* validate entries */
173               for (i = 0; i < size; i++ )
174               {
175                   if (!data[i])
176                   {
177                       /* Null elements are illegal */
178                       return NULL;
179                   }
180               }
181           
182               /* Allocate memory for the new array */
183               array = BCalloc(batch, size * sizeof(MI_Instance*), CALLSITE);
184               if (!array)
185                   return NULL;
186           
187               /* Clone each reference (or instance) */
188               for (i = 0; i < size; i++)
189               {
190 mike  1.1         MI_Result r = Instance_Clone(data[i], &array[i], batch);
191                   if (r != MI_RESULT_OK)
192                       return NULL;
193               }
194           
195               return array;
196           }
197           
198           INLINE void _Copy(
199               Field* dest, 
200               const Field* src,
201               MI_Type type)
202           {
203               memcpy(dest, src, _fieldSizes[(int)type]);
204           }
205           
206           static void _Swap(
207               Field* field1, 
208               Field* field2, 
209               MI_Type type)
210           {
211 mike  1.1     Field tmp;
212               _Copy(&tmp, field1, type);
213               _Copy(field1, field2, type);
214               _Copy(field2, &tmp, type);
215           }
216           
217           static void _Fill(
218               Field* self, 
219               MI_Type type,
220               MI_Uint8 x)
221           {
222               memset(self, x, _fieldSizes[(int)type]);
223           }
224           
225           /*
226           **==============================================================================
227           **
228           ** Public definitions
229           **
230           **==============================================================================
231           */
232 mike  1.1 
233           MI_Result Field_Construct(
234               Field* self,
235               MI_Type type,
236               const MI_Value* value,
237               MI_Uint32 flags,
238               Batch* batch)
239           {
240               MI_Result r;
241           
242               /* Zero out self */
243               _Fill(self, type, 0);
244           
245               /* Handle null case up front */
246               if (flags & MI_FLAG_NULL)
247                   MI_RETURN(MI_RESULT_OK);
248           
249               /* Reject null values */
250               /* ATTN: Tolerate this for now */
251               if (!value)
252                   MI_RETURN(MI_RESULT_OK);
253 mike  1.1 
254               switch (type)
255               {
256                   case MI_BOOLEAN:
257                   {
258                       self->boolean.value = value->boolean;
259                       self->boolean.exists = MI_TRUE;
260                       break;
261                   }
262                   case MI_UINT8:
263                   {
264                       self->uint8.value = value->uint8;
265                       self->uint8.exists = MI_TRUE;
266                       break;
267                   }
268                   case MI_SINT8:
269                   {
270                       self->sint8.value = value->sint8;
271                       self->sint8.exists = MI_TRUE;
272                       break;
273                   }
274 mike  1.1         case MI_UINT16:
275                   {
276                       self->uint16.value = value->uint16;
277                       self->uint16.exists = MI_TRUE;
278                       break;
279                   }
280                   case MI_SINT16:
281                   {
282                       self->sint16.value = value->sint16;
283                       self->sint16.exists = MI_TRUE;
284                       break;
285                   }
286                   case MI_UINT32:
287                   {
288                       self->uint32.value = value->uint32;
289                       self->uint32.exists = MI_TRUE;
290                       break;
291                   }
292                   case MI_SINT32:
293                   {
294                       self->sint32.value = value->sint32;
295 mike  1.1             self->sint32.exists = MI_TRUE;
296                       break;
297                   }
298                   case MI_UINT64:
299                   {
300                       self->uint64.value = value->uint64;
301                       self->uint64.exists = MI_TRUE;
302                       break;
303                   }
304                   case MI_SINT64:
305                   {
306                       self->sint64.value = value->sint64;
307                       self->sint64.exists = MI_TRUE;
308                       break;
309                   }
310                   case MI_REAL32:
311                   {
312                       self->real32.value = value->real32;
313                       self->real32.exists = MI_TRUE;
314                       break;
315                   }
316 mike  1.1         case MI_REAL64:
317                   {
318                       self->real64.value = value->real64;
319                       self->real64.exists = MI_TRUE;
320                       break;
321                   }
322                   case MI_CHAR16:
323                   {
324                       self->char16.value = value->char16;
325                       self->char16.exists = MI_TRUE;
326                       break;
327                   }
328                   case MI_DATETIME:
329                   {
330                       self->datetime.value = value->datetime;
331                       self->datetime.exists = MI_TRUE;
332                       break;
333                   }
334                   case MI_STRING:
335                   {
336                       if (value->string)
337 mike  1.1             {
338                           MI_Char* str;
339           
340                           if (flags & MI_FLAG_BORROW)
341                           {
342                               self->string.value = value->string;
343                               self->string.exists = MI_TRUE;
344                               self->string.flags = _BORROW;
345                               break;
346                           }
347           
348                           str = BStrdup(batch, value->string, CALLSITE);
349                           if (!str)
350                               MI_RETURN(MI_RESULT_FAILED);
351           
352                           self->string.value = str;
353                           self->string.exists = MI_TRUE;
354                       }
355                       else
356                       {
357                           self->string.value = NULL;
358 mike  1.1                 self->string.exists = MI_FALSE;
359                           self->string.flags = 0;
360                       }
361                       break;
362                   }
363                   case MI_INSTANCE:
364                   case MI_REFERENCE:
365                   {
366                       if (value->instance)
367                       {
368                           MI_Instance* instance;
369           
370                           if (flags & MI_FLAG_BORROW)
371                           {
372                               self->instance.value = value->instance;
373                               self->instance.exists = MI_TRUE;
374                               self->instance.flags = _BORROW;
375                               break;
376                           }
377           
378                           r = Instance_Clone(value->instance, &instance, batch);
379 mike  1.1                 if (r != MI_RESULT_OK)
380                               MI_RETURN(r);
381           
382                           self->instance.value = instance;
383                           self->instance.exists = MI_TRUE;
384                       }
385                       else
386                       {
387                           self->instance.value = NULL;
388                           self->instance.exists = MI_FALSE;
389                           self->instance.flags = 0;
390                       }
391                       break;
392                   }
393                   case MI_BOOLEANA:
394                   case MI_UINT8A:
395                   case MI_SINT8A:
396                   case MI_UINT16A:
397                   case MI_SINT16A:
398                   case MI_UINT32A:
399                   case MI_SINT32A:
400 mike  1.1         case MI_UINT64A:
401                   case MI_SINT64A:
402                   case MI_REAL32A:
403                   case MI_REAL64A:
404                   case MI_CHAR16A:
405                   case MI_DATETIMEA:
406                   {
407                       if (value->array.data)
408                       {
409                           void* data;
410           
411                           if (flags & MI_FLAG_BORROW)
412                           {
413                               self->array.value = value->array;
414                               self->array.exists = MI_TRUE;
415                               self->array.flags = _BORROW;;
416                               break;
417                           }
418           
419                           data = _CloneSimpleArray(
420                               value->array.data, value->array.size, type, batch);
421 mike  1.1                 if (!data)
422                               MI_RETURN(MI_RESULT_FAILED);
423           
424                           self->array.value.data = data;
425                           self->array.value.size = value->array.size;
426                           self->array.exists = MI_TRUE;
427                       }
428                       else
429                       {
430                           self->array.value.data = NULL;
431                           self->array.value.size = 0;
432                           self->array.exists = MI_FALSE;
433                       }
434                       break;
435                   }
436                   case MI_STRINGA:
437                   {
438                       MI_Char** data;
439           
440                       if (value->array.data)
441                       {
442 mike  1.1                 if (flags & MI_FLAG_BORROW)
443                           {
444                               self->stringa.value = value->stringa;
445                               self->stringa.exists = MI_TRUE;
446                               self->stringa.flags = _BORROW;;
447                               break;
448                           }
449           
450                           data = _CloneStringArray((const MI_Char**)value->stringa.data, 
451                               value->stringa.size, batch);
452                           if (!data)
453                               MI_RETURN(MI_RESULT_FAILED);
454           
455                           self->stringa.value.data = data;
456                           self->stringa.value.size = value->array.size;
457                           self->stringa.exists = MI_TRUE;
458                       }
459                       else
460                       {
461                           self->stringa.value.data = NULL;
462                           self->stringa.value.size = 0;
463 mike  1.1                 self->stringa.exists = MI_FALSE;
464                       }
465                       break;
466                   }
467                   case MI_INSTANCEA:
468                   case MI_REFERENCEA:
469                   {
470                       if (value->instancea.data)
471                       {
472                           MI_Instance** data;
473           
474                           if (flags & MI_FLAG_BORROW)
475                           {
476                               self->instancea.value = value->instancea;
477                               self->instancea.exists = MI_TRUE;
478                               self->instancea.flags = _BORROW;;
479                               break;
480                           }
481           
482                           data = _CloneInstanceArray(value->instancea.data, 
483                               value->instancea.size, batch);
484 mike  1.1                 if (!data)
485                               MI_RETURN(MI_RESULT_FAILED);
486           
487                           self->instancea.value.data = data;
488                           self->instancea.value.size = value->array.size;
489                           self->instancea.exists = MI_TRUE;
490                       }
491                       else
492                       {
493                           self->instancea.value.data = NULL;
494                           self->instancea.value.size = 0;
495                           self->instancea.exists = MI_FALSE;
496                       }
497                       break;
498                   }
499               }
500           
501               return MI_RESULT_OK;
502           }
503           
504           void Field_Destruct(
505 mike  1.1     Field* self,
506               MI_Type type,
507               Batch* batch)
508           {
509               switch (type)
510               {
511                   case MI_STRING:
512                   {
513                       MI_StringField* f = &self->string;
514           
515                       if (!(f->flags & _BORROW) && f->value)
516                           BFree(batch, f->value, CALLSITE);
517                       break;
518                   }
519                   case MI_BOOLEANA:
520                   case MI_SINT8A:
521                   case MI_UINT8A:
522                   case MI_SINT16A:
523                   case MI_UINT16A:
524                   case MI_SINT32A:
525                   case MI_UINT32A:
526 mike  1.1         case MI_SINT64A:
527                   case MI_UINT64A:
528                   case MI_REAL32A:
529                   case MI_REAL64A:
530                   case MI_CHAR16A:
531                   case MI_DATETIMEA:
532                   case MI_STRINGA:
533                   {
534                       MI_ArrayField* f = &self->array;
535           
536                       if (!(f->flags & _BORROW) && f->value.data)
537                           BFree(batch, f->value.data, CALLSITE);
538                       break;
539                   }
540                   case MI_INSTANCE:
541                   case MI_REFERENCE:
542                   {
543                       MI_InstanceField* f = &self->instance;
544           
545                       if (!(f->flags & _BORROW) && f->value)
546                           MI_Instance_Delete(f->value);
547 mike  1.1             break;
548                   }
549                   case MI_INSTANCEA:
550                   case MI_REFERENCEA:
551                   {
552                       MI_InstanceAField* f = &self->instancea;
553           
554                       if (!(f->flags & _BORROW) && f->value.data)
555                       {
556                           MI_Uint32 j;
557           
558                           for (j = 0; j < f->value.size; j++ )
559                               MI_Instance_Delete(f->value.data[j]);
560           
561                           BFree(batch, f->value.data, CALLSITE);
562                       }
563                       break;
564                   }
565                   default:
566                       break;
567               }
568 mike  1.1 
569               /* Fill with illegal character */
570               _Fill(self, type, 0xDD);
571           }
572           
573           MI_Result Field_Set(
574               Field* self,
575               MI_Type type,
576               const MI_Value* value,
577               MI_Uint32 flags,
578               Batch* batch)
579           {
580               Field field;
581               MI_Result r;
582           
583               /* Initialize new field */
584               r = Field_Construct(&field, type, value, flags, batch);
585               if (r != MI_RESULT_OK)
586                   MI_RETURN(r);
587           
588               /* Destroy self */
589 mike  1.1     Field_Destruct(self, type, batch);
590           
591               /* Swap new field with self */
592               _Swap(self, &field, type);
593           
594               return MI_RESULT_OK;
595           }
596           
597           MI_Result Field_Copy(
598               Field* self,
599               MI_Type type,
600               const Field* field,
601               Batch* batch)
602           {
603               MI_Value value;
604               MI_Boolean exists;
605               MI_Uint8 flags;
606               MI_Uint32 tflags = 0;
607               MI_Result r;
608           
609               Field_Extract(field, type, &value, &exists, &flags);
610 mike  1.1 
611               if (!exists)
612                   tflags |= MI_FLAG_NULL;
613           
614               r = Field_Construct(self, type, &value, tflags, batch);
615           
616               return r;
617           }
618           
619           void Field_Clear(
620               Field* self,
621               MI_Type type,
622               Batch* batch)
623           {
624               Field_Destruct(self, type, batch);
625               _Fill(self, type, 0);
626           }
627           
628           void Field_Extract(
629               const Field* self,
630               MI_Type type,
631 mike  1.1     MI_Value* valueOut,
632               MI_Boolean* existsOut,
633               MI_Uint8* flagsOut)
634           {
635               size_t size = Type_SizeOf(type);
636               memcpy(valueOut, self, size);
637               *existsOut = *(MI_Boolean*)((char*)self + size);
638               *flagsOut = *(MI_Uint8*)((char*)self + size + sizeof(MI_Boolean));
639           }
640           
641           void Field_Print(
642               const Field* self,
643               FILE* os, 
644               MI_Type type, 
645               MI_Uint32 level)
646           {
647               MI_Value v;
648               MI_Boolean e;
649               MI_Uint8 f;
650               Field_Extract(self, type, &v, &e, &f);
651           
652 mike  1.1     if (!e)
653               {
654                   fprintf(os, "NULL");
655                   return;
656               }
657               else 
658               {
659                   switch (type)
660                   {
661                       case MI_BOOLEAN:
662                       {
663                           const MI_Boolean* p = (const MI_Boolean*)&v;
664                           fprintf(os, "%s", *p ? "true" : "false");
665                           break;
666                       }
667                       case MI_SINT8:
668                       {
669                           fprintf(os, "%d", *((const MI_Sint8*)&v));
670                           break;
671                       }
672                       case MI_UINT8:
673 mike  1.1             {
674                           fprintf(os, "%u", *((const MI_Uint8*)&v));
675                           break;
676                       }
677                       case MI_SINT16:
678                       {
679                           fprintf(os, "%d", *((const MI_Sint16*)&v));
680                           break;
681                       }
682                       case MI_UINT16:
683                       {
684                           fprintf(os, "%u", *((const MI_Uint16*)&v));
685                           break;
686                       }
687                       case MI_SINT32:
688                       {
689                           fprintf(os, "%d", *((const MI_Sint32*)&v));
690                           break;
691                       }
692                       case MI_UINT32:
693                       {
694 mike  1.1                 fprintf(os, "%u", *((const MI_Uint32*)&v));
695                           break;
696                       }
697                       case MI_SINT64:
698                       {
699                           fprintf(os, SINT64_FMT, *((const MI_Sint64*)&v));
700                           break;
701                       }
702                       case MI_UINT64:
703                       {
704                           fprintf(os, UINT64_FMT, *((const MI_Uint64*)&v));
705                           break;
706                       }
707                       case MI_REAL32:
708                       {
709                           fprintf(os, "%g", *((const MI_Real32*)&v));
710                           break;
711                       }
712                       case MI_REAL64:
713                       {
714                           fprintf(os, "%g", *((const MI_Real64*)&v));
715 mike  1.1                 break;
716                       }
717                       case MI_CHAR16:
718                       {
719                           fprintf(os, "%u", *((const MI_Char16*)&v));
720                           break;
721                       }
722                       case MI_DATETIME:
723                       {
724                           MI_Char buf[26];
725                           DatetimeToStr((const MI_Datetime*)&v, buf);
726                           Fzprintf(os, T("%s"), buf);
727                           break;
728                       }
729                       case MI_STRING:
730                       {
731                           Fzprintf(os, T("%s"), *((MI_Char**)&v));
732                           break;
733                       }
734                       case MI_BOOLEANA:
735                       case MI_SINT8A:
736 mike  1.1             case MI_UINT8A:
737                       case MI_SINT16A:
738                       case MI_UINT16A:
739                       case MI_SINT32A:
740                       case MI_UINT32A:
741                       case MI_SINT64A:
742                       case MI_UINT64A:
743                       case MI_REAL32A:
744                       case MI_REAL64A:
745                       case MI_CHAR16A:
746                       case MI_DATETIMEA:
747                       {
748                           MI_BooleanA* arr = (MI_BooleanA*)&v;
749                           char* ptr = (char*)arr->data;
750                           MI_Uint32 i;
751           
752                           fprintf(os, "{");
753           
754                           for (i = 0; i < arr->size; i++)
755                           {
756                               MI_Type stype = Type_ScalarOf(type);
757 mike  1.1                     MI_Type ssize = Type_SizeOf(stype);
758                               Field field;
759           
760                               /* Build dummy field */
761                               memcpy(&field, ptr, ssize);
762                               *(MI_Boolean*)((char*)&field + ssize) = MI_TRUE;
763                               *(MI_Uint8*)((char*)&field + ssize + 1) = 0;
764           
765                               /* Print dummy field */
766                               Field_Print(&field, os, stype, level);
767                               ptr += ssize;
768           
769                               if (i + 1 != arr->size)
770                                   fprintf(os, ", ");
771                           }
772           
773                           fprintf(os, "}");
774                           break;
775                       }
776                       case MI_STRINGA:
777                       {
778 mike  1.1                 MI_StringA* arr = (MI_StringA*)&v;
779                           MI_Uint32 i;
780           
781                           fprintf(os, "{");
782           
783                           for (i = 0; i < arr->size; i++)
784                           {
785                               Fzprintf(os, T("%s"), arr->data[i]);
786           
787                               if (i + 1 != arr->size)
788                                   fprintf(os, ", ");
789                           }
790           
791                           fprintf(os, "}");
792                           break;
793                       }
794                       case MI_INSTANCE:
795                       case MI_REFERENCE:
796                       {
797                           MI_Instance* inst = *((MI_Instance**)&v);
798           
799 mike  1.1                 if ( type == MI_REFERENCE)
800                               fprintf(os, " REF ");
801           
802                           __MI_Instance_Print(inst, os, level);
803                           break;
804                       }
805                       case MI_INSTANCEA:
806                       case MI_REFERENCEA:
807                       {
808                           MI_InstanceA* inst = ((MI_InstanceA*)&v);
809                           MI_Uint32 i;
810           
811                           if ( type == MI_REFERENCEA)
812                               fprintf(os, " REF ");
813           
814           #if 0
815                           fprintf(os, "[%d]\n", (int)inst->size);
816           #endif
817                           fprintf(os, "\n");
818           
819                           Indent(os, level);
820 mike  1.1                 fprintf(os, "{\n");
821           
822                           for (i = 0; i < inst->size; i++)
823                           {
824                               __MI_Instance_Print(inst->data[i], os, level + 1);
825                           }
826           
827                           Indent(os, level);
828                           fprintf(os, "}");
829           
830                           break;
831                       }
832                       default:
833                           break;
834                   }
835               }
836           }
837           
838           static MI_Boolean _MatchDatetime(
839               const MI_Datetime* x,
840               const MI_Datetime* y)
841 mike  1.1 {
842               if (x->isTimestamp)
843               {
844                   if (!y->isTimestamp)
845                       return MI_FALSE;
846           
847                   return 
848                       x->u.timestamp.year == y->u.timestamp.year &&
849                       x->u.timestamp.month == y->u.timestamp.month &&
850                       x->u.timestamp.day == y->u.timestamp.day &&
851                       x->u.timestamp.hour == y->u.timestamp.hour &&
852                       x->u.timestamp.minute == y->u.timestamp.minute &&
853                       x->u.timestamp.second == y->u.timestamp.second &&
854                       x->u.timestamp.microseconds == y->u.timestamp.microseconds &&
855                       x->u.timestamp.utc == y->u.timestamp.utc;
856               }
857               else
858               {
859                   if (y->isTimestamp)
860                       return MI_FALSE;
861           
862 mike  1.1         return 
863                       x->u.interval.days == y->u.interval.days &&
864                       x->u.interval.hours == y->u.interval.hours &&
865                       x->u.interval.minutes == y->u.interval.minutes &&
866                       x->u.interval.seconds == y->u.interval.seconds &&
867                       x->u.interval.microseconds == y->u.interval.microseconds;
868               }
869           }
870           
871           MI_Boolean Field_MatchKey(
872               const Field* f1,
873               const Field* f2, 
874               MI_Type type)
875           {
876               MI_Boolean e1 = Field_GetExists(f1, type);
877               MI_Boolean e2 = Field_GetExists(f2, type);
878               int f = MI_FALSE;
879           
880               if ((e1 && !e2) || (e2 && !e1))
881                   return MI_FALSE;
882           
883 mike  1.1     switch (type)
884               {
885                   case MI_BOOLEAN:
886                       f = f1->boolean.value == f2->boolean.value;
887                       break;
888                   case MI_UINT8:
889                       f = f1->uint8.value == f2->uint8.value;
890                       break;
891                   case MI_SINT8:
892                       f = f1->sint8.value == f2->sint8.value;
893                       break;
894                   case MI_UINT16:
895                       f = f1->uint16.value == f2->uint16.value;
896                       break;
897                   case MI_SINT16:
898                       f = f1->sint16.value == f2->sint16.value;
899                       break;
900                   case MI_UINT32:
901                       f = f1->uint32.value == f2->uint32.value;
902                       break;
903                   case MI_SINT32:
904 mike  1.1             f = f1->sint32.value == f2->sint32.value;
905                       break;
906                   case MI_UINT64:
907                       f = f1->uint64.value == f2->uint64.value;
908                       break;
909                   case MI_SINT64:
910                       f = f1->sint64.value == f2->sint64.value;
911                       break;
912                   case MI_REAL32:
913                       f = f1->real32.value == f2->real32.value;
914                       break;
915                   case MI_REAL64:
916                       f = f1->real64.value == f2->real64.value;
917                       break;
918                   case MI_CHAR16:
919                       f = f1->char16.value == f2->char16.value;
920                       break;
921                   case MI_DATETIME:
922                       f = _MatchDatetime(&f1->datetime.value, &f2->datetime.value);
923                       break;
924                   case MI_STRING:
925 mike  1.1             f = Zcmp(f1->string.value, f2->string.value) == 0;
926                       break;
927                   case MI_REFERENCE:
928                   {
929                       if (!f1->reference.value && !f2->reference.value)
930                           return MI_TRUE;
931           
932                       f = Instance_MatchKeys(f1->reference.value, f2->reference.value);
933                       break;
934                   }
935                   case MI_INSTANCE:
936                       /* Instances cannot be keys */
937                       f = MI_FALSE;
938                       break;
939                   default:
940                       /* Arrays cannot be keys */
941                       f = MI_FALSE;
942                       break;
943               }
944           
945               return f ? MI_TRUE : MI_FALSE;
946 mike  1.1 }

ViewCVS 0.9.2