/dx-4.4.4/src/exec/libdx/lbextract.c
# · C · 1185 lines · 816 code · 237 blank · 132 comment · 200 complexity · 95a46cf3b93d40dadc0418c319897fcd MD5 · raw file
- /***********************************************************************/
- /* Open Visualization Data Explorer */
- /* (C) Copyright IBM Corp. 1989,1999 */
- /* ALL RIGHTS RESERVED */
- /* This code licensed under the */
- /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
- /***********************************************************************/
- #include <dxconfig.h>
- #include <string.h>
- #include <dx/dx.h>
- /*
- * simple routines for common cases
- */
- Object DXExtractInteger(Object o, int *ip)
- {
- return DXExtractParameter(o, TYPE_INT, 0, 1, (Pointer)ip);
- }
- Object DXExtractFloat(Object o, float *fp)
- {
- return DXExtractParameter(o, TYPE_FLOAT, 0, 1, (Pointer)fp);
- }
- /* slightly different - it returns a pointer to the start of the string.
- * the caller doesn't need to allocate space for it.
- */
- Object DXExtractString(Object o, char **cp)
- {
- char *c;
- int len;
- Type t;
- /* this does the checking to be sure it is either a String object,
- * or a TYPE_STRING array.
- */
- if(!DXQueryParameter(o, TYPE_STRING, 1, NULL))
- return NULL;
-
- if(DXGetObjectClass(o) == CLASS_STRING) {
- if (cp)
- *cp = DXGetString((String)o);
- return o;
- }
-
- DXGetArrayInfo((Array) o, &len, &t, NULL, NULL, NULL);
-
- if (t == TYPE_STRING) {
- if (len > 1)
- return NULL;
- if (cp)
- *cp = (char *)DXGetArrayData((Array)o);
- return o;
- }
- /* for backwards compatibility - TYPE_UBYTE */
- c = (char *)DXGetArrayData((Array)o);
-
- while (--len > 0) {
-
- if (*c++) /* fail if there are imbedded NULLs... */
- continue;
-
- return NULL;
- }
- if (*c) /* ...or if there isn't a trailing NULL */
- return NULL;
-
- if (cp)
- *cp = (char *)DXGetArrayData((Array)o);
- return o;
- }
- Object DXExtractNthString (Object o, int n, char **cp)
- {
- char *c, *cs;
- int len;
- Type type;
- int shape;
- if (n < 0)
- return (NULL);
- /* only returns ok if object class String or Array TYPE_STRING or UBYTE */
- if (! DXQueryParameter (o, TYPE_STRING, 1, NULL))
- return (NULL);
- if (DXGetObjectClass(o) == CLASS_STRING) {
- /* String objects are 1 string, so asking for any string
- * but the 0th is bad.
- */
- if (n)
- return (NULL);
-
- if (cp)
- *cp = DXGetString ((String) o);
- return (o);
- }
- DXGetArrayInfo ((Array) o, &len, &type, NULL, NULL, NULL);
- if (type == TYPE_STRING) {
- /* len is number of strings in array */
- if (n >= len)
- return NULL;
- /* the Query call above made sure this is rank 1,
- * so shape is safe here
- */
- DXGetArrayInfo ((Array) o, NULL, NULL, NULL, NULL, &shape);
- cs = (char *) DXGetArrayData ((Array) o);
- if (cp)
- *cp = cs + (n * shape);
- return o;
- }
- /* here for backward compatibility -
- * null separated chars in a UBYTE array
- */
- cs = (char *) DXGetArrayData ((Array) o);
-
- for (c=cs; len--; ) {
-
- if (*c++)
- continue;
-
- if (n == 0) {
- if (cp)
- *cp = cs;
- return (o);
- }
-
- n--;
- cs = c;
- }
-
- return (NULL);
- }
- /* new code */
- #define CONVTYPE(from, to) \
- static Error \
- from##2##to(int count, from *fp, to *tp) \
- { \
- int i; \
- \
- for (i=0; i<count; i++) \
- *tp++ = (to) *fp++; \
- \
- return OK; \
- }
- CONVTYPE(byte, short)
- CONVTYPE(byte, int)
- CONVTYPE(byte, float)
- CONVTYPE(byte, double)
- CONVTYPE(ubyte, short )
- CONVTYPE(ubyte, ushort)
- CONVTYPE(ubyte, int)
- CONVTYPE(ubyte, uint)
- CONVTYPE(ubyte, float)
- CONVTYPE(ubyte, double)
- CONVTYPE(short, int)
- CONVTYPE(short, float)
- CONVTYPE(short, double)
- CONVTYPE(ushort, int)
- CONVTYPE(ushort, uint)
- CONVTYPE(ushort, float)
- CONVTYPE(ushort, double)
- CONVTYPE(int, float)
- CONVTYPE(int, double)
- CONVTYPE(uint, float)
- CONVTYPE(uint, double)
- CONVTYPE(float, double)
- struct convtable {
- int conversion; /* convert flags */
- Error (*convfunc)(); /* convert routine */
- /* parms are: (int count, Pointer from, Pointer to); */
- int hascommon; /* has common representation? */
- Type commontype; /* smallest common representation */
- };
- /* conversion flags */
- #define CONV_ILLEGAL 0 /* types don't convert without truncation */
- #define CONV_ALLOWED 1 /* conversion allowed */
- #define CONV_EQUAL 2 /* types already same */
- #define CONV_NOTIMPL 3 /* type not implemented */
- #define CONV_LOSSY 4 /* conversion may lose precision (not supported) */
- /* table indices for conversion function table */
- #define NUM_TYPES 11
- #define C_BYTE 0
- #define C_UBYTE 1
- #define C_SHORT 2
- #define C_USHORT 3
- #define C_INT 4
- #define C_UINT 5
- #define C_HYPER 6 /* currently unsupported */
- #define C_UHYPER 7 /* currently unsupported */
- #define C_FLOAT 8
- #define C_DOUBLE 9
- #define C_LDOUBLE 10 /* currently unsupported */
- #define TYPE_XXXX TYPE_BYTE /* fill in value for unimplemented types */
- /* hascommon flags */
- #define NO_COMMON 0
- #define HAS_COMMON 1
- static char *typename(Type t)
- {
- switch (t) {
- case TYPE_BYTE: return "byte";
- case TYPE_UBYTE: return "ubyte";
- case TYPE_SHORT: return "short";
- case TYPE_USHORT: return "ushort";
- case TYPE_INT: return "int";
- case TYPE_UINT: return "uint";
- case TYPE_HYPER: return "hyper";
- /* case TYPE_UHYPER: return "uhyper"; */
- case TYPE_FLOAT: return "float";
- case TYPE_DOUBLE: return "double";
- /* case TYPE_LDOUBLE: return "ldouble"; */
- default: return "unknown";
- }
- /* notreached */
- }
- static int typeindex(Type t)
- {
- switch (t) {
- case TYPE_BYTE: return C_BYTE;
- case TYPE_UBYTE: return C_UBYTE;
- case TYPE_SHORT: return C_SHORT;
- case TYPE_USHORT: return C_USHORT;
- case TYPE_INT: return C_INT;
- case TYPE_UINT: return C_UINT;
- case TYPE_HYPER: return C_HYPER;
- /* case TYPE_UHYPER: return C_UHYPER; */
- case TYPE_FLOAT: return C_FLOAT;
- case TYPE_DOUBLE: return C_DOUBLE;
- /* case TYPE_LDOUBLE: return C_LDOUBLE; */
- default: return -1;
- }
- /* notreached */
- }
- static struct convtable typetable[NUM_TYPES][NUM_TYPES] =
- {
- /* from BYTE */ /* to ... */
- { { CONV_EQUAL, NULL, HAS_COMMON, TYPE_BYTE }, /* BYTE */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* UBYTE */
- { CONV_ALLOWED, byte2short, HAS_COMMON, TYPE_SHORT }, /* SHORT */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* USHORT */
- { CONV_ALLOWED, byte2int, HAS_COMMON, TYPE_INT }, /* INT */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
- { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* UHYPER */
- { CONV_ALLOWED, byte2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_ALLOWED, byte2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from UBYTE */ /* to ... */
- { { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* BYTE */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_UBYTE }, /* UBYTE */
- { CONV_ALLOWED, ubyte2short, HAS_COMMON, TYPE_SHORT }, /* SHORT */
- { CONV_ALLOWED, ubyte2ushort, HAS_COMMON, TYPE_USHORT }, /* USHORT */
- { CONV_ALLOWED, ubyte2int, HAS_COMMON, TYPE_INT }, /* INT */
- { CONV_ALLOWED, ubyte2uint, HAS_COMMON, TYPE_UINT }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
- { CONV_ALLOWED, ubyte2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_ALLOWED, ubyte2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from SHORT */ /* to ... */
- { { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_SHORT }, /* BYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_SHORT }, /* UBYTE */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_SHORT }, /* SHORT */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* USHORT */
- { CONV_ALLOWED, short2int, HAS_COMMON, TYPE_INT }, /* INT */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
- { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* UHYPER */
- { CONV_ALLOWED, short2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_ALLOWED, short2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from USHORT */ /* to ... */
- { { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* BYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_USHORT }, /* UBYTE */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* SHORT */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_USHORT }, /* USHORT */
- { CONV_ALLOWED, ushort2int, HAS_COMMON, TYPE_INT }, /* INT */
- { CONV_ALLOWED, ushort2uint, HAS_COMMON, TYPE_UINT }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
- { CONV_ALLOWED, ushort2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_ALLOWED, ushort2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from INT */ /* to ... */
- { { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_INT }, /* BYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_INT }, /* UBYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_INT }, /* SHORT */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_INT }, /* USHORT */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_INT }, /* INT */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
- { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* UHYPER */
- { CONV_ALLOWED, int2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_ALLOWED, int2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from UINT */ /* to ... */
- { { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* BYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_UBYTE }, /* UBYTE */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* SHORT */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_USHORT }, /* USHORT */
- { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* INT */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_UINT }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
- { CONV_ALLOWED, uint2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_ALLOWED, uint2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from HYPER */ /* to ... */
- { { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* BYTE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* UBYTE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* SHORT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* USHORT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* INT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* UINT */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
- { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* UHYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from UHYPER */ /* to ... */
- { { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* BYTE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* UBYTE */
- { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* SHORT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* USHORT */
- { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* INT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* UINT */
- { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* HYPER */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from FLOAT */ /* to ... */
- { { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* BYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* UBYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* SHORT */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* USHORT */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* INT */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_FLOAT }, /* HYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_FLOAT }, /* UHYPER */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
- { CONV_ALLOWED, float2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from DOUBLE */ /* to ... */
- { { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* BYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* UBYTE */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* SHORT */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* USHORT */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* INT */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* HYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* UHYPER */
- { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* FLOAT */
- { CONV_EQUAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- /* from LDOUBLE */ /* to ... */
- { { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* BYTE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UBYTE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* SHORT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* USHORT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* INT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UINT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* HYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* FLOAT */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* DOUBLE */
- { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
- };
- /* these could probably be macro-ized somehow */
- /* THESE MUST WORK INPLACE!!! */
- #define INC(ptr, size) (Pointer)((long)(ptr) + (size))
- #define DEC(ptr, size) (Pointer)((long)(ptr) - (size))
- /* conversion is: a -> a + 0i */
- static Error real2complex(int count, Pointer from, Pointer to, int itemsize)
- {
- int i;
- Pointer efrom, eto;
- efrom = INC(from, itemsize * (count-1));
- eto = INC(to, 2 * itemsize * (count-1));
- for (i=count; i>0; i--) {
- memset(eto, '\0', itemsize);
- eto = DEC(to, itemsize);
- memcpy(efrom, eto, itemsize);
- efrom = DEC(from, itemsize);
- eto = DEC(to, itemsize);
- }
- return OK;
- }
- /* conversion is: a -> a + 0i + 0j + 0k */
- static Error real2quatern(int count, Pointer from, Pointer to, int itemsize)
- {
- int i;
- /*efrom = INC(from, itemsize * (count-1));*/
- /*eto = INC(to, 4 * itemsize * (count-1));*/
- for (i=count; i>0; i--) {
- memset(to, '\0', 3 * itemsize);
- to = DEC(to, 3 * itemsize);
- memcpy(from, to, itemsize);
- from = DEC(from, itemsize);
- to = DEC(to, itemsize);
- }
- return OK;
- }
- /* conversion is: a + bi -> a + bi + 0j + 0k */
- static Error complex2quatern(int count, Pointer from, Pointer to, int itemsize)
- {
- int i;
- /*efrom = INC(from, itemsize * (count-1));*/
- /*eto = INC(from, 2 * itemsize * (count-1));*/
- for (i=count; i>0; i--) {
- memset(to, '\0', itemsize);
- to = DEC(to, itemsize);
- memcpy(from, to, itemsize);
- from = DEC(from, itemsize);
- to = DEC(to, itemsize);
- }
- return OK;
- }
- struct convtable2 {
- int conversion;
- Error (*convfunc)(int count, Pointer from, Pointer to, int itemsize);
- int hascommon;
- Category commoncat;
- };
- /* (uses same conversion flags as above) */
- #define NUM_CATS 3
- #define C_REAL 0
- #define C_COMPLEX 1
- #define C_QUATERN 2
- static char *catname(Category c)
- {
- switch (c) {
- case CATEGORY_REAL: return "real";
- case CATEGORY_COMPLEX: return "complex";
- case CATEGORY_QUATERNION: return "quaternion";
- default: return "unknown";
- }
- /* notreached */
- }
- static int catindex(Category c)
- {
- switch (c) {
- case CATEGORY_REAL: return C_REAL;
- case CATEGORY_COMPLEX: return C_COMPLEX;
- case CATEGORY_QUATERNION: return C_QUATERN;
- default: return -1;
- }
- /* notreached */
- }
- static struct convtable2 cattable[NUM_CATS][NUM_CATS] =
- {
- /* from REAL */ /* to ... */
- { { CONV_EQUAL, NULL, HAS_COMMON, CATEGORY_REAL }, /* REAL */
- { CONV_ALLOWED, real2complex, HAS_COMMON, CATEGORY_COMPLEX }, /* COMPLEX */
- { CONV_ALLOWED, real2quatern, HAS_COMMON, CATEGORY_QUATERNION }, }, /* QUATERN */
- /* from COMPLEX */ /* to ... */
- { { CONV_ILLEGAL, NULL, HAS_COMMON, CATEGORY_COMPLEX }, /* REAL */
- { CONV_EQUAL, NULL, HAS_COMMON, CATEGORY_COMPLEX }, /* COMPLEX */
- { CONV_ALLOWED, complex2quatern, HAS_COMMON, CATEGORY_QUATERNION }, }, /* QUATERN */
- /* from QUATERN */ /* to ... */
- { { CONV_ILLEGAL, NULL, HAS_COMMON, CATEGORY_QUATERNION }, /* REAL */
- { CONV_ILLEGAL, NULL, HAS_COMMON, CATEGORY_QUATERNION }, /* COMPLEX */
- { CONV_EQUAL, NULL, HAS_COMMON, CATEGORY_QUATERNION }, }, /* QUATERN */
- };
- /* this modifies shape in place to squeeze out shapes of 1
- * (e.g. rank 3, shape 3 1 4 -> rank 2 shape 3 4)
- */
- static void SqueezeShape(int *rank, int *shape)
- {
- int i, j;
- i = 0;
- while (i < *rank) {
- if (shape[i] > 1)
- i++;
- else {
- (*rank)--;
- for (j=i; j<*rank; j++)
- shape[j] = shape[j+1];
- }
- }
-
- }
- /* this checks to see if it can squeeze the first rank/shape pair
- * to match the second, and if it can, it modifies them in place
- * and returns OK. otherwise it leaves them alone and returns ERROR
- * and sets the error code.
- * if it has to expand to match, it adds shape 1 at the end of the list.
- *
- * this routine isn't done yet.
- */
- #if 0
- static Error SqueezeToShape(int *rank, int *shape, int trank, int *tshape)
- {
- int i, j;
- i = 0;
- while (i < *rank) {
- if (shape[i] > 1)
- i++;
- else {
- (*rank)--;
- for (j=i; j<*rank; j++)
- shape[j] = shape[j+1];
- }
- }
- return ERROR;
- }
- #endif
- static Error
- ConvertArrayContents(Array from, Array to, int squeeze)
- {
- int i;
- int fi, ti;
- Pointer fromdp, todp;
- int count;
- int fromcount, tocount;
- Type fromtype, totype;
- Category fromcat, tocat;
- int fromrank, torank;
- int fromshape[100], toshape[100];
- DXGetArrayInfo(from, &fromcount, &fromtype, &fromcat, &fromrank, fromshape);
- DXGetArrayInfo(to, &tocount, &totype, &tocat, &torank, toshape);
- if (fromcount != tocount)
- DXErrorReturn(ERROR_DATA_INVALID, "array sizes don't match");
- /* squeeze out shapes of 1 from both and make sure they match. */
- if (squeeze) {
- SqueezeShape(&fromrank, fromshape);
- SqueezeShape(&torank, toshape);
- }
- if (fromrank != torank) {
- if (squeeze)
- DXErrorReturn(ERROR_DATA_INVALID, "data ranks don't match");
- return ConvertArrayContents(from, to, 1);
- }
- for (i=0; i<fromrank; i++)
- if (fromshape[i] != toshape[i]) {
- if (squeeze)
- DXErrorReturn(ERROR_DATA_INVALID, "data shapes don't match");
- return ConvertArrayContents(from, to, 1);
- }
- if (((fi = typeindex(fromtype)) < 0) || ((ti = typeindex(totype)) < 0))
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
-
- fromdp = DXGetArrayData(from);
- todp = DXGetArrayData(to);
- switch (typetable[fi][ti].conversion) {
- case CONV_EQUAL:
- memcpy(todp, fromdp, fromcount * DXGetItemSize(from));
- break;
-
- case CONV_ALLOWED:
- count = fromcount * (DXGetItemSize(from) / DXTypeSize(fromtype));
- if ((typetable[fi][ti].convfunc)(count, fromdp, todp) == ERROR)
- DXErrorReturn(ERROR_DATA_INVALID, "type conversion failed");
-
- break;
-
- case CONV_NOTIMPL:
- default:
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
-
- case CONV_ILLEGAL:
- case CONV_LOSSY:
- DXSetError(ERROR_DATA_INVALID, "cannot convert %s to %s",
- typename(fromtype), typename(totype));
- return ERROR;
-
- }
-
- if (((fi = catindex(fromcat)) < 0) || ((ti = catindex(tocat)) < 0))
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
-
- switch (cattable[fi][ti].conversion) {
- case CONV_EQUAL:
- break;
-
- case CONV_ALLOWED:
- count = fromcount * (DXGetItemSize(from) / DXCategorySize(fromcat));
- if ((cattable[fi][ti].convfunc)(count, todp, todp,
- DXGetItemSize(from)) == ERROR)
- DXErrorReturn(ERROR_DATA_INVALID, "category conversion failed");
-
- break;
-
- case CONV_NOTIMPL:
- default:
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
-
- case CONV_ILLEGAL:
- case CONV_LOSSY:
- DXSetError(ERROR_NOT_IMPLEMENTED, "cannot convert %s to %s",
- catname(fromcat), catname(tocat));
- return ERROR;
- }
- return OK;
- }
- static Array
- ArrayConvert(Array a, Type t, Category c, int rank, int *shape)
- {
- int i;
- Array out;
- ASSERT(rank<100);
- out = DXNewArrayV(t, c, rank, shape);
-
- DXGetArrayInfo(a, &i, NULL, NULL, NULL, NULL);
- if (!DXAddArrayData(out, 0, i, NULL))
- return NULL;
- if (!ConvertArrayContents(a, out, 0)) {
- DXDelete((Object)out);
- return NULL;
- }
- return out;
- }
- Array
- DXArrayConvert(Array a, Type t, Category c, int rank, ... )
- {
- int i;
- int shape[100];
- va_list arg;
- ASSERT(rank<100);
- /* collect args */
- va_start(arg,rank); /* no spaces allowed - this is a weird macro */
- for (i=0; i<rank; i++)
- shape[i] = va_arg(arg, int);
- va_end(arg);
- /* common code with V version. */
- return ArrayConvert(a, t, c, rank, shape);
- }
- Array
- DXArrayConvertV(Array a, Type t, Category c, int rank, int *shape)
- {
- return ArrayConvert(a, t, c, rank, shape);
- }
- /* sees if there is a common format and returns it. otherwise returns
- * NULL but and sets error code.
- */
- static Error
- QueryArrayCommon(Type *t, Category *c, int *rank, int *shape, int n,
- Array *a, int squeeze)
- {
- int i, j;
- int ni, cti, cci;
- Type nextt, comt;
- Category nextc, comc;
- int nextrank, comrank;
- int nextshape[100], comshape[100];
- ASSERT(n<100);
- if (n <= 0) {
- DXSetError(ERROR_DATA_INVALID,
- "array list count must be a positive integer");
- return ERROR;
- }
- if (!DXGetArrayInfo(a[0], NULL, &comt, &comc, &comrank, comshape))
- return ERROR;
- if (squeeze)
- SqueezeShape(&comrank, comshape);
-
- /* if the values don't match, see if they are compatible, and use
- * the minimum necessary changes.
- */
- for (i=1; i<n; i++) {
- if (!DXGetArrayInfo(a[i], NULL, &nextt, &nextc, &nextrank, nextshape))
- return ERROR;
-
- /* data type */
- if (comt != nextt) {
- if ((cti = typeindex(comt)) < 0)
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
-
- if ((ni = typeindex(nextt)) < 0)
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
-
- switch (typetable[cti][ni].hascommon) {
- case HAS_COMMON:
- comt = typetable[cti][ni].commontype;
- break;
-
- case NO_COMMON:
- DXSetError(ERROR_DATA_INVALID, "no common format for %s and %s",
- typename(comt), typename(nextt));
- return ERROR;
- }
-
- }
- /* data category */
- if (comc != nextc) {
- if ((cci = catindex(comc)) < 0)
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
-
- if ((ni = catindex(nextc)) < 0)
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
-
- switch (cattable[cci][ni].hascommon) {
- case HAS_COMMON:
- comc = cattable[cci][ni].commoncat;
- break;
-
- case NO_COMMON:
- DXSetError(ERROR_DATA_INVALID, "no common format for %s and %s",
- catname(comc), catname(nextc));
- return ERROR;
- }
- }
-
- /* data rank - squeeze out shapes of 1 */
- if (squeeze)
- SqueezeShape(&nextrank, nextshape);
-
- if (comrank != nextrank) {
- if (squeeze) {
- DXSetError(ERROR_DATA_INVALID,
- "data rank does not match (%d != %d)",
- comrank, nextrank);
- return ERROR;
- }
- return QueryArrayCommon(t, c, rank, shape, n, a, 1);
- }
- for (j=0; j<comrank; j++) {
- if (comshape[j] != nextshape[j]) {
- if (squeeze) {
- DXSetError(ERROR_DATA_INVALID,
- "data shape %d does not match (%d != %d)",
- j, comshape[j], nextshape[j]);
-
- return ERROR;
- }
-
- return QueryArrayCommon(t, c, rank, shape, n, a, 1);
- }
-
- }
- }
- /* ok - finally. return the results */
- if (t)
- *t = comt;
- if (c)
- *c = comc;
- if (rank)
- *rank = comrank;
- if (shape) {
- for (i=0; i<comrank; i++)
- shape[i] = comshape[i];
- }
- return OK;
- }
- Error
- DXQueryArrayCommon(Type *t, Category *c, int *rank, int *shape,
- int n, Array a, ...)
- {
- int i;
- Array alist[100];
- va_list arg;
- ASSERT(n<100);
- /* collect args */
- va_start(arg,a); /* no spaces allowed - this is a weird macro */
- for (i=0; i<n; i++)
- alist[i] = va_arg(arg, Array);
- va_end(arg);
- /* common code with V version. */
- return QueryArrayCommon(t, c, rank, shape, n, alist, 0);
- }
- Error
- DXQueryArrayCommonV(Type *t, Category *c, int *rank, int *shape,
- int n, Array *alist)
- {
- return QueryArrayCommon(t, c, rank, shape, n, alist, 0);
- }
- /* sees if the array can be converted to the requested format.
- * should this set the error code?? (it does right now)
- */
- static Error
- QueryArrayConvert(Array a, Type t, Category c, int rank, int *shape, int squeeze)
- {
- int i;
- int ai, rti, rci;
- Type at;
- Category ac;
- int arank;
- int ashape[100], rshape[100];
- if (!DXGetArrayInfo(a, NULL, &at, &ac, &arank, ashape))
- return ERROR;
- /* data type */
- if (at != t) {
- if ((rti = typeindex(t)) < 0)
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
-
- if ((ai = typeindex(at)) < 0)
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
-
- switch (typetable[ai][rti].conversion) {
- case CONV_EQUAL:
- case CONV_ALLOWED:
- break;
-
- default:
- DXSetError(ERROR_DATA_INVALID, "cannot convert type %s into %s",
- typename(at), typename(t));
- return ERROR;
- }
- }
-
- /* data category */
- if (ac != c) {
- if ((rci = catindex(c)) < 0)
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
-
- if ((ai = catindex(ac)) < 0)
- DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
-
- switch (cattable[ai][rci].conversion) {
- case CONV_EQUAL:
- case CONV_ALLOWED:
- break;
-
- default:
- DXSetError(ERROR_DATA_INVALID, "cannot convert category %s into %s",
- catname(ac), catname(c));
- return ERROR;
- }
-
- }
- /* get rid of 1's */
- if (squeeze) {
- SqueezeShape(&arank, ashape);
- for (i=0; i<rank; i++)
- rshape[i] = shape[i];
- SqueezeShape(&rank, rshape);
- }
-
- if (arank != rank) {
- if (squeeze) {
- DXSetError(ERROR_DATA_INVALID, "data rank does not match (%d > %d)",
- arank, rank);
- return ERROR;
- }
- return QueryArrayConvert(a, t, c, rank, shape, 1);
- }
-
- /* data rank and shape */
- for (i=0; i<rank; i++)
- if (shape[i] != rshape[i]) {
- if (squeeze) {
- DXSetError(ERROR_DATA_INVALID,
- "data shape does not match (%d != %d)",
- shape[i], ashape[i]);
-
- return ERROR;
- }
-
- return QueryArrayConvert(a, t, c, rank, shape, 1);
- }
- return OK;
- }
- Error
- DXQueryArrayConvert(Array a, Type t, Category c, int rank, ...)
- {
- int i;
- int shape[100];
- va_list arg;
- ASSERT(rank<100);
- /* collect args */
- va_start(arg,rank); /* no spaces allowed - this is a weird macro */
- for (i=0; i<rank; i++)
- shape[i] = va_arg(arg, int);
- va_end(arg);
- /* common code with V version. */
- return QueryArrayConvert(a, t, c, rank, shape, 0);
- }
- Error
- DXQueryArrayConvertV(Array a, Type t, Category c, int rank, int *shape)
- {
- return QueryArrayConvert(a, t, c, rank, shape, 0);
- }
- #define MAXDIM 32
- /* type check an object, and return the number if a list.
- */
- Object DXQueryParameter(Object o, Type t, int dim, int *count)
- {
- int nitems;
- Type at;
- Category ac;
- int ar, as[MAXDIM];
- /* assume the worst */
- if(count)
- *count = 0;
- if(!o)
- return NULL;
- /* slightly special case for char arrays, which might come in
- * as string objects.
- */
- if ((t == TYPE_STRING) && (DXGetObjectClass(o) == CLASS_STRING)) {
-
- char *cp = DXGetString((String)o);
-
- if(!cp || dim > 1)
- return NULL;
-
- if(dim == 0 && strlen(cp) > 1)
- return NULL;
-
- if(count)
- *count = strlen(cp);
-
- return o;
- }
-
- /* check general characteristics first, before worrying about
- * specific data types
- */
- if( DXGetObjectClass(o) != CLASS_ARRAY
- || !DXGetArrayInfo((Array)o, &nitems, &at, &ac, &ar, as)
- || ac != CATEGORY_REAL
- || ar > 1
- || nitems == 0)
- return NULL;
-
- /* don't do these checks for strings */
- if (at != TYPE_STRING) {
- /* if dim > 1, rank must be 1 and shape must match dim.
- * dim 0 or 1 both match rank 1 shape 1 and rank 0
- */
- if(dim > 1) {
- if(ar != 1 || as[0] != dim)
- return NULL;
- } else {
- if(ar > 1 || (ar == 1 && as[0] != 1))
- return NULL;
- }
- }
-
- if(count)
- *count = nitems;
- /* if types match exactly, you're done */
- if(at == t)
- return o;
- /* see if the types could be promoted ok. 'at' is the actual
- * array type, 't' is what they want.
- */
- if (dim == 0) {
- if (DXQueryArrayConvert((Array)o, t, CATEGORY_REAL, 0) == OK)
- return o;
- } else {
- if (DXQueryArrayConvert((Array)o, t, CATEGORY_REAL, 1, dim) == OK)
- return o;
- }
- DXResetError();
- return NULL;
- }
- /* given an object, and a caller-allocated buffer, copy the input
- * to the buffer, converting type if necessary.
- */
- Object DXExtractParameter(Object o, Type t, int dim, int count, Pointer p)
- {
- Array na;
- char *sp;
- int nitems;
- Type at;
- Category ac;
- int ar, as[MAXDIM];
- if(!o)
- return NULL;
- /* slightly special case for string arrays, which might come in
- * as string objects.
- */
- if(t == TYPE_STRING && DXGetObjectClass(o) == CLASS_STRING) {
- sp = DXGetString((String)o);
- if(!sp || dim > 1)
- return NULL;
- if(dim == 0 && strlen(sp) > 1)
- return NULL;
- if(count != strlen(sp))
- return NULL;
- if (p)
- strcpy((char *)p, sp);
- return o;
- }
-
- /* check general characteristics first, before worrying about
- * specific data types
- */
- if( DXGetObjectClass(o) != CLASS_ARRAY
- || !DXGetArrayInfo((Array)o, &nitems, &at, &ac, &ar, as)
- || ac != CATEGORY_REAL
- || ar > 1
- || nitems == 0
- || nitems != count)
- return NULL;
- /* if dim > 1, rank must be 1 and shape must match dim.
- * dim 0 or 1 both match rank 1 shape 1 and rank 0
- */
- if(dim > 1) {
- if(ar != 1 || as[0] != dim)
- return NULL;
- } else {
- if(ar > 1 || (ar == 1 && as[0] != 1))
- return NULL;
- }
- /* if types match exactly, just memcpy the number of bytes and return */
- if(at == t) {
- if (p)
- memcpy(p, DXGetArrayData((Array)o),
- nitems * DXGetItemSize((Array)o));
- return o;
- }
- /* types don't match exactly, so see if they can be converted.
- */
- if (dim == 0)
- na = DXArrayConvert((Array)o, t, CATEGORY_REAL, 0);
- else
- na = DXArrayConvert((Array)o, t, CATEGORY_REAL, 1, dim);
- if (!na) {
- DXResetError();
- return NULL;
- }
- if (p)
- memcpy(p, DXGetArrayData(na), nitems * DXGetItemSize(na));
- DXDelete((Object)na);
- return o;
- }