1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 
11 
12 
13 #include <string.h>
14 #include "fieldClass.h"
15 #include "internals.h"
16 
17 
18 static Field _CopyField(Field new, Field old, enum _dxd_copy copy);
19 
20 static Field
_NewField(struct field_class * class)21 _NewField(struct field_class *class)
22 {
23     Field f = (Field) _dxf_NewObject((struct object_class *)class);
24 
25     if (!f)
26 	return NULL;
27 
28     f->components = f->local;
29     f->ncomponents = 0;
30     f->comp_alloc = NCOMPONENTS;
31 
32     return f;
33 }
34 
35 
36 Field
DXNewField()37 DXNewField()
38 {
39     return _NewField(&_dxdfield_class);
40 }
41 
42 
43 Object
_dxfField_GetType(Field f,Type * t,Category * c,int * rank,int * shape)44 _dxfField_GetType(Field f, Type *t, Category *c, int *rank, int *shape)
45 {
46     Array a = (Array) DXGetComponentValue(f, "data");
47     if (!a)
48 	return NULL;
49     return DXGetType((Object)a, t, c, rank, shape);
50 }
51 
52 static
53 struct component *
look_component(Field f,char * name,int add)54 look_component(Field f, char *name, int add)
55 {
56     int i=0, m, n = f->ncomponents;
57     struct component *c = NULL;
58 
59     /* is component there? */
60     if (name) {
61 	/* quick check for pointer equality first */
62 	if (!add)
63 	    for (i=0, c=f->components; i<n; i++, c++)
64 		if (c->name==name)
65 		    break;
66 	/* now check for string equality */
67 	if (add || i>=n)
68 	    for (i=0, c=f->components; i<n; i++, c++)
69 		if (strcmp(c->name, name)==0)
70 		    break;
71 
72     } else {
73 	/* null name => new component */
74 	i = n;
75     }
76 
77     /* component is not there - add it */
78     if (i >= n) {
79 	if (add) {
80 	    /* re-alloc if necessary */
81 	    if (n >= f->comp_alloc) {
82 		if (f->comp_alloc==NCOMPONENTS) {
83 		    m = 2*NCOMPONENTS;
84 		    c = (struct component *)
85 			DXAllocate(m*sizeof(struct component));
86 		    if (c)
87 			memcpy(c, f->local, sizeof(f->local));
88 		} else {
89 		    m = f->comp_alloc*2 + 1;
90 		    c = (struct component *) DXReAllocate((Pointer)f->components,
91 			m * sizeof(struct component));
92 		}
93 		if (!c)
94 		    return NULL;
95 		f->components = c;
96 		f->comp_alloc = m;
97 	    }
98 	    c = f->components + n;
99 	    f->ncomponents = n+1;
100 	    c->name = _dxfstring(name, 1);
101 	    c->value = NULL;
102 	} else
103 	    c = NULL;
104     }
105     return c;
106 }
107 
108 
109 Field
DXSetComponentValue(Field f,char * name,Object value)110 DXSetComponentValue(Field f, char *name, Object value)
111 {
112     struct component *c;
113 
114     /* if value is null, this is a request to delete this component. */
115     if (!value)
116     {
117 	DXDeleteComponent(f, name);
118 	return f;
119     }
120 
121     CHECK(f, CLASS_FIELD);
122 
123     /* is component there? */
124     c = look_component(f, name, value? 1: 0);
125     if (!c)
126 	return NULL;
127 
128     /* put value in */
129     if (value!=c->value) {		/* MP performance */
130 	DXReference(value);		/* do first in case value==c->value */
131 	if (value && c->value)
132 	    DXCopyAttributes(value, c->value);
133 	DXDelete(c->value);
134 	c->value = value;
135     }
136 
137     return f;
138 }
139 
140 
141 Field
DXSetComponentAttribute(Field f,char * name,char * attribute,Object value)142 DXSetComponentAttribute(Field f, char *name, char *attribute, Object value)
143 {
144     Object c;
145     c = DXGetComponentValue(f, name);
146     if (!c)
147 	return NULL;
148     return DXSetAttribute(c, attribute, value)? f : NULL;
149 }
150 
151 
152 Object
DXGetComponentValue(Field f,char * name)153 DXGetComponentValue(Field f, char *name)
154 {
155     struct component *c;
156 
157     CHECK(f, CLASS_FIELD);
158     if (!name)
159 	return NULL;
160 
161     /* is component there? */
162     c = look_component(f, name, 0);
163     if (!c)
164 	return NULL;
165 
166     /* component is there */
167     return c->value;
168 }
169 
170 
171 Object
DXGetComponentAttribute(Field f,char * name,char * attribute)172 DXGetComponentAttribute(Field f, char *name, char *attribute)
173 {
174     Object c;
175     c = DXGetComponentValue(f, name);
176     if (!c)
177 	return NULL;
178     return DXGetAttribute(c, attribute);
179 }
180 
181 
182 Object
DXGetEnumeratedComponentValue(Field f,int n,char ** name)183 DXGetEnumeratedComponentValue(Field f, int n, char **name)
184 {
185     struct component *c;
186 
187     CHECK(f, CLASS_FIELD);
188 
189     /* is component there? */
190     if (n >= f->ncomponents)
191 	return NULL;
192     c = &(f->components[n]);
193 
194     /* component is there */
195     if (name)
196 	*name = c->name;
197     return c->value;
198 }
199 
200 
201 Object
DXGetEnumeratedComponentAttribute(Field f,int n,char ** name,char * attribute)202 DXGetEnumeratedComponentAttribute(Field f, int n, char **name, char *attribute)
203 {
204     Object c;
205     c = DXGetEnumeratedComponentValue(f, n, name);
206     if (!c)
207 	return NULL;
208     return DXGetAttribute(c, attribute);
209 }
210 
211 
212 static
213 int
_ComponentXX(Array a,Pointer * data,int * n,int nreq,Type t,int dim,int REQUIRED,int LOCAL)214 _ComponentXX(Array a, Pointer *data, int *n, int nreq, Type t, int dim,
215 		 int REQUIRED, int LOCAL)
216 {
217     int nn;
218     Type tt;
219     Category category;
220     int shape;
221     int rank;
222 
223     /* return 0 in *items, return NULL if component not there */
224     if (!a) {
225 	if (n)
226 	    *n = 0;
227 	if (data)
228 	    *data = NULL;
229 	if (REQUIRED) {
230 	    DXErrorReturn(ERROR_MISSING_DATA, "missing component");
231 	} else
232 	    return OK;
233     }
234 
235     /* get data */
236     if (data)
237 	*data = LOCAL? DXGetArrayDataLocal(a) : DXGetArrayData(a);
238 
239     /* more info */
240     DXGetArrayInfo(a, &nn, &tt, &category, &rank, NULL);
241 
242     /* return or check number of items */
243     if (n)
244 	*n = nn;
245     else if (nreq!=nn) {
246 	DXSetError(ERROR_DATA_INVALID,
247 		 "component has %d items, requires %d", nn, nreq);
248 	return ERROR;
249     }
250 
251     /* check type and category */
252     if (tt!=t || category!=CATEGORY_REAL)
253 	DXErrorReturn(ERROR_BAD_TYPE,
254 		    "component has bad type or category");
255 
256     /* check shape & rank */
257     /* XXX - loosened up the checking, hope this doesn't hurt */
258     if (rank==0) {
259 	if (dim!=0 && dim!=1)
260 	    DXErrorReturn(ERROR_BAD_TYPE, "component has wrong dimensionality");
261     } else if (rank==1) {
262 	DXGetArrayInfo(a, NULL, NULL, NULL, NULL, &shape);
263 	if (shape != (dim?dim:1))
264 	    DXErrorReturn(ERROR_BAD_TYPE, "component has wrong dimensionality");
265     } else
266 	DXErrorReturn(ERROR_BAD_TYPE, "component has wrong dimensionality");
267 
268     return OK;
269 }
270 
271 
DXComponentReq(Array a,Pointer * data,int * n,int nreq,Type t,int dim)272 int DXComponentReq(Array a, Pointer *data, int *n, int nreq, Type t, int dim)
273 {
274     return _ComponentXX(a, data, n, nreq, t, dim, 1, 0);
275 }
276 
277 
DXComponentOpt(Array a,Pointer * data,int * n,int nreq,Type t,int dim)278 int DXComponentOpt(Array a, Pointer *data, int *n, int nreq, Type t, int dim)
279 {
280     return _ComponentXX(a, data, n, nreq, t, dim, 0, 0);
281 }
282 
283 
DXComponentReqLoc(Array a,Pointer * data,int * n,int nreq,Type t,int dim)284 int DXComponentReqLoc(Array a, Pointer *data, int *n, int nreq, Type t, int dim)
285 {
286     return _ComponentXX(a, data, n, nreq, t, dim, 1, 1);
287 }
288 
289 
DXComponentOptLoc(Array a,Pointer * data,int * n,int nreq,Type t,int dim)290 int DXComponentOptLoc(Array a, Pointer *data, int *n, int nreq, Type t, int dim)
291 {
292     return _ComponentXX(a, data, n, nreq, t, dim, 0, 1);
293 }
294 
295 
296 Field
DXDeleteComponent(Field f,char * component)297 DXDeleteComponent(Field f, char *component)
298 {
299     int i, n = f->ncomponents;
300     struct component *c;
301 
302     CHECK(f, CLASS_FIELD);
303     if (!f)
304 	return NULL;
305     if (!component)
306 	return NULL;
307 
308     /* is component there? */
309     c = look_component(f, component, 0);
310     if (!c)
311 	return NULL;
312 
313     /* free it */
314     DXDelete(c->value);
315 
316     /* copy remaining components down */
317     for (i=c-f->components+1; i<n; i++)
318 	f->components[i-1] = f->components[i];
319     f->ncomponents -= 1;
320 
321     return f;
322 }
323 
324 
325 int
_dxfField_Delete(Field f)326 _dxfField_Delete(Field f)
327 {
328     int i, n;
329     struct component *c;
330 
331     n = f->ncomponents;
332     for (i=0, c=f->components; i<n; i++, c++)
333 	DXDelete(c->value);
334     if (f->components!=f->local)
335 	DXFree((Pointer)f->components);
336 
337     return OK;
338 }
339 
340 
341 int
DXEmptyField(Field f)342 DXEmptyField(Field f)
343 {
344     Array a;
345     int n;
346     if (f->ncomponents==0)
347 	return 1;
348     a = (Array) DXGetComponentValue(f, POSITIONS);
349     if (!a)
350 	return 1;
351     DXGetArrayInfo(a, &n, NULL, NULL, NULL, NULL);
352     if (n==0)
353 	return 1;
354     return 0;
355 }
356 
357 
358 /*
359  * Produces a new field that shares components, etc. with existing
360  * field.
361  *
362  * XXX - should this be done instead by putting a pointer to old
363  * field in new field and doing sharing at lookup?  That is, should
364  * semantics be to see changes made to old field?
365  */
366 
367 Object
_dxfField_Copy(Field old,enum _dxd_copy copy)368 _dxfField_Copy(Field old, enum _dxd_copy copy)
369 {
370     Field new;
371 
372     /* create new field */
373     new = DXNewField();
374     if (!new)
375 	return NULL;
376 
377     /* XXX - check return code and delete - but clean up _CopyField first! */
378     return (Object) _CopyField(new, old, copy);
379 }
380 
381 
382 static Field
_CopyField(Field new,Field old,enum _dxd_copy copy)383 _CopyField(Field new, Field old, enum _dxd_copy copy)
384 {
385     int i, n = old->ncomponents;
386     struct component *oc, *nc;
387 
388     /* copy superclass */
389     if (!_dxf_CopyObject((Object)new, (Object)old, copy))
390 	return NULL;
391     if (copy==COPY_ATTRIBUTES)
392 	return new;
393 
394     /* allocate components */
395     if (n<=NCOMPONENTS) {
396 	nc = new->local;
397 	new->comp_alloc = NCOMPONENTS;
398     } else {
399 	nc = (struct component *)  DXAllocate(n*sizeof(struct component));
400 	if (!nc)
401 	    return NULL;
402 	new->comp_alloc = n;
403     }
404     new->components = nc;
405     new->ncomponents = n;
406 
407     /* fill in components */
408     for (i=0, oc=old->components; i<n; i++, oc++, nc++) {
409 	nc->name = oc->name;
410 	if (copy==COPY_DATA) {
411 	    nc->value = DXCopy(oc->value, copy);
412 	    if (nc->value==NULL) /* XXX - cleanup! */
413 		return NULL;
414 	} else
415 	    nc->value = DXReference(oc->value);
416     }
417 
418     return new;
419 }
420 
421 
422 
423 
424