[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, &copy },
};

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