version 1.2, 2015/04/20 18:10:09
|
version 1.3, 2015/04/20 18:19:49
|
|
|
*/ | */ |
| |
#include "buf.h" | #include "buf.h" |
#include "strings.h" |
#include <pal/strings.h> |
| |
#define _MIN_CAPACITY 256 | #define _MIN_CAPACITY 256 |
| |
|
|
capacity = _MIN_CAPACITY; | capacity = _MIN_CAPACITY; |
| |
/* Allocate data buffer */ | /* Allocate data buffer */ |
page = (Page*)malloc(sizeof(Page) + capacity); |
page = (Page*)PAL_Malloc(sizeof(Page) + capacity); |
| |
if (!page) | if (!page) |
return MI_RESULT_FAILED; | return MI_RESULT_FAILED; |
|
|
self->offset = 0; | self->offset = 0; |
| |
#ifdef CONFIG_ENABLE_DEBUG | #ifdef CONFIG_ENABLE_DEBUG |
|
#ifdef _PREFAST_ |
|
#pragma prefast(push) |
|
#pragma prefast(disable:22107) |
|
#endif |
memset(self->data,0xAA,self->capacity); | memset(self->data,0xAA,self->capacity); |
|
#ifdef _PREFAST_ |
|
#pragma prefast(pop) |
|
#endif |
#endif | #endif |
| |
return MI_RESULT_OK; | return MI_RESULT_OK; |
|
|
Buf* self) | Buf* self) |
{ | { |
if (self->data) | if (self->data) |
free((Page*)self->data - 1); |
PAL_Free((Page*)self->data - 1); |
} | } |
| |
MI_Result Buf_Reserve( | MI_Result Buf_Reserve( |
|
|
if (self->data) | if (self->data) |
{ | { |
page = (Page*)self->data - 1; | page = (Page*)self->data - 1; |
page = (Page*)realloc(page, sizeof(Page) + capacity); |
page = (Page*)PAL_Realloc(page, sizeof(Page) + capacity); |
#ifdef CONFIG_ENABLE_DEBUG | #ifdef CONFIG_ENABLE_DEBUG |
|
if (page) |
memset(((char*)(page+1)) + self->capacity,0xAA,capacity - self->capacity); | memset(((char*)(page+1)) + self->capacity,0xAA,capacity - self->capacity); |
#endif | #endif |
} | } |
else | else |
{ | { |
page = (Page*)malloc(sizeof(Page) + capacity); |
page = (Page*)PAL_Malloc(sizeof(Page) + capacity); |
#ifdef CONFIG_ENABLE_DEBUG | #ifdef CONFIG_ENABLE_DEBUG |
|
if(page) |
memset(page,0xAA,sizeof(Page) + capacity); | memset(page,0xAA,sizeof(Page) + capacity); |
#endif | #endif |
} | } |
|
|
return MI_RESULT_OK; | return MI_RESULT_OK; |
} | } |
| |
MI_Result Buf_App( |
MI_Result __Buf_App( |
Buf* self, | Buf* self, |
const void* data, | const void* data, |
MI_Uint32 size) | MI_Uint32 size) |
{ | { |
/* Calculate the new size */ |
MI_Result r = Buf_Reserve(self, self->size + size); |
MI_Uint32 newSize = self->size + size; |
|
|
|
/* Expand allocation if we need more space */ |
|
if (newSize > self->capacity) |
|
{ |
|
MI_Result r = Buf_Reserve(self, newSize); |
|
| |
if (r != MI_RESULT_OK) | if (r != MI_RESULT_OK) |
return MI_RESULT_FAILED; | return MI_RESULT_FAILED; |
} |
|
| |
/* Copy in the new data */ |
|
memcpy((char*)self->data + self->size, data, size); | memcpy((char*)self->data + self->size, data, size); |
self->size += size; | self->size += size; |
| |
|
|
| |
MI_Result Buf_PackStr( | MI_Result Buf_PackStr( |
Buf* self, | Buf* self, |
const MI_Char* x) |
const ZChar* x) |
{ | { |
MI_Uint32 size; | MI_Uint32 size; |
| |
|
|
return Buf_PackU32(self, 0); | return Buf_PackU32(self, 0); |
| |
/* Pack the size of the string (size including null terminator) */ | /* Pack the size of the string (size including null terminator) */ |
size = (MI_Uint32)Zlen(x) + 1; |
size = (MI_Uint32)Tcslen(x) + 1; |
MI_RETURN_ERR(Buf_PackU32(self, size)); | MI_RETURN_ERR(Buf_PackU32(self, size)); |
| |
/* Pack the characters (including the null terminator) */ | /* Pack the characters (including the null terminator) */ |
MI_RETURN_ERR(Buf_App(self, x, size * sizeof(MI_Char))); |
MI_RETURN_ERR(Buf_App(self, x, size * sizeof(ZChar))); |
|
|
|
return MI_RESULT_OK; |
|
} |
|
|
|
MI_Result Buf_PackStrLen( |
|
Buf* self, |
|
const ZChar* x, |
|
MI_Uint32 size) |
|
{ |
|
/* Pack null strings as 0 */ |
|
if (!x) |
|
return Buf_PackU32(self, 0); |
|
|
|
/* Pack the size of the string (size including null terminator) */ |
|
MI_RETURN_ERR(Buf_PackU32(self, size + 1)); |
|
|
|
/* Pack the characters (including the null terminator) */ |
|
MI_RETURN_ERR(Buf_App(self, x, (size + 1) * sizeof(ZChar))); |
| |
return MI_RESULT_OK; | return MI_RESULT_OK; |
} | } |
|
|
| |
MI_Result Buf_UnpackStr( | MI_Result Buf_UnpackStr( |
Buf* self, | Buf* self, |
const MI_Char** x) |
const ZChar** x) |
{ | { |
MI_Uint32 size; | MI_Uint32 size; |
| |
|
|
} | } |
| |
/* Check whether there are enough bytes left */ | /* Check whether there are enough bytes left */ |
if (self->offset + size * sizeof(MI_Char) > self->size) |
if (self->offset + size * sizeof(ZChar) > self->size) |
return MI_RESULT_FAILED; | return MI_RESULT_FAILED; |
| |
/* Store pointer to array */ | /* Store pointer to array */ |
*x = (const MI_Char*)((char*)self->data + self->offset); |
*x = (const ZChar*)((char*)self->data + self->offset); |
self->offset += size * sizeof(MI_Char); |
self->offset += size * sizeof(ZChar); |
| |
return MI_RESULT_OK; | return MI_RESULT_OK; |
} | } |
| |
|
MI_Result Buf_PackPtrdiff_t ( |
|
Buf* self, |
|
ptrdiff_t data) |
|
{ |
|
#if defined(PAL_64BIT) |
|
MI_RETURN_ERR(Buf_PackU64(self, (MI_Uint64)data)); |
|
#elif defined(PAL_32BIT) |
|
MI_RETURN_ERR(Buf_PackU32(self, (MI_Uint32)data)); |
|
#else |
|
return MI_RESULT_NOT_SUPPORTED; |
|
#endif |
|
return MI_RESULT_OK; |
|
} |
|
|
|
MI_Result Buf_UnpackPtrdiff_t ( |
|
Buf* self, |
|
ptrdiff_t* x) |
|
{ |
|
#if defined(PAL_64BIT) |
|
MI_RETURN_ERR(Buf_UnpackU64(self, (MI_Uint64*)x)); |
|
#elif defined(PAL_32BIT) |
|
MI_RETURN_ERR(Buf_UnpackU32(self, (MI_Uint32*)x)); |
|
#else |
|
return MI_RESULT_NOT_SUPPORTED; |
|
#endif |
|
return MI_RESULT_OK; |
|
} |
|
|
MI_Result Buf_PackStrA( | MI_Result Buf_PackStrA( |
Buf* self, | Buf* self, |
const MI_Char** data, |
const ZChar** data, |
MI_Uint32 size) | MI_Uint32 size) |
{ | { |
MI_Uint32 i; | MI_Uint32 i; |
|
|
| |
if (size) | if (size) |
{ | { |
MI_Uint32 sizes[64]; |
ptrdiff_t sizes[64]; |
|
ptrdiff_t offset; |
| |
if (!data) | if (!data) |
return MI_RESULT_FAILED; | return MI_RESULT_FAILED; |
| |
/* Put sizes of all strings first. Each size is encoded as a 64-bit |
MI_RETURN_ERR(Buf_Pad64(self)); |
|
|
|
/* Let "size(string) times size(ZChar)" be denoted by ZCharSize(string). |
|
* Put ZCharSize offsets of all strings first. |
|
* |
|
* For example: consider the string "RED\0GREEN\0BLUE\0" |
|
* We put four ZCharSize offsets in the buffer: |
|
* 0*sizeof(ZChar) | (4)*sizeof(ZChar) | (4+6)*sizeof(ZChar) | (4+6+5)*sizeof(ZChar) |
|
* |
|
* Each ZCharSize offset is encoded as a 64-bit |
* integer. The unpack function replaces this integer with a pointer | * integer. The unpack function replaces this integer with a pointer |
* to the corresponding string. This avoids having to allocate memory | * to the corresponding string. This avoids having to allocate memory |
* for the pointer array while unpacking. | * for the pointer array while unpacking. |
*/ | */ |
|
|
|
/* Pack the ZCharSize offsets */ |
|
offset = 0; |
for (i = 0; i < size; i++) | for (i = 0; i < size; i++) |
{ | { |
MI_Uint32 n; |
ptrdiff_t n; |
| |
if (!data[i]) | if (!data[i]) |
return MI_RESULT_FAILED; | return MI_RESULT_FAILED; |
| |
n = (MI_Uint32)Zlen(data[i]) + 1; |
n = ((ptrdiff_t)Tcslen(data[i]) + 1) * sizeof(ZChar); |
| |
/* Save size so that it will not have to be recalculated by the | /* Save size so that it will not have to be recalculated by the |
* next loop using strlen. | * next loop using strlen. |
|
|
if (i < MI_COUNT(sizes)) | if (i < MI_COUNT(sizes)) |
sizes[i] = n; | sizes[i] = n; |
| |
MI_RETURN_ERR(Buf_PackU64(self, (MI_Uint64)n)); |
/* Pack according to the platform */ |
|
MI_RETURN_ERR(Buf_PackPtrdiff_t (self, offset)); |
|
|
|
/* Accumulate the ZCharSizes */ |
|
offset += n; |
} | } |
| |
|
/* Pack the total size */ |
|
MI_RETURN_ERR(Buf_PackPtrdiff_t(self, offset)); |
|
|
/* Pack strings one after the other. */ | /* Pack strings one after the other. */ |
for (i = 0; i < size; i++) | for (i = 0; i < size; i++) |
{ | { |
MI_Uint32 n; | MI_Uint32 n; |
| |
if (i < MI_COUNT(sizes)) | if (i < MI_COUNT(sizes)) |
n = sizes[i]; |
n = (MI_Uint32)sizes[i]; |
else | else |
n = (MI_Uint32)Zlen(data[i]) + 1; |
n = ((MI_Uint32)Tcslen(data[i]) + 1) * sizeof(ZChar); |
| |
MI_RETURN_ERR(Buf_App(self, data[i], n * sizeof(MI_Char))); |
MI_RETURN_ERR(Buf_App(self, data[i], n)); |
} | } |
} | } |
| |
|
|
| |
MI_Result Buf_UnpackStrA( | MI_Result Buf_UnpackStrA( |
Buf* self, | Buf* self, |
const MI_Char*** dataOut, |
const ZChar*** dataOut, |
MI_Uint32* sizeOut) | MI_Uint32* sizeOut) |
{ | { |
const MI_Char** data; |
const ZChar** data; |
MI_Uint32 size; | MI_Uint32 size; |
MI_Uint32 i; | MI_Uint32 i; |
MI_Uint32 offset; | MI_Uint32 offset; |
|
ptrdiff_t start; |
| |
/* Unpack the size of the array */ | /* Unpack the size of the array */ |
MI_RETURN_ERR(Buf_UnpackU32(self, &size)); | MI_RETURN_ERR(Buf_UnpackU32(self, &size)); |
|
|
MI_RETURN_ERR(Buf_Align64(self)); | MI_RETURN_ERR(Buf_Align64(self)); |
| |
/* Set pointer data array */ | /* Set pointer data array */ |
data = (const MI_Char**)((char*)self->data + self->offset); |
data = (const ZChar**)((char*)self->data + self->offset); |
| |
/* Calculate offset to first string in array (data[0]) */ | /* Calculate offset to first string in array (data[0]) */ |
offset = self->offset + (size * sizeof(MI_Uint64)); |
offset = self->offset + ((size+1) * sizeof(ptrdiff_t)); |
| |
/* Fail if offset is beyond end of buffer */ | /* Fail if offset is beyond end of buffer */ |
if (offset > self->size) | if (offset > self->size) |
return MI_RESULT_FAILED; | return MI_RESULT_FAILED; |
| |
/* Unpack the string sizes and covert to string pointers */ |
/* Unpack the string ZCharSizes/pointers and convert to string pointers |
for (i = 0; i < size; i++) |
* We intentionally iterate (size + 1) times. |
|
*/ |
|
start = 0; |
|
for (i = 0; i <= size; i++) |
{ | { |
MI_Uint64 tmp; |
ptrdiff_t n; |
MI_Uint32 n; |
|
| |
/* Unpack size of next string in array */ | /* Unpack size of next string in array */ |
MI_RETURN_ERR(Buf_UnpackU64(self, &tmp)); |
MI_RETURN_ERR(Buf_UnpackPtrdiff_t (self, &n)); |
n = (MI_Uint32)tmp; |
|
|
/* Remember the first element - this will be the base */ |
|
if (i == 0) |
|
start = n; |
| |
/* Fail if not enough room left in buffer for string */ | /* Fail if not enough room left in buffer for string */ |
if (offset + n * sizeof(MI_Char) > self->size) |
if (offset + (n-start) > self->size) |
return MI_RESULT_FAILED; | return MI_RESULT_FAILED; |
| |
/* Add string to array */ |
/* Add string pointer to array */ |
data[i] = (MI_Char*)((char*)self->data + offset); |
data[i] = (ZChar*)((char*)self->data + offset + (n-start)); |
offset += n * sizeof(MI_Char); |
|
} | } |
| |
/* Update the offset */ | /* Update the offset */ |
self->offset = offset; |
self->offset = offset + (MI_Uint32)(((ptrdiff_t)data[size]) - ((ptrdiff_t)data[0])); |
| |
/* Set the output parameters */ | /* Set the output parameters */ |
*dataOut = data; | *dataOut = data; |
|
|
| |
return NULL; | return NULL; |
} | } |
|
|
|
MI_Result Buf_AppStr( |
|
Buf* self, |
|
const ZChar* str) |
|
{ |
|
return Buf_App(self, str, (MI_Uint32)Tcslen(str) * sizeof(ZChar)); |
|
} |
|
|
|
MI_Result Buf_AppStrN( |
|
Buf* self, |
|
const ZChar* str, |
|
size_t size) |
|
{ |
|
return Buf_App(self, str, (MI_Uint32)size * sizeof(ZChar)); |
|
} |
|
|