1
2 /***********************************************************************/
3 /* Open Visualization Data Explorer */
4 /* (C) Copyright IBM Corp. 1989,1999 */
5 /* ALL RIGHTS RESERVED */
6 /* This code licensed under the */
7 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
8 /***********************************************************************/
9
10 #include <dxconfig.h>
11
12
13 /*
14 * Header: /usr/people/gresh/code/svs/src/libdx/RCS/invalid.c,v 5.1 93/01/20 14:26:14 gda Exp Locker: gresh
15 *
16 */
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <dx/dx.h>
21
22 static Array CullArray(Array, int, int, InvalidComponentHandle);
23
24 static Array _dxfReRef(Array, int *);
25 static int *MakeMap(InvalidComponentHandle, int, int *);
26
27 static Object C_Field(Field);
28 static Object C_Field_Standard(Field);
29 static Object C_Field_PE(Field);
30 static Object C_Field_FLE(Field);
31
32 static Object IC_Field(Field);
33 static Object IC_Field_Standard(Field);
34 static Object IC_Field_PE(Field);
35 static Object IC_Field_FLE(Field);
36
37 static Object IUP_Field(Field);
38 static Object IUP_Field_Standard(Field);
39 static Object IUP_Field_PE(Field);
40 static Object IUP_Field_FLE(Field);
41
42 /* --FIXME
43 * Never defined --remove after determining not used
44 *
45
46 static Object C_Object(Object);
47 static Object IC_Object(Object);
48 static Object IUP_Object(Object);
49
50 */
51
52 static Field DeleteFieldContents(Field);
53
54 /*
55 * The following checks to find the maximum point reference in the
56 * connections array and whether the references skip any in the
57 * range. This is a fast out for InvalidateUnreferencedPositions...
58 * if the max. reference matches the length of the positions array
59 * and no holes were found, then no points are unreferenced.
60 */
61 #define ERROR_OCCURRED -1
62 #define HOLES_FOUND -2
63 static int GridSize(Array);
64
65 #ifndef TRUE
66 #define TRUE 1
67 #endif
68
69 #ifndef FALSE
70 #define FALSE 0
71 #endif
72
73 /*
74 * DEP ARRAY lower-bound thresholds
75 * DEP_STORAGE_THRESHOLD - When to switch to a DEP ARRAY when writing a field
76 * component (< -- SORTED_LIST; >= -- DEP_ARRAY)
77 * DEP_MEM_THRESHOLD - When to use a DEP for in-memory
78 * (i.e. InvalidComponentHandle) operations
79 *
80 * These are different because one should favor storage size, while the
81 * other should favors fast processing.
82 */
83 #define DEP_STORAGE_THRESHOLD(nItems) ( 0.20*(nItems) )
84 #define DEP_MEM_THRESHOLD(nItems) ( 1024 )
85
86
87 #define TRAVERSE(objectMethod, fieldMethod) \
88 { \
89 switch(DXGetObjectClass(object)) \
90 { \
91 case CLASS_FIELD: \
92 return (fieldMethod)((Field)object); \
93 \
94 case CLASS_GROUP: \
95 { \
96 int i = 0; \
97 Group g = (Group)object; \
98 Object c; \
99 while(NULL != (c = DXGetEnumeratedMember(g, i++, NULL))) \
100 { \
101 if (NULL == (objectMethod)(c)) \
102 return NULL; \
103 } \
104 return object; \
105 } \
106 \
107 case CLASS_XFORM: \
108 { \
109 Object c; \
110 if (! DXGetXformInfo((Xform)object, &c, NULL)) \
111 return NULL; \
112 c = (objectMethod)(c); \
113 if (! c) \
114 return NULL; \
115 return object; \
116 } \
117 \
118 case CLASS_CLIPPED: \
119 { \
120 Object c; \
121 if (! DXGetClippedInfo((Clipped)object, &c, NULL)) \
122 return NULL; \
123 c = (objectMethod)(c); \
124 if (! c) \
125 return NULL; \
126 return object; \
127 } \
128 \
129 default: \
130 return object; \
131 } \
132 }
133
134
135 Object
DXCull(Object object)136 DXCull(Object object)
137 {
138 TRAVERSE(DXCull, C_Field);
139 }
140
141 Object
DXInvalidateConnections(Object object)142 DXInvalidateConnections(Object object)
143 {
144 TRAVERSE(DXInvalidateConnections, IC_Field);
145 }
146
147
148 Object
DXInvalidateUnreferencedPositions(Object object)149 DXInvalidateUnreferencedPositions(Object object)
150 {
151 TRAVERSE(DXInvalidateUnreferencedPositions, IUP_Field);
152 }
153
154 Object
DXCullConditional(Object object)155 DXCullConditional(Object object)
156 {
157 return DXCull(object);
158 }
159
160 static Object
C_Field(Field field)161 C_Field(Field field)
162 {
163 if (DXGetComponentValue(field, "polylines"))
164 {
165 return C_Field_PE(field);
166 }
167 else if (DXGetComponentValue(field, "faces"))
168 {
169 return C_Field_FLE(field);
170 }
171 else
172 {
173 return C_Field_Standard(field);
174 }
175 }
176
177 static Object
C_Field_PE(Field field)178 C_Field_PE(Field field)
179 {
180 Array pArray, plArray, eArray;
181 Array child, newChild;
182 int nPositions, nPolylines, nEdges, nInvP, nInvPl;
183 int nNewPositions, nNewPolylines;
184 int i, j, k, knt;
185 int *validPositionsMap, *validPolylinesMap;
186 Object attr;
187 char *reference, *dependence;
188 char *name;
189 char *toDelete[32];
190 int nDelete = 0;
191 InvalidComponentHandle vpHandle = NULL;
192 InvalidComponentHandle vplHandle = NULL;
193 Array nPlArray = NULL, nEArray = NULL;
194 int *polylines, *npolylines;
195 int *edges, *nedges;
196
197 if (DXEmptyField(field))
198 return (Object)field;
199
200 vplHandle = NULL;
201 vpHandle = NULL;
202 validPolylinesMap = NULL;
203 validPositionsMap = NULL;
204 child = NULL;
205
206 pArray = (Array)DXGetComponentValue(field, "positions");
207 if (! pArray)
208 {
209 DXSetError(ERROR_MISSING_DATA, "positions component");
210 goto error;
211 }
212
213 if (! DXGetArrayInfo(pArray, &nPositions, NULL, NULL, NULL, NULL))
214 goto error;
215
216 plArray = (Array)DXGetComponentValue(field, "polylines");
217 if (plArray)
218 {
219 if (! DXGetArrayInfo(plArray, &nPolylines, NULL, NULL, NULL, NULL))
220 goto error;
221 }
222 else
223 nPolylines = 0;
224
225 eArray = (Array)DXGetComponentValue(field, "edges");
226 if (eArray)
227 {
228 if (! DXGetArrayInfo(eArray, &nEdges, NULL, NULL, NULL, NULL))
229 goto error;
230 }
231 else
232 nEdges = 0;
233
234 vpHandle = DXCreateInvalidComponentHandle((Object)field, NULL, "positions");
235 if (! vpHandle)
236 goto error;
237
238 nInvP = DXGetInvalidCount(vpHandle);
239 if (nInvP)
240 {
241 if (NULL == (validPositionsMap =
242 MakeMap(vpHandle, nPositions, &nNewPositions)))
243 goto error;
244
245 if (nNewPositions == 0)
246 {
247 if (! (Object)DeleteFieldContents(field))
248 goto error;
249
250 goto done;
251 }
252 }
253 else
254 {
255 DXFreeInvalidComponentHandle(vpHandle);
256 vpHandle = NULL;
257 }
258
259 if (plArray)
260 {
261 vplHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
262 "polylines");
263 if (! vplHandle)
264 goto error;
265
266 nInvPl = DXGetInvalidCount(vplHandle);
267 }
268 else
269 nInvPl = 0;
270
271 if (nInvPl)
272 {
273 if (NULL == (validPolylinesMap =
274 MakeMap(vplHandle, nPolylines, &nNewPolylines)))
275 goto error;
276 }
277 else
278 {
279 DXFreeInvalidComponentHandle(vplHandle);
280 vplHandle = NULL;
281 }
282
283 if (nInvP == 0 && nInvPl == 0)
284 {
285 DXDeleteComponent(field, "invalid polylines");
286 DXDeleteComponent(field, "invalid positions");
287 return (Object)field;
288 }
289
290 /*
291 * Handle polylines and edges components
292 */
293 polylines = (int *)DXGetArrayData(plArray);
294 edges = (int *)DXGetArrayData(eArray);
295
296 /*
297 * count the resulting edges
298 */
299 for (i = 0, knt = 0; i < nPolylines; i++)
300 {
301 if (DXIsElementValid(vplHandle, i))
302 {
303 int start = polylines[i];
304 int end = (i == nPolylines-1) ? nEdges : polylines[i+1];
305
306 knt += end - start;
307 }
308 }
309
310 nPlArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
311 nEArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
312 if (! nPlArray || ! nEArray)
313 goto error;
314
315 if (! DXAddArrayData(nPlArray, 0, (nPolylines-nInvPl), NULL))
316 goto error;
317
318 if (! DXAddArrayData(nEArray, 0, knt, NULL))
319 goto error;
320
321 npolylines = (int *)DXGetArrayData(nPlArray);
322 nedges = (int *)DXGetArrayData(nEArray);
323
324 for (i = 0, j = 0, k = 0; i < nPolylines; i++)
325 {
326 if (DXIsElementValid(vplHandle, i))
327 {
328 int start = polylines[i];
329 int end = (i == nPolylines-1) ? nEdges : polylines[i+1];
330 int n = end - start;
331 int ii;
332
333 npolylines[j++] = k;
334
335 for (ii = 0; ii < n; ii++)
336 nedges[k + ii] = edges[start + ii];
337
338 k += n;
339 }
340 }
341
342 if (! DXSetAttribute((Object)nPlArray, "ref",
343 (Object)DXNewString("edges")))
344 goto error;
345
346 if (! DXSetComponentValue(field, "polylines", (Object)nPlArray))
347 goto error;
348 nPlArray = NULL;
349
350 if (! DXSetAttribute((Object)nEArray, "ref",
351 (Object)DXNewString("positions")))
352 goto error;
353
354 if (! DXSetComponentValue(field, "edges", (Object)nEArray))
355 goto error;
356 nEArray = NULL;
357
358 i = 0;
359 while (NULL !=
360 (child = (Array)DXGetEnumeratedComponentValue(field, i, &name)))
361 {
362 if (! strncmp(name, "invalid ", 8))
363 {
364 toDelete[nDelete++] = name;
365 i++;
366 continue;
367 }
368
369 if (! strcmp(name, "polylines"))
370 {
371 i++;
372 continue;
373 }
374
375 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "der");
376 if (attr && strcmp(name, "neighbors"))
377 {
378 toDelete[nDelete++] = name;
379 i++;
380 continue;
381 }
382
383 DXReference((Object)child);
384
385 dependence = NULL;
386
387 if (! strcmp(name, "positions"))
388 dependence = "positions";
389 else if (! strcmp(name, "polylines"))
390 dependence = "polylines";
391 else
392 {
393 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "dep");
394 if (attr)
395 dependence = DXGetString((String)attr);
396 }
397
398 /*
399 * If the component is dependent on something, then do to the
400 * component whatever is appropriate for the component on which
401 * it is dependent.
402 */
403 if (dependence)
404 {
405 /*
406 * If its dependent on positions...
407 */
408 if (! strcmp(dependence, "positions"))
409 {
410 /*
411 * and there are invalidated positions, cull the component
412 */
413 if (vpHandle)
414 {
415 if (nNewPositions == 0)
416 {
417 toDelete[nDelete++] = name;
418 DXDelete((Object)child);
419 child = NULL;
420 i++;
421 continue;
422 }
423 else
424 {
425 newChild = CullArray(child, nPositions,
426 nNewPositions, vpHandle);
427 if (! newChild)
428 goto error;
429
430 DXDelete((Object)child);
431 child = (Array)DXReference((Object)newChild);
432 }
433 }
434 }
435 /*
436 * Else if its dependent on polylines...
437 */
438 else if (! strcmp(dependence, "polylines"))
439 {
440 if (! plArray)
441 {
442 DXSetError(ERROR_DATA_INVALID,
443 "component dependent on nonexistent polylines");
444 goto error;
445 }
446
447 /*
448 * and there is a validPolylines array, cull the component.
449 */
450 if (vplHandle)
451 {
452 if (nNewPolylines == 0)
453 {
454 toDelete[nDelete++] = name;
455 DXDelete((Object)child);
456 child = NULL;
457 i++;
458 continue;
459 }
460 else
461 {
462 newChild = CullArray(child, nPolylines,
463 nNewPolylines, vplHandle);
464
465 if (! newChild)
466 goto error;
467
468 DXDelete((Object)child);
469 child = (Array)DXReference((Object)newChild);
470 }
471 }
472 }
473 }
474
475 /*
476 * Now we consider components that ref. If the component they ref
477 * has been culled, we need to renumber the references to reflect
478 * the culled referenced array.
479 */
480 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "ref");
481 if (attr)
482 {
483 reference = DXGetString((String)attr);
484
485 /*
486 * If it references polylines...
487 */
488 if (!strcmp(reference, "polylines"))
489 {
490 if (! plArray)
491 {
492 DXSetError(ERROR_DATA_INVALID,
493 "component refers to nonexistent polylines");
494 goto error;
495 }
496
497 /*
498 * And polylines have been culled, renumber the references.
499 */
500 if (validPolylinesMap)
501 {
502 newChild = _dxfReRef(child, validPolylinesMap);
503 if (! newChild)
504 goto error;
505
506 DXDelete((Object)child);
507 child = (Array)DXReference((Object)newChild);
508 }
509 }
510 /*
511 * Else if it references positions...
512 */
513 else if (!strcmp(reference, "positions"))
514 {
515 /*
516 * And positions have been culled, renumber the references.
517 */
518 if (validPositionsMap)
519 {
520 newChild = _dxfReRef(child, validPositionsMap);
521 if (! newChild)
522 goto error;
523
524 DXDelete((Object)child);
525 child = (Array)DXReference((Object)newChild);
526 }
527 }
528 }
529
530 if (! DXSetComponentValue(field, name, (Object)child))
531 goto error;
532
533 /*
534 * Remove local reference
535 */
536 DXDelete((Object)child);
537 child = NULL;
538
539 i++;
540 }
541
542 for (nDelete--; nDelete >= 0; nDelete--)
543 DXDeleteComponent(field, toDelete[nDelete]);
544
545 field = DXEndField(field);
546
547 done:
548 DXFree((Pointer)validPolylinesMap);
549 DXFree((Pointer)validPositionsMap);
550 DXFreeInvalidComponentHandle(vpHandle);
551 DXFreeInvalidComponentHandle(vplHandle);
552
553 return (Object)field;
554
555 error:
556 DXDelete((Object)nPlArray);
557 DXDelete((Object)nEArray);
558 DXDelete((Object)child);
559 DXFreeInvalidComponentHandle(vpHandle);
560 DXFreeInvalidComponentHandle(vplHandle);
561 DXFree((Pointer)validPolylinesMap);
562 DXFree((Pointer)validPositionsMap);
563
564 return NULL;
565 }
566
567 static Object
C_Field_FLE(Field field)568 C_Field_FLE(Field field)
569 {
570 Array pArray, fArray, lArray, eArray;
571 Array child, newChild;
572 int nPositions, nFaces, nLoops;
573 int nEdges, nInvP, nInvF;
574 int nNewPositions, nNewFaces;
575 int i, f, nfknt, nlknt, neknt;
576 int *validPositionsMap, *validFacesMap;
577 Object attr;
578 char *reference, *dependence;
579 char *name;
580 char *toDelete[32];
581 int nDelete = 0;
582 InvalidComponentHandle vpHandle = NULL;
583 InvalidComponentHandle vfHandle = NULL;
584 Array nLArray = NULL, nFArray = NULL, nEArray = NULL;
585 int *faces, *nfaces;
586 int *loops, *nloops;
587 int *edges, *nedges;
588
589 if (DXEmptyField(field))
590 return (Object)field;
591
592 vfHandle = NULL;
593 vpHandle = NULL;
594 validFacesMap = NULL;
595 validPositionsMap = NULL;
596 child = NULL;
597
598 pArray = (Array)DXGetComponentValue(field, "positions");
599 if (! pArray)
600 {
601 DXSetError(ERROR_MISSING_DATA, "positions component");
602 goto error;
603 }
604
605 if (! DXGetArrayInfo(pArray, &nPositions, NULL, NULL, NULL, NULL))
606 goto error;
607
608 fArray = (Array)DXGetComponentValue(field, "faces");
609 if (fArray)
610 {
611 if (! DXGetArrayInfo(fArray, &nFaces, NULL, NULL, NULL, NULL))
612 goto error;
613 }
614 else
615 nFaces = 0;
616
617 lArray = (Array)DXGetComponentValue(field, "loops");
618 if (lArray)
619 {
620 if (! DXGetArrayInfo(lArray, &nLoops, NULL, NULL, NULL, NULL))
621 goto error;
622 }
623 else
624 nLoops = 0;
625
626 eArray = (Array)DXGetComponentValue(field, "edges");
627 if (eArray)
628 {
629 if (! DXGetArrayInfo(eArray, &nEdges, NULL, NULL, NULL, NULL))
630 goto error;
631 }
632 else
633 nEdges = 0;
634
635 vpHandle = DXCreateInvalidComponentHandle((Object)field, NULL, "positions");
636 if (! vpHandle)
637 goto error;
638
639 nInvP = DXGetInvalidCount(vpHandle);
640 if (nInvP)
641 {
642 if (NULL == (validPositionsMap =
643 MakeMap(vpHandle, nPositions, &nNewPositions)))
644 goto error;
645
646 if (nNewPositions == 0)
647 {
648 if (! (Object)DeleteFieldContents(field))
649 goto error;
650
651 goto done;
652 }
653 }
654 else
655 {
656 DXFreeInvalidComponentHandle(vpHandle);
657 vpHandle = NULL;
658 }
659
660 if (fArray)
661 {
662 vfHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
663 "faces");
664 if (! vfHandle)
665 goto error;
666
667 nInvF = DXGetInvalidCount(vfHandle);
668 }
669 else
670 nInvF = 0;
671
672 if (nInvF)
673 {
674 if (NULL == (validFacesMap =
675 MakeMap(vfHandle, nFaces, &nNewFaces)))
676 goto error;
677 }
678 else
679 {
680 DXFreeInvalidComponentHandle(vfHandle);
681 vfHandle = NULL;
682 }
683
684 if (nInvP == 0 && nInvF == 0)
685 {
686 DXDeleteComponent(field, "invalid faces");
687 DXDeleteComponent(field, "invalid positions");
688 return (Object)field;
689 }
690
691 /*
692 * Handle polylines and edges components
693 */
694 faces = (int *)DXGetArrayData(fArray);
695 loops = (int *)DXGetArrayData(lArray);
696 edges = (int *)DXGetArrayData(eArray);
697
698 /*
699 * count the resulting loops and edges
700 */
701 for (f = 0, nfknt = nlknt = neknt = 0; f < nFaces; f++)
702 {
703 if (!vfHandle || DXIsElementValid(vfHandle, f))
704 {
705 int lstart = faces[f];
706 int lend = (f == nFaces-1) ? nLoops : faces[f+1];
707 int l;
708
709 for (l = lstart; l < lend; l++)
710 {
711 int estart = loops[l];
712 int eend = (l == nLoops-1) ? nEdges : loops[l+1];
713 neknt += eend - estart ;
714 }
715
716 nlknt += lend - lstart;
717 nfknt ++;
718 }
719 }
720
721 nFArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
722 nLArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
723 nEArray = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
724 if (! nFArray || ! nEArray || ! nLArray)
725 goto error;
726
727 if (! DXAddArrayData(nFArray, 0, nfknt, NULL))
728 goto error;
729
730 if (! DXAddArrayData(nLArray, 0, nlknt, NULL))
731 goto error;
732
733 if (! DXAddArrayData(nEArray, 0, neknt, NULL))
734 goto error;
735
736 nfaces = (int *)DXGetArrayData(nFArray);
737 nloops = (int *)DXGetArrayData(nLArray);
738 nedges = (int *)DXGetArrayData(nEArray);
739
740 for (f = 0, nfknt = neknt = nlknt = 0; f < nFaces; f++)
741 {
742 if (!vfHandle || DXIsElementValid(vfHandle, f))
743 {
744 int lstart = faces[f];
745 int lend = (f == nFaces-1) ? nLoops : faces[f+1];
746 int l;
747
748 nfaces[nfknt++] = nlknt;
749
750 for (l = lstart; l < lend; l++)
751 {
752 int estart = loops[l];
753 int eend = (l == nLoops-1) ? nEdges : loops[l+1];
754 int e;
755
756 nloops[nlknt++] = neknt;
757
758 for (e = estart; e < eend; e++)
759 nedges[neknt++] = edges[e];
760 }
761 }
762 }
763
764 if (! DXSetAttribute((Object)nFArray, "ref",
765 (Object)DXNewString("loops")))
766 goto error;
767
768 if (! DXSetComponentValue(field, "faces", (Object)nFArray))
769 goto error;
770 nFArray = NULL;
771
772 if (! DXSetAttribute((Object)nLArray, "ref",
773 (Object)DXNewString("edges")))
774 goto error;
775
776 if (! DXSetComponentValue(field, "loops", (Object)nLArray))
777 goto error;
778 nLArray = NULL;
779
780 if (! DXSetAttribute((Object)nEArray, "ref",
781 (Object)DXNewString("positions")))
782 goto error;
783
784 if (! DXSetComponentValue(field, "edges", (Object)nEArray))
785 goto error;
786 nEArray = NULL;
787
788 i = 0;
789 while (NULL !=
790 (child = (Array)DXGetEnumeratedComponentValue(field, i, &name)))
791 {
792 if (! strncmp(name, "invalid ", 8))
793 {
794 toDelete[nDelete++] = name;
795 i++;
796 continue;
797 }
798
799 if (! strcmp(name, "faces") ||
800 ! strcmp(name, "loops"))
801 {
802 i++;
803 continue;
804 }
805
806 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "der");
807 if (attr && strcmp(name, "neighbors"))
808 {
809 toDelete[nDelete++] = name;
810 i++;
811 continue;
812 }
813
814 DXReference((Object)child);
815
816 dependence = NULL;
817
818 if (! strcmp(name, "positions"))
819 dependence = "positions";
820 else if (! strcmp(name, "faces"))
821 dependence = "faces";
822 else
823 {
824 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "dep");
825 if (attr)
826 dependence = DXGetString((String)attr);
827 }
828
829 /*
830 * If the component is dependent on something, then do to the
831 * component whatever is appropriate for the component on which
832 * it is dependent.
833 */
834 if (dependence)
835 {
836 /*
837 * If its dependent on positions...
838 */
839 if (! strcmp(dependence, "positions"))
840 {
841 /*
842 * and there are invalidated positions, cull the component
843 */
844 if (vpHandle)
845 {
846 if (nNewPositions == 0)
847 {
848 toDelete[nDelete++] = name;
849 DXDelete((Object)child);
850 child = NULL;
851 i++;
852 continue;
853 }
854 else
855 {
856 newChild = CullArray(child, nPositions,
857 nNewPositions, vpHandle);
858 if (! newChild)
859 goto error;
860
861 DXDelete((Object)child);
862 child = (Array)DXReference((Object)newChild);
863 }
864 }
865 }
866 /*
867 * Else if its dependent on faces...
868 */
869 else if (! strcmp(dependence, "faces"))
870 {
871 if (! fArray)
872 {
873 DXSetError(ERROR_DATA_INVALID,
874 "component dependent on nonexistent faces");
875 goto error;
876 }
877
878 /*
879 * and there is a validFaces array, cull the component.
880 */
881 if (vfHandle)
882 {
883 if (nNewFaces == 0)
884 {
885 toDelete[nDelete++] = name;
886 DXDelete((Object)child);
887 child = NULL;
888 i++;
889 continue;
890 }
891 else
892 {
893 newChild = CullArray(child, nFaces,
894 nNewFaces, vfHandle);
895
896 if (! newChild)
897 goto error;
898
899 DXDelete((Object)child);
900 child = (Array)DXReference((Object)newChild);
901 }
902 }
903 }
904 }
905
906 /*
907 * Now we consider components that ref. If the component they ref
908 * has been culled, we need to renumber the references to reflect
909 * the culled referenced array.
910 */
911 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "ref");
912 if (attr)
913 {
914 reference = DXGetString((String)attr);
915
916 /*
917 * If it references faces...
918 */
919 if (!strcmp(reference, "faces"))
920 {
921 if (! fArray)
922 {
923 DXSetError(ERROR_DATA_INVALID,
924 "component refers to nonexistent faces");
925 goto error;
926 }
927
928 /*
929 * And faces have been culled, renumber the references.
930 */
931 if (validFacesMap)
932 {
933 newChild = _dxfReRef(child, validFacesMap);
934 if (! newChild)
935 goto error;
936
937 DXDelete((Object)child);
938 child = (Array)DXReference((Object)newChild);
939 }
940 }
941 /*
942 * Else if it references positions...
943 */
944 else if (!strcmp(reference, "positions"))
945 {
946 /*
947 * And positions have been culled, renumber the references.
948 */
949 if (validPositionsMap)
950 {
951 newChild = _dxfReRef(child, validPositionsMap);
952 if (! newChild)
953 goto error;
954
955 DXDelete((Object)child);
956 child = (Array)DXReference((Object)newChild);
957 }
958 }
959 }
960
961 if (! DXSetComponentValue(field, name, (Object)child))
962 goto error;
963
964 /*
965 * Remove local reference
966 */
967 DXDelete((Object)child);
968 child = NULL;
969
970 i++;
971 }
972
973 for (nDelete--; nDelete >= 0; nDelete--)
974 DXDeleteComponent(field, toDelete[nDelete]);
975
976 field = DXEndField(field);
977
978 done:
979 DXFree((Pointer)validFacesMap);
980 DXFree((Pointer)validPositionsMap);
981 DXFreeInvalidComponentHandle(vpHandle);
982 DXFreeInvalidComponentHandle(vfHandle);
983
984 return (Object)field;
985
986 error:
987 DXDelete((Object)nFArray);
988 DXDelete((Object)nLArray);
989 DXDelete((Object)nEArray);
990 DXDelete((Object)child);
991 DXFreeInvalidComponentHandle(vpHandle);
992 DXFreeInvalidComponentHandle(vfHandle);
993 DXFree((Pointer)validFacesMap);
994 DXFree((Pointer)validPositionsMap);
995
996 return NULL;
997 }
998
999 static Object
C_Field_Standard(Field field)1000 C_Field_Standard(Field field)
1001 {
1002 Array pArray, cArray;
1003 Array child, newChild;
1004 int nPositions, nConnections, nInvP, nInvC;
1005 int nNewPositions, nNewConnections;
1006 int i;
1007 int *validPositionsMap, *validConnectionsMap;
1008 Object attr;
1009 char *reference, *dependence;
1010 char *name;
1011 char *toDelete[32];
1012 int nDelete = 0;
1013 InvalidComponentHandle vpHandle = NULL;
1014 InvalidComponentHandle vcHandle = NULL;
1015
1016 if (DXEmptyField(field))
1017 return (Object)field;
1018
1019 vcHandle = NULL;
1020 vpHandle = NULL;
1021 validConnectionsMap = NULL;
1022 validPositionsMap = NULL;
1023 child = NULL;
1024
1025 pArray = (Array)DXGetComponentValue(field, "positions");
1026 if (! pArray)
1027 {
1028 DXSetError(ERROR_MISSING_DATA, "positions component");
1029 goto error;
1030 }
1031
1032 if (! DXGetArrayInfo(pArray, &nPositions, NULL, NULL, NULL, NULL))
1033 goto error;
1034
1035 cArray = (Array)DXGetComponentValue(field, "connections");
1036 if (cArray)
1037 {
1038 if (! DXGetArrayInfo(cArray, &nConnections, NULL, NULL, NULL, NULL))
1039 goto error;
1040 }
1041 else
1042 nConnections = 0;
1043
1044 vpHandle = DXCreateInvalidComponentHandle((Object)field, NULL, "positions");
1045 if (! vpHandle)
1046 goto error;
1047
1048 nInvP = DXGetInvalidCount(vpHandle);
1049 if (nInvP)
1050 {
1051 if (NULL == (validPositionsMap =
1052 MakeMap(vpHandle, nPositions, &nNewPositions)))
1053 goto error;
1054
1055 if (nNewPositions == 0)
1056 {
1057 if (! (Object)DeleteFieldContents(field))
1058 goto error;
1059
1060 goto done;
1061 }
1062 }
1063 else
1064 {
1065 DXFreeInvalidComponentHandle(vpHandle);
1066 vpHandle = NULL;
1067 }
1068
1069 if (cArray)
1070 {
1071 vcHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
1072 "connections");
1073 if (! vcHandle)
1074 goto error;
1075
1076 nInvC = DXGetInvalidCount(vcHandle);
1077 }
1078 else
1079 nInvC = 0;
1080
1081 if (nInvC)
1082 {
1083 if (NULL == (validConnectionsMap =
1084 MakeMap(vcHandle, nConnections, &nNewConnections)))
1085 goto error;
1086 }
1087 else
1088 {
1089 DXFreeInvalidComponentHandle(vcHandle);
1090 vcHandle = NULL;
1091 }
1092
1093 if (nInvP == 0 && nInvC == 0)
1094 {
1095 DXDeleteComponent(field, "invalid connections");
1096 DXDeleteComponent(field, "invalid positions");
1097 return (Object)field;
1098 }
1099
1100 i = 0;
1101 while (NULL !=
1102 (child = (Array)DXGetEnumeratedComponentValue(field, i, &name)))
1103 {
1104 if (! strncmp(name, "invalid ", 8))
1105 {
1106 toDelete[nDelete++] = name;
1107 i++;
1108 continue;
1109 }
1110
1111 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "der");
1112 if (attr && strcmp(name, "neighbors"))
1113 {
1114 toDelete[nDelete++] = name;
1115 i++;
1116 continue;
1117 }
1118
1119 DXReference((Object)child);
1120
1121 dependence = NULL;
1122
1123 if (! strcmp(name, "positions"))
1124 dependence = "positions";
1125 else if (! strcmp(name, "connections"))
1126 dependence = "connections";
1127 else
1128 {
1129 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "dep");
1130 if (attr)
1131 dependence = DXGetString((String)attr);
1132 }
1133
1134 /*
1135 * If the component is dependent on something, then do to the
1136 * component whatever is appropriate for the component on which
1137 * it is dependent.
1138 */
1139 if (dependence)
1140 {
1141 /*
1142 * If its dependent on positions...
1143 */
1144 if (! strcmp(dependence, "positions"))
1145 {
1146 /*
1147 * and there are invalidated positions, cull the component
1148 */
1149 if (vpHandle)
1150 {
1151 if (nNewPositions == 0)
1152 {
1153 toDelete[nDelete++] = name;
1154 DXDelete((Object)child);
1155 child = NULL;
1156 i++;
1157 continue;
1158 }
1159 else
1160 {
1161 newChild = CullArray(child, nPositions,
1162 nNewPositions, vpHandle);
1163 if (! newChild)
1164 goto error;
1165
1166 DXDelete((Object)child);
1167 child = (Array)DXReference((Object)newChild);
1168 }
1169 }
1170 }
1171 /*
1172 * Else if its dependent on connections...
1173 */
1174 else if (! strcmp(dependence, "connections"))
1175 {
1176 if (! cArray)
1177 {
1178 DXSetError(ERROR_DATA_INVALID,
1179 "component dependent on nonexistent connections");
1180 goto error;
1181 }
1182
1183 /*
1184 * and there is a validConnections array, cull the component.
1185 */
1186 if (vcHandle)
1187 {
1188 if (nNewConnections == 0)
1189 {
1190 toDelete[nDelete++] = name;
1191 DXDelete((Object)child);
1192 child = NULL;
1193 i++;
1194 continue;
1195 }
1196 else
1197 {
1198 newChild = CullArray(child, nConnections,
1199 nNewConnections, vcHandle);
1200
1201 if (! newChild)
1202 goto error;
1203
1204 DXDelete((Object)child);
1205 child = (Array)DXReference((Object)newChild);
1206 }
1207 }
1208 }
1209 }
1210
1211 /*
1212 * Now we consider components that ref. If the component they ref
1213 * has been culled, we need to renumber the references to reflect
1214 * the culled referenced array.
1215 */
1216 attr = DXGetEnumeratedComponentAttribute(field, i, NULL, "ref");
1217 if (attr)
1218 {
1219 reference = DXGetString((String)attr);
1220
1221 /*
1222 * If it references connections...
1223 */
1224 if (!strcmp(reference, "connections"))
1225 {
1226 if (! cArray)
1227 {
1228 DXSetError(ERROR_DATA_INVALID,
1229 "component refers to nonexistent connections");
1230 goto error;
1231 }
1232
1233 /*
1234 * And connections have been culled, renumber the references.
1235 */
1236 if (validConnectionsMap)
1237 {
1238 newChild = _dxfReRef(child, validConnectionsMap);
1239 if (! newChild)
1240 goto error;
1241
1242 DXDelete((Object)child);
1243 child = (Array)DXReference((Object)newChild);
1244 }
1245 }
1246 /*
1247 * Else if it references positions...
1248 */
1249 else if (!strcmp(reference, "positions"))
1250 {
1251 /*
1252 * And positions have been culled, renumber the references.
1253 */
1254 if (validPositionsMap)
1255 {
1256 newChild = _dxfReRef(child, validPositionsMap);
1257 if (! newChild)
1258 goto error;
1259
1260 DXDelete((Object)child);
1261 child = (Array)DXReference((Object)newChild);
1262 }
1263 }
1264 }
1265
1266 if (! DXSetComponentValue(field, name, (Object)child))
1267 goto error;
1268
1269 /*
1270 * Remove local reference
1271 */
1272 DXDelete((Object)child);
1273 child = NULL;
1274
1275 i++;
1276 }
1277
1278 for (nDelete--; nDelete >= 0; nDelete--)
1279 DXDeleteComponent(field, toDelete[nDelete]);
1280
1281 field = DXEndField(field);
1282
1283 done:
1284 DXFree((Pointer)validConnectionsMap);
1285 DXFree((Pointer)validPositionsMap);
1286 DXFreeInvalidComponentHandle(vpHandle);
1287 DXFreeInvalidComponentHandle(vcHandle);
1288
1289 return (Object)field;
1290
1291 error:
1292 DXDelete((Object)child);
1293 DXFreeInvalidComponentHandle(vpHandle);
1294 DXFreeInvalidComponentHandle(vcHandle);
1295 DXFree((Pointer)validConnectionsMap);
1296 DXFree((Pointer)validPositionsMap);
1297
1298 return NULL;
1299 }
1300
1301 static Array
CullArray(Array oldArray,int nOld,int nNew,InvalidComponentHandle handle)1302 CullArray(Array oldArray, int nOld, int nNew, InvalidComponentHandle handle)
1303 {
1304 Array newArray;
1305 Type type;
1306 Category cat;
1307 int rank;
1308 int shape[100];
1309 Pointer buf = NULL;
1310 ArrayHandle aHandle = NULL;
1311
1312 DXGetArrayInfo(oldArray, NULL, &type, &cat, &rank, shape);
1313
1314 if (DXQueryConstantArray(oldArray, NULL, NULL))
1315 {
1316 newArray = (Array)DXNewConstantArrayV(nNew,
1317 DXGetConstantArrayData((Array)oldArray), type, cat, rank, shape);
1318 }
1319 else
1320 {
1321 int itemSize, i, nKnt;
1322 ubyte *nPtr;
1323
1324 itemSize = DXGetItemSize(oldArray);
1325 buf = DXAllocate(itemSize);
1326 aHandle = DXCreateArrayHandle(oldArray);
1327 newArray = DXNewArrayV(type, cat, rank, shape);
1328 if (! buf || ! aHandle || ! newArray)
1329 goto error;
1330
1331 if (! DXAddArrayData(newArray, 0, nNew, NULL))
1332 goto error;
1333
1334 nPtr = (ubyte *)DXGetArrayData(newArray);
1335
1336 for (i = 0, nKnt = 0; i < nOld; i++)
1337 if (! DXIsElementInvalidSequential(handle, i))
1338 {
1339 memcpy(nPtr, DXGetArrayEntry(aHandle, i, buf), itemSize);
1340 nPtr += itemSize;
1341 if (++nKnt > nNew)
1342 {
1343 DXSetError(ERROR_INTERNAL, "invalid count mismatch");
1344 goto error;
1345 }
1346 }
1347
1348 DXFree(buf); buf = NULL;
1349 DXFreeArrayHandle(aHandle); aHandle = NULL;
1350 }
1351
1352 return newArray;
1353
1354 error:
1355 DXFree(buf);
1356 DXFreeArrayHandle(aHandle);
1357 DXDelete((Object)newArray);
1358 return NULL;
1359 }
1360
1361 static Array
_dxfReRef(Array oldArray,int * map)1362 _dxfReRef(Array oldArray, int *map)
1363 {
1364 Array newArray;
1365 Type type;
1366 Category cat;
1367 int rank, shape[32];
1368 int *oldPtr, *newPtr;
1369 int i, itemSize;
1370 int nElements;
1371
1372 if (! DXGetArrayInfo(oldArray, &nElements, &type, &cat, &rank, shape))
1373 return NULL;
1374
1375 if (type != TYPE_INT || cat != CATEGORY_REAL)
1376 {
1377 DXSetError(ERROR_DATA_INVALID, "invalid data array is not int/real");
1378 return NULL;
1379 }
1380
1381 itemSize = 1;
1382 for(i = 0; i < rank; i++)
1383 itemSize *= shape[i];
1384
1385 if (NULL == (oldPtr = (int *)DXGetArrayData(oldArray)))
1386 return NULL;
1387
1388 if (NULL == (newArray = DXNewArrayV(type, cat, rank, shape)))
1389 return NULL;
1390
1391 if (! DXAddArrayData(newArray, 0, nElements, NULL))
1392 {
1393 DXDelete((Object)newArray);
1394 return NULL;
1395 }
1396
1397 if (NULL == (newPtr = (int *)DXGetArrayData(newArray)))
1398 {
1399 DXDelete((Object)newArray);
1400 return NULL;
1401 }
1402
1403 if (NULL == (oldPtr = (int *)DXGetArrayData(oldArray)))
1404 {
1405 DXDelete((Object)newArray);
1406 return NULL;
1407 }
1408
1409 for (i = 0; i < nElements*itemSize; i++)
1410 {
1411 if (*oldPtr != -1)
1412 *newPtr = map[*oldPtr];
1413 else
1414 *newPtr = -1;
1415
1416 oldPtr++;
1417 newPtr++;
1418 }
1419
1420 return newArray;
1421 }
1422
1423 static int *
MakeMap(InvalidComponentHandle handle,int nIn,int * nNew)1424 MakeMap(InvalidComponentHandle handle, int nIn, int *nNew)
1425 {
1426 int *map;
1427 int i, j;
1428
1429 map = (int *)DXAllocate(nIn * sizeof(int));
1430 if (! map)
1431 return NULL;
1432
1433 for (i = 0, j = 0; i < nIn; i++)
1434 if (DXIsElementInvalidSequential(handle, i))
1435 map[i] = -1;
1436 else
1437 map[i] = j++;
1438
1439 *nNew = j;
1440
1441 return map;
1442 }
1443
1444 /*
1445 * Any connections referencing invalidated positions are invalidated.
1446 */
1447 static Object
IC_Field(Field field)1448 IC_Field(Field field)
1449 {
1450 if (DXGetComponentValue(field, "polylines"))
1451 {
1452 return IC_Field_PE(field);
1453 }
1454 else if (DXGetComponentValue(field, "faces"))
1455 {
1456 return IC_Field_FLE(field);
1457 }
1458 else
1459 {
1460 return IC_Field_Standard(field);
1461 }
1462 }
1463
1464 /*
1465 * Any polylines referencing invalidated positions are invalidated.
1466 */
1467 static Object
IC_Field_PE(Field field)1468 IC_Field_PE(Field field)
1469 {
1470 Array plArray, eArray;
1471 InvalidComponentHandle vp = NULL, vplIn = NULL, vplOut = NULL;
1472 int i, j;
1473 int nPl, nE;
1474 int *polylines = NULL, *edges = NULL;
1475
1476 if (DXEmptyField(field))
1477 return (Object)field;
1478
1479 /*
1480 * If there are no polylines, then there are none to invalidate
1481 */
1482 if (NULL == (plArray = (Array)DXGetComponentValue(field, "polylines")))
1483 return (Object)field;
1484
1485 if (! DXGetArrayInfo(plArray, &nPl, NULL, NULL, NULL, NULL))
1486 goto error;
1487
1488
1489 if (nPl == 0)
1490 return (Object)field;
1491
1492 eArray = (Array)DXGetComponentValue(field, "edges");
1493 if (! eArray)
1494 {
1495 DXSetError(ERROR_DATA_INVALID, "polylines with no edges");
1496 goto error;
1497 }
1498
1499 if (! DXGetArrayInfo(eArray, &nE, NULL, NULL, NULL, NULL))
1500 goto error;
1501
1502 vplIn = NULL;
1503 vplOut = NULL;
1504
1505 /*
1506 * Get the valid positions array. If there isn't one, then we
1507 * assume all positions are valid and there's nothing to do.
1508 */
1509 vp = DXCreateInvalidComponentHandle((Object)field, NULL,
1510 "positions");
1511 if (! vp)
1512 goto error;
1513
1514 if (DXGetInvalidCount(vp) == 0)
1515 {
1516 DXFreeInvalidComponentHandle(vp);
1517 return (Object)field;
1518 }
1519
1520 vplIn = DXCreateInvalidComponentHandle((Object)field, NULL,
1521 "polylines");
1522 if (! vplIn)
1523 goto error;
1524
1525 if (DXGetInvalidCount(vplIn) == 0)
1526 {
1527 DXFreeInvalidComponentHandle(vplIn);
1528 vplIn = NULL;
1529 }
1530
1531 polylines = (int *)DXGetArrayData(plArray);
1532 edges = (int *)DXGetArrayData(eArray);
1533
1534 /*
1535 * For each connections element, consider each referent. If its
1536 * invalid, invalidate the connections element.
1537 */
1538 for (i = 0; i < nPl; i++)
1539 {
1540 int valid = !vplIn || !DXIsElementInvalidSequential(vplIn, i);
1541
1542 if (valid)
1543 {
1544 int start = polylines[i];
1545 int end = (i == nPl-1) ? nE - 1 : polylines[i+1] - 1;
1546
1547 for (j = start; j <= end && valid; j++)
1548 valid = ! DXIsElementInvalid(vp, edges[start+j]);
1549 }
1550
1551 if (! valid)
1552 {
1553 /*
1554 * If we haven't invalidated anything yet,
1555 * we need to set up the invalid connections
1556 * array, creating one and initializing it
1557 * if necessary.
1558 */
1559 if (! vplOut)
1560 {
1561 vplOut = DXCreateInvalidComponentHandle((Object)field, NULL,
1562 "polylines");
1563
1564 if (! vplOut)
1565 goto error;
1566 }
1567
1568 if (! DXSetElementInvalid(vplOut, i))
1569 goto error;
1570 }
1571 }
1572
1573 if (vplOut)
1574 {
1575 if (! DXSaveInvalidComponent(field, vplOut))
1576 goto error;
1577 }
1578
1579 DXFreeInvalidComponentHandle(vp);
1580 DXFreeInvalidComponentHandle(vplIn);
1581 DXFreeInvalidComponentHandle(vplOut);
1582
1583 return (Object)field;
1584
1585 error:
1586
1587 DXFreeInvalidComponentHandle(vp);
1588 DXFreeInvalidComponentHandle(vplIn);
1589 DXFreeInvalidComponentHandle(vplOut);
1590
1591 return NULL;
1592 }
1593
1594 /*
1595 * Any faces referencing invalidated positions are invalidated.
1596 */
1597 static Object
IC_Field_FLE(Field field)1598 IC_Field_FLE(Field field)
1599 {
1600 Array fArray, lArray, eArray;
1601 InvalidComponentHandle vp = NULL, vfIn = NULL, vfOut = NULL;
1602 int face;
1603 int nF, nL, nE;
1604 int *faces = NULL, *loops = NULL, *edges = NULL;
1605
1606 if (DXEmptyField(field))
1607 return (Object)field;
1608
1609 /*
1610 * If there are no faces, then there are none to invalidate
1611 */
1612 if (NULL == (fArray = (Array)DXGetComponentValue(field, "faces")))
1613 return (Object)field;
1614
1615 if (! DXGetArrayInfo(fArray, &nF, NULL, NULL, NULL, NULL))
1616 goto error;
1617
1618 if (nF == 0)
1619 return (Object)field;
1620
1621 lArray = (Array)DXGetComponentValue(field, "loops");
1622 if (! lArray)
1623 {
1624 DXSetError(ERROR_DATA_INVALID, "faces with no loops");
1625 goto error;
1626 }
1627
1628 if (! DXGetArrayInfo(lArray, &nL, NULL, NULL, NULL, NULL))
1629 goto error;
1630
1631 eArray = (Array)DXGetComponentValue(field, "edges");
1632 if (! eArray)
1633 {
1634 DXSetError(ERROR_DATA_INVALID, "faces with no edges");
1635 goto error;
1636 }
1637
1638 if (! DXGetArrayInfo(eArray, &nE, NULL, NULL, NULL, NULL))
1639 goto error;
1640
1641 vfIn = NULL;
1642 vfOut = NULL;
1643
1644 /*
1645 * Get the valid positions array. If there isn't one, then we
1646 * assume all positions are valid and there's nothing to do.
1647 */
1648 vp = DXCreateInvalidComponentHandle((Object)field, NULL,
1649 "positions");
1650 if (! vp)
1651 goto error;
1652
1653 if (DXGetInvalidCount(vp) == 0)
1654 {
1655 DXFreeInvalidComponentHandle(vp);
1656 return (Object)field;
1657 }
1658
1659 vfIn = DXCreateInvalidComponentHandle((Object)field, NULL,
1660 "faces");
1661 if (! vfIn)
1662 goto error;
1663
1664 if (DXGetInvalidCount(vfIn) == 0)
1665 {
1666 DXFreeInvalidComponentHandle(vfIn);
1667 vfIn = NULL;
1668 }
1669
1670 faces = (int *)DXGetArrayData(fArray);
1671 loops = (int *)DXGetArrayData(lArray);
1672 edges = (int *)DXGetArrayData(eArray);
1673
1674 /*
1675 * For each connections element, consider each referent. If its
1676 * invalid, invalidate the connections element.
1677 */
1678 for (face = 0; face < nF; face++)
1679 {
1680 int valid = !vfIn || !DXIsElementInvalidSequential(vfIn, face);
1681
1682 if (valid)
1683 {
1684 int lstart = faces[face];
1685 int lend = (face == nF-1) ? nL : faces[face+1];
1686 int loop;
1687
1688 for (loop = lstart; loop < lend && valid; loop++)
1689 {
1690 int estart = loops[loop];
1691 int eend = (loop == nL-1) ? nE : loops[loop+1];
1692 int edge;
1693
1694 for (edge = estart; edge < eend && valid; edge++)
1695 valid = ! DXIsElementInvalid(vp, edges[edge]);
1696 }
1697 }
1698
1699 if (! valid)
1700 {
1701 /*
1702 * If we haven't invalidated anything yet,
1703 * we need to set up the invalid connections
1704 * array, creating one and initializing it
1705 * if necessary.
1706 */
1707 if (! vfOut)
1708 {
1709 vfOut = DXCreateInvalidComponentHandle((Object)field, NULL,
1710 "faces");
1711
1712 if (! vfOut)
1713 goto error;
1714 }
1715
1716 if (! DXSetElementInvalid(vfOut, face))
1717 goto error;
1718 }
1719 }
1720
1721 if (vfOut)
1722 {
1723 if (! DXSaveInvalidComponent(field, vfOut))
1724 goto error;
1725 }
1726
1727 DXFreeInvalidComponentHandle(vp);
1728 DXFreeInvalidComponentHandle(vfIn);
1729 DXFreeInvalidComponentHandle(vfOut);
1730
1731 return (Object)field;
1732
1733 error:
1734
1735 DXFreeInvalidComponentHandle(vp);
1736 DXFreeInvalidComponentHandle(vfIn);
1737 DXFreeInvalidComponentHandle(vfOut);
1738
1739 return NULL;
1740 }
1741
1742 /*
1743 * Any connections referencing invalidated positions are invalidated.
1744 */
1745 static Object
IC_Field_Standard(Field field)1746 IC_Field_Standard(Field field)
1747 {
1748 Array cArray;
1749 InvalidComponentHandle vp = NULL, vcIn = NULL, vcOut = NULL;
1750 int ptsPerPrim;
1751 int *cPtr = NULL;
1752 int i, j, nCons;
1753 ArrayHandle cHandle = NULL;
1754 Pointer cBuf = NULL;
1755
1756 if (DXEmptyField(field))
1757 return (Object)field;
1758
1759 /*
1760 * If there are no connections, then there are none to invalidate
1761 */
1762 if (NULL == (cArray = (Array)DXGetComponentValue(field, "connections")))
1763 return (Object)field;
1764
1765 vcIn = NULL;
1766 vcOut = NULL;
1767
1768 /*
1769 * Get the valid positions array. If there isn't one, then we
1770 * assume all positions are valid and there's nothing to do.
1771 */
1772 vp = DXCreateInvalidComponentHandle((Object)field, NULL,
1773 "positions");
1774 if (! vp)
1775 goto error;
1776
1777 if (DXGetInvalidCount(vp) == 0)
1778 {
1779 DXFreeInvalidComponentHandle(vp);
1780 return (Object)field;
1781 }
1782
1783 vcIn = DXCreateInvalidComponentHandle((Object)field, NULL,
1784 "connections");
1785 if (! vcIn)
1786 goto error;
1787
1788 if (DXGetInvalidCount(vcIn) == 0)
1789 {
1790 DXFreeInvalidComponentHandle(vcIn);
1791 vcIn = NULL;
1792 }
1793
1794 cBuf = DXAllocate(DXGetItemSize(cArray));
1795 if (! cBuf)
1796 goto error;
1797
1798 cHandle = DXCreateArrayHandle(cArray);
1799 if (! cHandle)
1800 goto error;
1801
1802 if (! DXGetArrayInfo(cArray, &nCons, NULL, NULL, NULL, &ptsPerPrim))
1803 goto error;
1804
1805 /*
1806 * For each connections element, consider each referent. If its
1807 * invalid, invalidate the connections element.
1808 */
1809 for (i = 0; i < nCons; i++)
1810 {
1811 int valid = !vcIn || !DXIsElementInvalidSequential(vcIn, i);
1812
1813 if (valid)
1814 {
1815 cPtr = (int *)DXGetArrayEntry(cHandle, i, (Pointer)cBuf);
1816
1817 for (j = 0; j < ptsPerPrim && valid; j++)
1818 valid = ! DXIsElementInvalid(vp, cPtr[j]);
1819 }
1820
1821 if (! valid)
1822 {
1823 /*
1824 * If we haven't invalidated anything yet,
1825 * we need to set up the invalid connections
1826 * array, creating one and initializing it
1827 * if necessary.
1828 */
1829 if (! vcOut)
1830 {
1831 vcOut = DXCreateInvalidComponentHandle((Object)field, NULL,
1832 "connections");
1833
1834 if (! vcOut)
1835 goto error;
1836 }
1837
1838 if (! DXSetElementInvalid(vcOut, i))
1839 goto error;
1840 }
1841 }
1842
1843 if (vcOut)
1844 {
1845 if (! DXSaveInvalidComponent(field, vcOut))
1846 goto error;
1847 }
1848
1849 DXFree(cBuf);
1850 DXFreeArrayHandle(cHandle);
1851 DXFreeInvalidComponentHandle(vp);
1852 DXFreeInvalidComponentHandle(vcIn);
1853 DXFreeInvalidComponentHandle(vcOut);
1854
1855 return (Object)field;
1856
1857 error:
1858
1859 DXFree(cBuf);
1860 DXFreeArrayHandle(cHandle);
1861 DXFreeInvalidComponentHandle(vp);
1862 DXFreeInvalidComponentHandle(vcIn);
1863 DXFreeInvalidComponentHandle(vcOut);
1864
1865 return NULL;
1866 }
1867
1868 /*
1869 * Any connections referencing invalidated positions are invalidated.
1870 */
1871 static Object
IUP_Field(Field field)1872 IUP_Field(Field field)
1873 {
1874 if (DXGetComponentValue(field, "polylines"))
1875 {
1876 return IUP_Field_PE(field);
1877 }
1878 else if (DXGetComponentValue(field, "faces"))
1879 {
1880 return IUP_Field_FLE(field);
1881 }
1882 else
1883 {
1884 return IUP_Field_Standard(field);
1885 }
1886 }
1887
1888 static Object
IUP_Field_Standard(Field field)1889 IUP_Field_Standard(Field field)
1890 {
1891 Array pArray, cArray;
1892 InvalidComponentHandle vpHandle = NULL, vcHandle = NULL;
1893 int *refs = NULL, *cons;
1894 int i, j, ptsPerPrim, nCons, nPts;
1895 int unReffedPositions;
1896 ArrayHandle cHandle = NULL;
1897 Pointer cBuf = NULL;
1898
1899 if (DXEmptyField(field))
1900 return (Object)field;
1901
1902 if (NULL == (pArray = (Array)DXGetComponentValue(field, "positions")))
1903 return (Object)field;
1904
1905 if (! DXGetArrayInfo(pArray, &nPts, NULL, NULL, NULL, NULL))
1906 goto error;
1907
1908 /*
1909 * Allow for no connections component... If none are present, all
1910 * positions are invalidated
1911 */
1912 if (NULL == (cArray = (Array)DXGetComponentValue(field, "connections")))
1913 {
1914 Array invPos;
1915 byte valid;
1916
1917 valid = DATA_INVALID;
1918
1919 invPos = (Array)DXNewConstantArray(nPts, (Pointer)&valid,
1920 TYPE_UBYTE, CATEGORY_REAL, 0);
1921 if (! invPos)
1922 goto error;
1923
1924 if (! DXSetComponentValue(field, "invalid positions", (Object)invPos))
1925 goto error;
1926
1927 if (! DXSetComponentAttribute(field, "invalid positions", "dep",
1928 (Object)DXNewString("positions")))
1929 goto error;
1930
1931 goto done;
1932 }
1933
1934 /*
1935 * Get the valid connections information
1936 */
1937 vcHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
1938 "connections");
1939 if (! vcHandle)
1940 goto error;
1941
1942 /*
1943 * If no connections are invalidated, we have regular positions and
1944 * connections and the counts match, all are valid - take the fast
1945 * path.
1946 */
1947 if (DXGetInvalidCount(vcHandle) == 0)
1948 {
1949 int nRef = GridSize(cArray);
1950 if (nRef == ERROR_OCCURRED)
1951 goto error;
1952 else if (nRef != HOLES_FOUND && nRef == nPts)
1953 goto done;
1954 }
1955
1956 if (! DXGetArrayInfo(cArray, &nCons, NULL, NULL, NULL, &ptsPerPrim))
1957 return NULL;
1958
1959 cHandle = DXCreateArrayHandle(cArray);
1960 if (! cHandle)
1961 goto error;
1962
1963 cBuf = DXAllocate(DXGetItemSize(cArray));
1964 if (! cBuf)
1965 goto error;
1966
1967 if (NULL == (refs = (int *)DXAllocateZero(nPts*sizeof(int))))
1968 return NULL;
1969
1970 /*
1971 * Assume that we have already invalidated the connections.
1972 * If there's no valid connections input info, assume all connection
1973 * elements are valid. Otherwise, test on an element by element basis
1974 */
1975 for (i = 0; i < nCons; i++)
1976 {
1977 if (! DXIsElementInvalidSequential(vcHandle, i))
1978 {
1979 cons = (int *)DXGetArrayEntry(cHandle, i, cBuf);
1980
1981 for (j = 0; j < ptsPerPrim; j++)
1982 refs[*cons++]++;
1983 }
1984 }
1985
1986 /*
1987 * See if we have any unreffed positions
1988 */
1989 for (i = 0; i < nPts; i++)
1990 if (! refs[i])
1991 break;
1992
1993 if (i != nPts)
1994 unReffedPositions = 1;
1995 else
1996 unReffedPositions = 0;
1997
1998 vpHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
1999 "positions");
2000 if (! vpHandle)
2001 goto error;
2002
2003 /*
2004 * Invalidate unreferenced positions
2005 */
2006 if (unReffedPositions)
2007 {
2008 for (i = 0; i < nPts; i++)
2009 if (! refs[i])
2010 DXSetElementInvalid(vpHandle, i);
2011 }
2012
2013 if (! DXSaveInvalidComponent(field, vpHandle))
2014 goto error;
2015
2016 done:
2017 DXFreeInvalidComponentHandle(vcHandle);
2018 DXFreeInvalidComponentHandle(vpHandle);
2019 DXFreeArrayHandle(cHandle);
2020 DXFree(cBuf);
2021 DXFree((Pointer)refs);
2022
2023 return (Object)field;
2024
2025 error:
2026 DXFreeInvalidComponentHandle(vcHandle);
2027 DXFreeInvalidComponentHandle(vpHandle);
2028 DXFreeArrayHandle(cHandle);
2029 DXFree(cBuf);
2030 DXFree((Pointer)refs);
2031 return NULL;
2032 }
2033
2034 static Object
IUP_Field_PE(Field field)2035 IUP_Field_PE(Field field)
2036 {
2037 Array pArray, plArray, eArray;
2038 InvalidComponentHandle vpHandle = NULL, vplHandle = NULL;
2039 ubyte *refs = NULL;
2040 int i, j, nPls, nEs, nPts;
2041 int unReffedPositions;
2042 ArrayHandle plHandle = NULL, eHandle = NULL;
2043
2044 if (DXEmptyField(field))
2045 return (Object)field;
2046
2047 if (NULL == (pArray = (Array)DXGetComponentValue(field, "positions")))
2048 return (Object)field;
2049
2050 if (! DXGetArrayInfo(pArray, &nPts, NULL, NULL, NULL, NULL))
2051 goto error;
2052
2053 /*
2054 * We wouldn't get here unless we found a polylines component
2055 */
2056 plArray = (Array)DXGetComponentValue(field, "polylines");
2057
2058 eArray = (Array)DXGetComponentValue(field, "edges");
2059 if (! eArray)
2060 {
2061 DXSetError(ERROR_DATA_INVALID, "polylines with no edges component");
2062 goto error;
2063 }
2064
2065 plHandle = DXCreateArrayHandle(plArray);
2066 eHandle = DXCreateArrayHandle(eArray);
2067 if (! plHandle || ! eHandle)
2068 goto error;
2069
2070 DXGetArrayInfo(plArray, &nPls, NULL, NULL, NULL, NULL);
2071 DXGetArrayInfo(eArray, &nEs, NULL, NULL, NULL, NULL);
2072 DXGetArrayInfo(pArray, &nPts, NULL, NULL, NULL, NULL);
2073
2074 refs = (ubyte *)DXAllocateZero(nPts*sizeof(ubyte));
2075 if (! refs)
2076 goto error;
2077
2078 /*
2079 * Get the valid connections information
2080 */
2081 vplHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
2082 "polylines");
2083 if (! vplHandle)
2084 goto error;
2085
2086 /*
2087 * Assume that we have already invalidated the connections.
2088 * If there's no valid connections input info, assume all connection
2089 * elements are valid. Otherwise, test on an element by element basis
2090 */
2091 for (i = 0; i < nPls; i++)
2092 {
2093 if (! DXIsElementInvalidSequential(vplHandle, i))
2094 {
2095 int startBuf, *start;
2096 int endBuf, *end;
2097
2098 start = (int *)DXGetArrayEntry(plHandle, i, (Pointer)&startBuf);
2099 if (i == (nPls-1))
2100 end = &nEs;
2101 else
2102 end = (int *)DXGetArrayEntry(plHandle, i+1, (Pointer)&endBuf);
2103
2104 for (j = *start; j < *end; j++)
2105 {
2106 int ptrBuf, *ptr;
2107
2108 ptr = (int *)DXGetArrayEntry(eHandle, j, (Pointer)&ptrBuf);
2109 refs[*ptr] = 1;
2110 }
2111 }
2112 }
2113
2114 /*
2115 * See if we have any unreffed positions
2116 */
2117 for (i = 0; i < nPts; i++)
2118 if (! refs[i])
2119 break;
2120
2121 if (i != nPts)
2122 unReffedPositions = 1;
2123 else
2124 unReffedPositions = 0;
2125
2126 vpHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
2127 "positions");
2128 if (! vpHandle)
2129 goto error;
2130
2131 /*
2132 * Invalidate unreferenced positions
2133 */
2134 if (unReffedPositions)
2135 {
2136 for (i = 0; i < nPts; i++)
2137 if (! refs[i])
2138 DXSetElementInvalid(vpHandle, i);
2139 }
2140
2141 if (! DXSaveInvalidComponent(field, vpHandle))
2142 goto error;
2143
2144 /* done: */
2145 DXFreeInvalidComponentHandle(vpHandle);
2146 DXFreeInvalidComponentHandle(vplHandle);
2147 DXFreeArrayHandle(plHandle);
2148 DXFreeArrayHandle(eHandle);
2149 DXFree((Pointer)refs);
2150
2151 return (Object)field;
2152
2153 error:
2154 DXFreeInvalidComponentHandle(vpHandle);
2155 DXFreeInvalidComponentHandle(vplHandle);
2156 DXFreeArrayHandle(plHandle);
2157 DXFreeArrayHandle(eHandle);
2158 DXFree((Pointer)refs);
2159
2160 return NULL;
2161 }
2162
2163 static Object
IUP_Field_FLE(Field field)2164 IUP_Field_FLE(Field field)
2165 {
2166 Array pArray, fArray, lArray, eArray;
2167 InvalidComponentHandle vpHandle = NULL, vfHandle = NULL;
2168 ubyte *refs = NULL;
2169 int f, e, i, nFs, nLs, nEs, nPts;
2170 int unReffedPositions;
2171 ArrayHandle fHandle = NULL, lHandle = NULL, eHandle = NULL;
2172
2173 if (DXEmptyField(field))
2174 return (Object)field;
2175
2176 if (NULL == (pArray = (Array)DXGetComponentValue(field, "positions")))
2177 return (Object)field;
2178
2179 if (! DXGetArrayInfo(pArray, &nPts, NULL, NULL, NULL, NULL))
2180 goto error;
2181
2182 /*
2183 * We wouldn't get here unless we found a polylines component
2184 */
2185 fArray = (Array)DXGetComponentValue(field, "faces");
2186
2187 lArray = (Array)DXGetComponentValue(field, "loops");
2188 eArray = (Array)DXGetComponentValue(field, "edges");
2189 if (! eArray || ! lArray)
2190 {
2191 DXSetError(ERROR_DATA_INVALID,
2192 "faces with no edges or loops component");
2193 goto error;
2194 }
2195
2196 fHandle = DXCreateArrayHandle(fArray);
2197 lHandle = DXCreateArrayHandle(lArray);
2198 eHandle = DXCreateArrayHandle(eArray);
2199 if (! fHandle || ! lHandle || ! eHandle)
2200 goto error;
2201
2202 DXGetArrayInfo(fArray, &nFs, NULL, NULL, NULL, NULL);
2203 DXGetArrayInfo(lArray, &nLs, NULL, NULL, NULL, NULL);
2204 DXGetArrayInfo(eArray, &nEs, NULL, NULL, NULL, NULL);
2205 DXGetArrayInfo(pArray, &nPts, NULL, NULL, NULL, NULL);
2206
2207 refs = (ubyte *)DXAllocateZero(nPts*sizeof(ubyte));
2208 if (! refs)
2209 goto error;
2210
2211 /*
2212 * Get the valid connections information
2213 */
2214 vfHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
2215 "faces");
2216 if (! vfHandle)
2217 goto error;
2218
2219 /*
2220 * Assume that we have already invalidated the connections.
2221 * If there's no valid connections input info, assume all connection
2222 * elements are valid. Otherwise, test on an element by element basis
2223 */
2224 for (f = 0; f < nFs; f++)
2225 {
2226 int lStartBuf, *lStart;
2227 int lEndBuf, *lEnd;
2228 int l;
2229
2230 if (DXIsElementInvalidSequential(vfHandle, f))
2231 continue;
2232
2233 lStart = (int *)DXGetArrayEntry(fHandle, f, (Pointer)&lStartBuf);
2234 if (f == (nFs-1))
2235 lEnd = &nLs;
2236 else
2237 lEnd = (int *)DXGetArrayEntry(fHandle, f+1, (Pointer)&lEndBuf);
2238
2239 for (l = *lStart; l < *lEnd; l++)
2240 {
2241 int eStartBuf, *eStart;
2242 int eEndBuf, *eEnd;
2243
2244 eStart = (int *)DXGetArrayEntry(lHandle, l, (Pointer)&eStartBuf);
2245 if (l == (nLs-1))
2246 eEnd = &nEs;
2247 else
2248 eEnd = (int *)DXGetArrayEntry(lHandle, l+1, (Pointer)&eEndBuf);
2249
2250 for (e = *eStart; e < *eEnd; e++)
2251 {
2252 int ptrBuf, *ptr;
2253
2254 ptr = (int *)DXGetArrayEntry(eHandle, e, (Pointer)&ptrBuf);
2255 refs[*ptr] = 1;
2256 }
2257 }
2258 }
2259
2260 /*
2261 * See if we have any unreffed positions
2262 */
2263 for (i = 0; i < nPts; i++)
2264 if (! refs[i])
2265 break;
2266
2267 if (i != nPts)
2268 unReffedPositions = 1;
2269 else
2270 unReffedPositions = 0;
2271
2272 vpHandle = DXCreateInvalidComponentHandle((Object)field, NULL,
2273 "positions");
2274 if (! vpHandle)
2275 goto error;
2276
2277 /*
2278 * Invalidate unreferenced positions
2279 */
2280 if (unReffedPositions)
2281 {
2282 for (i = 0; i < nPts; i++)
2283 if (! refs[i])
2284 DXSetElementInvalid(vpHandle, i);
2285 }
2286
2287 if (! DXSaveInvalidComponent(field, vpHandle))
2288 goto error;
2289
2290 /* done: */
2291 DXFreeInvalidComponentHandle(vpHandle);
2292 DXFreeInvalidComponentHandle(vfHandle);
2293 DXFreeArrayHandle(fHandle);
2294 DXFreeArrayHandle(lHandle);
2295 DXFreeArrayHandle(eHandle);
2296 DXFree((Pointer)refs);
2297
2298 return (Object)field;
2299
2300 error:
2301 DXFreeInvalidComponentHandle(vpHandle);
2302 DXFreeInvalidComponentHandle(vfHandle);
2303 DXFreeArrayHandle(fHandle);
2304 DXFreeArrayHandle(lHandle);
2305 DXFreeArrayHandle(eHandle);
2306 DXFree((Pointer)refs);
2307
2308 return NULL;
2309 }
2310
2311 #define TYPE int
2312 #define LT(a,b) ((*(a))<(*(b)))
2313 #define GT(a,b) ((*(a))>(*(b)))
2314 #define QUICKSORT refsort
2315
2316 #include "qsort.c"
2317
2318 static Error SetMark(InvalidComponentHandle, int);
2319 static Error RemoveMark(InvalidComponentHandle, int);
2320 static int RemoveContents(InvalidComponentHandle);
2321 static Error IsElementMarked(InvalidComponentHandle, int);
2322 static Error MakeSortList(InvalidComponentHandle);
2323 static int GetNextMarked(InvalidComponentHandle);
2324
2325 InvalidComponentHandle
DXCreateInvalidComponentHandle(Object o,Array iarray,char * name)2326 DXCreateInvalidComponentHandle(Object o, Array iarray, char *name)
2327 {
2328 Field field = NULL;
2329 Array array;
2330 int nItems, nInv;
2331 InvalidComponentHandle handle = NULL;
2332
2333 if (o)
2334 {
2335 if (DXGetObjectClass(o) == CLASS_FIELD)
2336 {
2337 char sbuf[128];
2338
2339 field = (Field)o;
2340
2341 if (! name)
2342 {
2343 DXSetError(ERROR_BAD_PARAMETER, "null invalid component name");
2344 goto error;
2345 }
2346
2347 if (name == NULL)
2348 {
2349 DXSetError(ERROR_BAD_PARAMETER, "component name required");
2350 goto error;
2351 }
2352
2353 array = (Array)DXGetComponentValue(field, name);
2354 if (! array)
2355 {
2356 DXSetError(ERROR_BAD_PARAMETER,
2357 "cannot create invalid component handle for component %s",
2358 name);
2359 goto error;
2360 }
2361
2362 sprintf(sbuf, "invalid %s", name);
2363
2364 if (! iarray)
2365 iarray = (Array)DXGetComponentValue(field, sbuf);
2366
2367 }
2368 else if (DXGetObjectClass(o) == CLASS_ARRAY)
2369 {
2370 array = (Array)o;
2371 }
2372 else
2373 {
2374 DXSetError(ERROR_BAD_CLASS, "unknown object class");
2375 goto error;
2376 }
2377
2378 DXGetArrayInfo(array, &nItems, NULL, NULL, NULL, NULL);
2379 }
2380 else
2381 {
2382 nItems = -1;
2383 }
2384
2385
2386 handle = (InvalidComponentHandle)
2387 DXAllocateZero(sizeof(struct invalidComponentHandle));
2388 if (! handle)
2389 goto error;
2390
2391 handle->nItems = nItems;
2392 handle->sense = IC_MARKS_INDICATE_INVALID;
2393
2394 if (name)
2395 {
2396 handle->iName = (char *)DXAllocate(strlen(name) + 1);
2397 if (! handle->iName)
2398 goto error;
2399
2400 sprintf(handle->iName, "%s", name);
2401 }
2402 else
2403 handle->iName = NULL;
2404
2405 /*
2406 * If there's any pre-existing invalid data, initialize with it.
2407 */
2408 if (iarray)
2409 {
2410 Type type;
2411 Category cat;
2412 int rank, shape[100];
2413 int i;
2414 ubyte *dPtr;
2415
2416 DXGetArrayInfo(iarray, &nInv, &type, &cat, &rank, shape);
2417
2418 /*
2419 * If there was no original array, then we can get a
2420 * dependency size here.
2421 */
2422 nItems = nInv;
2423
2424 /*
2425 * If so, is is dependent or referential?
2426 */
2427 if (DXGetAttribute((Object)iarray, "dep"))
2428 {
2429 if ( nInv != nItems ||
2430 (type != TYPE_UBYTE && type != TYPE_BYTE) ||
2431 cat != CATEGORY_REAL ||
2432 rank != 0)
2433 {
2434 DXSetError(ERROR_DATA_INVALID,
2435 "dependent invalid data component must be scalar bytes");
2436 goto error;
2437 }
2438
2439 /*
2440 * If its a constant array, then its either all valid or all
2441 * invalid.
2442 */
2443 if (DXGetArrayClass(iarray) == CLASS_CONSTANTARRAY)
2444 {
2445 ubyte v = *(ubyte *)DXGetConstantArrayData(iarray);
2446
2447 handle->array = NULL;
2448
2449 if (v == DATA_INVALID)
2450 {
2451 handle->nMarkedItems = nInv;
2452 handle->type = IC_ALL_MARKED;
2453 }
2454 else if (v == DATA_VALID)
2455 {
2456 handle->nMarkedItems = 0;
2457 handle->type = IC_ALL_UNMARKED;
2458 }
2459 else
2460 {
2461 DXSetError(ERROR_DATA_INVALID,
2462 "invalid component array");
2463 goto error;
2464 }
2465
2466 }
2467 else
2468 {
2469 handle->type = IC_DEP_ARRAY;
2470
2471 handle->array = (Array)DXReference((Object)iarray);
2472 handle->data = (byte *)DXGetArrayData(iarray);
2473
2474 handle->nMarkedItems = 0;
2475 dPtr = (ubyte *)(handle->data);
2476 for (i = 0; i < nInv; i++)
2477 if (*dPtr++ == DATA_INVALID)
2478 handle->nMarkedItems ++;
2479 }
2480 }
2481 else if (DXGetAttribute((Object)iarray, "ref"))
2482 {
2483 int *iPtr, i;
2484
2485 if ((type != TYPE_INT && type != TYPE_UINT) ||
2486 cat != CATEGORY_REAL ||
2487 rank != 0)
2488 {
2489 DXSetError(ERROR_DATA_INVALID,
2490 "referential invalid data component is wrong type, %s",
2491 "category, or not scalar");
2492 goto error;
2493 }
2494
2495 DXGetArrayInfo(iarray, &nInv, NULL, NULL, NULL, NULL);
2496
2497 if (nInv == 0)
2498 {
2499 handle->type = IC_ALL_UNMARKED;
2500 handle->nMarkedItems = 0;
2501 }
2502 else
2503 {
2504 /* Accessing the elements of a large IC_SORTED_LIST via */
2505 /* binary search is hideously slow. Use a HASH or DEP */
2506 /* internally. */
2507 if (handle->nItems != -1 &&
2508 nInv >= DEP_MEM_THRESHOLD(handle->nItems))
2509 {
2510 ubyte *data = (ubyte *)DXAllocate(
2511 handle->nItems*sizeof(ubyte));
2512 if (!data)
2513 goto error;
2514 memset(data, IC_ELEMENT_UNMARKED, handle->nItems);
2515
2516 handle->nMarkedItems = 0;
2517 iPtr = (int *)DXGetArrayData(iarray);
2518 for (i = 0; i < nInv; i++, iPtr++)
2519 {
2520 if (data[*iPtr] == IC_ELEMENT_UNMARKED)
2521 handle->nMarkedItems++;
2522 data[*iPtr] = IC_ELEMENT_MARKED;
2523 }
2524
2525 handle->type = IC_DEP_ARRAY;
2526 handle->data = data;
2527 }
2528 else
2529 {
2530 long li;
2531 HashTable hash = DXCreateHash(sizeof(long), NULL, NULL);
2532 if (!hash)
2533 goto error;
2534
2535 iPtr = (int *)DXGetArrayData(iarray);
2536 for (i = 0; i < nInv; i++, iPtr++) {
2537 li = *iPtr;
2538 if (! DXInsertHashElement(hash, (Element)&li))
2539 goto error;
2540 }
2541
2542 handle->nMarkedItems = 0;
2543 DXInitGetNextHashElement(hash);
2544 while (DXGetNextHashElement(hash))
2545 handle->nMarkedItems++;
2546
2547 handle->type = IC_HASH;
2548 handle->hash = hash;
2549 }
2550 }
2551 }
2552 else
2553 {
2554 DXSetError(ERROR_DATA_INVALID,
2555 "invalid component has neither dep nor ref attribute");
2556 goto error;
2557 }
2558 }
2559 else
2560 {
2561 /*
2562 * Otherwise, the everything so far is assumed to be valid.
2563 */
2564 handle->type = IC_ALL_UNMARKED;
2565 }
2566
2567 return handle;
2568
2569 error:
2570 DXFreeInvalidComponentHandle(handle);
2571 return NULL;
2572 }
2573
2574 Error
DXFreeInvalidComponentHandle(InvalidComponentHandle handle)2575 DXFreeInvalidComponentHandle(InvalidComponentHandle handle)
2576 {
2577 if (handle)
2578 {
2579 if (handle->iName)
2580 DXFree((Pointer)handle->iName);
2581 if (handle->array)
2582 DXDelete((Object)handle->array);
2583 if (handle->hash)
2584 DXDestroyHash(handle->hash);
2585 if (handle->data && !handle->array)
2586 DXFree((Pointer)handle->data);
2587 if (handle->seglist)
2588 DXDeleteSegList(handle->seglist);
2589 DXFree((Pointer)handle->sortList);
2590
2591 DXFree((Pointer)handle);
2592 }
2593
2594 return OK;
2595 }
2596
2597 Error
DXSaveInvalidComponent(Field field,InvalidComponentHandle handle)2598 DXSaveInvalidComponent(Field field, InvalidComponentHandle handle)
2599 {
2600 Array array;
2601 char sbuf[128];
2602
2603 if (! handle->iName)
2604 {
2605 DXSetError(ERROR_INTERNAL, "unknown invalid component name");
2606 return ERROR;
2607 }
2608
2609 sprintf(sbuf, "invalid %s", handle->iName);
2610
2611 if (DXGetComponentValue(field, sbuf))
2612 DXDeleteComponent(field, sbuf);
2613
2614 if (handle->type == IC_ALL_UNMARKED &&
2615 handle->sense == IC_MARKS_INDICATE_INVALID)
2616 {
2617 return OK;
2618 }
2619
2620 if (handle->type == IC_ALL_MARKED &&
2621 handle->sense == IC_MARKS_INDICATE_VALID)
2622 {
2623 return OK;
2624 }
2625
2626 array = DXGetInvalidComponentArray(handle);
2627 if (! array)
2628 return ERROR;
2629
2630 if (! DXSetComponentValue(field, sbuf, (Object)array))
2631 return ERROR;
2632
2633 return OK;
2634 }
2635
2636 #define DEP_ARRAY 1
2637 #define REF_ARRAY 2
2638
2639 Array
DXGetInvalidComponentArray(InvalidComponentHandle handle)2640 DXGetInvalidComponentArray(InvalidComponentHandle handle)
2641 {
2642 Array array = NULL;
2643 Object attr;
2644 int nInvalid;
2645 int type = 0;
2646 long li;
2647
2648 if (! handle)
2649 goto error;
2650
2651 if (handle->array)
2652 return handle->array;
2653
2654 if (handle->sense == IC_MARKS_INDICATE_VALID)
2655 nInvalid = handle->nItems - handle->nMarkedItems;
2656 else
2657 nInvalid = handle->nMarkedItems;
2658
2659 if ((nInvalid == handle->nItems) ||
2660 ((handle->type == IC_ALL_MARKED &&
2661 handle->sense == IC_MARKS_INDICATE_INVALID)) ||
2662 ((handle->type == IC_ALL_UNMARKED &&
2663 handle->sense == IC_MARKS_INDICATE_VALID)))
2664 {
2665 ubyte value = DATA_INVALID;
2666
2667 type = DEP_ARRAY;
2668
2669 array = (Array)DXNewConstantArray(handle->nItems, &value,
2670 TYPE_UBYTE, CATEGORY_REAL, 0);
2671 if (! array)
2672 goto error;
2673 }
2674 else if (nInvalid == 0 ||
2675 ((handle->type == IC_ALL_MARKED &&
2676 handle->sense == IC_MARKS_INDICATE_VALID)) ||
2677 ((handle->type == IC_ALL_UNMARKED &&
2678 handle->sense == IC_MARKS_INDICATE_INVALID)))
2679 {
2680 ubyte value = DATA_VALID;
2681
2682 type = DEP_ARRAY;
2683
2684 array = (Array)DXNewConstantArray(handle->nItems, &value,
2685 TYPE_UBYTE, CATEGORY_REAL, 0);
2686 if (! array)
2687 goto error;
2688 }
2689 else if (handle->type == IC_DEP_ARRAY)
2690 {
2691
2692 /*
2693 * If there are enough actually invalid, output a dep array.
2694 * Otherwise, create a sort list.
2695 */
2696 if (handle->nItems != -1 &&
2697 nInvalid >= DEP_STORAGE_THRESHOLD(handle->nItems))
2698 {
2699 type = DEP_ARRAY;
2700
2701 array = DXNewArray(TYPE_UBYTE, CATEGORY_REAL, 0);
2702 if (! array)
2703 goto error;
2704
2705 /*
2706 * We may have to invert the byte vector to get the right sense.
2707 */
2708 if (handle->sense == IC_MARKS_INDICATE_VALID)
2709 {
2710 int i;
2711 ubyte *ptr;
2712
2713 ptr = (ubyte *)handle->data;
2714 for (i = 0; i < handle->nItems; i++, ptr++)
2715 if (*ptr == IC_ELEMENT_MARKED)
2716 *ptr = IC_ELEMENT_UNMARKED;
2717 else
2718 *ptr = IC_ELEMENT_MARKED;
2719
2720 handle->sense = IC_MARKS_INDICATE_INVALID;
2721 }
2722
2723 if (! DXAddArrayData(array, 0, handle->nItems, handle->data))
2724 goto error;
2725 }
2726 else
2727 {
2728 ubyte target;
2729 int i;
2730 ubyte *bptr;
2731 int *iptr;
2732
2733 type = REF_ARRAY;
2734
2735 array = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
2736 if (! array)
2737 goto error;
2738
2739 if (!DXAddArrayData(array, 0, nInvalid, NULL))
2740 goto error;
2741
2742 if (handle->sense == IC_MARKS_INDICATE_VALID)
2743 target = IC_ELEMENT_UNMARKED;
2744 else
2745 target = IC_ELEMENT_MARKED;
2746
2747 iptr = (int *)DXGetArrayData(array);
2748 bptr = (ubyte *)handle->data;
2749 for (i = 0; i < handle->nItems; i++)
2750 if (*bptr++ == target)
2751 *iptr++ = i;
2752 }
2753 }
2754 else if (handle->type == IC_SORTED_LIST)
2755 {
2756 type = REF_ARRAY;
2757
2758 array = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
2759 if (! array)
2760 goto error;
2761
2762 if (!DXAddArrayData(array, 0, nInvalid, handle->data))
2763 goto error;
2764 }
2765 else if (handle->type == IC_HASH)
2766 {
2767 /*
2768 * If its a hash table, then we may return either a dep
2769 * or ref result, depending on which will be larger.
2770 * This depends on the number actually invalid, regardless
2771 * of the sense of the hash table.
2772 */
2773 int *dPtr;
2774
2775 if (handle->nItems != -1 &&
2776 nInvalid >= DEP_STORAGE_THRESHOLD(handle->nItems))
2777 {
2778 ubyte *data;
2779 long *sPtr;
2780
2781 type = DEP_ARRAY;
2782
2783 array = DXNewArray(TYPE_UBYTE, CATEGORY_REAL, 0);
2784 if (! array)
2785 goto error;
2786
2787 if (! DXAddArrayData(array, 0, handle->nItems, NULL))
2788 goto error;
2789
2790 data = (ubyte *)DXGetArrayData(array);
2791
2792 /*
2793 * If marks indicate invalid, then initialize the array
2794 * to valid, then traverse the hash list setting the
2795 * array entries corresponding to the hash table
2796 * contents to INVALID. Otherwise, do it the opposite
2797 * way.
2798 */
2799 if (handle->sense == IC_MARKS_INDICATE_INVALID)
2800 {
2801 memset(data, DATA_VALID, handle->nItems*sizeof(ubyte));
2802
2803 DXInitGetNextHashElement(handle->hash);
2804 while(NULL !=
2805 (sPtr = (long *)DXGetNextHashElement(handle->hash)))
2806 {
2807 data[*sPtr] = DATA_INVALID;
2808 }
2809 }
2810 else
2811 {
2812 memset(data, DATA_INVALID, handle->nItems*sizeof(ubyte));
2813
2814 DXInitGetNextHashElement(handle->hash);
2815 while(NULL !=
2816 (sPtr = (long *)DXGetNextHashElement(handle->hash)))
2817 {
2818 data[*sPtr] = DATA_VALID;
2819 }
2820 }
2821 }
2822 else
2823 {
2824 long *sPtr;
2825
2826 type = REF_ARRAY;
2827
2828 array = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
2829 if (! array)
2830 goto error;
2831
2832 if (! DXAddArrayData(array, 0, nInvalid, NULL))
2833 goto error;
2834
2835 dPtr = (int *)DXGetArrayData(array);
2836
2837 /*
2838 * If the marks indicate valid, then we need to
2839 * determine the elements that DO NOT reside in the
2840 * hash table. We do this by trying all of them.
2841 * This ain't great, but nothing better comes to
2842 * mind. If the marks indicate invalid, then we have
2843 * the easy case.
2844 */
2845 if (handle->sense == IC_MARKS_INDICATE_VALID)
2846 {
2847 for (li = 0; li < handle->nItems; li++)
2848 {
2849 if (! DXQueryHashElement(handle->hash, (Key)&li))
2850 *dPtr++ = li;
2851 }
2852 }
2853 else
2854 {
2855 DXInitGetNextHashElement(handle->hash);
2856 while(NULL !=
2857 (sPtr = (long *)DXGetNextHashElement(handle->hash)))
2858 {
2859 *dPtr++ = *sPtr;
2860 }
2861 }
2862 }
2863 }
2864 else
2865 {
2866 DXSetError(ERROR_INTERNAL, "bad invalid component handle");
2867 goto error;
2868 }
2869
2870 if (handle->iName)
2871 {
2872 attr = (Object)DXNewString(handle->iName);
2873 if (! attr)
2874 goto error;
2875
2876 if (type == DEP_ARRAY)
2877 DXSetAttribute((Object)array, "dep", attr);
2878 else if (type == REF_ARRAY)
2879 DXSetAttribute((Object)array, "ref", attr);
2880 else
2881 {
2882 DXSetError(ERROR_INTERNAL, "unknown invalid array type");
2883 goto error;
2884 }
2885 }
2886
2887 return array;
2888
2889 error:
2890 DXDelete((Object)array);
2891 return NULL;
2892 }
2893
2894 int
DXIsElementInvalid(InvalidComponentHandle handle,int index)2895 DXIsElementInvalid(InvalidComponentHandle handle, int index)
2896 {
2897 if (handle->sense == IC_MARKS_INDICATE_VALID)
2898 return ! IsElementMarked(handle, index);
2899 else
2900 return IsElementMarked(handle, index);
2901 }
2902
2903 int
DXIsElementValid(InvalidComponentHandle handle,int index)2904 DXIsElementValid(InvalidComponentHandle handle, int index)
2905 {
2906 if (handle->sense == IC_MARKS_INDICATE_INVALID)
2907 return ! IsElementMarked(handle, index);
2908 else
2909 return IsElementMarked(handle, index);
2910 }
2911
2912 static int
IsElementMarked(InvalidComponentHandle handle,int index)2913 IsElementMarked(InvalidComponentHandle handle, int index)
2914 {
2915 switch(handle->type)
2916 {
2917 case IC_ALL_MARKED:
2918 {
2919 return TRUE;
2920 }
2921
2922 case IC_ALL_UNMARKED:
2923 {
2924 return FALSE;
2925 }
2926
2927 case IC_DEP_ARRAY:
2928 {
2929 if (((ubyte *)(handle->data))[index] == IC_ELEMENT_MARKED)
2930 return TRUE;
2931 else
2932 return FALSE;
2933 }
2934
2935 case IC_HASH:
2936 {
2937 long li = index;
2938
2939 if (DXQueryHashElement(handle->hash, (Key)&li))
2940 return TRUE;
2941 else
2942 return FALSE;
2943 }
2944
2945 case IC_SORTED_LIST:
2946 {
2947 int *base = (int *)handle->data;
2948 int max = handle->nMarkedItems-1;
2949 int min = 0, mid;
2950
2951 if (handle->nMarkedItems == 0 ||
2952 base[0] > index ||
2953 base[max] < index)
2954 {
2955 return FALSE;
2956 }
2957
2958 for (mid = (max + min) >> 1; mid != min; mid = (min + max) >> 1)
2959 if (base[mid] > index)
2960 max = mid;
2961 else if (base[mid] < index)
2962 min = mid;
2963 else
2964 return TRUE;
2965
2966 if (base[min] == index || base[max] == index)
2967 return TRUE;
2968 else
2969 return FALSE;
2970 }
2971 }
2972 /* Function should always short circuit, but just incase */
2973 return FALSE;
2974 }
2975
2976 Error
DXSetElementInvalid(InvalidComponentHandle handle,int index)2977 DXSetElementInvalid(InvalidComponentHandle handle, int index)
2978 {
2979 if (handle->sense == IC_MARKS_INDICATE_VALID)
2980 return RemoveMark(handle, index);
2981 else
2982 return SetMark(handle, index);
2983 }
2984
2985 Error
DXSetElementValid(InvalidComponentHandle handle,int index)2986 DXSetElementValid(InvalidComponentHandle handle, int index)
2987 {
2988 if (handle->sense == IC_MARKS_INDICATE_VALID)
2989 return SetMark(handle, index);
2990 else
2991 return RemoveMark(handle, index);
2992 }
2993
2994 static Error
SetMark(InvalidComponentHandle handle,int index)2995 SetMark(InvalidComponentHandle handle, int index)
2996 {
2997 long li;
2998
2999 if (handle->type == IC_ALL_MARKED)
3000 return OK;
3001
3002 /*
3003 * If this is the first invalidation, then we need to set up
3004 * a hash table to swallow invalidations until the threshold
3005 */
3006 if (handle->type == IC_ALL_UNMARKED)
3007 {
3008 handle->nMarkedItems = 0;
3009
3010 handle->type = IC_HASH;
3011
3012 /*
3013 * Hashing will use a straight key
3014 */
3015 handle->hash = DXCreateHash(sizeof(long), NULL, NULL);
3016 if (! handle->hash)
3017 goto error;
3018 }
3019
3020 /*
3021 * Now save the invalidation
3022 */
3023 switch(handle->type)
3024 {
3025 case IC_DEP_ARRAY:
3026 {
3027 if (handle->array)
3028 {
3029 ubyte *tmp = DXAllocate(handle->nItems*sizeof(ubyte));
3030 if (! tmp)
3031 goto error;
3032
3033 memcpy(tmp, handle->data, handle->nItems*sizeof(ubyte));
3034
3035 DXDelete((Object)handle->array);
3036 handle->array = NULL;
3037 handle->data = tmp;
3038 }
3039
3040 if (((ubyte *)(handle->data))[index] != IC_ELEMENT_MARKED)
3041 {
3042 ((ubyte *)(handle->data))[index] = IC_ELEMENT_MARKED;
3043 handle->nMarkedItems ++;
3044 }
3045 break;
3046 }
3047
3048 case IC_HASH:
3049 {
3050 li = index;
3051
3052 if (! DXQueryHashElement(handle->hash, (Key)&li))
3053 {
3054 if (! DXInsertHashElement(handle->hash, (Element)&li))
3055 goto error;
3056 handle->nMarkedItems ++;
3057 }
3058 break;
3059 }
3060
3061 case IC_SORTED_LIST:
3062 {
3063 /*
3064 * If the thing is currently a sorted list and we are
3065 * doing an insert, transform to a hash table
3066 */
3067 int i, *iPtr;
3068 HashTable hash = DXCreateHash(sizeof(long), NULL, NULL);
3069 if (! hash)
3070 goto error;
3071
3072 for (i = 0, iPtr = (int *)handle->data; i < handle->nMarkedItems; i++)
3073 {
3074 li = *iPtr++;
3075
3076 if (! DXInsertHashElement(hash, (Element)&li))
3077 goto error;
3078 }
3079
3080 if (handle->array)
3081 {
3082 DXDelete((Object)handle->array);
3083 handle->array = NULL;
3084 handle->data = NULL;
3085 }
3086 else
3087 {
3088 DXFree((Pointer)handle->data);
3089 handle->data = NULL;
3090 }
3091
3092 handle->hash = hash;
3093 handle->type = IC_HASH;
3094
3095 /*
3096 * Now add to hash table
3097 */
3098 li = index;
3099 if (! DXQueryHashElement(handle->hash, (Key)&li))
3100 {
3101 if (! DXInsertHashElement(handle->hash, (Element)&li))
3102 goto error;
3103 handle->nMarkedItems ++;
3104 }
3105 break;
3106 }
3107
3108 default:
3109 {
3110 DXSetError(ERROR_INTERNAL, "unknown handle type");
3111 goto error;
3112 }
3113 }
3114
3115 /*
3116 * If not already a dependent array and we have passed the threshold,
3117 * convert to a dependent array. IF we know the overall size.
3118 */
3119 if ((handle->type != IC_DEP_ARRAY) && (handle->nItems != -1) &&
3120 (handle->nMarkedItems >= DEP_MEM_THRESHOLD(handle->nItems)))
3121 {
3122 ubyte *depArray = (ubyte *)DXAllocate(handle->nItems*sizeof(ubyte));
3123 if (! depArray)
3124 goto error;
3125
3126 memset(depArray, IC_ELEMENT_UNMARKED, handle->nItems);
3127
3128 /*
3129 * At this point, if we came in with a sorted list we will already
3130 * have converted to a hash table, so if its not dependent, it
3131 * must be hash.
3132 */
3133 if (handle->type == IC_HASH)
3134 {
3135 long *iPtr;
3136
3137 DXInitGetNextHashElement(handle->hash);
3138 while(NULL != (iPtr = (long *)DXGetNextHashElement(handle->hash)))
3139 depArray[*iPtr] = IC_ELEMENT_MARKED;
3140
3141 DXDestroyHash(handle->hash);
3142 handle->hash = NULL;
3143 }
3144 else
3145 {
3146 DXSetError(ERROR_INTERNAL,
3147 "attempting to expand an invalid type of invalid component");
3148 goto error;
3149 }
3150
3151 handle->data = depArray;
3152 handle->array = NULL;
3153 handle->type = IC_DEP_ARRAY;
3154 }
3155
3156 return OK;
3157
3158 error:
3159 return ERROR;
3160 }
3161
3162 static Error
RemoveMark(InvalidComponentHandle handle,int index)3163 RemoveMark(InvalidComponentHandle handle, int index)
3164 {
3165 if (handle->type == IC_ALL_UNMARKED)
3166 return OK;
3167
3168 /*
3169 * If this is the first invalidation, then we need to set up
3170 * a hash table to swallow invalidations until the threshold
3171 */
3172 if (handle->type == IC_ALL_MARKED)
3173 {
3174 handle->type = IC_HASH;
3175 handle->nMarkedItems = 0;
3176 handle->sense = !handle->sense;
3177
3178 /*
3179 * Hashing will use a straight key
3180 */
3181 handle->hash = DXCreateHash(sizeof(long), NULL, NULL);
3182 if (! handle->hash)
3183 goto error;
3184
3185 if (! SetMark(handle, index))
3186 goto error;
3187
3188 return OK;
3189 }
3190
3191 /*
3192 * Now save the invalidation
3193 */
3194 switch(handle->type)
3195 {
3196 case IC_DEP_ARRAY:
3197 {
3198 if (handle->array)
3199 {
3200 ubyte *tmp = DXAllocate(handle->nItems*sizeof(ubyte));
3201 if (! tmp)
3202 goto error;
3203
3204 memcpy(tmp, handle->data, handle->nItems*sizeof(ubyte));
3205
3206 DXDelete((Object)handle->array);
3207 handle->array = NULL;
3208 handle->data = tmp;
3209 }
3210
3211 if (((ubyte *)(handle->data))[index] != IC_ELEMENT_UNMARKED)
3212 {
3213 ((ubyte *)(handle->data))[index] = IC_ELEMENT_UNMARKED;
3214 handle->nMarkedItems --;
3215 }
3216 break;
3217 }
3218
3219 case IC_HASH:
3220 {
3221 long li = index;
3222
3223 if (DXQueryHashElement(handle->hash, (Key)&li))
3224 {
3225 if (! DXDeleteHashElement(handle->hash, (Element)&li))
3226 goto error;
3227 handle->nMarkedItems --;
3228 }
3229 break;
3230 }
3231
3232 case IC_SORTED_LIST:
3233 {
3234 /*
3235 * If the thing is currently a sorted list and we are
3236 * doing an deletion, transform to a hash table
3237 */
3238 int i, *iPtr;
3239 long li;
3240
3241 HashTable hash = DXCreateHash(sizeof(long), NULL, NULL);
3242 if (! hash)
3243 goto error;
3244
3245 iPtr = (int *)handle->data;
3246 for (i = 0; i < handle->nMarkedItems; i++)
3247 {
3248 li = *iPtr++;
3249 if (! DXInsertHashElement(hash, (Element)&li))
3250 goto error;
3251 }
3252
3253 if (handle->array)
3254 {
3255 DXDelete((Object)handle->array);
3256 handle->array = NULL;
3257 handle->data = NULL;
3258 }
3259 else
3260 {
3261 DXFree((Pointer)handle->data);
3262 handle->data = NULL;
3263 }
3264
3265 handle->hash = hash;
3266 handle->type = IC_HASH;
3267
3268 /*
3269 * Now add to hash table
3270 */
3271 li = index;
3272 if (DXQueryHashElement(handle->hash, (Key)&li))
3273 {
3274 if (! DXDeleteHashElement(handle->hash, (Element)&li))
3275 goto error;
3276 handle->nMarkedItems --;
3277 }
3278 break;
3279 }
3280
3281 default:
3282 {
3283 DXSetError(ERROR_INTERNAL, "unknown handle type");
3284 goto error;
3285 }
3286 }
3287
3288 /*
3289 * If not already a dependent array and we have passed the threshold,
3290 * convert to a dependent array.
3291 */
3292 if ((handle->type != IC_DEP_ARRAY) && (handle->nItems != -1) &&
3293 (handle->nMarkedItems >= DEP_MEM_THRESHOLD(handle->nItems)))
3294 {
3295 ubyte *depArray = (ubyte *)DXAllocate(handle->nItems*sizeof(ubyte));
3296 if (! depArray)
3297 goto error;
3298
3299 memset(depArray, IC_ELEMENT_UNMARKED, handle->nItems);
3300
3301 /*
3302 * At this point, if we came in with a sorted list we will already
3303 * have converted to a hash table, so if its not dependent, it
3304 * must be hash.
3305 */
3306 if (handle->type == IC_HASH)
3307 {
3308 long *lPtr;
3309
3310 DXInitGetNextHashElement(handle->hash);
3311 while(NULL != (lPtr = (long *)DXGetNextHashElement(handle->hash)))
3312 depArray[*lPtr] = IC_ELEMENT_MARKED;
3313
3314 DXDestroyHash(handle->hash);
3315 handle->hash = NULL;
3316 }
3317 else
3318 {
3319 DXSetError(ERROR_INTERNAL,
3320 "attempting to expand an invalid type of invalid component");
3321 goto error;
3322 }
3323
3324 handle->data = depArray;
3325 handle->array = NULL;
3326 handle->type = IC_DEP_ARRAY;
3327 }
3328
3329 return OK;
3330
3331 error:
3332 return ERROR;
3333 }
3334
3335 int
DXIsElementInvalidSequential(InvalidComponentHandle handle,int index)3336 DXIsElementInvalidSequential(InvalidComponentHandle handle, int index)
3337 {
3338 /*
3339 if (handle->type == IC_ALL_UNMARKED)
3340 return FALSE;
3341 else if (handle->type == IC_ALL_MARKED)
3342 return TRUE;
3343 else if (handle->type == IC_SORTED_LIST)
3344 {
3345 int *data;
3346
3347 if (index == 0)
3348 handle->next = 0;
3349
3350 if (handle->next >= handle->nMarkedItems)
3351 return FALSE;
3352
3353 data = (int *)(handle->data);
3354
3355 do
3356 {
3357 if (index < data[handle->next])
3358 return FALSE;
3359 if (index == data[handle->next])
3360 return TRUE;
3361 }
3362 while (++(handle->next) < handle->nMarkedItems);
3363
3364 return FALSE;
3365 }
3366 else
3367 */
3368 if(handle)
3369 return DXIsElementInvalid(handle, index);
3370 return 0;
3371 }
3372
3373
3374 int
DXIsElementValidSequential(InvalidComponentHandle handle,int index)3375 DXIsElementValidSequential(InvalidComponentHandle handle, int index)
3376 {
3377 /*
3378 if (handle->type == IC_ALL_UNMARKED)
3379 return FALSE;
3380 else if (handle->type == IC_ALL_MARKED)
3381 return TRUE;
3382 else if (handle->type == IC_SORTED_LIST)
3383 {
3384 int *data;
3385
3386 if (index == 0)
3387 handle->next = 0;
3388
3389 if (handle->next >= handle->nMarkedItems)
3390 return FALSE;
3391
3392 data = (int *)(handle->data);
3393
3394 do
3395 {
3396 if (index < data[handle->next])
3397 return FALSE;
3398 if (index == data[handle->next])
3399 return TRUE;
3400 }
3401 while (++(handle->next) < handle->nMarkedItems);
3402
3403 return FALSE;
3404 }
3405 else
3406 */
3407 return DXIsElementValid(handle, index);
3408 }
3409
3410 int
DXGetInvalidCount(InvalidComponentHandle handle)3411 DXGetInvalidCount(InvalidComponentHandle handle)
3412 {
3413 if (handle->sense == IC_MARKS_INDICATE_VALID)
3414 return handle->nItems - handle->nMarkedItems;
3415 else
3416 return handle->nMarkedItems;
3417 }
3418
3419 int
DXGetValidCount(InvalidComponentHandle handle)3420 DXGetValidCount(InvalidComponentHandle handle)
3421 {
3422 if (handle->sense == IC_MARKS_INDICATE_INVALID)
3423 return handle->nItems - handle->nMarkedItems;
3424 else
3425 return handle->nMarkedItems;
3426 }
3427
3428 static Field
DeleteFieldContents(Field f)3429 DeleteFieldContents(Field f)
3430 {
3431 char *cNames[1000];
3432 int n;
3433
3434 for (n = 0; DXGetEnumeratedComponentValue(f, n, cNames+n); n++);
3435
3436 while (--n >= 0)
3437 DXDeleteComponent(f, cNames[n]);
3438
3439 return DXEndField(f);
3440 }
3441
3442 Error
DXSetAllValid(InvalidComponentHandle handle)3443 DXSetAllValid(InvalidComponentHandle handle)
3444 {
3445 if (! RemoveContents(handle))
3446 return ERROR;
3447
3448 handle->type = IC_ALL_UNMARKED;
3449 handle->sense = IC_MARKS_INDICATE_INVALID;
3450
3451 return OK;
3452 }
3453
3454 Error
DXSetAllInvalid(InvalidComponentHandle handle)3455 DXSetAllInvalid(InvalidComponentHandle handle)
3456 {
3457 if (! RemoveContents(handle))
3458 return ERROR;
3459
3460 handle->type = IC_ALL_UNMARKED;
3461 handle->sense = IC_MARKS_INDICATE_VALID;
3462
3463 return OK;
3464 }
3465
3466 static Error
RemoveContents(InvalidComponentHandle handle)3467 RemoveContents(InvalidComponentHandle handle)
3468 {
3469 switch(handle->type)
3470 {
3471 case IC_ALL_UNMARKED:
3472 case IC_ALL_MARKED:
3473 {
3474 break;
3475 }
3476
3477 case IC_DEP_ARRAY:
3478 case IC_SORTED_LIST:
3479 {
3480 if (handle->array)
3481 {
3482 DXDelete((Object)handle->array);
3483 handle->array = NULL;
3484 handle->data = NULL;
3485 }
3486 else
3487 {
3488 DXFree((Pointer)handle->data);
3489 handle->data = NULL;
3490 }
3491
3492 break;
3493 }
3494
3495 case IC_HASH:
3496 {
3497 DXDestroyHash(handle->hash);
3498 handle->hash = NULL;
3499
3500 break;
3501 }
3502
3503 default:
3504 DXSetError(ERROR_INTERNAL,
3505 "unknown invalid component handle type");
3506 goto error;
3507 }
3508
3509 return OK;
3510
3511 error:
3512 return ERROR;
3513 }
3514
3515 Error
DXInitGetNextInvalidElementIndex(InvalidComponentHandle handle)3516 DXInitGetNextInvalidElementIndex(InvalidComponentHandle handle)
3517 {
3518 handle->nextCand = 0;
3519 handle->nextSlot = 0;
3520 handle->nextMarkI = -1;
3521
3522 if (handle->type == IC_HASH)
3523 if (! MakeSortList(handle))
3524 goto error;
3525
3526 handle->nextMark = GetNextMarked(handle);
3527
3528 return OK;
3529
3530 error:
3531 return ERROR;
3532 }
3533
3534 Error
DXInitGetNextValidElementIndex(InvalidComponentHandle handle)3535 DXInitGetNextValidElementIndex(InvalidComponentHandle handle)
3536 {
3537 return DXInitGetNextInvalidElementIndex(handle);
3538 }
3539
3540 int
DXGetNextValidElementIndex(InvalidComponentHandle handle)3541 DXGetNextValidElementIndex(InvalidComponentHandle handle)
3542 {
3543 if (handle->sense == IC_MARKS_INDICATE_VALID)
3544 {
3545 int next = handle->nextMark;
3546 handle->nextMark = GetNextMarked(handle);
3547 return next;
3548 }
3549 else
3550 {
3551
3552 /*
3553 * While there remain marks and our next candidate is marked, bump
3554 * them both.
3555 */
3556 while (handle->nextMark != -1 && handle->nextCand == handle->nextMark)
3557 {
3558 handle->nextCand ++;
3559 handle->nextMark = GetNextMarked(handle);
3560 }
3561
3562 /*
3563 * If there are no remaining marks and we are not done...
3564 */
3565 if (handle->nextCand < handle->nItems)
3566 return handle->nextCand++;
3567 else
3568 return -1;
3569 }
3570 }
3571
3572
3573 int
DXGetNextInvalidElementIndex(InvalidComponentHandle handle)3574 DXGetNextInvalidElementIndex(InvalidComponentHandle handle)
3575 {
3576 if (handle->sense == IC_MARKS_INDICATE_INVALID)
3577 {
3578 int next = handle->nextMark;
3579 handle->nextMark = GetNextMarked(handle);
3580 return next;
3581 }
3582 else
3583 {
3584
3585 /*
3586 * While there remain marks and our next candidate is marked, bump
3587 * them both.
3588 */
3589 while (handle->nextMark != -1 && handle->nextCand == handle->nextMark)
3590 {
3591 handle->nextCand ++;
3592 handle->nextMark = GetNextMarked(handle);
3593 }
3594
3595 /*
3596 * If there are no remaining marks and we are not done...
3597 */
3598 if (handle->nextCand < handle->nItems)
3599 return handle->nextCand++;
3600 else
3601 return -1;
3602 }
3603 }
3604
3605 Error
DXInvertValidity(InvalidComponentHandle handle)3606 DXInvertValidity(InvalidComponentHandle handle)
3607 {
3608 if (handle->sense == IC_MARKS_INDICATE_INVALID)
3609 handle->sense = IC_MARKS_INDICATE_VALID;
3610 else
3611 handle->sense = IC_MARKS_INDICATE_INVALID;
3612
3613 return OK;
3614 }
3615
3616 static Error
MakeSortList(InvalidComponentHandle handle)3617 MakeSortList(InvalidComponentHandle handle)
3618 {
3619 int i;
3620 long *p;
3621
3622 if (handle->sortListSize != handle->nMarkedItems)
3623 {
3624 DXFree((int *)handle->sortList);
3625 handle->sortList = (int *)DXAllocate(handle->nMarkedItems*sizeof(int));
3626 if (! handle->sortList)
3627 goto error;
3628 handle->sortListSize = handle->nMarkedItems;
3629 }
3630
3631 DXInitGetNextHashElement(handle->hash); i = 0;
3632 while (NULL != (p = (long *)DXGetNextHashElement(handle->hash)))
3633 {
3634 if (i == handle->sortListSize)
3635 {
3636 DXSetError(ERROR_INTERNAL, "sort list too short!");
3637 goto error;
3638 }
3639
3640 handle->sortList[i++] = *p;
3641 }
3642
3643 if (i != handle->sortListSize)
3644 {
3645 DXSetError(ERROR_INTERNAL, "sort list wrong size!");
3646 goto error;
3647 }
3648
3649 refsort(handle->sortList, handle->sortListSize);
3650
3651 return OK;
3652
3653 error:
3654 return ERROR;
3655 }
3656
3657 static int
GetNextMarked(InvalidComponentHandle handle)3658 GetNextMarked(InvalidComponentHandle handle)
3659 {
3660 if (handle->nextMarkI >= handle->nItems)
3661 return -1;
3662
3663 switch(handle->type)
3664 {
3665 case IC_ALL_MARKED:
3666 {
3667 if (handle->nextMarkI >= handle->nItems - 1)
3668 return -1;
3669 else
3670 return (++(handle->nextMarkI));
3671 }
3672
3673 case IC_ALL_UNMARKED:
3674 {
3675 return -1;
3676 }
3677
3678 case IC_SORTED_LIST:
3679 {
3680 if (handle->nextSlot == handle->nMarkedItems)
3681 return -1;
3682 else
3683 return ((int *)(handle->data))[handle->nextSlot++];
3684 }
3685
3686 case IC_HASH:
3687 {
3688 if (handle->nextSlot == handle->sortListSize)
3689 return -1;
3690 else
3691 return ((int *)(handle->sortList))[handle->nextSlot++];
3692 }
3693
3694 case IC_DEP_ARRAY:
3695 {
3696 int i;
3697 ubyte *ptr = (ubyte *)handle->data + handle->nextMarkI + 1;
3698
3699 for (i = handle->nextMarkI+1; i < handle->nItems; i++)
3700 if (*ptr++ == IC_ELEMENT_MARKED)
3701 {
3702 handle->nextMarkI = i;
3703 return i;
3704 }
3705
3706 return -1;
3707 }
3708 }
3709 /* Function should be already returned, but just incase */
3710 return -1;
3711 }
3712
3713
3714 static int
GridSize(Array grid)3715 GridSize(Array grid)
3716 {
3717 switch(DXGetArrayClass(grid))
3718 {
3719 case CLASS_PATHARRAY:
3720 {
3721 int count;
3722
3723 DXGetPathArrayInfo((PathArray)grid, &count);
3724 return count;
3725 }
3726
3727 case CLASS_ARRAY:
3728 {
3729 byte *map = NULL;
3730 int max, i, n, *elts, *e, nElements, nVerts, r;
3731 Type t;
3732 Category c;
3733
3734 DXGetArrayInfo((Array)grid, &nElements, &t, &c, &r, &nVerts);
3735
3736 if (t != TYPE_INT || c != CATEGORY_REAL || r != 1)
3737 {
3738 DXSetError(ERROR_DATA_INVALID, "connections");
3739 return -1;
3740 }
3741
3742 elts = (int *)DXGetArrayData(grid);
3743
3744 n = nElements*nVerts;
3745
3746 for (i = 0, e = elts, max = -1; i < n; i++, e++)
3747 if (*e > max)
3748 max = *e;
3749
3750 map = (byte *)DXAllocateZero((max+1)*sizeof(byte));
3751 if (! map)
3752 return ERROR_OCCURRED;
3753
3754 for (i = 0, e = elts; i < n; i++, e++)
3755 if (*e >= 0)
3756 map[*e] = 1;
3757
3758 for (i = 0; i < max; i++)
3759 if (map[i] == 0)
3760 {
3761 DXFree((Pointer)map);
3762 return HOLES_FOUND;
3763 }
3764
3765 DXFree((Pointer)map);
3766 return max + 1;
3767 }
3768
3769 case CLASS_MESHARRAY:
3770 {
3771 int nTerms, i, max;
3772 Array terms[100];
3773 int rtn;
3774
3775 DXGetMeshArrayInfo((MeshArray)grid, &nTerms, terms);
3776
3777 for (max = 1, i = 0; i < nTerms; i++)
3778 {
3779 rtn = GridSize(terms[i]);
3780 if (rtn < 0)
3781 return rtn;
3782 max *= rtn;
3783 }
3784
3785 return max;
3786 }
3787
3788 default:
3789 {
3790 DXSetError(ERROR_DATA_INVALID, "connections component");
3791 return ERROR_OCCURRED;
3792 }
3793 }
3794 }
3795