Annotation of sql/sqlite/libltdl/slist.c, revision 1.1
1.1 ! moko 1: /* slist.c -- generalised singly linked lists
! 2:
! 3: Copyright (C) 2000, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
! 4: Written by Gary V. Vaughan, 2000
! 5:
! 6: NOTE: The canonical source of this file is maintained with the
! 7: GNU Libtool package. Report bugs to bug-libtool@gnu.org.
! 8:
! 9: GNU Libltdl is free software; you can redistribute it and/or
! 10: modify it under the terms of the GNU Lesser General Public
! 11: License as published by the Free Software Foundation; either
! 12: version 2 of the License, or (at your option) any later version.
! 13:
! 14: As a special exception to the GNU Lesser General Public License,
! 15: if you distribute this file as part of a program or library that
! 16: is built using GNU Libtool, you may include this file under the
! 17: same distribution terms that you use for the rest of that program.
! 18:
! 19: GNU Libltdl is distributed in the hope that it will be useful,
! 20: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 21: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 22: GNU Lesser General Public License for more details.
! 23:
! 24: You should have received a copy of the GNU Lesser General Public
! 25: License along with GNU Libltdl; see the file COPYING.LIB. If not, a
! 26: copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
! 27: or obtained by writing to the Free Software Foundation, Inc.,
! 28: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
! 29: */
! 30:
! 31: #include <assert.h>
! 32:
! 33: #include "slist.h"
! 34: #include <stddef.h>
! 35: #include <stdlib.h>
! 36:
! 37: static SList * slist_sort_merge (SList *left, SList *right,
! 38: SListCompare *compare, void *userdata);
! 39:
! 40:
! 41: /* Call DELETE repeatedly on each element of HEAD.
! 42:
! 43: CAVEAT: If you call this when HEAD is the start of a list of boxed
! 44: items, you must remember that each item passed back to your
! 45: DELETE function will be a boxed item that must be slist_unbox()ed
! 46: before operating on its contents.
! 47:
! 48: e.g. void boxed_delete (void *item) { item_free (slist_unbox (item)); }
! 49: ...
! 50: slist = slist_delete (slist, boxed_delete);
! 51: ...
! 52: */
! 53: SList *
! 54: slist_delete (SList *head, void (*delete_fct) (void *item))
! 55: {
! 56: assert (delete_fct);
! 57:
! 58: while (head)
! 59: {
! 60: SList *next = head->next;
! 61: (*delete_fct) (head);
! 62: head = next;
! 63: }
! 64:
! 65: return 0;
! 66: }
! 67:
! 68: /* Call FIND repeatedly with MATCHDATA and each item of *PHEAD, until
! 69: FIND returns non-NULL, or the list is exhausted. If a match is found
! 70: the matching item is destructively removed from *PHEAD, and the value
! 71: returned by the matching call to FIND is returned.
! 72:
! 73: CAVEAT: To avoid memory leaks, unless you already have the address of
! 74: the stale item, you should probably return that from FIND if
! 75: it makes a successful match. Don't forget to slist_unbox()
! 76: every item in a boxed list before operating on its contents. */
! 77: SList *
! 78: slist_remove (SList **phead, SListCallback *find, void *matchdata)
! 79: {
! 80: SList *stale = 0;
! 81: void *result = 0;
! 82:
! 83: assert (find);
! 84:
! 85: if (!phead || !*phead)
! 86: return 0;
! 87:
! 88: /* Does the head of the passed list match? */
! 89: result = (*find) (*phead, matchdata);
! 90: if (result)
! 91: {
! 92: stale = *phead;
! 93: *phead = stale->next;
! 94: }
! 95: /* what about the rest of the elements? */
! 96: else
! 97: {
! 98: SList *head;
! 99: for (head = *phead; head->next; head = head->next)
! 100: {
! 101: result = (*find) (head->next, matchdata);
! 102: if (result)
! 103: {
! 104: stale = head->next;
! 105: head->next = stale->next;
! 106: break;
! 107: }
! 108: }
! 109: }
! 110:
! 111: return (SList *) result;
! 112: }
! 113:
! 114: /* Call FIND repeatedly with each element of SLIST and MATCHDATA, until
! 115: FIND returns non-NULL, or the list is exhausted. If a match is found
! 116: the value returned by the matching call to FIND is returned. */
! 117: void *
! 118: slist_find (SList *slist, SListCallback *find, void *matchdata)
! 119: {
! 120: void *result = 0;
! 121:
! 122: assert (find);
! 123:
! 124: for (; slist; slist = slist->next)
! 125: {
! 126: result = (*find) (slist, matchdata);
! 127: if (result)
! 128: break;
! 129: }
! 130:
! 131: return result;
! 132: }
! 133:
! 134: /* Return a single list, composed by destructively concatenating the
! 135: items in HEAD and TAIL. The values of HEAD and TAIL are undefined
! 136: after calling this function.
! 137:
! 138: CAVEAT: Don't mix boxed and unboxed items in a single list.
! 139:
! 140: e.g. slist1 = slist_concat (slist1, slist2); */
! 141: SList *
! 142: slist_concat (SList *head, SList *tail)
! 143: {
! 144: SList *last;
! 145:
! 146: if (!head)
! 147: {
! 148: return tail;
! 149: }
! 150:
! 151: last = head;
! 152: while (last->next)
! 153: last = last->next;
! 154:
! 155: last->next = tail;
! 156:
! 157: return head;
! 158: }
! 159:
! 160: /* Return a single list, composed by destructively appending all of
! 161: the items in SLIST to ITEM. The values of ITEM and SLIST are undefined
! 162: after calling this function.
! 163:
! 164: CAVEAT: Don't mix boxed and unboxed items in a single list.
! 165:
! 166: e.g. slist1 = slist_cons (slist_box (data), slist1); */
! 167: SList *
! 168: slist_cons (SList *item, SList *slist)
! 169: {
! 170: if (!item)
! 171: {
! 172: return slist;
! 173: }
! 174:
! 175: assert (!item->next);
! 176:
! 177: item->next = slist;
! 178: return item;
! 179: }
! 180:
! 181: /* Return a list starting at the second item of SLIST. */
! 182: SList *
! 183: slist_tail (SList *slist)
! 184: {
! 185: return slist ? slist->next : NULL;
! 186: }
! 187:
! 188: /* Return a list starting at the Nth item of SLIST. If SLIST is less
! 189: than N items long, NULL is returned. Just to be confusing, list items
! 190: are counted from 1, to get the 2nd element of slist:
! 191:
! 192: e.g. shared_list = slist_nth (slist, 2); */
! 193: SList *
! 194: slist_nth (SList *slist, size_t n)
! 195: {
! 196: for (;n > 1 && slist; n--)
! 197: slist = slist->next;
! 198:
! 199: return slist;
! 200: }
! 201:
! 202: /* Return the number of items in SLIST. We start counting from 1, so
! 203: the length of a list with no items is 0, and so on. */
! 204: size_t
! 205: slist_length (SList *slist)
! 206: {
! 207: size_t n;
! 208:
! 209: for (n = 0; slist; ++n)
! 210: slist = slist->next;
! 211:
! 212: return n;
! 213: }
! 214:
! 215: /* Destructively reverse the order of items in SLIST. The value of SLIST
! 216: is undefined after calling this function.
! 217:
! 218: CAVEAT: You must store the result of this function, or you might not
! 219: be able to get all the items except the first one back again.
! 220:
! 221: e.g. slist = slist_reverse (slist); */
! 222: SList *
! 223: slist_reverse (SList *slist)
! 224: {
! 225: SList *result = 0;
! 226: SList *next;
! 227:
! 228: while (slist)
! 229: {
! 230: next = slist->next;
! 231: slist->next = result;
! 232: result = slist;
! 233: slist = next;
! 234: }
! 235:
! 236: return result;
! 237: }
! 238:
! 239: /* Call FOREACH once for each item in SLIST, passing both the item and
! 240: USERDATA on each call. */
! 241: void *
! 242: slist_foreach (SList *slist, SListCallback *foreach, void *userdata)
! 243: {
! 244: void *result = 0;
! 245:
! 246: assert (foreach);
! 247:
! 248: while (slist)
! 249: {
! 250: SList *next = slist->next;
! 251: result = (*foreach) (slist, userdata);
! 252:
! 253: if (result)
! 254: break;
! 255:
! 256: slist = next;
! 257: }
! 258:
! 259: return result;
! 260: }
! 261:
! 262: /* Destructively merge the items of two ordered lists LEFT and RIGHT,
! 263: returning a single sorted list containing the items of both -- Part of
! 264: the quicksort algorithm. The values of LEFT and RIGHT are undefined
! 265: after calling this function.
! 266:
! 267: At each iteration, add another item to the merged list by taking the
! 268: lowest valued item from the head of either LEFT or RIGHT, determined
! 269: by passing those items and USERDATA to COMPARE. COMPARE should return
! 270: less than 0 if the head of LEFT has the lower value, greater than 0 if
! 271: the head of RIGHT has the lower value, otherwise 0. */
! 272: static SList *
! 273: slist_sort_merge (SList *left, SList *right, SListCompare *compare,
! 274: void *userdata)
! 275: {
! 276: SList merged, *insert;
! 277:
! 278: insert = &merged;
! 279:
! 280: while (left && right)
! 281: {
! 282: if ((*compare) (left, right, userdata) <= 0)
! 283: {
! 284: insert = insert->next = left;
! 285: left = left->next;
! 286: }
! 287: else
! 288: {
! 289: insert = insert->next = right;
! 290: right = right->next;
! 291: }
! 292: }
! 293:
! 294: insert->next = left ? left : right;
! 295:
! 296: return merged.next;
! 297: }
! 298:
! 299: /* Perform a destructive quicksort on the items in SLIST, by repeatedly
! 300: calling COMPARE with a pair of items from SLIST along with USERDATA
! 301: at every iteration. COMPARE is a function as defined above for
! 302: slist_sort_merge(). The value of SLIST is undefined after calling
! 303: this function.
! 304:
! 305: e.g. slist = slist_sort (slist, compare, 0); */
! 306: SList *
! 307: slist_sort (SList *slist, SListCompare *compare, void *userdata)
! 308: {
! 309: SList *left, *right;
! 310:
! 311: if (!slist)
! 312: return slist;
! 313:
! 314: /* Be sure that LEFT and RIGHT never contain the same item. */
! 315: left = slist;
! 316: right = slist->next;
! 317:
! 318: if (!right)
! 319: return left;
! 320:
! 321: /* Skip two items with RIGHT and one with SLIST, until RIGHT falls off
! 322: the end. SLIST must be about half way along. */
! 323: while (right && (right = right->next))
! 324: {
! 325: if (!right || !(right = right->next))
! 326: break;
! 327: slist = slist->next;
! 328: }
! 329: right = slist->next;
! 330: slist->next = 0;
! 331:
! 332: /* Sort LEFT and RIGHT, then merge the two. */
! 333: return slist_sort_merge (slist_sort (left, compare, userdata),
! 334: slist_sort (right, compare, userdata),
! 335: compare, userdata);
! 336: }
! 337:
! 338:
! 339: /* Aside from using the functions above to manage chained structures of
! 340: any type that has a NEXT pointer as its first field, SLISTs can
! 341: be comprised of boxed items. The boxes are chained together in
! 342: that case, so there is no need for a NEXT field in the item proper.
! 343: Some care must be taken to slist_box and slist_unbox each item in
! 344: a boxed list at the appropriate points to avoid leaking the memory
! 345: used for the boxes. It us usually a very bad idea to mix boxed and
! 346: non-boxed items in a single list. */
! 347:
! 348: /* Return a `boxed' freshly mallocated 1 element list containing
! 349: USERDATA. */
! 350: SList *
! 351: slist_box (const void *userdata)
! 352: {
! 353: SList *item = (SList *) malloc (sizeof *item);
! 354:
! 355: if (item)
! 356: {
! 357: item->next = 0;
! 358: item->userdata = userdata;
! 359: }
! 360:
! 361: return item;
! 362: }
! 363:
! 364: /* Return the contents of a `boxed' ITEM, recycling the box itself. */
! 365: void *
! 366: slist_unbox (SList *item)
! 367: {
! 368: void *userdata = 0;
! 369:
! 370: if (item)
! 371: {
! 372: /* Strip the const, because responsibility for this memory
! 373: passes to the caller on return. */
! 374: userdata = (void *) item->userdata;
! 375: free (item);
! 376: }
! 377:
! 378: return userdata;
! 379: }
E-mail: