version 1.1, 2012/05/30 22:47:49
|
version 1.5, 2015/09/25 20:24:20
|
|
|
#include "instance.h" | #include "instance.h" |
#include "return.h" | #include "return.h" |
#include "types.h" | #include "types.h" |
#include "indent.h" |
#include <pal/strings.h> |
#include "strings.h" |
#include "miextras.h" |
#include "io.h" |
#include <pal/intsafe.h> |
|
#include <pal/format.h> |
|
#include <pal/file.h> |
#include "helpers.h" | #include "helpers.h" |
|
#include "strarr.h" |
| |
#define T MI_T |
|
#define _BORROW 0x01 | #define _BORROW 0x01 |
| |
/* | /* |
|
|
sizeof(MI_InstanceAField), | sizeof(MI_InstanceAField), |
}; | }; |
| |
|
MI_INLINE size_t FieldSizeOf(MI_Type type) |
|
{ |
|
return _fieldSizes[(int)type]; |
|
} |
|
|
static void* _CloneSimpleArray( | static void* _CloneSimpleArray( |
const void* data, | const void* data, |
MI_Uint32 size, |
size_t size, |
MI_Uint32 type, | MI_Uint32 type, |
Batch* batch) | Batch* batch) |
{ | { |
|
|
return array; | return array; |
} | } |
| |
static MI_Char** _CloneStringArray( |
|
const MI_Char** data, |
|
MI_Uint32 size, |
|
Batch* batch) |
|
{ |
|
size_t n; |
|
MI_Uint32 i; |
|
MI_Char* ptr; |
|
MI_Char** array; |
|
|
|
/* Empty arrays are represented by NULL */ |
|
if (!data || size == 0) |
|
return NULL; |
|
|
|
/* Calculate space for pointer array */ |
|
n = size * sizeof(MI_Char*); |
|
|
|
/* Calculate space for strings (add space for zero terminators) */ |
|
for (i = 0; i < size; i++) |
|
{ |
|
if (!data[i]) |
|
{ |
|
/* Null elements are illegal */ |
|
return NULL; |
|
} |
|
|
|
n += (Zlen(data[i]) + 1) * sizeof(MI_Char); |
|
} |
|
|
|
/* Allocate memory */ |
|
array = (MI_Char**)BAlloc(batch, n, CALLSITE); |
|
|
|
if (!array) |
|
return NULL; |
|
|
|
ptr = (MI_Char*)&array[size]; |
|
|
|
/* Copy the strings */ |
|
for (i = 0; i < size; i++) |
|
{ |
|
size_t count = Zlen(data[i]) + 1; |
|
memcpy(ptr, data[i], count * sizeof(MI_Char)); |
|
array[i] = ptr; |
|
ptr += count; |
|
} |
|
|
|
return array; |
|
} |
|
|
|
static void* _CloneInstanceArray( | static void* _CloneInstanceArray( |
const void* data_, | const void* data_, |
MI_Uint32 size, |
size_t size, |
Batch* batch) | Batch* batch) |
{ | { |
const MI_Instance** data = (const MI_Instance**)data_; | const MI_Instance** data = (const MI_Instance**)data_; |
MI_Instance** array; | MI_Instance** array; |
MI_Uint32 i; |
size_t i; |
| |
/* Handle empty arrays up front */ | /* Handle empty arrays up front */ |
if (!data || size == 0) | if (!data || size == 0) |
|
|
const Field* src, | const Field* src, |
MI_Type type) | MI_Type type) |
{ | { |
memcpy(dest, src, _fieldSizes[(int)type]); |
memcpy(dest, src, FieldSizeOf(type)); |
} | } |
| |
static void _Swap( | static void _Swap( |
|
|
MI_Type type, | MI_Type type, |
MI_Uint8 x) | MI_Uint8 x) |
{ | { |
memset(self, x, _fieldSizes[(int)type]); |
memset(self, x, FieldSizeOf(type)); |
} | } |
| |
/* | /* |
|
|
{ | { |
if (value->string) | if (value->string) |
{ | { |
MI_Char* str; |
ZChar* str; |
| |
if (flags & MI_FLAG_BORROW) | if (flags & MI_FLAG_BORROW) |
{ | { |
|
|
| |
data = _CloneSimpleArray( | data = _CloneSimpleArray( |
value->array.data, value->array.size, type, batch); | value->array.data, value->array.size, type, batch); |
if (!data) |
|
|
if ((value->array.size != 0) && !data) |
MI_RETURN(MI_RESULT_FAILED); | MI_RETURN(MI_RESULT_FAILED); |
| |
self->array.value.data = data; | self->array.value.data = data; |
|
|
{ | { |
self->array.value.data = NULL; | self->array.value.data = NULL; |
self->array.value.size = 0; | self->array.value.size = 0; |
self->array.exists = MI_FALSE; |
self->array.exists = MI_TRUE; |
} | } |
break; | break; |
} | } |
case MI_STRINGA: | case MI_STRINGA: |
{ | { |
MI_Char** data; |
ZChar** data; |
| |
if (value->array.data) | if (value->array.data) |
{ | { |
|
|
break; | break; |
} | } |
| |
data = _CloneStringArray((const MI_Char**)value->stringa.data, |
data = CloneStringArray((const ZChar**)value->stringa.data, |
value->stringa.size, batch); | value->stringa.size, batch); |
if (!data) | if (!data) |
MI_RETURN(MI_RESULT_FAILED); | MI_RETURN(MI_RESULT_FAILED); |
|
|
{ | { |
self->stringa.value.data = NULL; | self->stringa.value.data = NULL; |
self->stringa.value.size = 0; | self->stringa.value.size = 0; |
self->stringa.exists = MI_FALSE; |
self->stringa.exists = MI_TRUE; |
} | } |
break; | break; |
} | } |
|
|
{ | { |
self->instancea.value.data = NULL; | self->instancea.value.data = NULL; |
self->instancea.value.size = 0; | self->instancea.value.size = 0; |
self->instancea.exists = MI_FALSE; |
self->instancea.exists = MI_TRUE; |
} | } |
break; | break; |
} | } |
|
|
{ | { |
size_t size = Type_SizeOf(type); | size_t size = Type_SizeOf(type); |
memcpy(valueOut, self, size); | memcpy(valueOut, self, size); |
*existsOut = *(MI_Boolean*)((char*)self + size); |
*existsOut = *(MI_Boolean*)((const char*)self + size); |
*flagsOut = *(MI_Uint8*)((char*)self + size + sizeof(MI_Boolean)); |
*flagsOut = *(MI_Uint8*)((const char*)self + size + sizeof(MI_Boolean)); |
} |
|
|
|
void Field_Print( |
|
const Field* self, |
|
FILE* os, |
|
MI_Type type, |
|
MI_Uint32 level) |
|
{ |
|
MI_Value v; |
|
MI_Boolean e; |
|
MI_Uint8 f; |
|
Field_Extract(self, type, &v, &e, &f); |
|
|
|
if (!e) |
|
{ |
|
fprintf(os, "NULL"); |
|
return; |
|
} |
|
else |
|
{ |
|
switch (type) |
|
{ |
|
case MI_BOOLEAN: |
|
{ |
|
const MI_Boolean* p = (const MI_Boolean*)&v; |
|
fprintf(os, "%s", *p ? "true" : "false"); |
|
break; |
|
} |
|
case MI_SINT8: |
|
{ |
|
fprintf(os, "%d", *((const MI_Sint8*)&v)); |
|
break; |
|
} |
|
case MI_UINT8: |
|
{ |
|
fprintf(os, "%u", *((const MI_Uint8*)&v)); |
|
break; |
|
} |
|
case MI_SINT16: |
|
{ |
|
fprintf(os, "%d", *((const MI_Sint16*)&v)); |
|
break; |
|
} |
|
case MI_UINT16: |
|
{ |
|
fprintf(os, "%u", *((const MI_Uint16*)&v)); |
|
break; |
|
} |
|
case MI_SINT32: |
|
{ |
|
fprintf(os, "%d", *((const MI_Sint32*)&v)); |
|
break; |
|
} |
|
case MI_UINT32: |
|
{ |
|
fprintf(os, "%u", *((const MI_Uint32*)&v)); |
|
break; |
|
} |
|
case MI_SINT64: |
|
{ |
|
fprintf(os, SINT64_FMT, *((const MI_Sint64*)&v)); |
|
break; |
|
} |
|
case MI_UINT64: |
|
{ |
|
fprintf(os, UINT64_FMT, *((const MI_Uint64*)&v)); |
|
break; |
|
} |
|
case MI_REAL32: |
|
{ |
|
fprintf(os, "%g", *((const MI_Real32*)&v)); |
|
break; |
|
} |
|
case MI_REAL64: |
|
{ |
|
fprintf(os, "%g", *((const MI_Real64*)&v)); |
|
break; |
|
} |
|
case MI_CHAR16: |
|
{ |
|
fprintf(os, "%u", *((const MI_Char16*)&v)); |
|
break; |
|
} |
|
case MI_DATETIME: |
|
{ |
|
MI_Char buf[26]; |
|
DatetimeToStr((const MI_Datetime*)&v, buf); |
|
Fzprintf(os, T("%s"), buf); |
|
break; |
|
} |
|
case MI_STRING: |
|
{ |
|
Fzprintf(os, T("%s"), *((MI_Char**)&v)); |
|
break; |
|
} |
|
case MI_BOOLEANA: |
|
case MI_SINT8A: |
|
case MI_UINT8A: |
|
case MI_SINT16A: |
|
case MI_UINT16A: |
|
case MI_SINT32A: |
|
case MI_UINT32A: |
|
case MI_SINT64A: |
|
case MI_UINT64A: |
|
case MI_REAL32A: |
|
case MI_REAL64A: |
|
case MI_CHAR16A: |
|
case MI_DATETIMEA: |
|
{ |
|
MI_BooleanA* arr = (MI_BooleanA*)&v; |
|
char* ptr = (char*)arr->data; |
|
MI_Uint32 i; |
|
|
|
fprintf(os, "{"); |
|
|
|
for (i = 0; i < arr->size; i++) |
|
{ |
|
MI_Type stype = Type_ScalarOf(type); |
|
MI_Type ssize = Type_SizeOf(stype); |
|
Field field; |
|
|
|
/* Build dummy field */ |
|
memcpy(&field, ptr, ssize); |
|
*(MI_Boolean*)((char*)&field + ssize) = MI_TRUE; |
|
*(MI_Uint8*)((char*)&field + ssize + 1) = 0; |
|
|
|
/* Print dummy field */ |
|
Field_Print(&field, os, stype, level); |
|
ptr += ssize; |
|
|
|
if (i + 1 != arr->size) |
|
fprintf(os, ", "); |
|
} |
|
|
|
fprintf(os, "}"); |
|
break; |
|
} |
|
case MI_STRINGA: |
|
{ |
|
MI_StringA* arr = (MI_StringA*)&v; |
|
MI_Uint32 i; |
|
|
|
fprintf(os, "{"); |
|
|
|
for (i = 0; i < arr->size; i++) |
|
{ |
|
Fzprintf(os, T("%s"), arr->data[i]); |
|
|
|
if (i + 1 != arr->size) |
|
fprintf(os, ", "); |
|
} |
|
|
|
fprintf(os, "}"); |
|
break; |
|
} |
|
case MI_INSTANCE: |
|
case MI_REFERENCE: |
|
{ |
|
MI_Instance* inst = *((MI_Instance**)&v); |
|
|
|
if ( type == MI_REFERENCE) |
|
fprintf(os, " REF "); |
|
|
|
__MI_Instance_Print(inst, os, level); |
|
break; |
|
} |
|
case MI_INSTANCEA: |
|
case MI_REFERENCEA: |
|
{ |
|
MI_InstanceA* inst = ((MI_InstanceA*)&v); |
|
MI_Uint32 i; |
|
|
|
if ( type == MI_REFERENCEA) |
|
fprintf(os, " REF "); |
|
|
|
#if 0 |
|
fprintf(os, "[%d]\n", (int)inst->size); |
|
#endif |
|
fprintf(os, "\n"); |
|
|
|
Indent(os, level); |
|
fprintf(os, "{\n"); |
|
|
|
for (i = 0; i < inst->size; i++) |
|
{ |
|
__MI_Instance_Print(inst->data[i], os, level + 1); |
|
} |
|
|
|
Indent(os, level); |
|
fprintf(os, "}"); |
|
|
|
break; |
|
} |
|
default: |
|
break; |
|
} |
|
} |
|
} | } |
| |
static MI_Boolean _MatchDatetime( | static MI_Boolean _MatchDatetime( |
|
|
f = _MatchDatetime(&f1->datetime.value, &f2->datetime.value); | f = _MatchDatetime(&f1->datetime.value, &f2->datetime.value); |
break; | break; |
case MI_STRING: | case MI_STRING: |
f = Zcmp(f1->string.value, f2->string.value) == 0; |
f = Tcscmp(f1->string.value, f2->string.value) == 0; |
break; | break; |
case MI_REFERENCE: | case MI_REFERENCE: |
{ | { |