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