pjs/include/ds.h

268 строки
6.9 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef __DS_h_
#define __DS_h_
#ifdef XP_WIN32
#include <windows.h>
#endif /* XP_WIN32 */
#ifdef XP_OS2
#define INCL_WIN
#define INCL_GPI
#define TID OS2TID /* global rename in OS2 H's! */
#include <os2.h>
#undef TID /* and restore */
#endif
#include "xp_mcom.h"
XP_BEGIN_PROTOS
/* Typedefs */
typedef struct DSArrayStr DSArray;
typedef struct DSLinkStr DSLink;
typedef struct DSListStr DSList;
typedef struct DSArenaStr DSArena;
#define DS_MIN(a,b) ((a)<(b)?(a):(b))
#define DS_MAX(a,b) ((a)>(b)?(a):(b))
/*
** Your basic boolean. Done as an enum to cause compiler warnings when a
** boolean procedure doesn't return the right value.
** LISA SEZ: Please do not use this; use PRBool instead. Eventually
** (as soon as I can "make it so") DSBool is going away in favor of PRBool.
*/
typedef enum DSBoolEnum {
DSTrue = 1,
DSFalse = 0
} DSBool;
/*
** A status code. Status's are used by procedures that return status
** values. Again the motivation is so that a compiler can generate
** warnings when return values are wrong. Correct testing of status codes:
**
** DSStatus rv;
** rv = some_function (some_argument);
** if (rv != DSSuccess)
** do_an_error_thing();
**
*/
typedef enum DSStatusEnum {
DSWouldBlock = -2,
DSFailure = -1,
DSSuccess = 0
} DSStatus;
/*
** A comparison code. Used for procedures that return comparision
** values. Again the motivation is so that a compiler can generate
** warnings when return values are wrong.
*/
typedef enum DSComparisonEnum {
DSLessThan = -1,
DSEqual = 0,
DSGreaterThan = 1
} DSComparison;
typedef void (*DSElementFreeFunc)(void *e1, DSBool freeit);
typedef int (*DSElementCompareFunc)(void *e1, void *e2);
/************************************************************************/
/*
** Simple variable length array of pointers. The array keeps a NULL
** pointer at the end of the array.
*/
struct DSArrayStr {
void **things;
DSElementFreeFunc freeElement;
};
extern DSArray *DS_CreateArray(int slots);
extern DSStatus DS_GrowArray(DSArray *da, int slots);
extern void DS_SetArrayMethods(DSArray *da, DSElementFreeFunc freeFunc);
extern void DS_DestroyArray(DSArray *da, DSBool freeit);
extern void DS_Sort(DSArray *da, DSElementCompareFunc compare);
extern int DS_Elements(DSArray *da);
extern DSStatus DS_AddElement(DSArray *da, void *element);
extern void DS_RemoveElement(DSArray *da, void *element);
/************************************************************************/
/*
** Circular linked list. Each link contains a pointer to the object that
** is actually in the list.
*/
struct DSLinkStr {
DSLink *next;
DSLink *prev;
void *thing;
};
struct DSListStr {
DSLink link;
};
#define DS_InitList(lst) \
{ \
(lst)->link.next = &(lst)->link; \
(lst)->link.prev = &(lst)->link; \
(lst)->link.thing = 0; \
}
#define DS_ListEmpty(lst) \
((lst)->link.next == &(lst)->link)
#define DS_ListHead(lst) \
((lst)->link.next)
#define DS_ListTail(lst) \
((lst)->link.prev)
#define DS_ListIterDone(lst,lnk) \
((lnk) == &(lst)->link)
#define DS_AppendLink(lst,lnk) \
{ \
(lnk)->next = &(lst)->link; \
(lnk)->prev = (lst)->link.prev; \
(lst)->link.prev->next = (lnk); \
(lst)->link.prev = (lnk); \
}
#define DS_InsertLink(lst,lnk) \
{ \
(lnk)->next = (lst)->link.next; \
(lnk)->prev = &(lst)->link; \
(lst)->link.next->prev = (lnk); \
(lst)->link.next = (lnk); \
}
#define DS_RemoveLink(lnk) \
{ \
(lnk)->next->prev = (lnk)->prev; \
(lnk)->prev->next = (lnk)->next; \
(lnk)->next = 0; \
(lnk)->prev = 0; \
}
extern DSLink *DS_NewLink(void *thing);
extern DSLink *DS_FindLink(DSList *lst, void *thing);
extern void DS_DestroyLink(DSLink *lnk, DSBool freeit);
/************************************************************************/
/*
** Memory manager
*/
/*
** at one time XP_Block was a float* to force clients to cast things
** before use. Now DSBlock is defined since that will be most convenient
** for almost all uses.
*/
typedef unsigned char *DSBlock;
/*
** Allocate some memory. Always allocates at least one byte of memory.
*/
extern void *DS_Alloc(size_t bytes);
/*
** Reallocate some memory, growing or shrinking the memory.
*/
extern void *DS_Realloc(void *oldptr, size_t bytes);
/*
** Allocate and then zero some memory. Always allocates at least one byte
** of memory.
*/
extern void *DS_Zalloc(size_t bytes);
/*
** Allocate a block of memory. Always allocates at least one byte of
** memory.
*/
extern DSBlock DS_AllocBlock(size_t bytes);
/*
** Reallocate a block of memory, growing or shrinking the memory block.
*/
extern DSBlock DS_ReallocBlock(DSBlock block, size_t newBytes);
/*
** Free a block of memory. Safe to use on null pointers.
*/
extern void DS_FreeBlock(DSBlock block);
/*
** Free a chunk of memory. Safe to use on null pointers.
*/
extern void DS_Free(void *ptr);
/*
** Zero and then free a chunk of memory. Safe to use on null pointers.
*/
extern void DS_Zfree(void *ptr, size_t bytes);
/*
* Low cost Malloc Arenas.
*
* The chunks are a linked list.
* The beginning of each chunk is a pointer to the next chunk.
*/
struct DSArenaStr {
unsigned long chunkSize; /* size of each chunk */
unsigned int refCount; /* reference count */
void ** firstChunk; /* pointer to first chunk */
void ** lastChunk; /* pointer to last chunk */
void * pLast; /* last item allocated */
void * pCur; /* beginning of free area */
void * pCurEnd; /* end of free area in current chunk */
};
/* make a new arena */
extern DSArena *
DS_NewArena(unsigned long chunkSize);
/* destroy an arena, and free all memory associated with it */
extern void
DS_FreeArena(DSArena *arena, DSBool zero);
/* malloc a chunk of data from the arena */
extern void *
DS_ArenaAlloc(DSArena *arena, unsigned long size);
/* malloc a chunk of data from the arena, zero filling it */
extern void *
DS_ArenaZalloc(DSArena *arena, unsigned long size);
/* change the size of an object, works best if it was the last object
* allocated
*/
extern void *
DS_ArenaGrow(DSArena *arena, void *pOld, unsigned long oldsize,
unsigned long newsize);
XP_END_PROTOS
#endif /* __DS_h_ */