/******************************************************************************
 *{@C
 *      Copyright:      2005-2010 Paul Obermeier (obermeier@tcl3d.org)
 *
 *                      See the file "Tcl3D_License.txt" for information on
 *                      usage and redistribution of this file, and for a
 *                      DISCLAIMER OF ALL WARRANTIES.
 *
 *      Module:         Tcl3D
 *      Filename:       tcl3dPointer.i
 *
 *      Author:         Paul Obermeier
 *
 *      Description:    SWIG file defining utility C functions and typemaps for
 *                      wrapping pointer and array parameters.
 *
 *****************************************************************************/

%{

static int GetDoubleVector (Tcl_Interp *interp, Tcl_Obj *obj, 
                            int n, double *doublePtr)
{
    int objc, i;
    Tcl_Obj **objv;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return TCL_ERROR;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetDoubleFromObj(interp, objv[i], doublePtr+i) != TCL_OK) {
            return TCL_ERROR;
        }
    }
    for (i=i; i<n; i++) {
        doublePtr[i] = 0.0;
    }
    return TCL_OK;
}

static int GetFloatVector (Tcl_Interp *interp, Tcl_Obj *obj, 
                           int n, float *floatPtr)
{
    int objc, i;
    Tcl_Obj **objv;
    double tmp;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return TCL_ERROR;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetDoubleFromObj(interp, objv[i], &tmp) != TCL_OK) {
            return TCL_ERROR;
        } else {
            floatPtr[i] = tmp;
        }
    }
    for (i=i; i<n; i++) {
        floatPtr[i] = 0.0f;
    }
    return TCL_OK;
}

static int GetIntVector (Tcl_Interp *interp, Tcl_Obj *obj,
                         int n, int *intPtr)
{
    int objc, i;
    Tcl_Obj **objv;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return TCL_ERROR;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], intPtr+i) != TCL_OK) {
            return TCL_ERROR;
        }
    }
    for (i=i; i<n; i++) {
        intPtr[i] = 0;
    }
    return TCL_OK;
}

static int GetUIntVector (Tcl_Interp *interp, Tcl_Obj *obj, 
                          int n, unsigned int *uintPtr)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return TCL_ERROR;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            return TCL_ERROR;
        } else {
            uintPtr[i] = (unsigned int) tmp;
        }
    }
    for (i=i; i<n; i++) {
        uintPtr[i] = 0;
    }
    return TCL_OK;
}

static int GetShortVector (Tcl_Interp *interp, Tcl_Obj *obj, 
                           int n, short *shortPtr)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return TCL_ERROR;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            return TCL_ERROR;
        } else {
            shortPtr[i] = (short) tmp;
        }
    }
    for (i=i; i<n; i++) {
        shortPtr[i] = 0;
    }
    return TCL_OK;
}

static int GetUShortVector (Tcl_Interp *interp, Tcl_Obj *obj, 
                            int n, unsigned short *ushortPtr)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return TCL_ERROR;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            return TCL_ERROR;
        } else {
            ushortPtr[i] = (unsigned short) tmp;
        }
    }
    for (i=i; i<n; i++) {
        ushortPtr[i] = 0;
    }
    return TCL_OK;
}

static int GetByteVector (Tcl_Interp *interp, Tcl_Obj *obj,
                          int n, signed char *charPtr)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return TCL_ERROR;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            return TCL_ERROR;
        } else {
            charPtr[i] = (signed char) tmp;
        }
    }
    for (i=i; i<n; i++) {
        charPtr[i] = 0;
    }
    return TCL_OK;
}

static int GetUByteVector (Tcl_Interp *interp, Tcl_Obj *obj, 
                           int n, unsigned char *ucharPtr)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return TCL_ERROR;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            return TCL_ERROR;
        } else {
            ucharPtr[i] = (unsigned char) tmp;
        }
    }
    for (i=i; i<n; i++) {
        ucharPtr[i] = 0;
    }
    return TCL_OK;
}

static double *GetDoubleList (Tcl_Interp *interp, Tcl_Obj *obj)
{
    int objc, i;
    Tcl_Obj **objv;
    double tmp;
    double *listPtr;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return NULL;
    }
    listPtr = (double *)malloc (objc * sizeof (double));
    if (!listPtr) {
        return NULL;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetDoubleFromObj(interp, objv[i], &tmp) != TCL_OK) {
            free (listPtr);
            return NULL;
        } else {
            listPtr[i] = tmp;
        }
    }
    return listPtr;
}

static float *GetFloatList (Tcl_Interp *interp, Tcl_Obj *obj)
{
    int objc, i;
    Tcl_Obj **objv;
    double tmp;
    float  *listPtr;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return NULL;
    }
    listPtr = (float *)malloc (objc * sizeof (float));
    if (!listPtr) {
        return NULL;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetDoubleFromObj(interp, objv[i], &tmp) != TCL_OK) {
            free (listPtr);
            return NULL;
        } else {
            listPtr[i] = (float) tmp;
        }
    }
    return listPtr;
}

