2 * Bacula doubly linked list routines.
4 * dlist is a doubly linked list with the links being in the
7 * Kern Sibbald, July MMIII
13 Copyright (C) 2000-2005 Kern Sibbald
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License
17 version 2 as ammended with additional clauses defined in the
18 file LICENSE in the main source directory.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 the file LICENSE for additional details.
29 /* ===================================================================
34 * Append an item to the list
36 void dlist::append(void *item)
38 ((dlink *)(((char *)item)+loffset))->next = NULL;
39 ((dlink *)(((char *)item)+loffset))->prev = tail;
41 ((dlink *)(((char *)tail)+loffset))->next = item;
44 if (head == NULL) { /* if empty list, */
45 head = item; /* item is head as well */
51 * Append an item to the list
53 void dlist::prepend(void *item)
55 ((dlink *)(((char *)item)+loffset))->next = head;
56 ((dlink *)(((char *)item)+loffset))->prev = NULL;
58 ((dlink *)(((char *)head)+loffset))->prev = item;
61 if (tail == NULL) { /* if empty list, */
62 tail = item; /* item is tail too */
67 void dlist::insert_before(void *item, void *where)
69 dlink *where_link = (dlink *)((char *)where+loffset);
71 ((dlink *)(((char *)item)+loffset))->next = where;
72 ((dlink *)(((char *)item)+loffset))->prev = where_link->prev;
74 if (where_link->prev) {
75 ((dlink *)(((char *)(where_link->prev))+loffset))->next = item;
77 where_link->prev = item;
84 void dlist::insert_after(void *item, void *where)
86 dlink *where_link = (dlink *)((char *)where+loffset);
88 ((dlink *)(((char *)item)+loffset))->next = where_link->next;
89 ((dlink *)(((char *)item)+loffset))->prev = where;
91 if (where_link->next) {
92 ((dlink *)(((char *)(where_link->next))+loffset))->prev = item;
94 where_link->next = item;
102 * Insert an item in the list, but only if it is unique
103 * otherwise, the item is returned non inserted
105 * Returns: item if item inserted
106 * other_item if same value already exists (item not inserted)
108 void *dlist::unique_binary_insert(void *item, int compare(void *item1, void *item2))
114 if (num_items == 0) {
115 //Dmsg0(000, "Append first.\n");
119 if (num_items == 1) {
120 comp = compare(item, first());
123 //Dmsg0(000, "Insert before first.\n");
125 } else if (comp > 0) {
126 insert_after(item, first());
127 //Dmsg0(000, "Insert after first.\n");
130 //Dmsg0(000, "Same as first.\n");
134 /* Check against last item */
135 comp = compare(item, last());
138 //Dmsg0(000, "Appended item.\n");
140 } else if (comp == 0) {
141 //Dmsg0(000, "Same as last.\n");
144 /* Check against first item */
145 comp = compare(item, first());
148 //Dmsg0(000, "Inserted item before.\n");
150 } else if (comp == 0) {
151 //Dmsg0(000, "Same as first.\n");
154 if (num_items == 2) {
155 insert_after(item, first());
156 //Dmsg0(000, "Inserted item after.\n");
165 nxt = (low + high) / 2;
167 cur_item = next(cur_item);
171 cur_item = prev(cur_item);
174 //Dmsg1(000, "Compare item to %d\n", cur);
175 comp = compare(item, cur_item);
176 //Dmsg2(000, "Compare item to %d = %d\n", cur, comp);
179 //Dmsg2(000, "set high; low=%d high=%d\n", low, high);
180 } else if (comp > 0) {
182 //Dmsg2(000, "set low; low=%d high=%d\n", low, high);
184 //Dmsg1(000, "Same as item %d\n", cur);
189 insert_before(item, cur_item);
190 //Dmsg1(000, "Insert before item %d\n", cur);
192 insert_after(item, cur_item);
193 //Dmsg1(000, "Insert after item %d\n", cur);
200 * Insert an item in the list, regardless if it is unique
203 void dlist::binary_insert(void *item, int compare(void *item1, void *item2))
205 void *ins_item = unique_binary_insert(item, compare);
206 /* If identical, insert after the one found */
207 if (ins_item != item) {
208 insert_after(item, ins_item);
213 void dlist::remove(void *item)
216 dlink *ilink = (dlink *)(((char *)item)+loffset); /* item's link */
220 ((dlink *)(((char *)head)+loffset))->prev = NULL;
225 } else if (item == tail) {
228 ((dlink *)(((char *)tail)+loffset))->next = NULL;
232 ((dlink *)(((char *)xitem)+loffset))->prev = ilink->prev;
234 ((dlink *)(((char *)xitem)+loffset))->next = ilink->next;
237 if (num_items == 0) {
242 void * dlist::next(const void *item) const
247 return ((dlink *)(((char *)item)+loffset))->next;
250 void * dlist::prev(const void *item) const
255 return ((dlink *)(((char *)item)+loffset))->prev;
259 /* Destroy the list contents */
260 void dlist::destroy()
262 for (void *n=head; n; ) {
263 void *ni = ((dlink *)(((char *)n)+loffset))->next;
280 static int my_compare(void *item1, void *item2)
284 jcr1 = (MYJCR *)item1;
285 jcr2 = (MYJCR *)item2;
286 comp = strcmp(jcr1->buf, jcr2->buf);
287 //Dmsg3(000, "compare=%d: %s to %s\n", comp, jcr1->buf, jcr2->buf);
297 MYJCR *save_jcr = NULL;
300 jcr_chain = (dlist *)malloc(sizeof(dlist));
301 jcr_chain->init(jcr, &jcr->link);
303 printf("Prepend 20 items 0-19\n");
304 for (int i=0; i<20; i++) {
305 sprintf(buf, "This is dlist item %d", i);
306 jcr = (MYJCR *)malloc(sizeof(MYJCR));
307 jcr->buf = bstrdup(buf);
308 jcr_chain->prepend(jcr);
314 next_jcr = (MYJCR *)jcr_chain->next(save_jcr);
315 printf("11th item=%s\n", next_jcr->buf);
316 jcr = (MYJCR *)malloc(sizeof(MYJCR));
317 jcr->buf = save_jcr->buf;
318 printf("Remove 10th item\n");
319 jcr_chain->remove(save_jcr);
320 printf("Re-insert 10th item\n");
321 jcr_chain->insert_before(jcr, next_jcr);
323 printf("Print remaining list.\n");
324 foreach_dlist (jcr, jcr_chain) {
325 printf("Dlist item = %s\n", jcr->buf);
328 jcr_chain->destroy();
331 jcr_chain = New(dlist(jcr, &jcr->link));
332 printf("append 20 items 0-19\n");
333 for (int i=0; i<20; i++) {
334 sprintf(buf, "This is dlist item %d", i);
335 jcr = (MYJCR *)malloc(sizeof(MYJCR));
336 jcr->buf = bstrdup(buf);
337 jcr_chain->append(jcr);
343 next_jcr = (MYJCR *)jcr_chain->next(save_jcr);
344 printf("11th item=%s\n", next_jcr->buf);
345 jcr = (MYJCR *)malloc(sizeof(MYJCR));
346 jcr->buf = save_jcr->buf;
347 printf("Remove 10th item\n");
348 jcr_chain->remove(save_jcr);
349 printf("Re-insert 10th item\n");
350 jcr_chain->insert_before(jcr, next_jcr);
352 printf("Print remaining list.\n");
353 foreach_dlist (jcr, jcr_chain) {
354 printf("Dlist item = %s\n", jcr->buf);
361 /* Now do a binary insert for the list */
362 jcr_chain = New(dlist(jcr, &jcr->link));
364 printf("append %d items\n", CNT*CNT*CNT);
367 for (int i=0; i<CNT; i++) {
368 for (int j=0; j<CNT; j++) {
369 for (int k=0; k<CNT; k++) {
371 if ((count & 0x3FF) == 0) {
372 Dmsg1(000, "At %d\n", count);
374 jcr = (MYJCR *)malloc(sizeof(MYJCR));
375 jcr->buf = bstrdup(buf);
376 jcr1 = (MYJCR *)jcr_chain->binary_insert(jcr, my_compare);
378 Dmsg2(000, "Insert of %s vs %s failed.\n", jcr->buf, jcr1->buf);
389 printf("Print sorted list.\n");
390 foreach_dlist (jcr, jcr_chain) {
391 printf("Dlist item = %s\n", jcr->buf);