/***********************************************************************/ /* 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 #include "dx/dx.h" #include "cat.h" static Error traverse(Object *, Object *); static Error doLeaf(Object *, Object *); static Error init_lookup(lookupinfo *ls); static Error do_lookup(lookupinfo *ls); static int get_int(catinfo *cp, char *s); Error m_Lookup(Object *in, Object *out) { int i; out[0] = NULL; if (in[0] == NULL) { DXSetError(ERROR_MISSING_DATA, "\"input\" must be specified"); return ERROR; } out[0] = DXCopy((Object)in[0], COPY_STRUCTURE); if (!traverse(in, out)) goto error; return OK; error: for (i = 0; i < 1; i++) { if (in[i] != out[i]) DXDelete(out[i]); out[i] = NULL; } return ERROR; } static Error traverse(Object *in, Object *out) { switch(DXGetObjectClass(in[0])) { case CLASS_FIELD: case CLASS_ARRAY: case CLASS_STRING: if (! doLeaf(in, out)) return ERROR; return OK; case CLASS_GROUP: { int i, j; int memknt; Category c; Type t; int rank; int shape[32]; Class groupClass = DXGetGroupClass((Group)in[0]); DXGetMemberCount((Group)in[0], &memknt); for (i = 0; i < memknt; i++) { Object new_in[7], new_out[1]; if (in[0]) new_in[0] = DXGetEnumeratedMember((Group)in[0], i, NULL); else new_in[0] = NULL; new_in[1] = in[1]; new_in[2] = in[2]; new_in[3] = in[3]; new_in[4] = in[4]; new_in[5] = in[5]; new_in[6] = in[6]; if (groupClass != CLASS_GROUP) { if (i == 0) { DXDelete((Object)out[0]); switch (groupClass) { case CLASS_SERIES: out[0] = (Group)DXNewSeries(); break; case CLASS_MULTIGRID: out[0] = (Group)DXNewMultiGrid(); break; case CLASS_COMPOSITEFIELD: out[0] = (Group)DXNewCompositeField(); break; default: return ERROR; } } new_out[0] = DXCopy((Object)new_in[0], COPY_STRUCTURE); if (! traverse(new_in, new_out)) return ERROR; if (i == 0) { if (! DXGetType((Object)new_out[0], &t, &c, &rank, shape)) return ERROR; if (! DXSetGroupTypeV((Group)out[0], t, c, rank, shape)) return ERROR; } } else { new_out[0] = DXGetEnumeratedMember((Group)out[0], i, NULL); if (! traverse(new_in, new_out)) return ERROR; } if (! DXSetEnumeratedMember((Group)out[0], i, new_out[0])) return ERROR; } return OK; } case CLASS_XFORM: { int i, j; Object new_in[7], new_out[1]; if (in[0]) DXGetXformInfo((Xform)in[0], &new_in[0], NULL); else new_in[0] = NULL; new_in[1] = in[1]; new_in[2] = in[2]; new_in[3] = in[3]; new_in[4] = in[4]; new_in[5] = in[5]; new_in[6] = in[6]; DXGetXformInfo((Xform)out[0], &new_out[0], NULL); if (! traverse(new_in, new_out)) return ERROR; DXSetXformObject((Xform)out[0], new_out[0]); return OK; } case CLASS_CLIPPED: { int i, j; Object new_in[7], new_out[1]; if (in[0]) DXGetClippedInfo((Clipped)in[0], &new_in[0], NULL); else new_in[0] = NULL; new_in[1] = in[1]; new_in[2] = in[2]; new_in[3] = in[3]; new_in[4] = in[4]; new_in[5] = in[5]; new_in[6] = in[6]; DXGetClippedInfo((Clipped)out[0], &new_out[0], NULL); if (! traverse(new_in, new_out)) return ERROR; DXSetClippedObjects((Clipped)out[0], new_out[0], NULL); return OK; } error: { DXSetError(ERROR_BAD_CLASS, "input must be Field or Group"); return ERROR; } } } static int doLeaf(Object *in, Object *out) { int i, result=0; Field field; int rank, shape[30]; Object attr, src_dependency_attr = NULL; Object table; Category category; char *src_dependency = NULL; char *cat_comp; char *data_comp; char *lookup_comp; char *value_comp; char *dest_comp; char *table_comp; float *data_data; Array input_array = NULL; Array array = NULL; Array table_array = NULL; Array lookup_array = NULL; Array value_array = NULL; float *out_data; int data_knt, cat_knt; int out_knt; Type cat_type, data_type; float floatmax; char value_str[200]; catinfo cat_data; catinfo cat_lookup; catinfo cat_value; catinfo cat_dest; lookupinfo look; char *ignore; int free_value = 0; int free_input = 0; Class in_class; Class in_data_class; char *str; memset(&cat_data, 0, sizeof(catinfo)); memset(&cat_lookup, 0, sizeof(catinfo)); memset(&cat_value, 0, sizeof(catinfo)); memset(&cat_dest, 0, sizeof(catinfo)); memset(&look, 0, sizeof(lookupinfo)); look.data = &cat_data; look.lookup = &cat_lookup; look.value = &cat_value; look.dest = &cat_dest; in_class = DXGetObjectClass((Object)in[0]); if (in_class == CLASS_FIELD) { field = (Field)in[0]; if (DXEmptyField(field)) return OK; } if (!DXExtractString((Object)in[2], &data_comp)) data_comp = STR_DATA; if (!DXExtractString((Object)in[3], &lookup_comp)) lookup_comp = STR_POSITIONS; if (!DXExtractString((Object)in[4], &value_comp)) { value_comp = STR_DATA; } if (!DXExtractString((Object)in[5], &dest_comp)) dest_comp = "lookedup"; for (i=0; DXExtractNthString((Object)in[6], i, &ignore); i++) { if (!strcmp(ignore, "none")) { } else if (!strcmp(ignore, "case")) { look.ignore |= CAT_I_CASE; } else if (!strcmp(ignore, "space")) { look.ignore |= CAT_I_SPACE; } else if (!strcmp(ignore, "lspace")) { look.ignore |= CAT_I_LSPACE; } else if (!strcmp(ignore, "rspace")) { look.ignore |= CAT_I_RSPACE; } else if (!strcmp(ignore, "lrspace")) { look.ignore |= CAT_I_LRSPACE; } else if (!strcmp(ignore, "punctuation")) { look.ignore |= CAT_I_PUNCT; } else { DXSetError(ERROR_BAD_PARAMETER, "ignore value \"%s\" must be one of" "none, case, space, lspace, rspace, lrspace, punctuation", ignore); goto error; } } if (look.ignore & CAT_I_SPACE) look.ignore &= ~(CAT_I_LSPACE | CAT_I_RSPACE | CAT_I_LRSPACE); if ((look.ignore & CAT_I_LSPACE) && (look.ignore & CAT_I_RSPACE)) look.ignore |= CAT_I_LRSPACE; if (look.ignore & CAT_I_LRSPACE) look.ignore &= ~(CAT_I_LSPACE | CAT_I_RSPACE); if (in_class == CLASS_STRING) { DXExtractString((Object)in[0], &str); input_array = DXNewArray(TYPE_STRING, CATEGORY_REAL, 1, strlen(str)+1); DXAddArrayData(input_array, 0, 1, str); in_class = CLASS_ARRAY; free_input = 1; } else if (in_class == CLASS_ARRAY) { input_array = (Array)in[0]; } else { input_array = (Array)DXGetComponentValue((Field)in[0], data_comp); } if (! input_array) { DXSetError(ERROR_MISSING_DATA, "\"input\" has no \"%s\" component", data_comp); goto error; } in_data_class = DXGetObjectClass((Object)input_array); if (in_data_class != CLASS_ARRAY && in_data_class != CLASS_STRING) { DXSetError(ERROR_BAD_CLASS, "component \"%s\" of \"input\" must be an array", data_comp); goto error; } if (in[1] == NULL) { if (in_class != CLASS_FIELD) { DXSetError(ERROR_BAD_PARAMETER, "table compononent must be supplied if input is an array"); goto error; } if (!strcmp(lookup_comp, STR_POSITIONS)) { sprintf(value_str, "%s lookup", data_comp); value_comp = value_str; value_array = (Array)DXGetComponentValue((Field)in[0], value_comp); if (!value_array) { DXSetError(ERROR_BAD_PARAMETER, "table component \"%s\" not found in input", value_str); goto error; } } else { sprintf(value_str, "%s lookup", data_comp); value_comp = value_str; lookup_array = (Array)DXGetComponentValue((Field)in[0], value_comp); if (!lookup_array) { DXSetError(ERROR_BAD_PARAMETER, "table component \"%s\" not found in input", value_str); goto error; } } } else if (DXExtractString((Object)in[1], &table_comp)) { if (in_class != CLASS_FIELD) { DXSetError(ERROR_BAD_PARAMETER, "table compononent must be supplied if input is an array"); goto error; } if (!strcmp(lookup_comp, STR_POSITIONS)) { value_array = (Array)DXGetComponentValue((Field)in[0], table_comp); if (!value_array) { DXSetError(ERROR_BAD_PARAMETER, "table component \"%s\" not found in input", table_comp); goto error; } } else { lookup_array = (Array)DXGetComponentValue((Field)in[0], table_comp); if (!lookup_array) { DXSetError(ERROR_BAD_PARAMETER, "table component \"%s\" not found in input", table_comp); goto error; } } } else if (DXGetObjectClass((Object)in[1]) == CLASS_ARRAY) { if (!strcmp(value_comp, STR_DATA)) value_array = (Array)in[1]; else lookup_array = (Array)in[1]; } else if (DXGetObjectClass((Object)in[1]) == CLASS_FIELD) { value_array = (Array)DXGetComponentValue((Field)in[1], value_comp); if (!value_array) { DXSetError(ERROR_BAD_PARAMETER, "value component \"%s\" not found in input", value_comp); goto error; } lookup_array = (Array)DXGetComponentValue((Field)in[1], lookup_comp); if (!lookup_array) { DXSetError(ERROR_BAD_PARAMETER, "lookup component \"%s\" not found in input", lookup_comp); goto error; } } /* if lookup_array not present, doing implicit lookup */ if (!lookup_array) { DXGetArrayInfo(input_array, &data_knt, &data_type, &category, &rank, shape); if ( (data_type != TYPE_BYTE && data_type != TYPE_UBYTE && data_type != TYPE_INT && data_type != TYPE_UINT && data_type != TYPE_FLOAT) || category != CATEGORY_REAL || !((rank == 0) || ((rank == 1)&&(shape[0] == 1)))) { DXSetError(ERROR_INVALID_DATA, "data component \"%s\" must be scalar integer or float " "if lookup is based on implicit index", data_comp); goto error; } } look.data->o = (Object)input_array; _dxf_cat_FindCompType(look.data); if (lookup_array) { look.lookup->o = (Object)lookup_array; _dxf_cat_FindCompType(look.lookup); } else { /* if no lookup_array, we already know data is an integer type */ memcpy(look.lookup, look.data, sizeof(catinfo)); } if (value_array) { look.value->o = (Object)value_array; _dxf_cat_FindCompType(look.value); } else { int i; int *p; look.value->o = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0); value_array = (Array)look.value->o; look.value->num = look.lookup->num; DXAddArrayData((Array)look.value->o, 0, look.value->num, NULL); p = (int *)DXGetArrayData((Array)look.value->o); for (i=0; inum; i++) p[i] = i; _dxf_cat_FindCompType(look.value); free_value = 1; } if ((look.data->cat_type != look.lookup->cat_type) || ((look.data->cat_type != CAT_STRING) && ((look.data->obj_size != look.lookup->obj_size) && (look.data->cat_type != CAT_SCALAR)))) { DXSetError(ERROR_INVALID_DATA, "data component type does not match lookup component"); goto error; } memcpy(look.dest, look.value, sizeof(catinfo)); DXGetArrayInfo(value_array, &data_knt, &data_type, &category, &rank, shape); look.dest->comp_array = (Array)DXNewArrayV(data_type, category, rank, shape); DXAddArrayData(look.dest->comp_array, 0, look.data->num, NULL); look.dest->comp_data = DXGetArrayData((Array)(look.dest->comp_array)); DXCopyAttributes((Object)look.dest->comp_array, (Object)input_array); if (lookup_array) look.lut = (table_entry *)DXAllocate(look.value->num * sizeof(table_entry)); init_lookup(&look); result = do_lookup(&look); if (! result) { if (DXGetError()==ERROR_NONE) DXSetError(ERROR_INTERNAL, "error return from user routine"); goto error; } if (free_input) { DXDelete((Object)input_array); input_array = NULL; } if (free_value) { DXDelete((Object)look.value->o); look.value->o = NULL; } if (look.ignore && look.data->free_data && look.data->comp_data) DXFree(look.data->comp_data); look.data->comp_data = NULL; if (look.ignore && look.lookup->free_data && look.lookup->comp_data) DXFree(look.lookup->comp_data); look.data->comp_data = NULL; if (!out[0]) { out[0] = DXCopy(in[0], COPY_STRUCTURE); } if (DXGetObjectClass((Object)in[0]) == CLASS_FIELD) { if (DXGetComponentValue((Field)out[0], dest_comp)) DXDeleteComponent((Field)out[0], dest_comp); if (! DXSetComponentValue((Field)out[0], dest_comp, (Object)look.dest->comp_array)) goto error; DXChangedComponentValues((Field)out[0], dest_comp); result = (int)DXEndField((Field)out[0]); } else { out[0] = (Object)look.dest->comp_array; result = OK; } return result; error: if (free_input) DXDelete((Object)input_array); if (free_value) DXDelete((Object)look.value->o); if (look.dest->comp_array) DXDelete((Object)look.dest->comp_array); look.dest->comp_array = NULL; if (look.ignore && look.data->free_data && look.data->comp_data) DXFree(look.data->comp_data); look.data->comp_data = NULL; if (look.ignore && look.lookup->free_data && look.lookup->comp_data) DXFree(look.lookup->comp_data); look.data->comp_data = NULL; return result; } static int lookupcmp(table_entry *t1, table_entry *t2) { return t1->cp->cmpcat(t1->cp, t1->lookup, t2->lookup); } static int searchcmp(char *s, table_entry *t) { return t->cp->cmpcat(t->cp, s, t->lookup); } static int get_int(catinfo *cp, char *s) { switch(cp->comp_type) { case TYPE_INT: return (int)(*((int *)s)); case TYPE_UBYTE: return (int)(*((ubyte *)s)); case TYPE_FLOAT: return (int)(*((float *)s) + 0.5); case TYPE_BYTE: return (int)(*s); case TYPE_SHORT: return (int)(*((short *)s)); case TYPE_USHORT: return (int)(*((ushort *)s)); case TYPE_UINT: return (int)(*((uint *)s)); case TYPE_DOUBLE: return (int)(*((double *)s) + 0.5); default: return (int)(*((int *)s)); } } static float get_float(catinfo *cp, char *s) { switch(cp->comp_type) { case TYPE_INT: return (float)(*((int *)s)); case TYPE_UBYTE: return (float)(*((ubyte *)s)); case TYPE_FLOAT: return (float)(*((float *)s)); case TYPE_BYTE: return (float)(*s); case TYPE_SHORT: return (float)(*((short *)s)); case TYPE_USHORT: return (float)(*((ushort *)s)); case TYPE_UINT: return (float)(*((uint *)s)); case TYPE_DOUBLE: return (float)(*((double *)s)); default: return (float)(*((int *)s)); } } static Error init_lookup(lookupinfo *l) { int i; char *s, *t; table_entry *lut; char *d; float *f; int *p; int size; int num; if (!l->lut) return OK; if (l->ignore && l->data->cat_type == CAT_STRING) { d = (char *)l->data->comp_data; l->data->comp_data = (Pointer)DXAllocate(l->data->obj_size * l->data->num); l->data->free_data = 1; size = l->data->obj_size; num = l->data->num; for (i=0, s=d, t=(char *)l->data->comp_data; iignore); } d = (char *)l->lookup->comp_data; l->lookup->comp_data = (Pointer)DXAllocate(l->lookup->obj_size * l->lookup->num); l->lookup->free_data = 1; size = l->lookup->obj_size; num = l->lookup->num; for (i=0, s=d, t=(char *)l->lookup->comp_data; iignore); } } if (l->data->cat_type == CAT_SCALAR && l->data->comp_type != l->lookup->comp_type) { if (l->data->comp_type == TYPE_FLOAT || l->lookup->comp_type == TYPE_FLOAT) { if (l->data->comp_type == TYPE_FLOAT) { d = (char *) l->lookup->comp_data; l->lookup->comp_data = (Pointer)DXAllocate(sizeof(float) * l->lookup->num); l->lookup->free_data = 1; f = (float *) l->lookup->comp_data; size = l->lookup->obj_size; num = l->lookup->num; for (i=0; ilookup, d); l->lookup->comp_type = TYPE_FLOAT; l->lookup->obj_size = sizeof(float); } else { d = (char *) l->data->comp_data; l->data->comp_data = (Pointer)DXAllocate(sizeof(float) * l->data->num); l->data->free_data = 1; f = (float *) l->data->comp_data; size = l->data->obj_size; num = l->data->num; for (i=0; idata, d); l->data->comp_type = TYPE_FLOAT; l->data->obj_size = sizeof(float); } } else { if (l->lookup->comp_type != TYPE_INT) { d = (char *) l->lookup->comp_data; l->lookup->comp_data = (Pointer)DXAllocate(sizeof(int) * l->lookup->num); l->lookup->free_data = 1; p = (int *) l->lookup->comp_data; size = l->lookup->obj_size; num = l->lookup->num; for (i=0; ilookup, d); l->lookup->comp_type = TYPE_INT; l->lookup->obj_size = sizeof(int); } if (l->data->comp_type != TYPE_INT) { d = (char *) l->data->comp_data; l->data->comp_data = (Pointer)DXAllocate(sizeof(int) * l->data->num); l->data->free_data = 1; p = (int *) l->data->comp_data; size = l->data->obj_size; num = l->data->num; for (i=0; idata, d); l->data->comp_type = TYPE_INT; l->data->obj_size = sizeof(int); } } } s = (char *)l->lookup->comp_data; t = (char *)l->value->comp_data; for (i=0, lut=l->lut; ilookup->num; i++, lut++) { lut->lookup = (Pointer)s; lut->value = (Pointer)t; lut->cp = l->lookup; s += l->lookup->obj_size; t += l->value->obj_size; } qsort(l->lut, l->value->num, sizeof(table_entry), lookupcmp); return OK; } static Error do_lookup(lookupinfo *l) { int i; char *s, *v; table_entry *lut; table_entry *found; int num = l->data->num; int size = l->value->obj_size; int datasize = l->data->obj_size; int n; s = (char *)l->data->comp_data; v = (char *)l->dest->comp_data; if (l->lut) { for (i=0; ilut, l->lookup->num, sizeof(table_entry), searchcmp); if (found) { memcpy(v, (char *)found->value, size); } else { memset(v, 0, size); } } } else { for (i=0; idata, s); if (n >= 0 && n < l->value->num) { memcpy(v, (char *)(&(((char *)(l->value->comp_data))[n*size])), size); } else { memset(v, 0, size); } } } return OK; }