diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenlib/BLI_stack.h | 14 | ||||
-rw-r--r-- | source/blender/blenlib/intern/stack.c | 69 |
2 files changed, 63 insertions, 20 deletions
diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h index d65c8f02462..1e0b29bc7e8 100644 --- a/source/blender/blenlib/BLI_stack.h +++ b/source/blender/blenlib/BLI_stack.h @@ -34,16 +34,20 @@ typedef struct BLI_Stack BLI_Stack; BLI_Stack *BLI_stack_new_ex( const size_t elem_size, const char *description, - const size_t chunk_size) ATTR_NONNULL(); + const size_t chunk_size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_Stack *BLI_stack_new( - const size_t elem_size, const char *description) ATTR_NONNULL(); + const size_t elem_size, const char *description) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL(); -void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL(); +void *BLI_stack_push_r(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL(); +void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) ATTR_NONNULL(); void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL(); -bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_NONNULL(); +size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -#endif +bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + +#endif /* __BLI_STACK_H__ */ diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c index c2ee73d9693..9d6eecdba55 100644 --- a/source/blender/blenlib/intern/stack.c +++ b/source/blender/blenlib/intern/stack.c @@ -35,7 +35,7 @@ #include "BLI_strict_flags.h" -// #define USE_TOTELEM +#define USE_TOTELEM #define CHUNK_EMPTY ((size_t)-1) /* target chunks size: 64kb */ @@ -135,7 +135,7 @@ void BLI_stack_free(BLI_Stack *stack) * Copies the source value onto the stack (note that it copies * elem_size bytes from 'src', the pointer itself is not stored) */ -void BLI_stack_push(BLI_Stack *stack, const void *src) +void *BLI_stack_push_r(BLI_Stack *stack) { stack->chunk_index++; @@ -161,8 +161,14 @@ void BLI_stack_push(BLI_Stack *stack, const void *src) stack->totelem++; #endif - /* Copy source to end of stack */ - memcpy(CHUNK_LAST_ELEM(stack), src, stack->elem_size); + /* Return end of stack */ + return CHUNK_LAST_ELEM(stack); +} + +void BLI_stack_push(BLI_Stack *stack, const void *src) +{ + void *dst = BLI_stack_push_r(stack); + memcpy(dst, src, stack->elem_size); } /** @@ -175,29 +181,62 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst) { BLI_assert(BLI_stack_is_empty(stack) == false); - if (!BLI_stack_is_empty(stack)) { - memcpy(dst, CHUNK_LAST_ELEM(stack), stack->elem_size); + memcpy(dst, CHUNK_LAST_ELEM(stack), stack->elem_size); #ifdef USE_TOTELEM - stack->totelem--; + stack->totelem--; #endif - if (--stack->chunk_index == CHUNK_EMPTY) { - struct StackChunk *chunk_free; + if (--stack->chunk_index == CHUNK_EMPTY) { + struct StackChunk *chunk_free; - chunk_free = stack->chunk_curr; - stack->chunk_curr = stack->chunk_curr->next; + chunk_free = stack->chunk_curr; + stack->chunk_curr = stack->chunk_curr->next; - chunk_free->next = stack->chunk_free; - stack->chunk_free = chunk_free; + chunk_free->next = stack->chunk_free; + stack->chunk_free = chunk_free; - stack->chunk_index = stack->chunk_elem_max - 1; - } + stack->chunk_index = stack->chunk_elem_max - 1; + } +} + +void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) +{ + BLI_assert(n <= BLI_stack_count(stack)); + + while (n--) { + BLI_stack_pop(stack, dst); + dst = (void *)((char *)dst + stack->elem_size); } } +size_t BLI_stack_count(const BLI_Stack *stack) +{ +#ifdef USE_TOTELEM + return stack->totelem; +#else + struct StackChunk *data = stack->chunk_curr; + size_t totelem = stack->chunk_index + 1; + size_t i; + if (totelem != stack->chunk_elem_max) { + data = data->next; + } + else { + totelem = 0; + } + for (i = 0; data; data = data->next) { + i++; + } + totelem += stack->chunk_elem_max * i; + return totelem; +#endif +} + /** * Returns true if the stack is empty, false otherwise */ bool BLI_stack_is_empty(const BLI_Stack *stack) { +#ifdef USE_TOTELEM + BLI_assert((stack->chunk_curr == NULL) == (stack->totelem == 0)); +#endif return (stack->chunk_curr == NULL); } |