#include "pbvm.h"
BOOL copy_val_ptr(vm_state *vm, value *val, blob *b, DWORD &pos, int size, bool field){
void *dest,*src;
if (pos+size -1 > b->len) return FALSE;
if (val->flags&IS_NULL||field){
dest=(void *)pbstg_alc(vm, size, GET_HEAP(vm));
val->value = (DWORD)dest;
val->flags = val->flags - IS_NULL;
}else{
dest=(void *)val->value;
}
src=(void*)(b->data+pos -1);
memcpy(dest, src, size);
pos+=size;
return TRUE;
}
BOOL extract(vm_state *vm, value *val, blob *b, DWORD &pos, bool field){
if (pos > b->len) return FALSE;
if (val->flags & IS_ARRAY){
long count;
value *v;
pb_array *parray=(pb_array *)val->value;
count=ot_array_num_items(vm, parray);
for (long i=0;i<count;i++){
v=ot_array_index(vm, parray, i);
if (!extract(vm, v, b, pos, false)) return FALSE;
}
return TRUE;
}
if (val->type & 0xC000){
long fields, first;
value field;
pb_class *pclass = (pb_class *)val->value;
fields = ob_get_no_fields(vm, pclass);
first = ob_get_first_user_field(vm, pclass);
for (int i=first;i<fields;i++){
ob_get_field(vm, pclass, i, &field);
if (!extract(vm, &field, b, pos, true)) return FALSE;
if (!(field.flags & IS_ARRAY)){
ob_set_field(vm, pclass, i, &field);
}
}
return TRUE;
}
//TODO, ansi / unicode conversions....
switch(val->type){
case pbvalue_int:
case pbvalue_boolean:
case pbvalue_uint:
case pbvalue_char:
{
if (pos+1 > b->len) return FALSE;
short *p = (short *)&b->data[pos -1];
val->value = *p;
val->flags=0x500;
pos+=2;
}
return TRUE;
case pbvalue_byte:
{
if (pos > b->len) return FALSE;
char *p = (char *)&b->data[pos -1];
val->value = *p;
pos++;
}
return TRUE;
case pbvalue_long:
case pbvalue_ulong:
{
if (pos+3 > b->len) return FALSE;
long *p = (long *)&b->data[pos -1];
val->value = *p;
val->flags=0x1d00;
pos+=4;
}
return TRUE;
case pbvalue_real:
{
if (pos+3 > b->len) return FALSE;
long *p = (long *)&b->data[pos -1];
val->value = *p;
val->flags=0x0900;
pos+=4;
}
return TRUE;
case pbvalue_string:
{
int len;
wchar_t *dest, *src;
len=(b->len - pos +1)/2;
src=(wchar_t*)(b->data+pos -1);
len=wcsnlen(src, len);
dest=(wchar_t *)pbstg_alc(vm, (len+1) *2, GET_HEAP(vm));
if ((!field)&&(!(val->flags&IS_NULL)))
ot_free_val_ptr(vm, val);
val->value = (DWORD)dest;
val->flags = 0x0d00;
wcsncpy(dest, src, len);
dest[len]=0;
pos+=(len+1)*2;
}
return TRUE;
case pbvalue_longlong:
case pbvalue_double:
return copy_val_ptr(vm, val, b, pos, 8, field);
case pbvalue_dec:
return copy_val_ptr(vm, val, b, pos, 16, field);
case pbvalue_date:
case pbvalue_time:
case pbvalue_datetime:
return copy_val_ptr(vm, val, b, pos, 12, field);
}
return FALSE;
}
// boolean blob_extract(ref any value, readonly blob data, ref ulong al_pos)
DWORD __declspec(dllexport) __stdcall Blob_Extract (vm_state *vm, DWORD arg_count){
DWORD isnull;
lvalue_ref *lv_val, *lv_pos;
value ret, *val, *v_pos;
blob *source;
last_vm = vm;
lv_val = ot_get_next_lvalue_arg(vm,&isnull);
val = get_lvalue(vm, lv_val);
source = (blob *)ot_get_valptr_arg(vm, &isnull);
lv_pos=ot_get_next_lvalue_arg(vm, &isnull);
v_pos = get_lvalue(vm, lv_pos);
ret.value=extract(vm, val, source, v_pos->value, false);
ret.type=pbvalue_boolean;
ret.flags=0x500;
ot_assign_ref_long(vm, lv_pos->ptr, v_pos->value, 0);
ot_set_return_val(vm, &ret);
return 1;
}
// PB10 only util function
DWORD __declspec(dllexport) __stdcall Get_Byte_Array (vm_state *vm, DWORD arg_count){
DWORD start=0, len, isnull;
blob *source;
value ret;
last_vm = vm;
source=(blob *)ot_get_valptr_arg(vm, &isnull);
len=source->len;
if (arg_count>=2){
start=ot_get_ulongarg(vm, &isnull) -1;
if (start<0) start=0;
len -= start;
if (arg_count>=3){
len=ot_get_ulongarg(vm, &isnull);
if (len + start > source->len) len=source->len - start;
if (len<0) len=0;
}
}
pb_array *parray=ot_array_create_unbounded(vm, MAKELONG(-1,pbvalue_uint), 0);
ret.value = (DWORD)parray;
ret.type = pbvalue_uint;
ret.flags = IS_ARRAY;
for (DWORD i=0;i<len;i++){
value *v=ot_array_index(vm, parray, i);
v->value=source->data[start+i] & 0xFF;
v->flags=0x0d00;
v->type=pbvalue_uint;
}
ot_set_return_val(vm, &ret);
return 1;
}
void expand_blob(vm_state *vm, value *bv, DWORD len){
blob *b = (blob*)bv->value;
if (b->len >= len) return;
DWORD buff_size = pbstg_sz(vm, b);
if (len+4 > buff_size){
buff_size = len+4;
if (buff_size>6144)
buff_size|=0xFFF;
b = (blob *)pbstg_realc(vm, b, buff_size, GET_HEAP(vm));
bv->value = (DWORD)b;
}
b->len = len;
}
BOOL import(vm_state *vm, value *val, value *bv, DWORD &pos){
if (val->flags&IS_NULL) return FALSE;
if (val->flags & IS_ARRAY){
long count;
value *v;
pb_array *parray=(pb_array *)val->value;
count=ot_array_num_items(vm, parray);
for (long i=0;i<count;i++){
v=ot_array_index(vm, parray, i);
if (!import(vm, v, bv, pos)) return FALSE;
}
return TRUE;
}
if (val->type & 0xC000){
long fields, first;
value field;
pb_class *pclass=(pb_class *)val->value;
fields = ob_get_no_fields(vm, pclass);
first = ob_get_first_user_field(vm, pclass);
for (int i=first;i<fields;i++){
ob_get_field(vm, pclass, i, &field);
if (!import(vm, &field, bv, pos)) return FALSE;
}
return TRUE;
}
int len;
char *p;
switch(val->type){
case pbvalue_int:
case pbvalue_boolean:
case pbvalue_uint:
case pbvalue_char:
len=2;
p=(char*)&val->value;
break;
case pbvalue_byte:
len=1;
p=(char*)&val->value;
break;
case pbvalue_long:
case pbvalue_ulong:
case pbvalue_real:
len=4;
p=(char*)&val->value;
break;
case pbvalue_string:
len = (wcslen((wchar_t *)val->value)+1)*2;
p=(char*)val->value;
break;
case pbvalue_longlong:
case pbvalue_double:
len=8;
p=(char*)val->value;
break;
case pbvalue_dec:
len=16;
p=(char*)val->value;
break;
case pbvalue_date:
case pbvalue_time:
case pbvalue_datetime:
len=12;
p=(char*)val->value;
break;
case pbvalue_blob:
{
blob *b = (blob *)val->value;
len=b->len;
p=(char*)&b->data;
}
}
expand_blob(vm, bv, pos+len-1);
blob *b = (blob *)bv->value;
memcpy(b->data+pos -1, p, len);
pos+=len;
return TRUE;
}
// boolean blob_import(readonly any value, ref blob data, ref ulong al_pos)
DWORD __declspec(dllexport) __stdcall Blob_Import (vm_state *vm, DWORD arg_count){
DWORD isnull;
DWORD pos;
value ret;
lvalue_ref *lv_pos;
value *v_pos;
last_vm = vm;
value *v_value = ot_get_next_evaled_arg_no_convert(vm);
lvalue_ref *lv_data = ot_get_next_lvalue_arg(vm,&isnull);
value *data = get_lvalue(vm, lv_data);
if (arg_count==3){
lv_pos=ot_get_next_lvalue_arg(vm, &isnull);
v_pos = get_lvalue(vm, lv_pos);
pos=v_pos->value;
}else{
pos=((blob *)data->value)->len +1;
}
ret.value=import(vm, v_value, data, pos);
ret.type=pbvalue_boolean;
ret.flags=0x500;
if (arg_count==3){
v_pos->value=pos;
ot_assign_ref_long(vm, lv_pos->ptr, v_pos->value, 0);
}
ot_set_return_val(vm, &ret);
return 1;
}
DWORD __declspec(dllexport) __stdcall Blob_Mid (vm_state *vm, DWORD arg_count){
DWORD start, len, isnull;
blob *source, *dest;
value v;
last_vm = vm;
source = (blob *)ot_get_valptr_arg(vm, &isnull);
if (isnull || source==NULL || source->len==0){
len =0;
}else{
start=ot_get_ulongarg(vm, &isnull);
if (isnull||start<1) start=1;
if (start>source->len){
len=0;
}else{
if (arg_count>=3){
len=ot_get_ulongarg(vm, &isnull);
if (isnull) len=0;
if (len>source->len - start+1) len = source->len - start+1;
}else{
len=source->len - start+1;
}
}
}
v.type=pbvalue_blob;
v.flags=0xd00;
dest = (blob *)pbstg_alc(vm, len +5, GET_HEAP(vm));
dest->len=len;
v.value=(DWORD)dest;
if (len>0)
memcpy(&dest->data[0], &source->data[start -1], len);
ot_set_return_val(vm, &v);
return 1;
}
DWORD __declspec(dllexport) __stdcall Blob_Alloc (vm_state *vm, DWORD arg_count){
DWORD isnull, new_size;
blob *dest;
int zero_memory=FALSE;
value v;
last_vm = vm;
new_size=ot_get_ulongarg(vm, &isnull);
if (isnull) new_size=0;
if (arg_count>=2){
zero_memory=ot_get_simple_intarg(vm, &isnull);
if (isnull) zero_memory=FALSE;
}
v.type=pbvalue_blob;
v.flags=0xd00;
dest = (blob *)pbstg_alc(vm, new_size +5, GET_HEAP(vm));
dest->len=new_size;
if (zero_memory){
ZeroMemory(&dest->data[0],new_size);
}
v.value=(DWORD)dest;
ot_set_return_val(vm, &v);
return 1;
}
File: blob_funcs.cpp
Size: 8653
Date: Tue, 08 May 2012 23:13:40 +0200
Type: cpp
Size: 8653
Date: Tue, 08 May 2012 23:13:40 +0200
Type: cpp