⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps_list.c

📁 PSlib是一个用来生成PostScript文件的类库。提供了一个生成PostScript文件的简单方法。
💻 C
字号:
/******************************************************************************					Copyright (C) 1991 Kendall Bennett.*							All rights reserved.** Filename:		$RCSfile: ps_list.c,v $* Version:		$Revision: 1.2 $** Language:		ANSI C* Environment:	any** Description:	Module to implement doubly linked lists. Includes a routine*				to peform a mergesort on the doubly linked list.** $Id: ps_list.c,v 1.2 2004/03/08 16:35:26 steinm Exp $*****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <signal.h>#include "libps/pslib.h"#include "ps_list.h"#define PUBLIC#define PRIVATE staticPUBLIC void *dlst_newnode(DLIST *l, int size)/****************************************************************************** Function:		dlst_newnode* Parameters:	l - list*             size - Amount of memory to allocate for node* Returns:      Pointer to the allocated node's user space.** Description:	Allocates the memory required for a node, adding a small*				header at the start of the node. We return a reference to*				the user space of the node, as if it had been allocated via*				malloc().*****************************************************************************/{	PS_DLST_BUCKET	*node;	if(l == NULL || l->malloc == NULL)		return NULL;	if ( NULL == (node = (PS_DLST_BUCKET*) l->malloc(NULL, size + sizeof(PS_DLST_BUCKET), "dlst_newnode")) ) {		fprintf(stderr,"Not enough memory to allocate list node.\n");/*		raise(SIGABRT);*/		return NULL;		}	return PS_DLST_USERSPACE(node);		/* Return pointer to user space */}PUBLIC void dlst_freenode(DLIST *l, void *node)/****************************************************************************** Function:		dlst_freenode* Parameters:	node	- Node to free.** Description:  Frees a node previously allocated with lst_newnode().*****************************************************************************/{	l->free(NULL, PS_DLST_HEADER(node));}PUBLIC DLIST *dlst_init(void* (*allocproc)(PSDoc *ps, size_t size, const char *caller), void* (*reallocproc)(PSDoc *ps, void *mem, size_t size, const char *caller), void  (*freeproc)(PSDoc *ps, void *mem))/****************************************************************************** Function:		dlst_init* Returns:      Pointer to a newly created list.** Description:	Initialises a list and returns a pointer to it.*****************************************************************************/{	DLIST	*l;	if(allocproc == NULL ||	   reallocproc == NULL ||		 freeproc == NULL)		return NULL;		if ((l = (DLIST*) (* allocproc) (NULL, sizeof(DLIST), "dlst_init")) != NULL) {		l->count = 0;		l->head = &(l->hz[0]);		l->z = &(l->hz[1]);		l->head->next = l->z->next = l->z;		l->z->prev = l->head->prev = l->head;		}	else {		fprintf(stderr,"Insufficient memory to allocate list\n");		/*raise(SIGABRT);*/		return NULL;		}	l->malloc = allocproc;	l->realloc = reallocproc;	l->free = freeproc;	return l;}PUBLIC void dlst_kill(DLIST *l,void (*freeNode)(DLIST *l, void *node))/****************************************************************************** Function:		dlst_kill* Parameters:	l			- List to kill*				freeNode	- Pointer to user routine to free a node** Description:	Kills the list l, by deleting all of the elements contained*				within the list one by one and then deleting the list*				itself. Note that we call the user supplied routine*				(*freeNode)() to free each list node. This allows the user*				program to perform any extra processing needed to kill each*				node (if each node contains pointers to other items on the*				heap for example). If no extra processing is required, just*				pass the address of dlst_freenode(), ie:**					dlst_kill(myList,dlst_freenode);*****************************************************************************/{	PS_DLST_BUCKET	*n,*p;	n = l->head->next;	while (n != l->z) {			/* Free all nodes in list				*/		p = n;		n = n->next;		(*freeNode)(l, PS_DLST_USERSPACE(p));		}	l->free(NULL, l);					/* Free the list itself					*/}PUBLIC void dlst_insertafter(DLIST *l,void *node,void *after)/****************************************************************************** Function:		lst_insertafter* Parameters:	l		- List to insert node into*				node	- Pointer to user space of node to insert*				after	- Pointer to user space of node to insert node after** Description:	Inserts a new node into the list after the node 'after'. To*				insert a new node at the beginning of the list, user the*				macro PS_DLST_HEAD in place of 'after'. ie:**					dlst_insertafter(mylist,node,PS_DLST_HEAD(mylist));*****************************************************************************/{	PS_DLST_BUCKET	*n = PS_DLST_HEADER(node),*a = PS_DLST_HEADER(after);	n->next = a->next;	a->next = n;	n->prev = a;	n->next->prev = n;	l->count++;}PUBLIC void *dlst_deletenext(DLIST *l,void *node)/****************************************************************************** Function:		lst_deletenext* Parameters:	l		- List to delete node from.*				node	- Node to delete the next node from* Returns:		Pointer to the deleted node's userspace.** Description:	Removes the node AFTER 'node' from the list l.*****************************************************************************/{	PS_DLST_BUCKET	*n = PS_DLST_HEADER(node);	node = PS_DLST_USERSPACE(n->next);	n->next->next->prev = n;	n->next = n->next->next;	l->count--;	return node;}PUBLIC void *dlst_first(DLIST *l)/****************************************************************************** Function:		dlst_first* Parameters:	l		- List to obtain first node from* Returns:		Pointer to first node in list, NULL if list is empty.** Description:	Returns a pointer to the user space of the first node in*				the list. If the list is empty, we return NULL.*****************************************************************************/{	PS_DLST_BUCKET	*n;	n = l->head->next;	return (n == l->z ? NULL : PS_DLST_USERSPACE(n));}PUBLIC void *dlst_last(DLIST *l)/****************************************************************************** Function:		dlst_last* Parameters:	l	- List to obtain last node from* Returns:		Pointer to last node in list, NULL if list is empty.** Description:	Returns a pointer to the user space of the last node in*				the list. If the list is empty, we return NULL.*****************************************************************************/{	PS_DLST_BUCKET	*n;	n = l->z->prev;	return (n == l->head ? NULL : PS_DLST_USERSPACE(n));}PUBLIC void *dlst_next(void *prev)/****************************************************************************** Function:		dlst_next* Parameters:	prev	- Previous node in list to obtain next node from* Returns:		Pointer to the next node in the list, NULL at end of list.** Description:	Returns a pointer to the user space of the next node in the*				list given a pointer to the user space of the previous node.*				If we have reached the end of the list, we return NULL. The*				end of the list is detected when the next pointer of a node*				points back to itself, as does the dummy last node's next*				pointer. This enables us to detect the end of the list*				without needed access to the list data structure itself.**				NOTE:	We do no checking to ensure that 'prev' is NOT a*						NULL pointer.*****************************************************************************/{	PS_DLST_BUCKET	*n = PS_DLST_HEADER(prev);	n = n->next;	return (n == n->next ? NULL : PS_DLST_USERSPACE(n));}PUBLIC void *dlst_prev(void *next)/****************************************************************************** Function:		dlst_prev* Parameters:	next	- Next node in list to obtain previous node from* Returns:		Pointer to the previous node in the list, NULL at start list.** Description:	Returns a pointer to the user space of the prev node in the*				list given a pointer to the user space of the next node.*				If we have reached the start of the list, we return NULL. The*				start of the list is detected when the prev pointer of a node*				points back to itself, as does the dummy head node's prev*				pointer. This enables us to detect the start of the list*				without needed access to the list data structure itself.**				NOTE:	We do no checking to ensure that 'next' is NOT a*						NULL pointer.*****************************************************************************/{	PS_DLST_BUCKET	*n = PS_DLST_HEADER(next);	n = n->prev;	return (n == n->prev ? NULL : PS_DLST_USERSPACE(n));}/* Static globals required by merge()	*/static PS_DLST_BUCKET	*z;static int 			(*cmp)(void*,void*);PRIVATE PS_DLST_BUCKET *merge(PS_DLST_BUCKET *a,PS_DLST_BUCKET *b,PS_DLST_BUCKET **end)/****************************************************************************** Function:		merge* Parameters:	a,b		- Sublist's to merge* Returns:		Pointer to the merged sublists.** Description:	Merges two sorted lists of nodes together into a single*				sorted list.*****************************************************************************/{	PS_DLST_BUCKET	*c;	/* Go through the lists, merging them together in sorted order	*/	c = z;	while (a != z && b != z) {		if ((*cmp)(PS_DLST_USERSPACE(a),PS_DLST_USERSPACE(b)) <= 0) {			c->next = a; c = a; a = a->next;			}		else {			c->next = b; c = b; b = b->next;			}		};	/* If one of the lists is not exhausted, then re-attach it to the end	 * of the newly merged list	 */	if (a != z) c->next = a;	if (b != z) c->next = b;	/* Set *end to point to the end of the newly merged list	*/	while (c->next != z) c = c->next;	*end = c;	/* Determine the start of the merged lists, and reset z to point to	 * itself	 */	c = z->next; z->next = z;	return c;}PUBLIC void dlst_mergesort(DLIST *l,int (*cmp_func)(void*,void*))/****************************************************************************** Function:		dlst_mergesort* Parameters:	l			- List to merge sort*				cmp_func	- Function to compare two user spaces** Description:	Mergesort's all the nodes in the list. 'cmp' must point to*				a comparison function that can compare the user spaces of*				two different nodes. 'cmp' should work the same as*				strcmp(), in terms of the values it returns. Rather than*				waste processing time keeping the previous pointers up to*				date while performing the mergesort, we simply run through*				the list at the end of the sort to fix the previous pointers.*****************************************************************************/{	int			i,N;	PS_DLST_BUCKET	*a,*b;		/* Pointers to sublists to merge			*/	PS_DLST_BUCKET	*c;			/* Pointer to end of sorted sublists		*/	PS_DLST_BUCKET	*head;		/* Pointer to dummy head node for list		*/	PS_DLST_BUCKET	*todo;		/* Pointer to sublists yet to be sorted		*/	PS_DLST_BUCKET	*t;			/* Temporary								*/	/* Set up globals required by merge() and pointer to head	*/	z = l->z; cmp = cmp_func; head = l->head;	for (N = 1,a = z; a != head->next; N = N + N) {		todo = head->next; c = head;		while (todo != z) {			/* Build first sublist to be merged, and splice from main list			 */			a = t = todo;			for (i = 1; i < N; i++) t = t->next;			b = t->next; t->next = z; t = b;			/* Build second sublist to be merged and splice from main list			 */			for (i = 1; i < N; i++) t = t->next;			todo = t->next; t->next = z;			/* Merge the two sublists created, and set 'c' to point to the			 * end of the newly merged sublists.			 */			c->next = merge(a,b,&t); c = t;			}		}	/* Fix the previous pointers for the list	*/	a = b = l->head;	b = b->next;	while (1) {		b->prev = a;		if (b == z)			break;		a = a->next;		b = b->next;		}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -