(file) Return to packing.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 "packing.h"
 26           
 27           /** Magic number for MI_Instance objects (binary buffer pack/unpack) */
 28           #define INSTANCE_MAGIC ((MI_Uint32)0x462b9957)
 29           
 30           /* The magic number that occurs at the end of an instance serialization */
 31           static const MI_Uint32 _END_MAGIC = 0x76f474e3;
 32           
 33           MI_INLINE void* _Alloc(Batch* batch, size_t size)
 34           {
 35               return batch ?  Batch_Get(batch, size) : malloc(size);
 36           }
 37           
 38           /* Obtain the self pointer from this instance */
 39           MI_INLINE Instance* _SelfOf(const MI_Instance* instance)
 40           {
 41               if (instance && ((Instance*)instance)->self)
 42                   return ((Instance*)instance)->self;
 43 mike  1.1     else
 44                   return (Instance*)instance;
 45           }
 46           
 47           static MI_Result _PackField(Buf* buf, const void* field, MI_Type type)
 48           {
 49               switch (type)
 50               {
 51                   case MI_BOOLEAN:
 52                   case MI_SINT8:
 53                   case MI_UINT8:
 54                   {
 55                       MI_Uint8Field* f = (MI_Uint8Field*)field;
 56                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
 57           
 58                       if (f->exists)
 59                           MI_RETURN_ERR(Buf_PackU8(buf, f->value));
 60                       break;
 61                   }
 62                   case MI_SINT16:
 63                   case MI_UINT16:
 64 mike  1.1         case MI_CHAR16:
 65                   {
 66                       MI_Uint16Field* f = (MI_Uint16Field*)field;
 67                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
 68           
 69                       if (f->exists)
 70                           MI_RETURN_ERR(Buf_PackU16(buf, f->value));
 71                       break;
 72                   }
 73                   case MI_SINT32:
 74                   case MI_UINT32:
 75                   case MI_REAL32:
 76                   {
 77                       MI_Uint32Field* f = (MI_Uint32Field*)field;
 78                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
 79           
 80                       if (f->exists)
 81                           MI_RETURN_ERR(Buf_PackU32(buf, f->value));
 82                       break;
 83                   }
 84                   case MI_SINT64:
 85 mike  1.1         case MI_UINT64:
 86                   case MI_REAL64:
 87                   {
 88                       MI_Uint64Field* f = (MI_Uint64Field*)field;
 89                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
 90           
 91                       if (f->exists)
 92                           MI_RETURN_ERR(Buf_PackU64(buf, f->value));
 93                       break;
 94                   }
 95                   case MI_DATETIME:
 96                   {
 97                       MI_DatetimeField* f = (MI_DatetimeField*)field;
 98                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
 99           
100                       if (f->exists)
101                           Buf_PackDT(buf, &f->value);
102                       break;
103                   }
104                   case MI_STRING:
105                   {
106 mike  1.1             MI_StringField* f = (MI_StringField*)field;
107                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
108           
109                       if (f->exists)
110                           MI_RETURN_ERR(Buf_PackStr(buf, f->value));
111                       break;
112                   }
113                   case MI_INSTANCE:
114                   case MI_REFERENCE:
115                   {
116                       MI_InstanceField* f = ((MI_InstanceField*)field);
117           
118                       if (f->exists && !f->value)
119                           MI_RETURN(MI_RESULT_FAILED);
120           
121                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
122           
123                       if (f->exists)
124                           MI_RETURN_ERR(Instance_Pack(f->value, type == MI_REFERENCE, 
125                               NULL, NULL, buf));
126           
127 mike  1.1             break;
128                   }
129                   case MI_BOOLEANA:
130                   case MI_SINT8A:
131                   case MI_UINT8A:
132                   {
133                       MI_Uint8AField* f = (MI_Uint8AField*)field;
134                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
135           
136                       if (f->exists)
137                       {
138                           if (!f->value.data)
139                               MI_RETURN(MI_RESULT_FAILED);
140           
141                           MI_RETURN_ERR(Buf_PackU8A(buf, f->value.data, 
142                               f->value.size));
143                       }
144                       break;
145                   }
146                   case MI_SINT16A:
147                   case MI_UINT16A:
148 mike  1.1         case MI_CHAR16A:
149                   {
150                       MI_Uint16AField* f = (MI_Uint16AField*)field;
151                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
152           
153                       if (f->exists)
154                       {
155                           if (!f->value.data)
156                               MI_RETURN(MI_RESULT_FAILED);
157           
158                           MI_RETURN_ERR(Buf_PackU16A(buf, f->value.data, 
159                               f->value.size));
160                       }
161                       break;
162                   }
163                   case MI_SINT32A:
164                   case MI_UINT32A:
165                   case MI_REAL32A:
166                   {
167                       MI_Uint32AField* f = (MI_Uint32AField*)field;
168                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
169 mike  1.1 
170                       if (f->exists)
171                       {
172                           if (!f->value.data)
173                               MI_RETURN(MI_RESULT_FAILED);
174           
175                           MI_RETURN_ERR(Buf_PackU32A(buf, f->value.data, 
176                               f->value.size));
177                       }
178                       break;
179                   }
180                   case MI_SINT64A:
181                   case MI_UINT64A:
182                   case MI_REAL64A:
183                   {
184                       MI_Uint64AField* f = (MI_Uint64AField*)field;
185                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
186           
187                       if (f->exists)
188                       {
189                           if (!f->value.data)
190 mike  1.1                     MI_RETURN(MI_RESULT_FAILED);
191           
192                           MI_RETURN_ERR(Buf_PackU64A(buf, f->value.data, 
193                               f->value.size));
194                       }
195                       break;
196                   }
197                   case MI_DATETIMEA:
198                   {
199                       MI_DatetimeAField* f = (MI_DatetimeAField*)field;
200                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
201           
202                       if (f->exists)
203                       {
204                           if (!f->value.data)
205                               MI_RETURN(MI_RESULT_FAILED);
206           
207                           MI_RETURN_ERR(Buf_PackDTA(buf, f->value.data,
208                               f->value.size));
209                       }
210                       break;
211 mike  1.1         }
212                   case MI_STRINGA:
213                   {
214                       MI_StringAField* f = (MI_StringAField*)field;
215           
216                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
217           
218                       if (f->exists)
219                       {
220                           MI_RETURN_ERR(Buf_PackStrA(buf, 
221                               (const MI_Char**)f->value.data, f->value.size));
222                       }
223                       break;
224                   }
225                   case MI_INSTANCEA:
226                   case MI_REFERENCEA:
227                   {
228                       MI_InstanceAField* f = ((MI_InstanceAField*)field);
229           
230                       MI_RETURN_ERR(Buf_PackU8(buf, f->exists));
231           
232 mike  1.1             if (f->exists)
233                       {
234                           MI_Uint32 index;
235                           MI_RETURN_ERR(Buf_PackU32(buf, f->value.size));
236           
237                           for ( index = 0; index < f->value.size; index++ )
238                           {
239                               MI_RETURN_ERR(Instance_Pack(f->value.data[index], 
240                                   type == MI_REFERENCEA, NULL, NULL, buf));
241                           }
242                       }
243                       break;
244                   }
245                   default:
246                       break;
247               }
248           
249               MI_RETURN(MI_RESULT_OK);
250           }
251           
252           static MI_Result _UnpackField(
253 mike  1.1     Buf* buf, 
254               MI_Value* value,
255               MI_Boolean* exists,
256               MI_Type type,
257               Batch* batch,
258               MI_Boolean copy)
259           {
260               /* Get exists flag */
261               MI_RETURN_ERR(Buf_UnpackU8(buf, exists));
262           
263               if (!*exists)
264               {
265                   memset(value, 0, sizeof(MI_Value));
266                   MI_RETURN(MI_RESULT_OK);
267               }
268           
269               /* Get value */
270               switch (type)
271               {
272                   case MI_UINT8:
273                   case MI_SINT8:
274 mike  1.1         case MI_BOOLEAN:
275                   {
276                       MI_RETURN_ERR(Buf_UnpackU8(buf, &value->uint8));
277                       break;
278                   }
279                   case MI_UINT16:
280                   case MI_SINT16:
281                   case MI_CHAR16:
282                   {
283                       MI_RETURN_ERR(Buf_UnpackU16(buf, &value->uint16));
284                       break;
285                   }
286                   case MI_UINT32:
287                   case MI_SINT32:
288                   case MI_REAL32:
289                   {
290                       MI_RETURN_ERR(Buf_UnpackU32(buf, &value->uint32));
291                       break;
292                   }
293                   case MI_UINT64:
294                   case MI_SINT64:
295 mike  1.1         case MI_REAL64:
296                   {
297                       MI_RETURN_ERR(Buf_UnpackU64(buf, &value->uint64));
298                       break;
299                   }
300                   case MI_DATETIME:
301                   {
302                       MI_RETURN_ERR(Buf_UnpackDT(buf, &value->datetime));
303                       break;
304                   }
305                   case MI_STRING:
306                   {
307                       MI_RETURN_ERR(Buf_UnpackStr(
308                           buf, (const MI_Char**)&value->string));
309           
310                       break;
311                   }
312                   case MI_REFERENCE:
313                   case MI_INSTANCE:
314                   {
315                       MI_RETURN(Instance_Unpack((MI_Instance**)&value->instance, buf, batch, copy));
316 mike  1.1             break;
317                   }
318                   case MI_BOOLEANA:
319                   case MI_UINT8A:
320                   case MI_SINT8A:
321                   {
322                       MI_RETURN_ERR(Buf_UnpackU8A(buf, 
323                           (const MI_Uint8**)&value->uint8a.data, &value->uint8a.size));
324                       break;
325                   }
326                   case MI_UINT16A:
327                   case MI_SINT16A:
328                   case MI_CHAR16A:
329                   {
330                       MI_RETURN_ERR(Buf_UnpackU16A(buf, 
331                           (const MI_Uint16**)&value->uint16a.data, &value->uint16a.size));
332                       break;
333                   }
334                   case MI_UINT32A:
335                   case MI_SINT32A:
336                   case MI_REAL32A:
337 mike  1.1         {
338                       MI_RETURN_ERR(Buf_UnpackU32A(buf, 
339                           (const MI_Uint32**)&value->uint32a.data, &value->uint32a.size));
340                       break;
341                   }
342                   case MI_UINT64A:
343                   case MI_SINT64A:
344                   case MI_REAL64A:
345                   {
346                       MI_RETURN_ERR(Buf_UnpackU64A(buf, 
347                           (const MI_Uint64**)&value->uint64a.data, &value->uint64a.size));
348                       break;
349                   }
350                   case MI_DATETIMEA:
351                   {
352                       MI_RETURN_ERR(Buf_UnpackDTA(buf, 
353                           (const MI_Datetime**)&value->datetimea.data, 
354                           &value->datetimea.size));
355                   }
356                   case MI_STRINGA:
357                   {
358 mike  1.1             MI_RETURN_ERR(Buf_UnpackStrA(buf, 
359                           (const MI_Char***)&value->stringa.data, &value->stringa.size));
360                       break;
361                   }
362                   case MI_INSTANCEA:
363                   case MI_REFERENCEA:
364                   {
365                       /* Unpack the size of the array */
366                       MI_RETURN_ERR(Buf_UnpackU32(buf, &value->instancea.size));
367           
368                       if (!value->instancea.size)
369                       {
370                           value->instancea.data = 0;
371                       }
372                       else
373                       {
374                           MI_Uint32 index;
375           
376                           value->instancea.data = (MI_Instance**)_Alloc(batch, 
377                               sizeof(MI_Instance*) * value->instancea.size);
378           
379 mike  1.1                 index = 0;
380                           if (!value->instancea.data)
381                           {
382                               MI_RETURN(MI_RESULT_FAILED);
383                           }
384           
385                           for ( index = 0; index < value->instancea.size; index++ )
386                           {
387                               MI_RETURN_ERR(Instance_Unpack(
388                                   &value->instancea.data[index], buf, batch, copy));
389                           }
390                       }
391                       break;
392                   }
393               }
394           
395               MI_RETURN(MI_RESULT_OK);
396           }
397           
398           MI_Result Instance_Pack(
399               const MI_Instance* self_,
400 mike  1.1     MI_Boolean keysOnly,
401               MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
402               void* filterPropertyData,
403               Buf* buf)
404           {
405               Instance* self = _SelfOf(self_);
406               MI_ClassDecl* cd = (MI_ClassDecl*)self->classDecl;
407               MI_Uint32 i;
408           
409               /* Check for null arguments */
410               if (!self || !buf)
411                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
412               
413               /* Pack magic number */
414               MI_RETURN_ERR(Buf_PackU32(buf, INSTANCE_MAGIC));
415           
416               /* Pack flags */
417               MI_RETURN_ERR(Buf_PackU32(buf, cd->flags));
418           
419               /* Pack the classname */
420               MI_RETURN_ERR(Buf_PackStr(buf, cd->name));
421 mike  1.1 
422               /* namespace */
423               MI_RETURN_ERR(Buf_PackStr(buf, self->nameSpace));
424           
425               /* Pack the properties */
426               if (keysOnly)
427               {
428                   /* adjust number of properties based on Keys number */
429                   MI_Uint32 keysNum = 0;
430           
431                   for (i = 0; i < cd->numProperties; i++)
432                   {
433                       const MI_PropertyDecl* pd = cd->properties[i];
434           
435                       if (pd->flags & MI_FLAG_KEY)
436                           keysNum++;
437                   }
438           
439                   MI_RETURN_ERR(Buf_PackU32(buf, keysNum));
440               }
441               else if (filterProperty)
442 mike  1.1     {
443                   /* Pack the number of unfiltered properties */
444                   MI_Uint32 n = 0;
445           
446                   for (i = 0; i < cd->numProperties; i++)
447                   {
448                       const MI_PropertyDecl* pd = cd->properties[i];
449           
450                       if ((*filterProperty)(pd->name, filterPropertyData))
451                           continue;
452           
453                       n++;
454                   }
455           
456                   MI_RETURN_ERR(Buf_PackU32(buf, n));
457               }
458               else
459               {
460                   MI_RETURN_ERR(Buf_PackU32(buf, cd->numProperties));
461               }
462           
463 mike  1.1     for (i = 0; i < cd->numProperties; i++)
464               {
465                   const MI_PropertyDecl* pd = cd->properties[i];
466                   const void* value = (char*)self + pd->offset;
467           
468                   /* Skip non-key properties (for references) */
469                   if (keysOnly && (pd->flags & MI_FLAG_KEY) == 0)
470                       continue;
471           
472                   /* Skip filtered properties */
473                   if (filterProperty && 
474                       (*filterProperty)(pd->name, filterPropertyData))
475                   {
476                       continue;
477                   }
478           
479                   /* Pack the flags */
480                   MI_RETURN_ERR(Buf_PackU32(buf, pd->flags));
481           
482                   /* Pack the propety name */
483                   MI_RETURN_ERR(Buf_PackStr(buf, pd->name));
484 mike  1.1 
485                   /* Pack the propety type */
486                   MI_RETURN_ERR(Buf_PackU32(buf, pd->type));
487           
488                   /* Pack the value */
489                   MI_RETURN_ERR(_PackField(buf, value, (MI_Type)pd->type));
490               }
491           
492               /* Pack ending magic number */
493               MI_RETURN_ERR(Buf_PackU32(buf, _END_MAGIC));
494           
495               MI_RETURN(MI_RESULT_OK);
496           }
497           
498           MI_Result Instance_Unpack(
499               MI_Instance** selfOut,
500               Buf* buf,
501               Batch* batch,
502               MI_Boolean copy)
503           {
504               MI_Uint32 magic;
505 mike  1.1     MI_Uint32 flags;
506               const MI_Char* className;
507               const MI_Char* nameSpace = 0;
508               MI_Instance* self;
509           
510               /* Check parameters */
511               if (!selfOut || !buf)
512                   MI_RETURN(MI_RESULT_INVALID_PARAMETER);
513           
514               /* Clear output parameter */
515               *selfOut = NULL;
516           
517               /* Unpack magic number */
518               MI_RETURN_ERR(Buf_UnpackU32(buf, &magic));
519           
520               if (INSTANCE_MAGIC != magic)
521                   MI_RETURN(MI_RESULT_FAILED);
522           
523               /* Unpack flags */
524               MI_RETURN_ERR(Buf_UnpackU32(buf, &flags));
525           
526 mike  1.1     /* Unpack the class name */
527               MI_RETURN_ERR(Buf_UnpackStr(buf, &className));
528           
529               /* Unpack the namespace */
530               MI_RETURN_ERR(Buf_UnpackStr(buf, &nameSpace));
531           
532               /* Unpack properties */
533               {
534                   MI_Uint32 numProperties;
535                   MI_Uint32 i;
536           
537                   MI_RETURN_ERR(Buf_UnpackU32(buf, &numProperties));
538           
539                   /* ATTN-B: prevent copying of className and superClass strings */
540                   /* Create dynamic instance */
541                   MI_RETURN_ERR(Instance_NewDynamic(&self, className, flags, batch));
542           
543                   MI_RETURN_ERR(MI_Instance_SetNameSpace(self, nameSpace));
544           
545                   for (i = 0; i < numProperties; i++)
546                   {
547 mike  1.1             const MI_Char* name;
548                       MI_Uint32 type, prop_flags;
549                       MI_Value value;
550                       const MI_Value* valuePtr;
551                       MI_Boolean exists;
552           
553                       /* ATTN-B: prevent copying of name by Instance_Add */
554                       /* Unpack the propety type */
555                       MI_RETURN_ERR(Buf_UnpackU32(buf, &prop_flags));
556           
557                       /* Unpack the propety name */
558                       MI_RETURN_ERR(Buf_UnpackStr(buf, &name));
559           
560                       /* Unpack the propety type */
561                       MI_RETURN_ERR(Buf_UnpackU32(buf, &type));
562           
563                       /* Unpack the value */
564                       MI_RETURN_ERR(_UnpackField(buf, &value, &exists, (MI_Type)type, 
565                           batch, copy));
566           
567                       /* Set valuePtr */
568 mike  1.1             if (exists)
569                           valuePtr = &value;
570                       else
571                           valuePtr = NULL;
572           
573                       /* ATTN-A: Handle prop_flags and className parameters */
574                       /* Add the property to the instance */
575           
576                       if (!copy)
577                           prop_flags |= MI_FLAG_BORROW;
578           
579                       MI_RETURN_ERR(MI_Instance_AddElement(self, name, valuePtr, 
580                           (MI_Type)type, prop_flags));
581                   }
582               }
583           
584               /* Check the ending magic number */
585               {
586                   MI_Uint32 endMagic;
587                   MI_RETURN_ERR(Buf_UnpackU32(buf, &endMagic));
588           
589 mike  1.1         if (endMagic != _END_MAGIC)
590                       MI_RETURN(MI_RESULT_INVALID_PARAMETER);
591               }
592           
593               /* Set output parameter */
594               *selfOut = self;
595           
596               /* ATTN-A: if batch is non-null, then attach buffer to batch */
597               MI_RETURN(MI_RESULT_OK);
598           }
599           
600           MI_Result InstanceToBatch(
601               const MI_Instance* instance,
602               MI_Boolean (*filterProperty)(const MI_Char* name, void* data),
603               void* filterPropertyData,
604               Batch* batch,
605               void** ptrOut,
606               MI_Uint32* sizeOut)
607           {
608               Buf buf;
609               MI_Result r;
610 mike  1.1     Page* page;
611           
612               r = Buf_Init(&buf, 16*1024);
613           
614               if (MI_RESULT_OK != r)
615                   return r;
616           
617               r = Instance_Pack(
618                   instance, MI_FALSE, filterProperty, filterPropertyData, &buf);
619           
620               if (MI_RESULT_OK != r)
621               {
622                   Buf_Destroy(&buf);
623                   return r;
624               }
625           
626               page = Buf_StealPage(&buf);
627               page->u.s.size = buf.size;
628           
629               Batch_AttachPage(batch, page);
630           
631 mike  1.1     *ptrOut = page + 1;
632               *sizeOut = (MI_Uint32)page->u.s.size;
633               return MI_RESULT_OK;
634           }

ViewCVS 0.9.2