BLI_stackdefines
[blender.git] / source / blender / blenlib / BLI_stackdefines.h
index 3a4957599d66ce764031c80aca3a1331ec83e97f..24cb043cd4376fadd9833aa956a11b63c1e6653e 100644 (file)
 
 /** \file BLI_stackdefines.h
  *  \ingroup bli
+ *
+ * Macro's for a simple array based stack
+ * \note Caller handles alloc & free).
  */
 
-/* simple stack */
-#define STACK_DECLARE(stack)   unsigned int _##stack##_index
-#define STACK_INIT(stack)      ((void)stack, (void)((_##stack##_index) = 0))
-#define STACK_SIZE(stack)      ((void)stack, (_##stack##_index))
-#define STACK_PUSH(stack, val)  (void)((stack)[(_##stack##_index)++] = val)
-#define STACK_PUSH_RET(stack)  ((void)stack, ((stack)[(_##stack##_index)++]))
-#define STACK_PUSH_RET_PTR(stack)  ((void)stack, &((stack)[(_##stack##_index)++]))
+/* only validate array-bounds in debug mode */
+#ifdef DEBUG
+#  define STACK_DECLARE(stack)   unsigned int _##stack##_index, _##stack##_totalloc
+#  define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_totalloc) = tot))
+#  define _STACK_SIZETEST(stack, off) (BLI_assert((_##stack##_index) + off <= _##stack##_totalloc))
+#  define _STACK_SWAP_TOTALLOC(stack_a, stack_b) SWAP(unsigned int, _##stack_a##_totalloc, _##stack_b##_totalloc)
+#else
+#  define STACK_DECLARE(stack)   unsigned int _##stack##_index
+#  define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(tot))
+#  define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off)
+#  define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b)
+#endif
+#define _STACK_BOUNDSTEST(stack, index) ((void)stack, BLI_assert(index >= 0 && index < _##stack##_index))
+
+
+#define STACK_SIZE(stack)           ((void)stack, (_##stack##_index))
+/** add item to stack */
+#define STACK_PUSH(stack, val)      ((void)stack, _STACK_SIZETEST(stack, 1),  ((stack)[(_##stack##_index)++] = val))
+#define STACK_PUSH_RET(stack)       ((void)stack, _STACK_SIZETEST(stack, 1),  ((stack)[(_##stack##_index)++]))
+#define STACK_PUSH_RET_PTR(stack)   ((void)stack, _STACK_SIZETEST(stack, 1), &((stack)[(_##stack##_index)++]))
+/** take last item from stack */
 #define STACK_POP(stack)            ((_##stack##_index) ?  ((stack)[--(_##stack##_index)]) : NULL)
 #define STACK_POP_PTR(stack)        ((_##stack##_index) ? &((stack)[--(_##stack##_index)]) : NULL)
 #define STACK_POP_DEFAULT(stack, r) ((_##stack##_index) ?  ((stack)[--(_##stack##_index)]) : r)
-/* take care, re-orders */
+/** look at last item (assumes non-empty stack) */
+#define STACK_PEEK(stack)           (BLI_assert(_##stack##_index),  ((stack)[_##stack##_index - 1]))
+#define STACK_PEEK_PTR(stack)       (BLI_assert(_##stack##_index), &((stack)[_##stack##_index - 1]))
+/** remove any item from the stack, take care, re-orders */
 #define STACK_REMOVE(stack, i) \
+       _STACK_BOUNDSTEST(stack, i); \
        if (--_##stack##_index != i) { \
                stack[i] = stack[_##stack##_index]; \
        } (void)0
 #define STACK_SWAP(stack_a, stack_b) { \
        SWAP(typeof(stack_a), stack_a, stack_b); \
        SWAP(unsigned int, _##stack_a##_index, _##stack_b##_index); \
+       _STACK_SWAP_TOTALLOC(stack_a, stack_b); \
        } (void)0
 #else
 #define STACK_SWAP(stack_a, stack_b) { \
        SWAP(void *, stack_a, stack_b); \
        SWAP(unsigned int, _##stack_a##_index, _##stack_b##_index); \
+       _STACK_SWAP_TOTALLOC(stack_a, stack_b); \
        } (void)0
 #endif