Merge branch 'blender2.7'
[blender.git] / source / blender / blenlib / BLI_utildefines_stack.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 #ifndef __BLI_UTILDEFINES_STACK_H__
22 #define __BLI_UTILDEFINES_STACK_H__
23
24 /** \file BLI_utildefines_stack.h
25  *  \ingroup bli
26  *
27  * Macro's for a simple array based stack
28  * \note Caller handles alloc & free).
29  */
30
31 /* only validate array-bounds in debug mode */
32 #ifdef DEBUG
33 #  define STACK_DECLARE(stack)   unsigned int _##stack##_index, _##stack##_totalloc
34 #  define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_totalloc) = (tot)))
35 #  define _STACK_SIZETEST(stack, off) (BLI_assert((_##stack##_index) + (off) <= _##stack##_totalloc))
36 #  define _STACK_SWAP_TOTALLOC(stack_a, stack_b) SWAP(unsigned int, _##stack_a##_totalloc, _##stack_b##_totalloc)
37 #else
38 #  define STACK_DECLARE(stack)   unsigned int _##stack##_index
39 #  define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? (tot) : 0))
40 #  define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off)
41 #  define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b)
42 #endif
43 #define _STACK_BOUNDSTEST(stack, index) ((void)stack, BLI_assert((unsigned int)(index) < _##stack##_index))
44
45
46 #define STACK_SIZE(stack)           ((void)stack, (_##stack##_index))
47 #define STACK_CLEAR(stack)          {(void)stack;  _##stack##_index = 0; } ((void)0)
48 /** add item to stack */
49 #define STACK_PUSH(stack, val)      ((void)stack, _STACK_SIZETEST(stack, 1),  ((stack)[(_##stack##_index)++] = (val)))
50 #define STACK_PUSH_RET(stack)       ((void)stack, _STACK_SIZETEST(stack, 1),  ((stack)[(_##stack##_index)++]))
51 #define STACK_PUSH_RET_PTR(stack)   ((void)stack, _STACK_SIZETEST(stack, 1), &((stack)[(_##stack##_index)++]))
52 /** take last item from stack */
53 #define STACK_POP(stack)            ((_##stack##_index) ?  ((stack)[--(_##stack##_index)]) : NULL)
54 #define STACK_POP_PTR(stack)        ((_##stack##_index) ? &((stack)[--(_##stack##_index)]) : NULL)
55 #define STACK_POP_DEFAULT(stack, r) ((_##stack##_index) ?  ((stack)[--(_##stack##_index)]) : (r))
56 /** look at last item (assumes non-empty stack) */
57 #define STACK_PEEK(stack)           (BLI_assert(_##stack##_index),  ((stack)[_##stack##_index - 1]))
58 #define STACK_PEEK_PTR(stack)       (BLI_assert(_##stack##_index), &((stack)[_##stack##_index - 1]))
59 /** remove any item from the stack, take care, re-orders */
60 #define STACK_REMOVE(stack, i) \
61         { \
62                 const unsigned int _i = i; \
63                 _STACK_BOUNDSTEST(stack, _i); \
64                 if (--_##stack##_index != _i) { \
65                         stack[_i] = stack[_##stack##_index]; \
66                 } \
67         } ((void)0)
68 #define STACK_DISCARD(stack, n) \
69         { \
70                 const unsigned int _n = n; \
71                 BLI_assert(_##stack##_index >= _n); \
72                 (void)stack; \
73                 _##stack##_index -= _n; \
74         } ((void)0)
75 #ifdef __GNUC__
76 #define STACK_SWAP(stack_a, stack_b) { \
77         SWAP(typeof(stack_a), stack_a, stack_b); \
78         SWAP(unsigned int, _##stack_a##_index, _##stack_b##_index); \
79         _STACK_SWAP_TOTALLOC(stack_a, stack_b); \
80 } ((void)0)
81 #else
82 #define STACK_SWAP(stack_a, stack_b) { \
83         SWAP(void *, stack_a, stack_b); \
84         SWAP(unsigned int, _##stack_a##_index, _##stack_b##_index); \
85         _STACK_SWAP_TOTALLOC(stack_a, stack_b); \
86 } ((void)0)
87 #endif
88
89 #endif  /* __BLI_UTILDEFINES_STACK_H__ */