[DGD] Extension (first try)
pete at ana.sk
pete at ana.sk
Sun Feb 3 16:24:59 CET 2002
Hi ppl.
If anyone is interested in extension with some usefull functions here it is.
What i am interested in is if someone can have a look at it and verify if i did
everything ok, or tell what is wrong, since its my first try to code dgd extension.
Im especially unsure about d_ref_imports usage...
Pete
==== c code follows ====
#ifndef DGD_EXTENSION
#error DGD_EXTENSION macro is needed to use extensions!
#endif
#include "dgd_ext.h"
static void lower_case(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval)
{
DGD_VALUE_T val;
DGD_STRING_T str;
char *p;
unsigned int i;
/* fetch the argument string */
val = DGD_FRAME_ARG(f, nargs, 0);
str = DGD_STRING_GETVAL(val);
/* make a copy */
str = DGD_STRING_NEW(DGD_STRING_TEXT(str), DGD_STRING_LENGTH(str));
/* turn to lowercase */
p = DGD_STRING_TEXT(str);
for (i = DGD_STRING_LENGTH(str); i != 0; --i, ++p)
if (*p >= 'A' && *p <= 'Z')
*p += 'a' - 'A';
/* put result in return value */
DGD_RETVAL_STR(retval, str);
}
static void upper_case(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval)
{
DGD_VALUE_T val;
DGD_STRING_T str;
char *p;
unsigned int i;
/* fetch the argument string */
val = DGD_FRAME_ARG(f, nargs, 0);
str = DGD_STRING_GETVAL(val);
/* make a copy */
str = DGD_STRING_NEW(DGD_STRING_TEXT(str), DGD_STRING_LENGTH(str));
/* turn to lowercase */
p = DGD_STRING_TEXT(str);
for (i = DGD_STRING_LENGTH(str); i != 0; --i, ++p)
if (*p >= 'a' && *p <= 'z')
*p -= 'a' - 'A';
/* put result in return value */
DGD_RETVAL_STR(retval, str);
}
static void capitalize(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval)
{
DGD_VALUE_T val;
DGD_STRING_T str;
char *p;
unsigned int i;
/* fetch the argument string */
val = DGD_FRAME_ARG(f, nargs, 0);
str = DGD_STRING_GETVAL(val);
/* make a copy */
str = DGD_STRING_NEW(DGD_STRING_TEXT(str), DGD_STRING_LENGTH(str));
/* turn to lowercase */
p = DGD_STRING_TEXT(str);
if(DGD_STRING_LENGTH(str) > 0 && *p >= 'a' && *p <= 'z')
*p -= 'a' - 'A';
/* put result in return value */
DGD_RETVAL_STR(retval, str);
}
static int __equals(DGD_VALUE_T *val1, DGD_VALUE_T *val2, int len, int inc)
{
DGD_FLOAT_T fl1, fl2;
DGD_ARRAY_T arr1;
DGD_ARRAY_T arr2;
DGD_MAPPING_T map1;
DGD_MAPPING_T map2;
DGD_LWOBJ_T lwo1;
DGD_LWOBJ_T lwo2;
DGD_VALUE_T *elts1, *elts2;
int i;
for( ; len > 0; len -= inc)
{
if(DGD_TYPEOF(*val1) != DGD_TYPEOF(*val2))
return 0;
switch(DGD_TYPEOF(*val1))
{
case DGD_TYPE_NIL:
break;
case DGD_TYPE_INT:
if(DGD_INT_GETVAL(*val1) != DGD_INT_GETVAL(*val2))
return 0;
break;
case DGD_TYPE_FLOAT:
DGD_FLOAT_GETVAL(*val1, fl1);
DGD_FLOAT_GETVAL(*val2, fl2);
if(flt_cmp(&fl1, &fl2))
return 0;
break;
case DGD_TYPE_STRING:
if(str_cmp(DGD_STRING_GETVAL(*val1), DGD_STRING_GETVAL(*val2)))
return 0;
break;
case DGD_TYPE_OBJECT:
if(DGD_OBJECT_GETVAL(*val1) != DGD_OBJECT_GETVAL(*val2))
return 0;
break;
case DGD_TYPE_ARRAY:
arr1 = DGD_ARRAY_GETVAL(*val1);
arr2 = DGD_ARRAY_GETVAL(*val2);
if(arr1 == arr2)
break;
if(DGD_ARRAY_SIZE(arr1) != DGD_ARRAY_SIZE(arr2))
return 0;
if(!__equals(DGD_ARRAY_ELTS(arr1), DGD_ARRAY_ELTS(arr2), DGD_ARRAY_SIZE(arr1), 1))
return 0;
break;
case DGD_TYPE_MAPPING:
map1 = DGD_MAPPING_GETVAL(*val1);
map2 = DGD_MAPPING_GETVAL(*val2);
if(map1 == map2)
break;
elts1 = DGD_MAPPING_ELTS(map1);
elts2 = DGD_MAPPING_ELTS(map2);
if(DGD_ARRAY_SIZE(map1) != DGD_ARRAY_SIZE(map2))
return 0;
for(i = DGD_ARRAY_SIZE(map1); i > 0; i -= 2)
{
if(DGD_TYPEOF(*elts1) != DGD_TYPEOF(*elts2))
return 0;
switch(DGD_TYPEOF(*elts1))
{
case DGD_TYPE_NIL:
break;
case DGD_TYPE_INT:
if(DGD_INT_GETVAL(*elts1) != DGD_INT_GETVAL(*elts2))
return 0;
break;
case DGD_TYPE_FLOAT:
DGD_FLOAT_GETVAL(*elts1, fl1);
DGD_FLOAT_GETVAL(*elts2, fl2);
if(flt_cmp(&fl1, &fl2))
return 0;
break;
case DGD_TYPE_STRING:
if(str_cmp(DGD_STRING_GETVAL(*elts1), DGD_STRING_GETVAL(*elts2)))
return 0;
break;
case DGD_TYPE_OBJECT:
if(DGD_OBJECT_GETVAL(*elts1) != DGD_OBJECT_GETVAL(*elts2))
return 0;
break;
case DGD_TYPE_ARRAY:
case DGD_TYPE_MAPPING:
case DGD_TYPE_LWOBJ:
if(DGD_ARRAY_GETVAL(*elts1) != DGD_ARRAY_GETVAL(*elts2))
return 0;
break;
default:
return 0;
}
elts1 += 2;
elts2 += 2;
}
if(!__equals(elts1 + 1, elts2 + 1, DGD_ARRAY_SIZE(map1), 2))
return 0;
break;
case DGD_TYPE_LWOBJ:
lwo1 = DGD_LWOBJ_GETVAL(*val1);
lwo2 = DGD_LWOBJ_GETVAL(*val2);
if(lwo1 == lwo2)
break;
if(DGD_LWOBJ_CHECKVAL(lwo1) != DGD_LWOBJ_CHECKVAL(lwo2))
return 0;
if(!DGD_LWOBJ_CHECKVAL(lwo1))
break;
if(DGD_ARRAY_SIZE(lwo1) != DGD_ARRAY_SIZE(lwo2))
return 0;
if(!__equals(DGD_ARRAY_ELTS(lwo1), DGD_ARRAY_ELTS(lwo2), DGD_ARRAY_SIZE(lwo1), 1))
return 0;
break;
default:
return 0;
}
val1 += inc;
val2 += inc;
}
return 1;
}
static void equals(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval)
{
DGD_VALUE_T val1, val2;
val1 = DGD_FRAME_ARG(f, nargs, 0);
val2 = DGD_FRAME_ARG(f, nargs, 1);
DGD_RETVAL_INT(retval, __equals(&val1, &val2, 1, 1));
}
static void indexof(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval)
{
DGD_FLOAT_T fl1, fl2;
DGD_VALUE_T val1, val2;
DGD_ARRAY_T arr;
DGD_VALUE_T *elts;
int i;
val1 = DGD_FRAME_ARG(f, nargs, 0);
val2 = DGD_FRAME_ARG(f, nargs, 1);
arr = DGD_ARRAY_GETVAL(val2);
elts = DGD_ARRAY_ELTS(arr);
for(i = 0; i < DGD_ARRAY_SIZE(arr); ++i, ++elts)
{
if(DGD_TYPEOF(val1) != DGD_TYPEOF(*elts))
continue;
switch(DGD_TYPEOF(val1))
{
case DGD_TYPE_NIL:
break;
case DGD_TYPE_INT:
if(DGD_INT_GETVAL(val1) != DGD_INT_GETVAL(*elts))
continue;
break;
case DGD_TYPE_FLOAT:
DGD_FLOAT_GETVAL(val1, fl1);
DGD_FLOAT_GETVAL(*elts, fl2);
if(flt_cmp(&fl1, &fl2))
continue;
break;
case DGD_TYPE_STRING:
if(str_cmp(DGD_STRING_GETVAL(val1), DGD_STRING_GETVAL(*elts)))
continue;
break;
case DGD_TYPE_OBJECT:
if(DGD_OBJECT_GETVAL(val1) != DGD_OBJECT_GETVAL(*elts))
continue;
break;
case DGD_TYPE_ARRAY:
case DGD_TYPE_MAPPING:
case DGD_TYPE_LWOBJ:
if(DGD_ARRAY_GETVAL(val1) != DGD_ARRAY_GETVAL(*elts))
continue;
break;
default:
continue;
}
DGD_RETVAL_INT(retval, i);
return;
}
DGD_RETVAL_INT(retval, -1);
}
static void __copy(DGD_DATASPACE_T ds, DGD_VALUE_T *val, DGD_VALUE_T *retval)
{
DGD_ARRAY_T arr;
DGD_ARRAY_T new_arr;
DGD_MAPPING_T map;
DGD_MAPPING_T new_map;
DGD_VALUE_T *elts;
int i;
switch(DGD_TYPEOF(*val))
{
case DGD_TYPE_NIL:
case DGD_TYPE_INT:
case DGD_TYPE_FLOAT:
case DGD_TYPE_STRING:
case DGD_TYPE_OBJECT:
i_copy(retval, val, 1);
break;
case DGD_TYPE_ARRAY:
arr = DGD_ARRAY_GETVAL(*val);
elts = DGD_ARRAY_ELTS(arr);
new_arr = arr_new(ds, DGD_ARRAY_SIZE(arr));
for(i = 0; i < DGD_ARRAY_SIZE(arr); ++i, ++elts)
__copy(ds, elts, &new_arr->elts[i]);
d_ref_imports(new_arr);
DGD_RETVAL_ARR(retval, new_arr);
break;
case DGD_TYPE_MAPPING:
map = DGD_MAPPING_GETVAL(*val);
elts = DGD_MAPPING_ELTS(map);
new_map = map_new(ds, DGD_ARRAY_SIZE(map));
for(i = 0; i < DGD_ARRAY_SIZE(map); ++i, ++elts)
if(!(i & 1))
i_copy(&new_map->elts[i], elts, 1);
else
__copy(ds, elts, &new_map->elts[i]);
d_ref_imports(new_map);
DGD_RETVAL_MAP(retval, new_map);
break;
case DGD_TYPE_LWOBJ:
if(!DGD_LWOBJ_CHECKVAL(DGD_LWOBJ_GETVAL(*val)))
{
PUT_INT(retval, 0);
retval->type = nil_type;
}
else
PUT_LWOVAL(retval, DGD_LWOBJ_COPY(ds, DGD_LWOBJ_GETVAL(*val)));
break;
}
}
static void copy(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval)
{
DGD_VALUE_T val;
val = DGD_FRAME_ARG(f, nargs, 0);
__copy(DGD_FRAME_DATASPACE(f), &val, retval);
}
static char strfunc_proto[] = { DGD_TYPE_STRING, DGD_TYPE_STRING, 0 };
static char equals_proto[] = { DGD_TYPE_INT, DGD_TYPE_MIXED, DGD_TYPE_MIXED, 0 };
static char indexof_proto[] = { DGD_TYPE_INT, DGD_TYPE_MIXED, DGD_TYPE_ARRAY_OF(DGD_TYPE_MIXED), 0 };
static char copy_proto[] = { DGD_TYPE_MIXED, DGD_TYPE_MIXED, 0 };
static DGD_EXTKFUN_T kf[7] =
{
{ "lower_case", strfunc_proto, &lower_case },
{ "upper_case", strfunc_proto, &upper_case },
{ "capitalize", strfunc_proto, &capitalize },
{ "equals", equals_proto, &equals },
{ "indexof", indexof_proto, &indexof },
{ "member_array", indexof_proto, &indexof },
{ "copy", copy_proto, © },
};
void extension_init(void)
{
DGD_EXT_KFUN(kf, 7);
}
_________________________________________________________________
List config page: http://list.imaginary.com/mailman/listinfo/dgd
More information about the DGD
mailing list