(file) Return to buf.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 "buf.h"
 26           #include "strings.h"
 27           
 28           #define _MIN_CAPACITY 256
 29           
 30           /*
 31           **==============================================================================
 32           **
 33           ** Local definitions
 34           **
 35           **==============================================================================
 36           */
 37           
 38           /* Round x up to the nearest power of 2 */
 39           static MI_Uint32 _RoundPow2(MI_Uint32 x)
 40           {
 41               MI_Uint32 r = x - 1;
 42               r |= (r >> 1);
 43 mike  1.1     r |= (r >> 2);
 44               r |= (r >> 4);
 45               r |= (r >> 8);
 46               r |= (r >> 16);
 47               return r + 1;
 48           }
 49           
 50           /*
 51           **==============================================================================
 52           **
 53           ** Public definitions
 54           **
 55           **==============================================================================
 56           */
 57           
 58           MI_Result Buf_Init(
 59               Buf* self,
 60               MI_Uint32 capacity)
 61           {
 62               Page* page;
 63           
 64 mike  1.1     /* Adjust capacity if too small */
 65               if (capacity < _MIN_CAPACITY)
 66                   capacity = _MIN_CAPACITY;
 67           
 68               /* Allocate data buffer */
 69               page = (Page*)malloc(sizeof(Page) + capacity);
 70           
 71               if (!page)
 72                   return MI_RESULT_FAILED;
 73           
 74               page->u.s.size = capacity;
 75               page->u.s.next = 0;
 76           
 77               /* Set fields */
 78               self->data = page + 1;
 79               self->size = 0;
 80               self->capacity = capacity;
 81               self->offset = 0;
 82           
 83           #ifdef CONFIG_ENABLE_DEBUG
 84               memset(self->data,0xAA,self->capacity);
 85 mike  1.1 #endif
 86           
 87               return MI_RESULT_OK;
 88           }
 89           
 90           void Buf_Destroy(
 91               Buf* self)
 92           {
 93               if (self->data)
 94                   free((Page*)self->data - 1);
 95           }
 96           
 97           MI_Result Buf_Reserve(
 98               Buf* self, 
 99               MI_Uint32 capacity)
