1 //
2 // ctable linked list routines
3 //
4 //
5 // $Id$
6 //
7 //#define LISTDEBUG
8
9
10 //
11 // ctable_ListInit - initialize a list -- zero out the row pointer from the list.
12 //
13 CTABLE_INTERNAL INLINE void
ctable_ListInit(ctable_BaseRow ** listPtr,CONST char * file,int line)14 ctable_ListInit (ctable_BaseRow **listPtr, CONST char *file, int line)
15 {
16 #ifdef LISTDEBUG
17 fprintf(stderr, "ctable_ListInit(0x%lx) at %s:%d\n", (long)listPtr, file, line);
18 #endif
19 *listPtr = NULL;
20 }
21
22 #ifndef FULLSTATIC
23 //
24 // ctable_ListEmpty - return 1 if the list is empty, else 0.
25 //
26 CTABLE_INTERNAL INLINE int
ctable_ListEmpty(ctable_BaseRow * list)27 ctable_ListEmpty (ctable_BaseRow *list)
28 {
29 #ifdef LISTDEBUG
30 fprintf(stderr, "%d == ctable_ListEmpty(0x%lx)\n", (list == NULL), (long)list);
31 #endif
32 return (list == NULL);
33 }
34 #endif
35
36 //
37 // ctable_ListRemove - remove a row from a list
38 //
39 CTABLE_INTERNAL INLINE void
ctable_ListRemove(ctable_BaseRow * row,int i)40 ctable_ListRemove (ctable_BaseRow *row, int i)
41 {
42 #ifdef LISTDEBUG
43 fprintf(stderr, "ctable_ListRemove(0x%lx, %d)\n", (long)row, i);
44 #endif
45 #ifdef SANITY_CHECKS
46 if(!row->_ll_nodes[i].prev) {
47 Tcl_Panic("Removing row not in list (0x%lx, %d)!", (long)row, i);
48 }
49 #endif
50 // if there's an object following me, make his prev be my prev
51 if (row->_ll_nodes[i].next != NULL) {
52 row->_ll_nodes[i].next->_ll_nodes[i].prev = row->_ll_nodes[i].prev;
53 }
54
55 // make my prev's next (or header) point to my next
56 *row->_ll_nodes[i].prev = row->_ll_nodes[i].next;
57
58 // i'm removed
59 row->_ll_nodes[i].prev = NULL;
60 }
61
62 //
63 // ctable_ListRemoveMightBeTheLastOne - remove a row from a list
64 //
65 CTABLE_INTERNAL INLINE int
ctable_ListRemoveMightBeTheLastOne(ctable_BaseRow * row,int i)66 ctable_ListRemoveMightBeTheLastOne (ctable_BaseRow *row, int i)
67 {
68 int mightBeTheLastOne;
69
70 #ifdef LISTDEBUG
71 fprintf(stderr, "ctable_ListRemoveMightBeTheLastOne(0x%lx, %d)\n", (long)row, i);
72 #endif
73 #ifdef SANITY_CHECKS
74 if(!row->_ll_nodes[i].prev) {
75 Tcl_Panic("Removing row not in list (0x%lx, %d)!", (long)row, i);
76 }
77 #endif
78 // if there's an object following me, make his prev be my prev
79 if (row->_ll_nodes[i].next != NULL) {
80 // set the next guy's prev ptr to be my prev ptr
81 row->_ll_nodes[i].next->_ll_nodes[i].prev = row->_ll_nodes[i].prev;
82 mightBeTheLastOne = 0;
83 } else {
84 // else note that there was nothing following me
85 mightBeTheLastOne = 1;
86 }
87
88 // make my prev's next (or header) point to my next
89 *row->_ll_nodes[i].prev = row->_ll_nodes[i].next;
90
91 // i'm removed
92 row->_ll_nodes[i].prev = NULL;
93
94 return mightBeTheLastOne;
95 }
96
97
98 CTABLE_INTERNAL INLINE void
ctable_ListInsertHead(ctable_BaseRow ** listPtr,ctable_BaseRow * row,int i)99 ctable_ListInsertHead (ctable_BaseRow **listPtr, ctable_BaseRow *row, int i)
100 {
101 #ifdef LISTDEBUG
102 fprintf(stderr, "ctable_ListInsertHead(0x%lx, 0x%lx, %d)\n", (long)listPtr, (long)row, i);
103 #endif
104 #ifdef SANITY_CHECKS
105 if(row->_ll_nodes[i].prev) {
106 Tcl_Panic("Inserting node twice (0x%lx, 0x%lx, %d)!", (long)listPtr, (long)row, i);
107 }
108 #endif
109
110 // make the row's prev point to the address of the head pointer. Do this
111 // first so it'll be in place before the readers can see it.
112 row->_ll_nodes[i].prev = listPtr;
113 row->_ll_nodes[i].head = listPtr;
114
115 // make the new row's next point to what the head currently points
116 // to, possibly NULL
117 if ((row->_ll_nodes[i].next = *listPtr) != NULL) {
118
119 // it wasn't null, make the node pointed to by head's prev
120 // point to the new row. We can do this now because the row
121 // itself is fully initialised.
122
123 (*listPtr)->_ll_nodes[i].prev = &row->_ll_nodes[i].next;
124 }
125
126 // Make the head point to the new row. Do this last, so that
127 // all links in row are intact before it's seen by readers.
128 *listPtr = row;
129
130 // printf ("insert head %lx i %d\n", (long unsigned int)listPtr, i);
131 }
132
133 #ifndef FULLSTATIC
134 //
135 // ctable_ListInsertBefore - insert row2 before row1
136 //
137 CTABLE_INTERNAL INLINE void
ctable_ListInsertBefore(ctable_BaseRow * row1,ctable_BaseRow * row2,int i)138 ctable_ListInsertBefore (ctable_BaseRow *row1, ctable_BaseRow *row2, int i)
139 {
140 volatile ctable_BaseRow **row1prev;
141
142 #ifdef LISTDEBUG
143 fprintf(stderr, "ctable_ListInsertBefore(0x%lx, 0x%lx, %d)\n", (long)row1, (long)row2, i);
144 #endif
145 // make row2's head point to row1's head
146 row2->_ll_nodes[i].head = row1->_ll_nodes[i].head;
147
148 // make row2's prev point to row1's prev
149 row2->_ll_nodes[i].prev = row1->_ll_nodes[i].prev;
150
151 // make row2's next point to row1
152 row2->_ll_nodes[i].next = row1;
153
154 // get row1's prev before we overwrite it, because we need to link it last.
155 row1prev = (volatile ctable_BaseRow **)row1->_ll_nodes[i].prev;
156
157 // make row1's prev point to row2's next
158 row1->_ll_nodes[i].prev = &row2->_ll_nodes[i].next;
159
160 // make row1's prev's *next* point to row2, and do this last
161 *row1prev = row2;
162 }
163 #endif
164
165 #ifndef FULLSTATIC
166 //
167 // ctable_ListInsertAfter - insert row2 after row1
168 //
169 CTABLE_INTERNAL INLINE void
ctable_ListInsertAfter(ctable_BaseRow * row1,ctable_BaseRow * row2,int i)170 ctable_ListInsertAfter (ctable_BaseRow *row1, ctable_BaseRow *row2, int i) {
171 #ifdef LISTDEBUG
172 fprintf(stderr, "ctable_ListInsertAfter(0x%lx, 0x%lx, %d)\n", (long)row1, (long)row2, i);
173 #endif
174 // make row2's head point to row1's head
175 row2->_ll_nodes[i].head = row1->_ll_nodes[i].head;
176
177 // make row2's prev point to the address of row1's next
178 row2->_ll_nodes[i].prev = &row1->_ll_nodes[i].next;
179
180 // set row2's next pointer to row1's next pointer and see if it's NULL
181 if ((row2->_ll_nodes[i].next = row1->_ll_nodes[i].next) != NULL) {
182
183 // it wasn't, make row1's next's prev point to the address of
184 // row2's next
185
186 row1->_ll_nodes[i].next->_ll_nodes[i].prev = &row2->_ll_nodes[i].next;
187 }
188
189 // make row1's next point to row2. This has to be last, so that the whole
190 // structure is in place before a reader can see it.
191 row1->_ll_nodes[i].next = row2;
192 }
193 #endif
194
195 // vim: set ts=8 sw=4 sts=4 noet :
196