home *** CD-ROM | disk | FTP | other *** search
- /* itemList.c
- routines to manage the data structures for gopher items. */
-
- /*---------------------------------------------------------------*/
- /* Xgopher version 1.3 08 April 1993 */
- /* version 1.2 20 November 1992 */
- /* version 1.1 20 April 1992 */
- /* version 1.0 04 March 1992 */
- /* X window system client for the University of Minnesota */
- /* Internet Gopher System. */
- /* Allan Tuchman, University of Illinois at Urbana-Champaign */
- /* Computing and Communications Services Office */
- /* Copyright 1992, 1993 by */
- /* the Board of Trustees of the University of Illinois */
- /* Permission is granted to freely copy and redistribute this */
- /* software with the copyright notice intact. */
- /*---------------------------------------------------------------*/
-
-
- #include <stdio.h>
-
- #include "gopher.h"
- #include "itemList.h"
- #include "dir.h"
- #include "listP.h"
-
- #include "osdep.h"
-
- static gopherItemList unusedItems = {NULL, NULL};
- static int firstItemAlloc = TRUE;
-
- #define FREE_ITEM_LIST_LENGTH itemListLength(&unusedItems)
-
-
- /* Item list management routines:
- initItemList(gopherItemListP) set list pointers to indicate empty
- appendItem(gopherItemListP, gopherItemP) add item to end of list
- getItemN(gopherItemListP, int) return pointer to Nth item in list
- nextItem(gopherItemP) return pointer to next item in list
- removeItemN(gopherItemListP, int) delete Nth item from a list
- removeItem(gopherItemListP, gopherItemP) delete given item from a list
- itemListLength(gopherItemListP) return length of item list
-
- for internal use only:
- pushItem(gopherItemListP, gopherItemP) push item to front of list
- printItemList(gopherItemListP, char *) Only defined if DEBUG is
-
- freeList management routines:
- acquireItem() return ptr to a gopherItem structure
- releaseItem(gopherItemP) Return a gopher item to the free list
- freeItemList(gopherItemP) return list of items to the free list
-
- freeList management routines (internal only):
- allocGopherItem(int) allocate N new items
- releaseItems(gopherItemP) Return items to the free list (internal)
- */
-
-
- /* acquireItem
- Allocate a gopher item from the free list */
-
- gopherItemP
- acquireItem()
- {
- gopherItemP gi;
-
-
- if (unusedItems.first == NULL) {
-
- /* out of gopher items. First reclaim those that
- are out of date, then allocate more if necessary */
-
- checkDirStack();
-
- if (unusedItems.first == NULL ||
- FREE_ITEM_LIST_LENGTH < itemIncrement) {
- allocGopherItem(firstItemAlloc ?
- itemStart : itemIncrement);
- firstItemAlloc = FALSE;
- }
- }
- gi = unusedItems.first;
- unusedItems.first = gi->next;
- if (unusedItems.first == NULL) unusedItems.last = NULL;
-
- gi->next = NULL;
-
- return gi;
- }
-
-
- /* initItemList
- Set the list pointers to indicate that the list is empty */
-
- void
- initItemList(list)
- gopherItemListP list;
- {
- list->first = list->last = NULL;
-
- return;
- }
-
-
- /* releaseItem
- Return a cleared out gopher item to the free list */
-
- void
- releaseItem(gi)
- gopherItemP gi;
- {
- if (gi != NULL)
- pushItem(&unusedItems, gi);
-
- return;
- }
-
-
- /* releaseItems
- Return a linked list of cleared out gopher items to the free list */
-
- static void
- releaseItems(gi)
- gopherItemP gi;
- {
- gopherItemP p;
- int n=0;
-
- while (gi != NULL) {
- p = gi->next;
- releaseItem(gi);
- n++;
- gi = p;
- }
-
- #ifdef NOT_USED
- /* this code is a more efficient way of doing the above */
-
- if (gi == NULL) return;
-
- /* set p to point to the end of the items */
-
- for (p=gi; p->next != NULL; p=p->next) ;
-
- if (unusedItems.last == NULL) unusedItems.last = p;
- p->next = unusedItems.first;
- unusedItems.first = gi;
- #endif /* NOT_USED */
-
- return;
- }
-
-
- /* freeItemList
- Return a list of gopher items to the free list and clear the
- list header */
-
- void
- freeItemList(list)
- gopherItemListP list;
- {
- gopherItemP p;
- int n=0;
-
- if (list != NULL) {
- /* if we know that they are already cleared out, we could use:
- releaseItems(list->first);
- but we don't, so free them one at a time. */
-
- gopherItemP gi=list->first;
-
- while (gi != NULL) {
- p = gi->next;
- freeItem(gi);
- n++;
- gi = p;
- }
-
- initItemList(list);
- }
-
- return;
- }
-
-
- /* itemListLength
- return the number of items in an item list */
-
- int
- itemListLength(list)
- gopherItemListP list;
- {
- int n;
- gopherItemP p;
-
- if (list == NULL) return 0;
-
- for (n=0, p=list->first; p != NULL; n++, p=p->next) ;
-
- return n;
- }
-
-
- /* appendItem
- append an item to the end of an item list */
-
- void
- appendItem(list, gi)
- gopherItemListP list;
- gopherItemP gi;
- {
- if (list == NULL || gi == NULL) return;
-
- if (list->last == NULL) {
- list->first = list->last = gi;
- } else {
- list->last->next = gi;
- list->last = gi;
- }
-
- gi->next = NULL;
-
- return;
- }
-
-
- /* removeItemN
- delete the Nth item from a list. The first item is numbered 0 */
-
- void
- removeItemN(list, n)
- gopherItemListP list;
- int n;
- {
- gopherItemP p, prev;
-
- if (list == NULL) return;
- if (n < 0) return;
- if ((p = list->first) == NULL) return;
-
- if (n == 0) {
- list->first = p->next;
- if (list->last == p) list->last = NULL;
- freeItem(p);
- } else {
- for (prev=p, p=p->next; p!= NULL; prev=p, p=p->next) {
- if (--n == 0) {
- prev->next = p->next;
- if (p == list->last) list->last = prev;
- freeItem(p);
- break;
- }
- }
- }
-
- return;
- }
-
-
- /* removeItem
- delete the a given item from a list. */
-
- void
- removeItem(list, gi)
- gopherItemListP list;
- gopherItemP gi;
- {
- gopherItemP p, prev;
-
- if (list == NULL) return;
- if ((p = list->first) == NULL) return;
-
- if (p == gi) {
- list->first = p->next;
- if (list->last == p) list->last = NULL;
- freeItem(p);
- } else {
- for (prev=p, p=p->next; p!= NULL; prev=p, p=p->next) {
- if (p == gi) {
- prev->next = p->next;
- if (p == list->last) list->last = prev;
- freeItem(p);
- break;
- }
- }
- }
-
- return;
- }
-
-
- /* getItemN
- return a pointer to the Nth item of the specified item list,
- starting with number 0 */
-
- gopherItemP
- getItemN(list, n)
- gopherItemListP list;
- int n;
- {
- gopherItemP p;
-
- if (n < 0) return NULL;
- if (list == NULL) return NULL;
-
- p = list->first;
- for ( ; p != NULL; p=p->next) {
- if (n-- == 0) break;
- }
-
- return p;
- }
-
-
- /* nextItem
- return a pointer to the next item in a list, given an existing item. */
-
- gopherItemP
- nextItem(gi)
- gopherItemP gi;
- {
- if (gi == NULL) return NULL;
- return gi->next;
- }
-
-
- /* pushItem
- push an item onto the front of a item list */
-
- static void
- pushItem(list, gi)
- gopherItemListP list;
- gopherItemP gi;
- {
- gi->next = list->first;
- list->first = gi;
- if (list->last == NULL) list->last = gi;
-
- return;
- }
-
-
- /* allocGopherItem
- Allocate n new gopher items, adding them to the free list */
-
- static void
- allocGopherItem(n)
- int n;
- {
- gopherItemP gil, p;
- int i;
-
- if (n <= 0) return;
-
- if ((gil = (gopherItemP) malloc(n * sizeof(gopherItem))) == NULL) {
- /* out of memory */
- fprintf (stderr, "There is not enough memory to continue.\n");
- exit(3);
- }
-
- for (i=0, p=gil; i<n-1; i++, p++) {
- initItemFields(p);
- p->next = p+1;
- }
- initItemFields(p);
- p->next = NULL;
- releaseItems(gil);
-
- return;
- }
-
-
- /* itemInList
- see if a gopher item is in an item list */
-
- BOOLEAN
- itemInList(list, item)
- gopherItemListP list;
- gopherItemP item;
- {
- gopherItemP p;
- BOOLEAN same;
-
- if (list == NULL || item == NULL) return FALSE;
-
- for (p = list->first; (p != item && p != NULL); p=p->next) {
- same = compareItem(item, p);
- if (same) break;
- }
-
- return (p != NULL);
- }
-
-
- #ifdef DEBUG_LIST
-
-
- /* printItemList
- Print a list of gopher items for checking the list contents */
-
- void
- printItemList(list, label)
- gopherItemListP list;
- char *label;
- {
- gopherItemP gi;
- int i;
-
- if (list == NULL) fprintf(stdout, "NULL list %s\n", label);
- else {
- gi = list->first;
- fprintf (stdout, "list %s:\n", label);
- while (gi != NULL) {
- fprintf (stdout, "\t(");
- for (i=0; i<PREFIX_LEN; i++)
- fprintf (stdout, " %d ",
- (int)((USER_STRING_PREFIX(gi))[i]));
- fprintf (stdout, ") ");
- fprintf (stdout, "(%s)\n", USER_STRING(gi));
- gi = gi->next;
- }
- fprintf (stdout, " end of list\n");
- }
- }
- #endif /* DEBUG_LIST */
-