/*
- * Bacula doubly linked list routines.
+ * Bacula doubly linked list routines.
*
* dlist is a doubly linked list with the links being in the
* list data item.
- *
+ *
* Kern Sibbald, July MMIII
*
* Version $Id$
*
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2003-2005 Kern Sibbald
This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
+ modify it under the terms of the GNU General Public License
+ version 2 as amended with additional clauses defined in the
+ file LICENSE in the main source directory.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ the file LICENSE for additional details.
*/
/* ===================================================================
* dlist
*/
+
/*
* Append an item to the list
*/
-void dlist::append(void *item)
+void dlist::append(void *item)
{
((dlink *)(((char *)item)+loffset))->next = NULL;
((dlink *)(((char *)item)+loffset))->prev = tail;
/*
* Append an item to the list
*/
-void dlist::prepend(void *item)
+void dlist::prepend(void *item)
{
((dlink *)(((char *)item)+loffset))->next = head;
((dlink *)(((char *)item)+loffset))->prev = NULL;
((dlink *)(((char *)head)+loffset))->prev = item;
}
head = item;
- if (tail == NULL) { /* if empty list, */
+ if (tail == NULL) { /* if empty list, */
tail = item; /* item is tail too */
}
num_items++;
}
-void dlist::insert_before(void *item, void *where)
+void dlist::insert_before(void *item, void *where)
{
- dlink *where_link = (dlink *)((char *)where+loffset);
+ dlink *where_link = (dlink *)((char *)where+loffset);
((dlink *)(((char *)item)+loffset))->next = where;
((dlink *)(((char *)item)+loffset))->prev = where_link->prev;
num_items++;
}
-void dlist::insert_after(void *item, void *where)
+void dlist::insert_after(void *item, void *where)
{
- dlink *where_link = (dlink *)((char *)where+loffset);
+ dlink *where_link = (dlink *)((char *)where+loffset);
((dlink *)(((char *)item)+loffset))->next = where_link->next;
((dlink *)(((char *)item)+loffset))->prev = where;
}
/*
+ * Insert an item in the list, but only if it is unique
+ * otherwise, the item is returned non inserted
+ *
* Returns: item if item inserted
* other_item if same value already exists (item not inserted)
*/
return item;
}
if (num_items == 1) {
- comp = compare(item, first());
+ comp = compare(item, first());
if (comp < 0) {
- insert_before(item, first());
+ prepend(item);
//Dmsg0(000, "Insert before first.\n");
return item;
} else if (comp > 0) {
/* Check against first item */
comp = compare(item, first());
if (comp < 0) {
- insert_before(item, first());
+ prepend(item);
//Dmsg0(000, "Inserted item before.\n");
return item;
} else if (comp == 0) {
cur++;
}
while (nxt < cur) {
- cur_item = prev(cur_item);
+ cur_item = prev(cur_item);
cur--;
}
//Dmsg1(000, "Compare item to %d\n", cur);
return item;
}
+/*
+ * Insert an item in the list, regardless if it is unique
+ * or not.
+ */
+void dlist::binary_insert_multiple(void *item, int compare(void *item1, void *item2))
+{
+ void *ins_item = binary_insert(item, compare);
+ /* If identical, insert after the one found */
+ if (ins_item != item) {
+ insert_after(item, ins_item);
+ }
+}
+
+/*
+ * Search for item
+ */
+void *dlist::binary_search(void *item, int compare(void *item1, void *item2))
+{
+ int comp;
+ int low, high, cur;
+ void *cur_item;
+
+
+ if (num_items == 0) {
+ return NULL;
+ }
+ cur_item = first();
+ if (num_items == 1) {
+ comp = compare(item, cur_item);
+ if (comp == 0) {
+ return cur_item;
+ } else {
+ return NULL;
+ }
+ }
+ low = 1;
+ high = num_items;
+ cur = 1;
+ cur_item = first();
+ while (low < high) {
+ int nxt;
+ nxt = (low + high) / 2;
+ /* Now get cur pointing to nxt */
+ while (nxt > cur) {
+ cur_item = next(cur_item);
+ cur++;
+ }
+ while (nxt < cur) {
+ cur_item = prev(cur_item);
+ cur--;
+ }
+ comp = compare(item, cur_item);
+ //Dmsg2(000, "Compare item to %d = %d\n", cur, comp);
+ if (comp < 0) {
+ high = cur;
+ //Dmsg2(000, "set high; low=%d high=%d\n", low, high);
+ } else if (comp > 0) {
+ low = cur + 1;
+ //Dmsg2(000, "set low; low=%d high=%d\n", low, high);
+ } else {
+ return cur_item;
+ }
+ }
+ /*
+ * low == high can only happen if low just
+ * got incremented from cur, and we have
+ * not yet tested cur+1
+ */
+ if (low == high) {
+ cur_item = next(cur_item);
+ comp = compare(item, cur_item);
+ if (comp == 0) {
+ return cur_item;
+ }
+ }
+ return NULL;
+}
+
void dlist::remove(void *item)
{
}
}
-void * dlist::next(void *item)
+void * dlist::next(const void *item) const
{
if (item == NULL) {
return head;
return ((dlink *)(((char *)item)+loffset))->next;
}
-void * dlist::prev(void *item)
+void * dlist::prev(const void *item) const
{
if (item == NULL) {
return tail;
jcr_chain = (dlist *)malloc(sizeof(dlist));
jcr_chain->init(jcr, &jcr->link);
-
+
printf("Prepend 20 items 0-19\n");
for (int i=0; i<20; i++) {
sprintf(buf, "This is dlist item %d", i);
next_jcr = (MYJCR *)jcr_chain->next(save_jcr);
printf("11th item=%s\n", next_jcr->buf);
- jcr = (MYJCR *)malloc(sizeof(MYJCR));
- jcr->buf = save_jcr->buf;
+ jcr1 = (MYJCR *)malloc(sizeof(MYJCR));
+ jcr1->buf = save_jcr->buf;
printf("Remove 10th item\n");
jcr_chain->remove(save_jcr);
+ free(save_jcr);
printf("Re-insert 10th item\n");
- jcr_chain->insert_before(jcr, next_jcr);
-
+ jcr_chain->insert_before(jcr1, next_jcr);
+
printf("Print remaining list.\n");
- foreach_dlist (jcr, jcr_chain) {
+ foreach_dlist(jcr, jcr_chain) {
printf("Dlist item = %s\n", jcr->buf);
free(jcr->buf);
}
jcr_chain->destroy();
free(jcr_chain);
- jcr_chain = new dlist(jcr, &jcr->link);
+ jcr_chain = New(dlist(jcr, &jcr->link));
printf("append 20 items 0-19\n");
for (int i=0; i<20; i++) {
sprintf(buf, "This is dlist item %d", i);
jcr->buf = save_jcr->buf;
printf("Remove 10th item\n");
jcr_chain->remove(save_jcr);
+ free(save_jcr);
printf("Re-insert 10th item\n");
jcr_chain->insert_before(jcr, next_jcr);
-
+
printf("Print remaining list.\n");
foreach_dlist (jcr, jcr_chain) {
printf("Dlist item = %s\n", jcr->buf);
/* Now do a binary insert for the list */
- jcr_chain = new dlist(jcr, &jcr->link);
+ jcr_chain = New(dlist(jcr, &jcr->link));
#define CNT 26
printf("append %d items\n", CNT*CNT*CNT);
strcpy(buf, "ZZZ");
buf[0]--;
}
- printf("Print sorted list.\n");
+ jcr = (MYJCR *)malloc(sizeof(MYJCR));
+ strcpy(buf, "a");
+ jcr->buf = bstrdup(buf);
+ if (jcr_chain->binary_search(jcr, my_compare)) {
+ printf("One less failed!!!!\n");
+ } else {
+ printf("One less: OK\n");
+ }
+ free(jcr->buf);
+ strcpy(buf, "ZZZZZZZZZZZZZZZZ");
+ jcr->buf = bstrdup(buf);
+ if (jcr_chain->binary_search(jcr, my_compare)) {
+ printf("One greater failed!!!!\n");
+ } else {
+ printf("One greater: OK\n");
+ }
+ free(jcr->buf);
+ free(jcr);
+
+
+ printf("Find each of %d items in list.\n", count);
+ foreach_dlist (jcr, jcr_chain) {
+ if (!jcr_chain->binary_search(jcr, my_compare)) {
+ printf("Dlist binary_search item not found = %s\n", jcr->buf);
+ }
+ }
+ printf("Free each of %d items in list.\n", count);
foreach_dlist (jcr, jcr_chain) {
- printf("Dlist item = %s\n", jcr->buf);
free(jcr->buf);
+ jcr->buf = NULL;
}
-
delete jcr_chain;