/***********************************************************************/ /* 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 #include "fieldClass.h" #include "internals.h" static Field _CopyField(Field new, Field old, enum copy copy); static Field _NewField(struct field_class *class) { Field f = (Field) _dxf_NewObject((struct object_class *)class); if (!f) return NULL; f->components = f->local; f->ncomponents = 0; f->comp_alloc = NCOMPONENTS; return f; } Field DXNewField() { return _NewField(&_dxdfield_class); } Object _dxfField_GetType(Field f, Type *t, Category *c, int *rank, int *shape) { Array a = (Array) DXGetComponentValue(f, "data"); if (!a) return NULL; return DXGetType((Object)a, t, c, rank, shape); } static struct component * look_component(Field f, char *name, int add) { int i, j, m, n = f->ncomponents; struct component *c = NULL; /* is component there? */ if (name) { /* quick check for pointer equality first */ if (!add) for (i=0, c=f->components; iname==name) break; /* now check for string equality */ if (add || i>=n) for (i=0, c=f->components; iname, name)==0) break; } else { /* null name => new component */ i = n; } /* component is not there - add it */ if (i >= n) { if (add) { /* re-alloc if necessary */ if (n >= f->comp_alloc) { if (f->comp_alloc==NCOMPONENTS) { m = 2*NCOMPONENTS; c = (struct component *) DXAllocate(m*sizeof(struct component)); if (c) memcpy(c, f->local, sizeof(f->local)); } else { m = f->comp_alloc*2 + 1; c = (struct component *) DXReAllocate((Pointer)f->components, m * sizeof(struct component)); } if (!c) return NULL; f->components = c; f->comp_alloc = m; } c = f->components + n; f->ncomponents = n+1; c->name = _dxfstring(name, 1); c->value = NULL; } else c = NULL; } return c; } Field DXSetComponentValue(Field f, char *name, Object value) { struct component *c; /* if value is null, this is a request to delete this component. */ if (!value) { DXDeleteComponent(f, name); return f; } CHECK(f, CLASS_FIELD); /* is component there? */ c = look_component(f, name, value? 1: 0); if (!c) return NULL; /* put value in */ if (value!=c->value) { /* MP performance */ DXReference(value); /* do first in case value==c->value */ if (value && c->value) DXCopyAttributes(value, c->value); DXDelete(c->value); c->value = value; } return f; } Field DXSetComponentAttribute(Field f, char *name, char *attribute, Object value) { Object c; c = DXGetComponentValue(f, name); if (!c) return NULL; return DXSetAttribute(c, attribute, value)? f : NULL; } Object DXGetComponentValue(Field f, char *name) { struct component *c; CHECK(f, CLASS_FIELD); if (!name) return NULL; /* is component there? */ c = look_component(f, name, 0); if (!c) return NULL; /* component is there */ return c->value; } Object DXGetComponentAttribute(Field f, char *name, char *attribute) { Object c; c = DXGetComponentValue(f, name); if (!c) return NULL; return DXGetAttribute(c, attribute); } Object DXGetEnumeratedComponentValue(Field f, int n, char **name) { struct component *c; CHECK(f, CLASS_FIELD); /* is component there? */ if (n >= f->ncomponents) return NULL; c = &(f->components[n]); /* component is there */ if (name) *name = c->name; return c->value; } Object DXGetEnumeratedComponentAttribute(Field f, int n, char **name, char *attribute) { Object c; c = DXGetEnumeratedComponentValue(f, n, name); if (!c) return NULL; return DXGetAttribute(c, attribute); } static int _ComponentXX(Array a, Pointer *data, int *n, int nreq, Type t, int dim, int REQUIRED, int LOCAL) { int nn; Type tt; Category category; int shape; int rank; /* return 0 in *items, return NULL if component not there */ if (!a) { if (n) *n = 0; if (data) *data = NULL; if (REQUIRED) { DXErrorReturn(ERROR_MISSING_DATA, "missing component"); } else return OK; } /* get data */ if (data) *data = LOCAL? DXGetArrayDataLocal(a) : DXGetArrayData(a); /* more info */ DXGetArrayInfo(a, &nn, &tt, &category, &rank, NULL); /* return or check number of items */ if (n) *n = nn; else if (nreq!=nn) { DXSetError(ERROR_INVALID_DATA, "component has %d items, requires %d", nn, nreq); return NULL; } /* check type and category */ if (tt!=t || category!=CATEGORY_REAL) DXErrorReturn(ERROR_BAD_TYPE, "component has bad type or category"); /* check shape & rank */ /* XXX - loosened up the checking, hope this doesn't hurt */ if (rank==0) { if (dim!=0 && dim!=1) DXErrorReturn(ERROR_BAD_TYPE, "component has wrong dimensionality"); } else if (rank==1) { DXGetArrayInfo(a, NULL, NULL, NULL, NULL, &shape); if (shape != (dim?dim:1)) DXErrorReturn(ERROR_BAD_TYPE, "component has wrong dimensionality"); } else DXErrorReturn(ERROR_BAD_TYPE, "component has wrong dimensionality"); return OK; } int DXComponentReq(Array a, Pointer *data, int *n, int nreq, Type t, int dim) { return _ComponentXX(a, data, n, nreq, t, dim, 1, 0); } int DXComponentOpt(Array a, Pointer *data, int *n, int nreq, Type t, int dim) { return _ComponentXX(a, data, n, nreq, t, dim, 0, 0); } int DXComponentReqLoc(Array a, Pointer *data, int *n, int nreq, Type t, int dim) { return _ComponentXX(a, data, n, nreq, t, dim, 1, 1); } int DXComponentOptLoc(Array a, Pointer *data, int *n, int nreq, Type t, int dim) { return _ComponentXX(a, data, n, nreq, t, dim, 0, 1); } Field DXDeleteComponent(Field f, char *component) { int i, n = f->ncomponents; struct component *c; CHECK(f, CLASS_FIELD); if (!f) return NULL; if (!component) return NULL; /* is component there? */ c = look_component(f, component, 0); if (!c) return NULL; /* free it */ DXDelete(c->value); /* copy remaining components down */ for (i=c-f->components+1; icomponents[i-1] = f->components[i]; f->ncomponents -= 1; return f; } int _dxfField_Delete(Field f) { int i, n; struct component *c; n = f->ncomponents; for (i=0, c=f->components; ivalue); if (f->components!=f->local) DXFree((Pointer)f->components); return OK; } int DXEmptyField(Field f) { Array a; int n; if (f->ncomponents==0) return 1; a = (Array) DXGetComponentValue(f, POSITIONS); if (!a) return 1; DXGetArrayInfo(a, &n, NULL, NULL, NULL, NULL); if (n==0) return 1; return 0; } /* * Produces a new field that shares components, etc. with existing * field. * * XXX - should this be done instead by putting a pointer to old * field in new field and doing sharing at lookup? That is, should * semantics be to see changes made to old field? */ Object _dxfField_Copy(Field old, enum copy copy) { Field new; /* create new field */ new = DXNewField(); if (!new) return NULL; /* XXX - check return code and delete - but clean up _CopyField first! */ return (Object) _CopyField(new, old, copy); } static Field _CopyField(Field new, Field old, enum copy copy) { int i, j, n = old->ncomponents; struct component *oc, *nc; /* copy superclass */ if (!_dxf_CopyObject((Object)new, (Object)old, copy)) return NULL; if (copy==COPY_ATTRIBUTES) return new; /* allocate components */ if (n<=NCOMPONENTS) { nc = new->local; new->comp_alloc = NCOMPONENTS; } else { nc = (struct component *) DXAllocate(n*sizeof(struct component)); if (!nc) return NULL; new->comp_alloc = n; } new->components = nc; new->ncomponents = n; /* fill in components */ for (i=0, oc=old->components; iname = oc->name; if (copy==COPY_DATA) { nc->value = DXCopy(oc->value, copy); if (nc->value==NULL) /* XXX - cleanup! */ return NULL; } else nc->value = DXReference(oc->value); } return new; }