1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
/***************************************************************************
* PHAST: PHylogenetic Analysis with Space/Time models
* Copyright (c) 2002-2005 University of California, 2006-2010 Cornell
* University. All rights reserved.
*
* This source code is distributed under a BSD-style license. See the
* file LICENSE.txt for details.
***************************************************************************/
/** @file stacks.h
Simple array-based stacks and supporting functions.
Supports storage of objects of arbitrary size in a stack format.
Convenience functions are available available for common data
types such as ints, doubles, and pointers.
@ingroup base
@see lists.h
*/
#ifndef STACKS_H
#define STACKS_H
#include "lists.h"
#include "external_libs.h"
/** Basic Stack object.
@note Stack object has same format as list objects.
The only difference between the two is that a stack object
is required to use stack functions.
@see list.h
*/
typedef List Stack;
/** \name Stack allocation functions
\{ */
/** Create new stack with specified starting size.
@param nelements Initial capacity of new stack
@param elementz Size of each element (bytes)
@result newly allocated stack
@note stack will grow as needed, but is most efficient when nelements=expected stack size
*/
static PHAST_INLINE
Stack* stk_new(int nelements, /* Starting number of elements */
int elementsz) /* Size of each element (bytes) */
{ return lst_new(nelements, elementsz); }
/** Create new stack of integers.
@param nelements Initial capacity of stack of integers the stack
@result newly allocated Stack object that stores integers.
@note stack will grow as needed, but is most efficient when nelements=expected stack size
@see stk_new*/
static PHAST_INLINE
Stack* stk_new_int(int nelements) /* Starting number of elements */
{ return lst_new(nelements, sizeof(int)); }
/** Create new stack of doubles.
@param nelements Initial capacity of new stack
@result newly allocated Stack object that stores doubles.
@note stack will grow as needed, but is most efficient when nelements=expected stack size
@see stk_new*/
static PHAST_INLINE
Stack* stk_new_dbl(int nelements) /* Starting number of elements */
{ return lst_new(nelements, sizeof(double)); }
/** Create new stack of pointers.
@param nelements Initial capacity of new stack
@result newly allocated Stack object, that stores pointers
@note stack will grow as needed, but is most efficient when nelements=expected stack size
@see stk_new*/
static PHAST_INLINE
Stack* stk_new_ptr(int nelements)
{ return lst_new(nelements, sizeof(void*)); }
/** \} \name Stack misc functions
\{ */
/** Test whether stack is empty.
@result 1 if empty, 0 otherwise. */
static PHAST_INLINE
int stk_empty(Stack *s) { return lst_empty(s); }
/** Obtain size of stack.
@result number of elements */
static PHAST_INLINE
int stk_size(Stack *s) { return lst_size(s); }
/** \} \name Stack push functions
\{ */
/** Push object on stack. */
static PHAST_INLINE
void stk_push(Stack *s, void *o) { lst_push(s, o); }
/** Push integer on stack. */
static PHAST_INLINE
void stk_push_int(Stack *s, int i) { lst_push_int(s, i); }
/** Push double on stack */
static PHAST_INLINE
void stk_push_dbl(Stack *s, double d) { lst_push_dbl(s, d); }
/** Push pointer on stack */
static PHAST_INLINE
void stk_push_ptr(Stack *s, void *ptr) { lst_push_ptr(s, ptr); }
/** \} \name Stack peek functions
\{ */
/** Peek at object at top of stack.
@result address of object at top of stack, or NULL if stack is empty.
@note Object is not removed.
@see stk_pop */
static PHAST_INLINE
void* stk_peek(Stack* s) {
if (stk_empty(s)) return NULL;
return lst_arr_get(s, s->ridx-1);
}
/** Peek at integer at top of stack.
@result integer from top of stack or 0 if stack is empty (use stk_empty).
@warning return value will be ambiguous when using numeric data
containing zeroes. Use stk_empty to tell when stack is empty.
@note Integer is not removed.
@see stk_empty */
static PHAST_INLINE
int stk_peek_int(Stack *s) {
int *ptr = (int*)stk_peek(s);
return (ptr == NULL ? 0 : *ptr);
}
/** Peek at double at top of stack.
@result double from top of stack or 0 if stack is empty (use stk_empty).
@warning return value will be ambiguous when using numeric data
containing zeroes. Use stk_empty to tell when stack is empty.
@note Double is not removed
@see stk_empty*/
static PHAST_INLINE
double stk_peek_dbl(Stack *s) {
double *ptr = (double*)stk_peek(s);
return (ptr == NULL ? 0 : *ptr);
}
/** Peek at pointer at top of stack.
@result pointer from top of stack or NULL if stack is empty.
@note pointer is not removed */
static PHAST_INLINE
void* stk_peek_ptr(Stack *s) {
void **ptr = (void**)stk_peek(s);
return (ptr == NULL ? NULL : *ptr);
}
/** \} \name Stack pop functions
\{ */
/** Pop object from stack.
@result address of object at top of stack, or NULL if stack is
empty.
@warning Object is removed.
@note If object is an int, you will need to access it with
*((int*)lst_get(...));
if object is a Node* and you seek the
attribute called "data", you will need to do
((Node*)lst_get(...))->data. */
static PHAST_INLINE
void* stk_pop(Stack* s) {
if (stk_empty(s)) return NULL;
return lst_arr_get(s, --s->ridx);
}
/** Pop integer from stack.
@result integer from top of stack, or 0 if stack is empty (use stk_empty).
@warning Integer is removed.
@warning return value will be ambiguous when using numeric data
containing zeroes. Use stk_empty to tell when stack is empty.
@see stk_empty */
static PHAST_INLINE
int stk_pop_int(Stack *s) {
int *ptr = (int*)stk_pop(s);
return (ptr == NULL ? 0 : *ptr);
}
/** Pop double from stack.
@result double from top of stack or 0 if stack is empty (use stk_empty).
@warning Double is removed
@warning return value will be ambiguous when using numeric data
containing zeroes. Use stk_empty to tell when stack is empty.
@see stk_empty */
static PHAST_INLINE
double stk_pop_dbl(Stack *s) {
double *ptr = (double*)stk_pop(s);
return (ptr == NULL ? 0 : *ptr);
}
/** Pop pointer from stack.
@result pointer from top of stack or NULL if stack is empty.
@warning Pointer is removed */
static PHAST_INLINE
void* stk_pop_ptr(Stack *s) {
void **ptr = (void**)stk_pop(s);
return (ptr == NULL ? NULL : *ptr);
}
/** \} \name Stack cleanup functions
\{ */
/** Clear contents of stack.
@note Contents will be cleared but memory will remain allocated unlike stk_free
@see stk_free */
static PHAST_INLINE
void stk_clear(Stack *s) { lst_clear(s); }
/** Free memory associated with stack.
@note Contents and Stack object itself will be freed unlike stk_clear.
@warning if the stack contains pointers, the objects pointed to are not freed
@see stk_clear*/
static PHAST_INLINE
void stk_free(Stack *s) { lst_free(s); }
/** \} */
#endif
|