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