mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
20
src/backend/lib/Makefile.inc
Normal file
20
src/backend/lib/Makefile.inc
Normal file
@ -0,0 +1,20 @@
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile.inc--
|
||||
# Makefile for the lib module (miscellaneous stuff)
|
||||
#
|
||||
# Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/lib/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
VPATH:=$(VPATH):$(CURDIR)/lib
|
||||
|
||||
|
||||
SRCS_LIB= bit.c fstack.c hasht.c lispsort.c qsort.c stringinfo.c dllist.c
|
||||
|
||||
HEADERS+= fstack.h hasht.h lispsort.h qsort.h stringinfo.h dllist.h
|
||||
|
45
src/backend/lib/bit.c
Normal file
45
src/backend/lib/bit.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* bit.c--
|
||||
* Standard bit array code.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/lib/Attic/bit.c,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* utils/memutils.h contains declarations of the functions in this file
|
||||
*/
|
||||
#include "utils/memutils.h"
|
||||
|
||||
void
|
||||
BitArraySetBit(BitArray bitArray, BitIndex bitIndex)
|
||||
{
|
||||
bitArray[bitIndex/BitsPerByte]
|
||||
|= (1 << (BitsPerByte - (bitIndex % BitsPerByte) - 1));
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
BitArrayClearBit(BitArray bitArray, BitIndex bitIndex)
|
||||
{
|
||||
bitArray[bitIndex/BitsPerByte]
|
||||
&= ~(1 << (BitsPerByte - (bitIndex % BitsPerByte) - 1));
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
BitArrayBitIsSet(BitArray bitArray, BitIndex bitIndex)
|
||||
{
|
||||
return( (bool) (((bitArray[bitIndex / BitsPerByte] &
|
||||
(1 << (BitsPerByte - (bitIndex % BitsPerByte)
|
||||
- 1)
|
||||
)
|
||||
) != 0 ) ? 1 : 0) );
|
||||
}
|
||||
|
204
src/backend/lib/dllist.c
Normal file
204
src/backend/lib/dllist.c
Normal file
@ -0,0 +1,204 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* dllist.c--
|
||||
* this is a simple doubly linked list implementation
|
||||
* replaces the old simplelists stuff
|
||||
* the elements of the lists are void*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "c.h"
|
||||
#include "lib/dllist.h"
|
||||
|
||||
Dllist*
|
||||
DLNewList()
|
||||
{
|
||||
Dllist* l;
|
||||
|
||||
l = malloc(sizeof(Dllist));
|
||||
l->dll_head = 0;
|
||||
l->dll_tail = 0;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/* free up a list and all the nodes in it*/
|
||||
void
|
||||
DLFreeList(Dllist* l)
|
||||
{
|
||||
Dlelem* curr;
|
||||
|
||||
while ( (curr = DLRemHead(l)) != 0)
|
||||
free(curr);
|
||||
|
||||
free(l);
|
||||
}
|
||||
|
||||
Dlelem*
|
||||
DLNewElem(void* val)
|
||||
{
|
||||
Dlelem* e;
|
||||
e = malloc(sizeof(Dlelem));
|
||||
e->dle_next = 0;
|
||||
e->dle_prev = 0;
|
||||
e->dle_val = val;
|
||||
e->dle_list = 0;
|
||||
return e;
|
||||
}
|
||||
|
||||
void
|
||||
DLFreeElem(Dlelem* e)
|
||||
{
|
||||
free(e);
|
||||
}
|
||||
|
||||
Dlelem*
|
||||
DLGetHead(Dllist* l)
|
||||
{
|
||||
return (l ? l->dll_head : 0);
|
||||
}
|
||||
|
||||
/* get the value stored in the first element */
|
||||
void*
|
||||
DLGetHeadVal(Dllist* l)
|
||||
{
|
||||
Dlelem* e = DLGetHead(l);
|
||||
|
||||
return (e ? e->dle_val : 0);
|
||||
}
|
||||
|
||||
Dlelem*
|
||||
DLGetTail(Dllist* l)
|
||||
{
|
||||
return (l ? l->dll_tail : 0);
|
||||
}
|
||||
|
||||
/* get the value stored in the first element */
|
||||
void*
|
||||
DLGetTailVal(Dllist* l)
|
||||
{
|
||||
Dlelem* e = DLGetTail(l);
|
||||
|
||||
return (e ? e->dle_val : 0);
|
||||
}
|
||||
|
||||
|
||||
Dlelem*
|
||||
DLGetPred(Dlelem* e) /* get predecessor */
|
||||
{
|
||||
return (e ? e->dle_prev : 0);
|
||||
}
|
||||
|
||||
Dlelem*
|
||||
DLGetSucc(Dlelem* e) /* get successor */
|
||||
{
|
||||
return (e ? e->dle_next : 0);
|
||||
}
|
||||
|
||||
void
|
||||
DLRemove(Dlelem* e)
|
||||
{
|
||||
Dllist* l;
|
||||
|
||||
if (e->dle_prev)
|
||||
e->dle_prev->dle_next = e->dle_next;
|
||||
if (e->dle_next)
|
||||
e->dle_next->dle_prev = e->dle_prev;
|
||||
|
||||
/* check to see if we're removing the head or tail */
|
||||
l = e->dle_list;
|
||||
if (e == l->dll_head)
|
||||
DLRemHead(l);
|
||||
if (e == l->dll_tail)
|
||||
DLRemTail(l);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
DLAddHead(Dllist* l, Dlelem* e)
|
||||
{
|
||||
e->dle_list = l;
|
||||
|
||||
if (l->dll_head) {
|
||||
l->dll_head->dle_prev = e;
|
||||
e->dle_next = l->dll_head;
|
||||
}
|
||||
e->dle_prev = 0;
|
||||
l->dll_head = e;
|
||||
|
||||
if (l->dll_tail == 0) /* if this is first element added */
|
||||
l->dll_tail = l->dll_head;
|
||||
}
|
||||
|
||||
void
|
||||
DLAddTail(Dllist* l, Dlelem* e)
|
||||
{
|
||||
e->dle_list = l;
|
||||
|
||||
if (l->dll_tail) {
|
||||
l->dll_tail->dle_next = e;
|
||||
e->dle_prev = l->dll_tail;
|
||||
}
|
||||
e->dle_next = 0;
|
||||
l->dll_tail = e;
|
||||
|
||||
if (l->dll_head == 0) /* if this is first element added */
|
||||
l->dll_head = l->dll_tail;
|
||||
}
|
||||
|
||||
Dlelem*
|
||||
DLRemHead(Dllist* l)
|
||||
{
|
||||
/* remove and return the head */
|
||||
Dlelem* result;
|
||||
|
||||
if (l->dll_head == 0)
|
||||
return 0;
|
||||
|
||||
result = l->dll_head;
|
||||
if (l->dll_head->dle_next) {
|
||||
l->dll_head->dle_next->dle_prev = 0;
|
||||
}
|
||||
|
||||
l->dll_head = l->dll_head->dle_next;
|
||||
|
||||
result->dle_next = 0;
|
||||
result->dle_list = 0;
|
||||
|
||||
if (result == l->dll_tail) /* if the head is also the tail */
|
||||
l->dll_tail = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Dlelem*
|
||||
DLRemTail(Dllist* l)
|
||||
{
|
||||
/* remove and return the tail */
|
||||
Dlelem* result;
|
||||
|
||||
if (l->dll_tail == 0 )
|
||||
return 0;
|
||||
|
||||
result = l->dll_tail;
|
||||
if (l->dll_tail->dle_prev) {
|
||||
l->dll_tail->dle_prev->dle_next = 0;
|
||||
}
|
||||
l->dll_tail = l->dll_tail->dle_prev;
|
||||
|
||||
result->dle_prev = 0;
|
||||
result->dle_list = 0;
|
||||
|
||||
if (result == l->dll_head) /* if the tail is also the head */
|
||||
l->dll_head = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
72
src/backend/lib/dllist.h
Normal file
72
src/backend/lib/dllist.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* dllist.h--
|
||||
* simple doubly linked list primitives
|
||||
* the elements of the list are void* so the lists can contain
|
||||
* anything
|
||||
* Dlelem can only be in one list at a time
|
||||
*
|
||||
*
|
||||
* Here's a small example of how to use Dllist's :
|
||||
*
|
||||
* Dllist *lst;
|
||||
* Dlelem *elt;
|
||||
* void *in_stuff; -- stuff to stick in the list
|
||||
* void *out_stuff
|
||||
*
|
||||
* lst = DLNewList(); -- make a new dllist
|
||||
* DLAddHead(lst, DLNewElem(in_stuff)); -- add a new element to the list
|
||||
* with in_stuff as the value
|
||||
* ...
|
||||
* elt = DLGetHead(lst); -- retrieve the head element
|
||||
* out_stuff = (void*)DLE_VAL(elt); -- get the stuff out
|
||||
* DLRemove(elt); -- removes the element from its list
|
||||
* DLFreeElem(elt); -- free the element since we don't
|
||||
* use it anymore
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: dllist.h,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef DLLIST_H
|
||||
#define DLLIST_H
|
||||
|
||||
#include "c.h"
|
||||
|
||||
struct Dllist;
|
||||
struct Dlelem;
|
||||
|
||||
typedef struct Dlelem {
|
||||
struct Dlelem *dle_next; /* next element */
|
||||
struct Dlelem *dle_prev; /* previous element */
|
||||
void *dle_val; /* value of the element */
|
||||
struct Dllist *dle_list; /* what list this element is in */
|
||||
} Dlelem;
|
||||
|
||||
typedef struct Dllist {
|
||||
Dlelem *dll_head;
|
||||
Dlelem *dll_tail;
|
||||
} Dllist;
|
||||
|
||||
extern Dllist* DLNewList(); /* initialize a new list */
|
||||
extern void DLFreeList(Dllist*); /* free up a list and all the nodes in it*/
|
||||
extern Dlelem* DLNewElem(void* val);
|
||||
extern void DLFreeElem(Dlelem*);
|
||||
extern Dlelem* DLGetHead(Dllist*);
|
||||
extern Dlelem* DLGetTail(Dllist*);
|
||||
extern void* DLGetHeadVal(Dllist*);
|
||||
extern void* DLGetTailVal(Dllist*);
|
||||
extern Dlelem* DLGetPred(Dlelem*); /* get predecessor */
|
||||
extern Dlelem* DLGetSucc(Dlelem*); /* get successor */
|
||||
extern void DLRemove(Dlelem*); /* removes node from list*/
|
||||
extern void DLAddHead(Dllist* list, Dlelem* node);
|
||||
extern void DLAddTail(Dllist* list, Dlelem* node);
|
||||
extern Dlelem* DLRemHead(Dllist* list); /* remove and return the head */
|
||||
extern Dlelem* DLRemTail(Dllist* list); /* remove and return the tail */
|
||||
|
||||
#define DLE_VAL(x) (x->dle_val)
|
||||
|
||||
#endif /* DLLIST_H */
|
153
src/backend/lib/fstack.c
Normal file
153
src/backend/lib/fstack.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* fstack.c--
|
||||
* Fixed format stack definitions.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/lib/Attic/fstack.c,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "c.h"
|
||||
#include "lib/fstack.h"
|
||||
|
||||
/*
|
||||
* Internal function definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* FixedItemIsValid --
|
||||
* True iff item is valid.
|
||||
*/
|
||||
#define FixedItemIsValid(item) PointerIsValid(item)
|
||||
|
||||
/*
|
||||
* FixedStackGetItemBase --
|
||||
* Returns base of enclosing structure.
|
||||
*/
|
||||
#define FixedStackGetItemBase(stack, item) \
|
||||
((Pointer)((char *)(item) - (stack)->offset))
|
||||
|
||||
/*
|
||||
* FixedStackGetItem --
|
||||
* Returns item of given pointer to enclosing structure.
|
||||
*/
|
||||
#define FixedStackGetItem(stack, pointer) \
|
||||
((FixedItem)((char *)(pointer) + (stack)->offset))
|
||||
|
||||
/*
|
||||
* External functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* FixedStackIsValid --
|
||||
* True iff stack is valid.
|
||||
*/
|
||||
static bool
|
||||
FixedStackIsValid(FixedStack stack)
|
||||
{
|
||||
return ((bool)PointerIsValid(stack));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FixedStackInit(FixedStack stack, Offset offset)
|
||||
{
|
||||
AssertArg(PointerIsValid(stack));
|
||||
|
||||
stack->top = NULL;
|
||||
stack->offset = offset;
|
||||
}
|
||||
|
||||
Pointer
|
||||
FixedStackPop(FixedStack stack)
|
||||
{
|
||||
Pointer pointer;
|
||||
|
||||
AssertArg(FixedStackIsValid(stack));
|
||||
|
||||
if (!PointerIsValid(stack->top)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pointer = FixedStackGetItemBase(stack, stack->top);
|
||||
stack->top = stack->top->next;
|
||||
|
||||
return (pointer);
|
||||
}
|
||||
|
||||
void
|
||||
FixedStackPush(FixedStack stack, Pointer pointer)
|
||||
{
|
||||
FixedItem item = FixedStackGetItem(stack, pointer);
|
||||
|
||||
AssertArg(FixedStackIsValid(stack));
|
||||
AssertArg(PointerIsValid(pointer));
|
||||
|
||||
item->next = stack->top;
|
||||
stack->top = item;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FixedStackContains --
|
||||
* True iff ordered stack contains given element.
|
||||
*
|
||||
* Note:
|
||||
* This is inefficient. It is intended for debugging use only.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if stack is invalid.
|
||||
* BadArg if pointer is invalid.
|
||||
*/
|
||||
static bool
|
||||
FixedStackContains(FixedStack stack, Pointer pointer)
|
||||
{
|
||||
FixedItem next;
|
||||
FixedItem item;
|
||||
|
||||
AssertArg(FixedStackIsValid(stack));
|
||||
AssertArg(PointerIsValid(pointer));
|
||||
|
||||
item = FixedStackGetItem(stack, pointer);
|
||||
|
||||
for (next = stack->top; FixedItemIsValid(next); next = next->next) {
|
||||
if (next == item) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
Pointer
|
||||
FixedStackGetTop(FixedStack stack)
|
||||
{
|
||||
AssertArg(FixedStackIsValid(stack));
|
||||
|
||||
if (!PointerIsValid(stack->top)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (FixedStackGetItemBase(stack, stack->top));
|
||||
}
|
||||
|
||||
Pointer
|
||||
FixedStackGetNext(FixedStack stack, Pointer pointer)
|
||||
{
|
||||
FixedItem item;
|
||||
|
||||
/* AssertArg(FixedStackIsValid(stack)); */
|
||||
/* AssertArg(PointerIsValid(pointer)); */
|
||||
AssertArg(FixedStackContains(stack, pointer));
|
||||
|
||||
item = FixedStackGetItem(stack, pointer)->next;
|
||||
|
||||
if (!PointerIsValid(item)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return(FixedStackGetItemBase(stack, item));
|
||||
}
|
113
src/backend/lib/fstack.h
Normal file
113
src/backend/lib/fstack.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* fstack.h--
|
||||
* Fixed format stack definitions.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: fstack.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* Note:
|
||||
* Fixed format stacks assist in the construction of FIFO stacks of
|
||||
* fixed format structures. Structures which are to be stackable
|
||||
* should contain a FixedItemData component. A stack is initilized
|
||||
* with the offset of the FixedItemData component of the structure
|
||||
* it will hold. By doing so, push and pop operations are simplified
|
||||
* for the callers. All references to stackable items are pointers
|
||||
* to the base of the structure instead of pointers to the
|
||||
* FixedItemData component.
|
||||
*
|
||||
*/
|
||||
#ifndef FSTACK_H
|
||||
#define FSTACK_H
|
||||
|
||||
#include "c.h"
|
||||
|
||||
/*
|
||||
* FixedItem --
|
||||
* Fixed format stackable item chain component.
|
||||
*
|
||||
* Note:
|
||||
* Structures must contain one FixedItemData component per stack in
|
||||
* which it will be an item.
|
||||
*/
|
||||
typedef struct FixedItemData FixedItemData;
|
||||
typedef FixedItemData *FixedItem;
|
||||
|
||||
struct FixedItemData {
|
||||
FixedItem next; /* next item or NULL */
|
||||
};
|
||||
|
||||
/*
|
||||
* FixedStack --
|
||||
* Fixed format stack.
|
||||
*/
|
||||
typedef struct FixedStackData {
|
||||
FixedItem top; /* Top item on the stack or NULL */
|
||||
Offset offset; /* Offset from struct base to item */
|
||||
/* this could be signed short int! */
|
||||
} FixedStackData;
|
||||
|
||||
typedef FixedStackData *FixedStack;
|
||||
|
||||
/*
|
||||
* FixedStackInit --
|
||||
* Iniitializes stack for structures with given fixed component offset.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if stack is invalid pointer.
|
||||
*/
|
||||
extern void FixedStackInit(FixedStack stack, Offset offset);
|
||||
|
||||
/*
|
||||
* FixedStackPop --
|
||||
* Returns pointer to top structure on stack or NULL if empty stack.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if stack is invalid.
|
||||
*/
|
||||
Pointer FixedStackPop(FixedStack stack);
|
||||
|
||||
/*
|
||||
* FixedStackPush --
|
||||
* Places structure associated with pointer onto top of stack.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if stack is invalid.
|
||||
* BadArg if pointer is invalid.
|
||||
*/
|
||||
extern void FixedStackPush(FixedStack stack, Pointer pointer);
|
||||
|
||||
/*
|
||||
* FixedStackGetTop --
|
||||
* Returns pointer to top structure of a stack. This item is not poped.
|
||||
*
|
||||
* Note:
|
||||
* This is not part of the normal stack interface. It is intended for
|
||||
* debugging use only.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if stack is invalid.
|
||||
*/
|
||||
extern Pointer FixedStackGetTop(FixedStack stack);
|
||||
|
||||
/*
|
||||
* FixedStackGetNext --
|
||||
* Returns pointer to next structure after pointer of a stack.
|
||||
*
|
||||
* Note:
|
||||
* This is not part of the normal stack interface. It is intended for
|
||||
* debugging use only.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if stack is invalid.
|
||||
* BadArg if pointer is invalid.
|
||||
* BadArg if stack does not contain pointer.
|
||||
*/
|
||||
extern Pointer FixedStackGetNext(FixedStack stack, Pointer pointer);
|
||||
|
||||
#endif /* FSTACK_H */
|
47
src/backend/lib/hasht.c
Normal file
47
src/backend/lib/hasht.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* hasht.c--
|
||||
* hash table related functions that are not directly supported
|
||||
* by the hashing packages under utils/hash.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/lib/Attic/hasht.c,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "c.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/hsearch.h"
|
||||
#include "lib/hasht.h"
|
||||
|
||||
/* -----------------------------------
|
||||
* HashTableWalk
|
||||
*
|
||||
* call function on every element in hashtable
|
||||
* one extra argument, arg may be supplied
|
||||
* -----------------------------------
|
||||
*/
|
||||
void
|
||||
HashTableWalk(HTAB *hashtable, HashtFunc function, int arg)
|
||||
{
|
||||
long *hashent;
|
||||
long *data;
|
||||
int keysize;
|
||||
|
||||
keysize = hashtable->hctl->keysize;
|
||||
(void)hash_seq((HTAB *)NULL);
|
||||
while ((hashent = hash_seq(hashtable)) != (long *) TRUE) {
|
||||
if (hashent == NULL)
|
||||
elog(FATAL, "error in HashTableWalk.");
|
||||
/*
|
||||
* XXX the corresponding hash table insertion does NOT
|
||||
* LONGALIGN -- make sure the keysize is ok
|
||||
*/
|
||||
data = (long *) LONGALIGN((char*) hashent + keysize);
|
||||
(*function)(data, arg);
|
||||
}
|
||||
}
|
23
src/backend/lib/hasht.h
Normal file
23
src/backend/lib/hasht.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* hasht.h--
|
||||
* hash table related functions that are not directly supported
|
||||
* under utils/hash.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: hasht.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef HASHT_H
|
||||
#define HASHT_H
|
||||
|
||||
#include "utils/hsearch.h"
|
||||
|
||||
typedef void (*HashtFunc)();
|
||||
|
||||
extern void HashTableWalk(HTAB *hashtable, HashtFunc function, int arg);
|
||||
|
||||
#endif /* HASHT_H */
|
56
src/backend/lib/lispsort.c
Normal file
56
src/backend/lib/lispsort.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* lispsort.c--
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/lib/Attic/lispsort.c,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/primnodes.h"
|
||||
#include "nodes/plannodes.h"
|
||||
#include "nodes/relation.h"
|
||||
#include "lib/lispsort.h"
|
||||
#include "utils/palloc.h"
|
||||
#include "lib/qsort.h"
|
||||
|
||||
/*
|
||||
** lisp_qsort: Takes a lisp list as input, copies it into an array of lisp
|
||||
** nodes which it sorts via qsort() with the comparison function
|
||||
** as passed into lisp_qsort(), and returns a new list with
|
||||
** the nodes sorted. The old list is *not* freed or modified (?)
|
||||
*/
|
||||
List *lisp_qsort(List *the_list, /* the list to be sorted */
|
||||
int (*compare)()) /* function to compare two nodes */
|
||||
{
|
||||
int i;
|
||||
size_t num;
|
||||
List **nodearray;
|
||||
List *tmp, *output;
|
||||
|
||||
/* find size of list */
|
||||
num = length(the_list);
|
||||
if (num < 2)
|
||||
return(copyObject(the_list));
|
||||
|
||||
/* copy elements of the list into an array */
|
||||
nodearray = (List **) palloc(num * sizeof(List *));
|
||||
|
||||
for (tmp = the_list, i = 0; tmp != NIL; tmp = lnext(tmp), i++)
|
||||
nodearray[i] = copyObject(lfirst(tmp));
|
||||
|
||||
/* sort the array */
|
||||
pg_qsort(nodearray, num, sizeof(List *), compare);
|
||||
|
||||
/* lcons together the array elements */
|
||||
output = NIL;
|
||||
for (i = num - 1; i >= 0; i--)
|
||||
output = lcons(nodearray[i], output);
|
||||
|
||||
return(output);
|
||||
}
|
18
src/backend/lib/lispsort.h
Normal file
18
src/backend/lib/lispsort.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* lispsort.h--
|
||||
*
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: lispsort.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef LISPSORT_H
|
||||
#define LISPSORT_H
|
||||
|
||||
extern List *lisp_qsort(List *the_list, int (*compare)());
|
||||
|
||||
#endif /* LISPSORT_H */
|
281
src/backend/lib/qsort.c
Normal file
281
src/backend/lib/qsort.c
Normal file
@ -0,0 +1,281 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* qsort.c--
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/lib/Attic/qsort.c,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 1980, 1983, 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)qsort.c 5.9 (Berkeley) 2/23/91";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "postgres.h"
|
||||
#include "lib/qsort.h"
|
||||
|
||||
/*
|
||||
* MTHRESH is the smallest partition for which we compare for a median
|
||||
* value instead of using the middle value.
|
||||
*/
|
||||
#define MTHRESH 6
|
||||
|
||||
/*
|
||||
* THRESH is the minimum number of entries in a partition for continued
|
||||
* partitioning.
|
||||
*/
|
||||
#define THRESH 4
|
||||
|
||||
static void insertion_sort(char* bot, int nmemb, int size, int (*compar)());
|
||||
static void quick_sort(char* bot, int nmemb, int size, int (*compar)());
|
||||
|
||||
void pg_qsort(void *bot,
|
||||
size_t nmemb,
|
||||
size_t size,
|
||||
int (*compar)(void *, void *))
|
||||
{
|
||||
|
||||
if (nmemb <= 1)
|
||||
return;
|
||||
|
||||
if (nmemb >= THRESH)
|
||||
quick_sort(bot, nmemb, size, compar);
|
||||
else
|
||||
insertion_sort(bot, nmemb, size, compar);
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap two areas of size number of bytes. Although qsort(3) permits random
|
||||
* blocks of memory to be sorted, sorting pointers is almost certainly the
|
||||
* common case (and, were it not, could easily be made so). Regardless, it
|
||||
* isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
|
||||
* arithmetic gets lost in the time required for comparison function calls.
|
||||
*/
|
||||
#define SWAP(a, b) { \
|
||||
cnt = size; \
|
||||
do { \
|
||||
ch = *a; \
|
||||
*a++ = *b; \
|
||||
*b++ = ch; \
|
||||
} while (--cnt); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Knuth, Vol. 3, page 116, Algorithm Q, step b, argues that a single pass
|
||||
* of straight insertion sort after partitioning is complete is better than
|
||||
* sorting each small partition as it is created. This isn't correct in this
|
||||
* implementation because comparisons require at least one (and often two)
|
||||
* function calls and are likely to be the dominating expense of the sort.
|
||||
* Doing a final insertion sort does more comparisons than are necessary
|
||||
* because it compares the "edges" and medians of the partitions which are
|
||||
* known to be already sorted.
|
||||
*
|
||||
* This is also the reasoning behind selecting a small THRESH value (see
|
||||
* Knuth, page 122, equation 26), since the quicksort algorithm does less
|
||||
* comparisons than the insertion sort.
|
||||
*/
|
||||
#define SORT(bot, n) { \
|
||||
if (n > 1) \
|
||||
if (n == 2) { \
|
||||
t1 = bot + size; \
|
||||
if (compar(t1, bot) < 0) \
|
||||
SWAP(t1, bot); \
|
||||
} else \
|
||||
insertion_sort(bot, n, size, compar); \
|
||||
}
|
||||
|
||||
static void
|
||||
quick_sort(char* bot, int nmemb, int size, int (*compar)())
|
||||
{
|
||||
register int cnt;
|
||||
register u_char ch;
|
||||
register char *top, *mid, *t1, *t2;
|
||||
register int n1, n2;
|
||||
char *bsv;
|
||||
|
||||
/* bot and nmemb must already be set. */
|
||||
partition:
|
||||
|
||||
/* find mid and top elements */
|
||||
mid = bot + size * (nmemb >> 1);
|
||||
top = bot + (nmemb - 1) * size;
|
||||
|
||||
/*
|
||||
* Find the median of the first, last and middle element (see Knuth,
|
||||
* Vol. 3, page 123, Eq. 28). This test order gets the equalities
|
||||
* right.
|
||||
*/
|
||||
if (nmemb >= MTHRESH) {
|
||||
n1 = compar(bot, mid);
|
||||
n2 = compar(mid, top);
|
||||
if (n1 < 0 && n2 > 0)
|
||||
t1 = compar(bot, top) < 0 ? top : bot;
|
||||
else if (n1 > 0 && n2 < 0)
|
||||
t1 = compar(bot, top) > 0 ? top : bot;
|
||||
else
|
||||
t1 = mid;
|
||||
|
||||
/* if mid element not selected, swap selection there */
|
||||
if (t1 != mid) {
|
||||
SWAP(t1, mid);
|
||||
mid -= size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Standard quicksort, Knuth, Vol. 3, page 116, Algorithm Q. */
|
||||
#define didswap n1
|
||||
#define newbot t1
|
||||
#define replace t2
|
||||
didswap = 0;
|
||||
for (bsv = bot;;) {
|
||||
for (; bot < mid && compar(bot, mid) <= 0; bot += size);
|
||||
while (top > mid) {
|
||||
if (compar(mid, top) <= 0) {
|
||||
top -= size;
|
||||
continue;
|
||||
}
|
||||
newbot = bot + size; /* value of bot after swap */
|
||||
if (bot == mid) /* top <-> mid, mid == top */
|
||||
replace = mid = top;
|
||||
else { /* bot <-> top */
|
||||
replace = top;
|
||||
top -= size;
|
||||
}
|
||||
goto swap;
|
||||
}
|
||||
if (bot == mid)
|
||||
break;
|
||||
|
||||
/* bot <-> mid, mid == bot */
|
||||
replace = mid;
|
||||
newbot = mid = bot; /* value of bot after swap */
|
||||
top -= size;
|
||||
|
||||
swap: SWAP(bot, replace);
|
||||
bot = newbot;
|
||||
didswap = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Quicksort behaves badly in the presence of data which is already
|
||||
* sorted (see Knuth, Vol. 3, page 119) going from O N lg N to O N^2.
|
||||
* To avoid this worst case behavior, if a re-partitioning occurs
|
||||
* without swapping any elements, it is not further partitioned and
|
||||
* is insert sorted. This wins big with almost sorted data sets and
|
||||
* only loses if the data set is very strangely partitioned. A fix
|
||||
* for those data sets would be to return prematurely if the insertion
|
||||
* sort routine is forced to make an excessive number of swaps, and
|
||||
* continue the partitioning.
|
||||
*/
|
||||
if (!didswap) {
|
||||
insertion_sort(bsv, nmemb, size, compar);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-partition or sort as necessary. Note that the mid element
|
||||
* itself is correctly positioned and can be ignored.
|
||||
*/
|
||||
#define nlower n1
|
||||
#define nupper n2
|
||||
bot = bsv;
|
||||
nlower = (mid - bot) / size; /* size of lower partition */
|
||||
mid += size;
|
||||
nupper = nmemb - nlower - 1; /* size of upper partition */
|
||||
|
||||
/*
|
||||
* If must call recursively, do it on the smaller partition; this
|
||||
* bounds the stack to lg N entries.
|
||||
*/
|
||||
if (nlower > nupper) {
|
||||
if (nupper >= THRESH)
|
||||
quick_sort(mid, nupper, size, compar);
|
||||
else {
|
||||
SORT(mid, nupper);
|
||||
if (nlower < THRESH) {
|
||||
SORT(bot, nlower);
|
||||
return;
|
||||
}
|
||||
}
|
||||
nmemb = nlower;
|
||||
} else {
|
||||
if (nlower >= THRESH)
|
||||
quick_sort(bot, nlower, size, compar);
|
||||
else {
|
||||
SORT(bot, nlower);
|
||||
if (nupper < THRESH) {
|
||||
SORT(mid, nupper);
|
||||
return;
|
||||
}
|
||||
}
|
||||
bot = mid;
|
||||
nmemb = nupper;
|
||||
}
|
||||
goto partition;
|
||||
}
|
||||
|
||||
static void
|
||||
insertion_sort(char* bot, int nmemb, int size, int (*compar)())
|
||||
{
|
||||
register int cnt;
|
||||
register u_char ch;
|
||||
register char *s1, *s2, *t1, *t2, *top;
|
||||
|
||||
/*
|
||||
* A simple insertion sort (see Knuth, Vol. 3, page 81, Algorithm
|
||||
* S). Insertion sort has the same worst case as most simple sorts
|
||||
* (O N^2). It gets used here because it is (O N) in the case of
|
||||
* sorted data.
|
||||
*/
|
||||
top = bot + nmemb * size;
|
||||
for (t1 = bot + size; t1 < top;) {
|
||||
for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;);
|
||||
if (t1 != (t2 += size)) {
|
||||
/* Bubble bytes up through each element. */
|
||||
for (cnt = size; cnt--; ++t1) {
|
||||
ch = *t1;
|
||||
for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2)
|
||||
*s1 = *s2;
|
||||
*s1 = ch;
|
||||
}
|
||||
} else
|
||||
t1 += size;
|
||||
}
|
||||
}
|
24
src/backend/lib/qsort.h
Normal file
24
src/backend/lib/qsort.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* qsort.h--
|
||||
*
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: qsort.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef QSORT_H
|
||||
#define QSORT_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
extern void pg_qsort(void *bot,
|
||||
size_t nmemb,
|
||||
size_t size,
|
||||
int (*compar)(void *, void *));
|
||||
|
||||
#endif /* QSORT_H */
|
||||
|
116
src/backend/lib/stringinfo.c
Normal file
116
src/backend/lib/stringinfo.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* stringinfo.c--
|
||||
* These are routines that can be used to write informations to a string,
|
||||
* without having to worry about string lengths, space allocation etc.
|
||||
* Ideally the interface should look like the file i/o interface,
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/lib/stringinfo.c,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "postgres.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/palloc.h"
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* makeStringInfo
|
||||
*
|
||||
* Create a StringInfoData & return a pointer to it.
|
||||
*
|
||||
*---------------------------------------------------------------------
|
||||
*/
|
||||
StringInfo
|
||||
makeStringInfo()
|
||||
{
|
||||
StringInfo res;
|
||||
long size;
|
||||
|
||||
res = (StringInfo) palloc(sizeof(StringInfoData));
|
||||
if (res == NULL) {
|
||||
elog(WARN, "makeStringInfo: Out of memory!");
|
||||
}
|
||||
|
||||
size = 100;
|
||||
res->data = palloc(size);
|
||||
if (res->data == NULL) {
|
||||
elog(WARN,
|
||||
"makeStringInfo: Out of memory! (%ld bytes requested)", size);
|
||||
}
|
||||
res->maxlen = size;
|
||||
res->len = 0;
|
||||
/*
|
||||
* NOTE: we must initialize `res->data' to the empty string because
|
||||
* we use 'strcat' in 'appendStringInfo', which of course it always
|
||||
* expects a null terminated string.
|
||||
*/
|
||||
res->data[0] = '\0';
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* appendStringInfo
|
||||
*
|
||||
* append to the current 'StringInfo' a new string.
|
||||
* If there is not enough space in the current 'data', then reallocate
|
||||
* some more...
|
||||
*
|
||||
* NOTE: if we reallocate space, we pfree the old one!
|
||||
*---------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
appendStringInfo(StringInfo str, char *buffer)
|
||||
{
|
||||
int buflen, newlen;
|
||||
char *s;
|
||||
|
||||
Assert((str!=NULL));
|
||||
|
||||
/*
|
||||
* do we have enough space to append the new string?
|
||||
* (don't forget to count the null string terminating char!)
|
||||
* If no, then reallocate some more.
|
||||
*/
|
||||
buflen = strlen(buffer);
|
||||
if (buflen + str->len >= str->maxlen-1) {
|
||||
/*
|
||||
* how much more space to allocate ?
|
||||
* Let's say double the current space...
|
||||
* However we must check if this is enough!
|
||||
*/
|
||||
newlen = 2 * str->len;
|
||||
while (buflen + str->len >= newlen-1) {
|
||||
newlen = 2 * newlen;
|
||||
}
|
||||
/*
|
||||
* allocate enough space.
|
||||
*/
|
||||
s = palloc(newlen);
|
||||
if (s==NULL) {
|
||||
elog(WARN,
|
||||
"appendStringInfo: Out of memory (%d bytes requested)",
|
||||
newlen);
|
||||
}
|
||||
memmove(s, str->data, str->len+1);
|
||||
pfree(str->data);
|
||||
str->maxlen = newlen;
|
||||
str->data = s;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, we have enough space now, append 'buffer' at the
|
||||
* end of the string & update the string length.
|
||||
* NOTE: this is a text string (i.e. printable characters)
|
||||
* so 'strcat' will do the job (no need to use 'bcopy' et all...)
|
||||
*/
|
||||
(void) strcat(str->data, buffer);
|
||||
str->len += buflen;
|
||||
}
|
47
src/backend/lib/stringinfo.h
Normal file
47
src/backend/lib/stringinfo.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* stringinfo.h--
|
||||
* Declarations/definitons for "string" functions.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: stringinfo.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef STRINGINFO_H
|
||||
#define STRINGINFO_H
|
||||
|
||||
/*#include "c.h" */ /* for 'String' */
|
||||
|
||||
/*-------------------------
|
||||
* StringInfoData holds information about a string.
|
||||
* 'data' is the string.
|
||||
* 'len' is the current string length (as returned by 'strlen')
|
||||
* 'maxlen' is the size in bytes of 'data', i.e. the maximum string
|
||||
* size (includeing the terminating '\0' char) that we can
|
||||
* currently store in 'data' without having to reallocate
|
||||
* more space.
|
||||
*/
|
||||
typedef struct StringInfoData {
|
||||
char *data;
|
||||
int maxlen;
|
||||
int len;
|
||||
} StringInfoData;
|
||||
|
||||
typedef StringInfoData *StringInfo;
|
||||
|
||||
/*------------------------
|
||||
* makeStringInfo
|
||||
* create a 'StringInfoData' & return a pointer to it.
|
||||
*/
|
||||
extern StringInfo makeStringInfo(void);
|
||||
|
||||
/*------------------------
|
||||
* appendStringInfo
|
||||
* similar to 'strcat' but reallocates more space if necessary...
|
||||
*/
|
||||
extern void appendStringInfo(StringInfo str, char *buffer);
|
||||
|
||||
#endif /* STRINGINFO_H */
|
Reference in New Issue
Block a user