static int *GetIntList (Tcl_Interp *interp, Tcl_Obj *obj)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;
    int *listPtr;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return NULL;
    }
    listPtr = (int *)malloc (objc * sizeof (int));
    if (!listPtr) {
        return NULL;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            free (listPtr);
            return NULL;
        } else {
            listPtr[i] = (int) tmp;
        }
    }
    return listPtr;
}

static unsigned int *GetUIntList (Tcl_Interp *interp, Tcl_Obj *obj)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;
    unsigned int *listPtr;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return NULL;
    }
    listPtr = (unsigned int *)malloc (objc * sizeof (unsigned int));
    if (!listPtr) {
        return NULL;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            free (listPtr);
            return NULL;
        } else {
            listPtr[i] = (unsigned int) tmp;
        }
    }
    return listPtr;
}

static short *GetShortList (Tcl_Interp *interp, Tcl_Obj *obj)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;
    short *listPtr;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return NULL;
    }
    listPtr = (short *)malloc (objc * sizeof (short));
    if (!listPtr) {
        return NULL;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            free (listPtr);
            return NULL;
        } else {
            listPtr[i] = (short) tmp;
        }
    }
    return listPtr;
}

static unsigned short *GetUShortList (Tcl_Interp *interp, Tcl_Obj *obj)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;
    unsigned short *listPtr;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return NULL;
    }
    listPtr = (unsigned short *)malloc (objc * sizeof (unsigned short));
    if (!listPtr) {
        return NULL;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            free (listPtr);
            return NULL;
        } else {
            listPtr[i] = (unsigned short) tmp;
        }
    }
    return listPtr;
}

static char *GetByteList (Tcl_Interp *interp, Tcl_Obj *obj)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;
    char *listPtr;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return NULL;
    }
    listPtr = (char *)malloc (objc * sizeof (char));
    if (!listPtr) {
        return NULL;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            free (listPtr);
            return NULL;
        } else {
            listPtr[i] = (char) tmp;
        }
    }
    return listPtr;
}

static unsigned char *GetUByteList (Tcl_Interp *interp, Tcl_Obj *obj)
{
    int objc, i;
    Tcl_Obj **objv;
    int tmp;
    unsigned char *listPtr;

    if (Tcl_ListObjGetElements(interp, obj, &objc, &objv) != TCL_OK) {
        return NULL;
    }
    listPtr = (unsigned char *)malloc (objc * sizeof (unsigned char));
    if (!listPtr) {
        return NULL;
    }
    for (i=0; i<objc; i++) {
        if (Tcl_GetIntFromObj(interp, objv[i], &tmp) != TCL_OK) {
            free (listPtr);
            return NULL;
        } else {
            listPtr[i] = (unsigned char) tmp;
        }
    }
    return listPtr;
}

%}

%typemap(in) const double[ANY] (double tmp[$dim0]) {
    if (GetDoubleVector (interp, $input, $dim0, $1 = tmp) != TCL_OK) {
        return TCL_ERROR;
    }
}

%typemap(in) const float[ANY] (float tmp[$dim0]) {
    if (GetFloatVector (interp, $input, $dim0, $1 = tmp) != TCL_OK) {
        return TCL_ERROR;
    }
}

%typemap(in) const int[ANY] (int tmp[$dim0]) {
    if (GetIntVector(interp, $input, $dim0, $1 = tmp) != TCL_OK) {
        return TCL_ERROR;
    }
}

%typemap(in) const unsigned int[ANY] (unsigned int tmp[$dim0]) {
    if (GetUIntVector (interp, $input, $dim0, $1 = tmp) != TCL_OK) {
        return TCL_ERROR;
    }
}

%typemap(in) const short[ANY] (short tmp[$dim0]) {
    if (GetShortVector (interp, $input, $dim0, $1 = tmp) != TCL_OK) {
        return TCL_ERROR;
    }
}

%typemap(in) const unsigned short[ANY] (unsigned short tmp[$dim0]) {
    if (GetUShortVector (interp, $input, $dim0, $1 = tmp) != TCL_OK) {
        return TCL_ERROR;
    }
}

%typemap(in) const char[ANY] (char tmp[$dim0]) {
    if (GetByteVector (interp, $input, $dim0, $1 = tmp) != TCL_OK) {
        return TCL_ERROR;
    }
}

%typemap(in) const unsigned char[ANY] (unsigned char tmp[$dim0]) {
    if (GetUByteVector (interp, $input, $dim0, $1 = tmp) != TCL_OK) {
        return TCL_ERROR;
    }
}