100           {
101               /* Expand allocation if we need more space */
102               if (capacity > self->capacity)
103               {
104                   Page* page;
105           
106 mike  1.1         capacity = _RoundPow2(capacity);
107           
108                   if (self->data)
109                   {
110                       page = (Page*)self->data - 1;
111                       page = (Page*)realloc(page, sizeof(Page) + capacity);
112           #ifdef CONFIG_ENABLE_DEBUG
113                       memset(((char*)(page+1)) + self->capacity,0xAA,capacity - self->capacity);
114           #endif
115                   }
116                   else
117                   {
118                       page = (Page*)malloc(sizeof(Page) + capacity);
119           #ifdef CONFIG_ENABLE_DEBUG
120                       memset(page,0xAA,sizeof(Page) + capacity);
121           #endif
122                   }
123           
124                   if (!page)
125                       return MI_RESULT_FAILED;
126           
127 mike  1.1         page->u.s.size = capacity;
128                   self->data = page + 1;
129                   self->capacity = capacity;
130               }
131           
132               return MI_RESULT_OK;
133           }
134           
135           MI_Result Buf_App(
136               Buf* self, 
137               const void* data, 
138               MI_Uint32 size)
139           {
140               /* Calculate the new size */
141               MI_Uint32 newSize = self->size + size;
142           
143               /* Expand allocation if we need more space */
144               if (newSize > self->capacity)
145               {
146                   MI_Result r = Buf_Reserve(self, newSize);
147           
148 mike  1.1         if (r != MI_RESULT_OK)
149                       return MI_RESULT_FAILED;
150               }
151           
152               /* Copy in the new data */
153               memcpy((char*)self->data + self->size, data, size);
154               self->size += size;
155           
156               return MI_RESULT_OK;
157           }
158           
159           MI_Result Buf_PackStr(
160               Buf* self,
161               const MI_Char* x)
162           {
163               MI_Uint32 size;
164           
165               /* Pack null strings as 0 */
166               if (!x)
167                   return Buf_PackU32(self, 0);
168               
169 mike  1.1     /* Pack the size of the string (size including null terminator) */
170               size = (MI_Uint32)Zlen(x) + 1;
171               MI_RETURN_ERR(Buf_PackU32(self, size));
172           
173               /* Pack the characters (including the null terminator) */
174               MI_RETURN_ERR(Buf_App(self, x, size * sizeof(MI_Char)));
175           
176               return MI_RESULT_OK;
177           }
178           
179           MI_Result Buf_UnpackU8A(
180               Buf* self,
181               const MI_Uint8** data,
182               MI_Uint32* size)
183           {
184               /* Unpack size */
185               MI_RETURN_ERR(Buf_UnpackU32(self, size));
186           
187               if (*size == 0)
188               {
189                   *data = NULL;
190 mike  1.1         return MI_RESULT_OK;
191               }
192               
193               /* Check whether there are enough bytes left */
194               if (self->offset + *size * sizeof(MI_Uint8) > self->size)
195                   return MI_RESULT_FAILED;
196           
197               /* Store pointer to array */
198               *data = (const MI_Uint8*)((char*)self->data + self->offset);
199               self->offset += *size * sizeof(MI_Uint8);
200           
201               return MI_RESULT_OK;
202           }
203           
204           MI_Result Buf_UnpackU16A(
205               Buf* self,
206               const MI_Uint16** data,
207               MI_Uint32* size)
208           {
209               /* Unpack size */
210               MI_RETURN_ERR(Buf_UnpackU32(self, size));
211 mike  1.1 
212               if (*size == 0)
213               {
214                   *data = NULL;
215                   return MI_RESULT_OK;
216               }
217               
218               /* Check whether there are enough bytes left */
219               if (self->offset + *size * sizeof(MI_Uint16) > self->size)
220                   return MI_RESULT_FAILED;
221           
222               /* Store pointer to array */
223               *data = (const MI_Uint16*)((char*)self->data + self->offset);
224               self->offset += *size * sizeof(MI_Uint16);
225           
226               return MI_RESULT_OK;
227           }
228           
229           MI_Result Buf_UnpackU32A(
230               Buf* self,
231               const MI_Uint32** data,
232 mike  1.1     MI_Uint32* size)
233           {
234               /* Unpack size */
235               MI_RETURN_ERR(Buf_UnpackU32(self, size));
236           
237               if (*size == 0)
238               {
239                   *data = NULL;
240                   return MI_RESULT_OK;
241               }
242               
243               /* Check whether there are enough bytes left */
244               if (self->offset + *size * sizeof(MI_Uint32) > self->size)
245                   return MI_RESULT_FAILED;
246           
247               /* Store pointer to array */
248               *data = (const MI_Uint32*)((char*)self->data + self->offset);
249               self->offset += *size * sizeof(MI_Uint32);
250           
251               return MI_RESULT_OK;
252           }
253 mike  1.1 
254           MI_Result Buf_UnpackU64A(
255               Buf* self,
256               const MI_Uint64** data,
257               MI_Uint32* size)
258           {
259               /* Unpack size */
260               MI_RETURN_ERR(Buf_UnpackU32(self, size));
261           
262               if (*size == 0)
263               {
264                   *data = NULL;
265                   return MI_RESULT_OK;
266               }
267           
268               /* Align buffer on 8 byte boundary */
269               MI_RETURN_ERR(Buf_Align64(self));
270               
271               /* Check whether there are enough bytes left */
272               if (self->offset + *size * sizeof(MI_Uint64) > self->size)
273                   return MI_RESULT_FAILED;
274 mike  1.1 
275               /* Store pointer to array */
276               *data = (const MI_Uint64*)((char*)self->data + self->offset);
277               self->offset += *size * sizeof(MI_Uint64);
278           
279               return MI_RESULT_OK;
280           }
281           
282           MI_Result Buf_UnpackStr(
283               Buf* self,
284               const MI_Char** x)
285           {
286               MI_Uint32 size;
287           
288               /* Unpack size */
289               MI_RETURN_ERR(Buf_UnpackU32(self, &size));
290           
291               if (size == 0)
292               {
293                   *x = NULL;
294                   return MI_RESULT_OK;
295 mike  1.1     }
296               
297               /* Check whether there are enough bytes left */
298               if (self->offset + size * sizeof(MI_Char) > self->size)
299                   return MI_RESULT_FAILED;
300           
301               /* Store pointer to array */
302               *x = (const MI_Char*)((char*)self->data + self->offset);
303               self->offset += size * sizeof(MI_Char);
304           
305               return MI_RESULT_OK;
306           }
307           
308           MI_Result Buf_PackStrA(
309               Buf* self,
310               const MI_Char** data,
311               MI_Uint32 size)
312           {
313               MI_Uint32 i;
314           
315               /* Pack the array size (the number of strings) */
316 mike  1.1     MI_RETURN_ERR(Buf_PackU32(self, size));
317           
318               if (size)
319               {
320                   MI_Uint32 sizes[64];
321           
322                   if (!data)
323                       return MI_RESULT_FAILED;
324           
325                   /* Put sizes of all strings first. Each size is encoded as a 64-bit
326                    * integer. The unpack function replaces this integer with a pointer
327                    * to the corresponding string. This avoids having to allocate memory
328                    * for the pointer array while unpacking.
329                    */
330                   for (i = 0; i < size; i++)
331                   {
332                       MI_Uint32 n;
333           
334                       if (!data[i])
335                           return MI_RESULT_FAILED;
336           
337 mike  1.1             n = (MI_Uint32)Zlen(data[i]) + 1;
338           
339                       /* Save size so that it will not have to be recalculated by the
340                        * next loop using strlen.
341                        */
342                       if (i < MI_COUNT(sizes))
343                           sizes[i] = n;
344           
345                       MI_RETURN_ERR(Buf_PackU64(self, (MI_Uint64)n));
346                   }
347           
348                   /* Pack strings one after the other. */
349                   for (i = 0; i < size; i++)
350                   {
351                       MI_Uint32 n;
352                       
353                       if (i < MI_COUNT(sizes))
354                           n = sizes[i];
355                       else 
356                           n = (MI_Uint32)Zlen(data[i]) + 1;
357           
358 mike  1.1             MI_RETURN_ERR(Buf_App(self, data[i], n * sizeof(MI_Char)));
359                   }
360               }
361           
362               return MI_RESULT_OK;
363           }
364           
365           MI_Result Buf_UnpackStrA(
366               Buf* self,
367               const MI_Char*** dataOut,
368               MI_Uint32* sizeOut)
369           {
370               const MI_Char** data;
371               MI_Uint32 size;
372               MI_Uint32 i;
373               MI_Uint32 offset;
374           
375               /* Unpack the size of the array */
376               MI_RETURN_ERR(Buf_UnpackU32(self, &size));
377           
378               /* Handle zero-size array case */
379 mike  1.1     if (size == 0)
380               {
381                   *dataOut = NULL;
382                   *sizeOut = 0;
383                   return MI_RESULT_OK;
384               }
385           
386               /* Align to read uint64 sizes */
387               MI_RETURN_ERR(Buf_Align64(self));
388           
389               /* Set pointer data array */
390               data = (const MI_Char**)((char*)self->data + self->offset);
391           
392               /* Calculate offset to first string in array (data[0]) */
393               offset = self->offset + (size * sizeof(MI_Uint64));
394           
395               /* Fail if offset is beyond end of buffer */
396               if (offset > self->size)
397                   return MI_RESULT_FAILED;
398           
399               /* Unpack the string sizes and covert to string pointers */
400 mike  1.1     for (i = 0; i < size; i++)
401               {
402                   MI_Uint64 tmp;
403                   MI_Uint32 n;
404           
405                   /* Unpack size of next string in array */
406                   MI_RETURN_ERR(Buf_UnpackU64(self, &tmp));
407                   n = (MI_Uint32)tmp;
408           
409                   /* Fail if not enough room left in buffer for string */
410                   if (offset + n * sizeof(MI_Char) > self->size)
411                       return MI_RESULT_FAILED;
412           
413                   /* Add string to array */
414                   data[i] = (MI_Char*)((char*)self->data + offset);
415                   offset += n * sizeof(MI_Char);
416               }
417           
418               /* Update the offset */
419               self->offset = offset;
420           
421 mike  1.1     /* Set the output parameters */
422               *dataOut = data;
423               *sizeOut = size;
424           
425               return MI_RESULT_OK;
426           }
427           
428           MI_Result Buf_PackDT(
429               Buf* self,
430               const MI_Datetime* x)
431           {
432               MI_RETURN_ERR(Buf_Pad32(self));
433               MI_RETURN_ERR(Buf_App(self, x, sizeof(MI_Datetime)));
434               return MI_RESULT_OK;
435           }
436           
437           MI_Result Buf_UnpackDT(
438               Buf* self,
439               MI_Datetime* x)
440           {
441               MI_Uint32 offset;
442 mike  1.1 
443               MI_RETURN_ERR(Buf_Align32(self));
444           
445               /* Find ending offset of datetime structure */
446               offset = self->offset + sizeof(MI_Datetime);
447           
448               if (offset > self->size)
449                   return MI_RESULT_FAILED;
450           
451               memcpy(x, (char*)self->data + self->offset, sizeof(MI_Datetime));
452               self->offset = offset;
453           
454               return MI_RESULT_OK;
455           }
456           
457           MI_Result Buf_PackDTA(
458               Buf* self,
459               const MI_Datetime* data,
460               MI_Uint32 size)
461           {
462               MI_RETURN_ERR(Buf_PackU32(self, size));
463 mike  1.1     MI_RETURN_ERR(Buf_App(self, data, size * sizeof(MI_Datetime)));
464               return MI_RESULT_OK;
465           }
466           
467           MI_Result Buf_UnpackDTA(
468               Buf* self,
469               const MI_Datetime** dataPtr,
470               MI_Uint32* sizePtr)
471           {
472               MI_Uint32 offset;
473           
474               /* Unpack the size */
475               MI_RETURN_ERR(Buf_UnpackU32(self, sizePtr));
476           
477               /* Handle zero-sized array (null data pointer) */
478               if (*sizePtr == 0)
479               {
480                   *dataPtr = NULL;
481                   return MI_RESULT_OK;
482               }
483           
484 mike  1.1     /* Find ending offset of datetime array */
485               offset = self->offset + *sizePtr * sizeof(MI_Datetime);
486           
487               /* Set pointer to data array */
488               *dataPtr = (const MI_Datetime*)((char*)self->data + self->offset);
489           
490               /* Advance offset beyond array */
491               self->offset = offset;
492           
493               return MI_RESULT_OK;
494           }
495           
496           Page* Buf_StealPage(
497               Buf* self)
498           {
499               if (self->data)
500               {
501                   Page* page = (Page*)self->data - 1;
502                   self->data = NULL;
503                   return page;
504               }
505 mike  1.1 
506               return NULL;
507           }

ViewCVS 0.9.2