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 "objectClass.h"
15 #include "internals.h"
16 
17 /*
18  * Tracing
19  */
20 
21 #if DEBUGGED
22 static int trace = 1;
23 #endif
24 
25 void
_dxfTraceObjects(int d)26 _dxfTraceObjects(int d)
27 {
28 #if DEBUGGED
29     trace = d;
30 #endif
31 }
32 
33 #if DEBUGGED
34 static struct table {			/* table of New/DXDelete per class */
35     lock_type lock;			/* lock for the table */
36     struct counts {			/* the counts */
37 	struct object_class *class;	/* class vector */
38 	int new;			/* how many created */
39 	int deleted;			/* how many deleted */
40     } counts[CLASS_MAX];		/* one per class, in global storage */
41 } *table;
42 
43 #define EVERY 500			/* how often to print out */
44 #endif
45 
46 #define BITS 24				/* this many bits in tag */
47 static int tag = 1;			/* per-processor */
48 
49 Error
_dxf_initobjects(void)50 _dxf_initobjects(void)
51 {
52 #if DEBUGGED
53     table = (struct table *) DXAllocateZero(sizeof(struct table));
54     if (!table)
55 	return NULL;
56     DXcreate_lock(&table->lock, "object statistics table");
57 #endif
58 
59     return OK;
60 }
61 
62 
63 
64 /*
65  *
66  */
67 
68 #define PERMANENT 999999999
69 
_dxf_SetPermanent(Object o)70 Object _dxf_SetPermanent(Object o)
71 {
72     o->count = PERMANENT;
73     return o;
74 }
75 
76 
77 #if DEBUGGED
78 #define ID DXProcessorId()
79 #else
80 #define ID 0
81 #endif
82 
DXReference(Object o)83 Object DXReference(Object o)
84 {
85     if (!o)
86 	return NULL;
87     if (o->count==PERMANENT)
88 	return o;
89 
90     /* lock & increment count */
91     DXfetch_and_add(&o->count, 1, &o->lock, ID);
92 
93     return o;
94 }
95 
96 
97 Error
DXDelete(Object o)98 DXDelete(Object o)
99 {
100     int rc = 0, i, n;
101     Class class;
102 
103     if (!o)
104 	return OK;
105     if (o->count==PERMANENT)
106 	return OK;
107 
108     /* sanity checks - up thru dx 2.1.1, this was if DEBUGGED only */
109     if (o->count < 0)
110 	DXErrorReturn(ERROR_DATA_INVALID,
111 		    "Object deleted too often! (or not an object)");
112     class = DXGetObjectClass(o);
113     if ((int)class<=(int)CLASS_MIN || (int)class>=(int)CLASS_MAX) {
114 	DXSetError(ERROR_DATA_INVALID,
115 		 "Deleting object of unknown class %d! (or not an object)",
116 		 class);
117 	return ERROR;
118     }
119 
120     /* lock & decrement count */
121     if (DXfetch_and_add(&o->count, -1, &o->lock, ID) > 1)
122 	return OK;
123 
124 #if DEBUGGED
125     /* tracing */
126     if (trace>=2)
127 	DXDebug("Q","deleting object class %s at 0x%x", CLASS_NAME(o->class), o);
128     if (trace>=1) {
129 	int n = (int) CLASS_CLASS(o->class);
130 	DXlock(&table->lock, 0);
131 	table->counts[n].deleted += 1;
132 	DXunlock(&table->lock, 0);
133     }
134 #endif
135 
136     /*
137      * delete attributes
138      * XXX - this should by in an _DeleteObject to be called by subclass
139      * i.e. _Delete should be handled like New and DXCopy
140      */
141     for (i=0, n=o->nattributes; i<n; i++)
142 	if (o->count != PERMANENT)
143 	    DXDelete(o->attributes[i].value);
144     if (o->attributes!=o->local)
145 	DXFree((Pointer)o->attributes);
146 
147     /* user deletion */
148     rc = _dxfDelete(o);
149 
150     /* in case we mistakenly delete this object again - same as above;
151      *  was only if DEBUGGED up through dx 2.1.1
152      */
153     o->class_id = CLASS_DELETED;
154     o->count = -1;
155     o->class = NULL;
156 
157     /* finish deleting our stuff */
158     DXdestroy_lock(&o->lock);
159     DXFree((Pointer)o);
160     return rc;
161 }
162 
163 
164 Error
DXUnreference(Object o)165 DXUnreference(Object o)
166 {
167     Class class;
168 
169     if (!o)
170 	return ERROR;
171     if (o->count==PERMANENT || o->count==0)
172 	return OK;
173 
174     /* sanity checks  - same comment as in DXDelete */
175     if (o->count < 0)
176 	DXErrorReturn(ERROR_DATA_INVALID,
177 		    "Object deleted too often! (or not an object)");
178     class = DXGetObjectClass(o);
179     if ((int)class<=(int)CLASS_MIN || (int)class>=(int)CLASS_MAX) {
180 	DXSetError(ERROR_DATA_INVALID,
181 		 "Deleting object of unknown class %d! (or not an object)",
182 		 class);
183 	return ERROR;
184     }
185 
186     /* lock & decrement count */
187     DXfetch_and_add(&o->count, -1, &o->lock, ID);
188 
189     return OK;
190 }
191 
192 
193 
194 
195 
196 Object
_dxf_NewObject(struct object_class * class)197 _dxf_NewObject(struct object_class *class)
198 {
199     Object o;
200 
201     o = (Object) DXAllocate(CLASS_SIZE(class));
202     if (!o)
203 	return NULL;
204 
205 #if DEBUGGED
206     /* tracing */
207     if (trace>=2)
208 	DXDebug("Q", "creating object class %s at 0x%x", CLASS_NAME(class), o);
209     if (trace>=1) {
210 	int n = (int) CLASS_CLASS(class);
211 	table->counts[n].class = class;
212 	DXlock(&table->lock, 0);
213 	table->counts[n].new += 1;
214 	if (table->counts[n].new%EVERY==0)
215 	    DXDebug("O", "%d %s objects created, %d deleted, net %d",
216 		  table->counts[n].new, CLASS_NAME(class),
217 		  table->counts[n].deleted,
218 		  table->counts[n].new-table->counts[n].deleted);
219 	DXunlock(&table->lock, 0);
220     }
221 #endif
222 
223     memset(o, 0, CLASS_SIZE(class));
224     o->class = class;
225     o->class_id = CLASS_CLASS(class);
226     DXcreate_lock(&o->lock, "object");
227     o->count = 0;
228     o->tag = (DXProcessorId()<<BITS) + tag++;
229     o->attributes = o->local;
230     o->nattributes = 0;
231     o->attr_alloc = NATTRIBUTES;
232     return o;
233 }
234 
235 
236 /*
237  * Tags
238  */
239 
240 int
DXGetObjectTag(Object o)241 DXGetObjectTag(Object o)
242 {
243     if (!o)
244 	return 0;
245     return o->tag;
246 }
247 
248 Object
DXSetObjectTag(Object o,int tag)249 DXSetObjectTag(Object o, int tag)
250 {
251     if (tag>=0) {
252 	DXSetError(ERROR_INTERNAL,
253 		 "tag value %d is illegal: must be less than 0", tag);
254 	return NULL;
255     }
256     if (!o)
257 	return NULL;
258     o->tag = tag;
259     return o;
260 }
261 
262 
263 
264 /*
265  * Attributes
266  */
267 
268 Object
DXSetAttribute(Object o,char * name,Object value)269 DXSetAttribute(Object o, char *name, Object value)
270 {
271     int i, m, n = o->nattributes;
272     struct attribute *a;
273 
274     if (!o)
275 	return NULL;
276 
277     if (!name)
278 	DXErrorReturn(ERROR_BAD_PARAMETER, "DXSetAttribute given null name");
279 
280     /* don't do quick check: assume usually not there */
281     for (i=0, a=o->attributes; i<n; i++, a++)
282 	if (a->name && strcmp(a->name, name)==0)
283 	    break;
284 
285     /* attribute is not there - add it if we are setting a value,
286      * or return ok if requesting to delete it.
287      */
288     if (i >= n) {
289 	if (!value)
290 	    return o;
291 	if (n >= o->attr_alloc) {
292 	    if (o->attr_alloc==NATTRIBUTES) {
293 		m = 2*NATTRIBUTES;
294 		a = (struct attribute *) DXAllocate(m*sizeof(struct attribute));
295 		if (a)
296 		    memcpy(a, o->local, sizeof(o->local));
297 	    } else {
298 		m = o->attr_alloc*2 + 1;
299 		a = (struct attribute *) DXReAllocate((Pointer)o->attributes,
300 					      m * sizeof(struct attribute));
301 	    }
302 	    if (!a)
303 		return NULL;
304 	    o->attributes = a;
305 	    o->attr_alloc = m;
306 	}
307 	a = o->attributes + n;
308 	o->nattributes = n+1;
309 	a->name = _dxfstring(name, 1);
310 	a->value = NULL;
311 
312     } else if (!value) {
313 
314 	/* copy remaining attributes down */
315 	DXDelete(a->value);
316 	for (i=i+1; i<n; i++)
317 	    o->attributes[i-1] = o->attributes[i];
318 	o->nattributes -= 1;
319 	return o;
320 
321     }
322 
323     /* put value in */
324     if (value!=a->value) {		/* MP performance */
325 	DXReference(value);		/* do first in case value==a->value */
326 	DXDelete(a->value);
327 	a->value = value;
328     }
329 
330     return o;
331 }
332 
333 
334 Object
DXDeleteAttribute(Object o,char * name)335 DXDeleteAttribute(Object o, char *name)
336 {
337     int i, n = o->nattributes;
338     struct attribute *a;
339 
340     if (!o)
341 	return NULL;
342 
343     if (!name)
344 	DXErrorReturn(ERROR_BAD_PARAMETER,
345 		      "DXDeleteAttribute given null name");
346 
347     /* quick check for pointer equality */
348     for (i=0, a=o->attributes; i<n; i++, a++)
349 	if (a->name==name)
350 	    break;
351 
352     /* now check for string equality */
353     if (i >= n)
354 	for (i=0, a=o->attributes; i<n; i++, a++)
355 	    if (a->name && strcmp(a->name, name)==0)
356 		break;
357 
358     /* attribute not there, return ok */
359     if (i >= n)
360 	return o;
361 
362     /* copy remaining attributes down */
363     DXDelete(a->value);
364     for (i=i+1; i<n; i++)
365 	o->attributes[i-1] = o->attributes[i];
366     o->nattributes -= 1;
367     return o;
368 }
369 
370 
371 Object
DXGetAttribute(Object o,char * name)372 DXGetAttribute(Object o, char *name)
373 {
374     int i, n;
375     struct attribute *a;
376 
377     if (!o)
378 	return NULL;
379     if (!name)
380 	DXErrorReturn(ERROR_BAD_PARAMETER, "DXGetAttribute given null name");
381 
382     /* quick check for pointer equality */
383     n = o->nattributes;
384     for (i=0, a=o->attributes; i<n; i++, a++)
385 	if (a->name==name)
386 	    break;
387 
388     /* now check for string equality */
389     if (i >= n)
390 	for (i=0, a=o->attributes; i<n; i++, a++)
391 	    if (a->name && strcmp(a->name, name)==0)
392 		break;
393 
394     /* no */
395     if (i >= n)
396 	return NULL;
397 
398     /* yes */
399     return a->value;
400 }
401 
402 
403 Object
DXGetEnumeratedAttribute(Object o,int n,char ** name)404 DXGetEnumeratedAttribute(Object o, int n, char **name)
405 {
406     struct attribute *a;
407     if (!o)
408 	return NULL;
409     if (n >= o->nattributes)
410 	return NULL;
411     a = o->attributes + n;
412     if (name)
413 	*name = a->name;
414     return a->value;
415 }
416 
417 Object
DXSetFloatAttribute(Object o,char * name,double x)418 DXSetFloatAttribute(Object o, char *name, double x)
419 {
420     Array a;
421     float *p;
422     a = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
423     p = (float *)DXGetArrayData(DXAddArrayData(a, 0, 1, NULL));
424     if (!p)
425 	return NULL;
426     *p = x;
427     if (!DXSetAttribute(o, name, (Object)a)) {
428 	DXDelete((Object)a);
429 	return NULL;
430     }
431     return o;
432 }
433 
434 Object
DXSetIntegerAttribute(Object o,char * name,int x)435 DXSetIntegerAttribute(Object o, char *name, int x)
436 {
437     Array a;
438     int *p;
439     a = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
440     p = (int *)DXGetArrayData(DXAddArrayData(a, 1, 0, NULL));
441     if (!p)
442 	return NULL;
443     *p = x;
444     if (!DXSetAttribute(o, name, (Object)a)) {
445 	DXDelete((Object)a);
446 	return NULL;
447     }
448     return o;
449 }
450 
451 Object
DXSetStringAttribute(Object o,char * name,char * x)452 DXSetStringAttribute(Object o, char *name, char *x)
453 {
454     String s;
455     s = DXNewString(x);
456     if (!s)
457 	return NULL;
458     if (!DXSetAttribute(o, name, (Object)s)) {
459 	DXDelete((Object)s);
460 	return NULL;
461     }
462     return o;
463 }
464 
465 Object
DXGetFloatAttribute(Object o,char * name,float * x)466 DXGetFloatAttribute(Object o, char *name, float *x)
467 {
468     Array a;
469     float *p;
470 
471     if (!(a = (Array)DXGetAttribute(o, name)))
472 	return NULL;
473 
474     if (DXGetObjectClass((Object)a) != CLASS_ARRAY)
475 	return NULL;
476 
477     if (!DXTypeCheck(a, TYPE_FLOAT, CATEGORY_REAL, 0))
478 	return NULL;
479 
480     if (!(p = (float *)DXGetArrayData(a)))
481 	return NULL;
482 
483     if (x)
484 	*x = *p;
485 
486     return o;
487 }
488 
489 Object
DXGetIntegerAttribute(Object o,char * name,int * x)490 DXGetIntegerAttribute(Object o, char *name, int *x)
491 {
492     Array a;
493     int *p;
494 
495     if (!(a = (Array)DXGetAttribute(o, name)))
496 	return NULL;
497 
498     if (DXGetObjectClass((Object)a) != CLASS_ARRAY)
499 	return NULL;
500 
501     if (!DXTypeCheck(a, TYPE_INT, CATEGORY_REAL, 0))
502 	return NULL;
503 
504     if (!(p = (int *)DXGetArrayData(a)))
505 	return NULL;
506 
507     if (x)
508 	*x = *p;
509 
510     return o;
511 }
512 
513 
514 Object
DXGetStringAttribute(Object o,char * name,char ** x)515 DXGetStringAttribute(Object o, char *name, char **x)
516 {
517     String s;
518 
519     if (!(s = (String)DXGetAttribute(o, name)))
520 	return NULL;
521 
522     if (DXGetObjectClass((Object)s) != CLASS_STRING)
523 	return NULL;
524 
525     if (x)
526 	*x = DXGetString(s);
527 
528     return o;
529 }
530 
531 
532 Object
DXCopyAttributes(Object dst,Object src)533 DXCopyAttributes(Object dst, Object src)
534 {
535     struct attribute *a;
536     int i;
537     if (!dst)
538 	return NULL;
539     if (!src)
540 	return dst;
541     for (i=0, a=src->attributes; i<src->nattributes; i++, a++)
542 	if (!DXSetAttribute(dst, a->name, a->value))
543 	    return NULL;
544     return dst;
545 }
546 
547 
548 /*
549  * Copying
550  * XXX - why is copying attributes done both here and in DXCopyAttributes?
551  */
552 
553 Object
_dxf_CopyObject(Object new,Object old,enum _dxd_copy copy)554 _dxf_CopyObject(Object new, Object old, enum _dxd_copy copy)
555 {
556     int i, n = old->nattributes;
557     struct attribute *oa, *na;
558 
559     /*
560      * DXCopy the attributes, no matter what the type of copy
561      */
562 
563     /* allocate attributes */
564     if (n<=NATTRIBUTES) {
565 	na = new->local;
566 	new->attr_alloc = NATTRIBUTES;
567     } else {
568 	na = (struct attribute *) DXAllocate(n * sizeof(struct attribute));
569 	if (!na)
570 	    return NULL;
571 	new->attr_alloc = n;
572     }
573     new->attributes = na;
574     new->nattributes = n;
575 
576     /* fill in attributes */
577     for (i=0, oa=old->attributes; i<n; i++, oa++, na++) {
578 	na->name = oa->name;
579 	na->value = DXReference(oa->value);
580     }
581     return new;
582 }
583 
584 Object
DXGetType(Object a,Type * b,Category * c,int * d,int * e)585 DXGetType(Object a, Type* b, Category* c, int* d, int* e)
586 {
587     return _dxfGetType((Object)a,b,c,d,e);
588 }
589 
590 Object
DXCopy(Object a,enum _dxd_copy b)591 DXCopy(Object a, enum _dxd_copy b)
592 {
593     return _dxfCopy((Object)a,b);
594 }
595 
596 Error
_dxfObject_Delete(Object o)597 _dxfObject_Delete(Object o)
598 {
599     return OK;
600 }
601 
602 Object
_dxfObject_BoundingBox(Object o,Point * p,Matrix * m,int valid)603 _dxfObject_BoundingBox(Object o, Point *p, Matrix *m, int valid)
604 {
605     return NULL;
606 }
607 
608 Error
_dxfObject_Shade(Object o,struct shade * s)609 _dxfObject_Shade(Object o, struct shade *s)
610 {
611     DXSetError(ERROR_BAD_CLASS, "#13880", CLASS_NAME(o->class));
612     return ERROR;
613 }
614