ucx/stack.c

Tue, 17 Oct 2017 15:15:54 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 17 Oct 2017 15:15:54 +0200
changeset 250
b7d1317b138e
parent 225
a1a068c2c4ef
permissions
-rw-r--r--

updates license

olaf@13 1 /*
universe@103 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
olaf@13 3 *
universe@250 4 * Copyright 2017 Olaf Wintermann. All rights reserved.
universe@103 5 *
universe@103 6 * Redistribution and use in source and binary forms, with or without
universe@103 7 * modification, are permitted provided that the following conditions are met:
universe@103 8 *
universe@103 9 * 1. Redistributions of source code must retain the above copyright
universe@103 10 * notice, this list of conditions and the following disclaimer.
universe@103 11 *
universe@103 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@103 13 * notice, this list of conditions and the following disclaimer in the
universe@103 14 * documentation and/or other materials provided with the distribution.
universe@103 15 *
universe@103 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@103 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@103 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@103 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@103 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@103 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@103 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@103 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@103 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@103 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@103 26 * POSSIBILITY OF SUCH DAMAGE.
olaf@13 27 */
olaf@13 28
universe@182 29 #include "stack.h"
olaf@13 30 #include <string.h>
olaf@13 31
universe@185 32 static size_t ucx_stack_align(size_t n) {
universe@185 33 int align = n % sizeof(void*);
universe@185 34 if (align) {
universe@185 35 n += sizeof(void*) - align;
universe@185 36 }
universe@185 37 return n;
universe@185 38 }
universe@185 39
universe@185 40 void ucx_stack_init(UcxStack *stack, char* space, size_t size) {
universe@185 41 stack->size = size - size % sizeof(void*);
universe@185 42 stack->space = space;
universe@185 43 stack->top = NULL;
universe@182 44
universe@185 45 stack->allocator.pool = stack;
universe@185 46 stack->allocator.malloc = (ucx_allocator_malloc) ucx_stack_malloc;
universe@185 47 stack->allocator.calloc = (ucx_allocator_calloc) ucx_stack_calloc;
universe@185 48 stack->allocator.realloc = (ucx_allocator_realloc) ucx_stack_realloc;
universe@185 49 stack->allocator.free = (ucx_allocator_free) ucx_stack_free;
olaf@13 50 }
olaf@13 51
universe@182 52 void *ucx_stack_malloc(UcxStack *stack, size_t n) {
universe@182 53
universe@185 54 if (ucx_stack_avail(stack) < ucx_stack_align(n)) {
universe@135 55 return NULL;
universe@135 56 } else {
universe@185 57 char *prev = stack->top;
universe@185 58 if (stack->top) {
universe@185 59 stack->top += ucx_stack_align(ucx_stack_topsize(stack));
universe@185 60 } else {
universe@185 61 stack->top = stack->space;
universe@185 62 }
universe@182 63
universe@185 64 ((struct ucx_stack_metadata*)stack->top)->prev = prev;
universe@185 65 ((struct ucx_stack_metadata*)stack->top)->size = n;
universe@185 66 stack->top += sizeof(struct ucx_stack_metadata);
universe@182 67
universe@185 68 return stack->top;
universe@15 69 }
olaf@13 70 }
olaf@13 71
universe@182 72 void *ucx_stack_calloc(UcxStack *stack, size_t nelem, size_t elsize) {
universe@182 73 void *mem = ucx_stack_malloc(stack, nelem*elsize);
universe@182 74 memset(mem, 0, nelem*elsize);
universe@182 75 return mem;
olaf@13 76 }
olaf@13 77
universe@182 78 void *ucx_stack_realloc(UcxStack *stack, void *ptr, size_t n) {
universe@185 79 if (ptr == stack->top) {
universe@185 80 if (stack->size - (stack->top - stack->space) < ucx_stack_align(n)) {
universe@185 81 return NULL;
universe@185 82 } else {
universe@185 83 ((struct ucx_stack_metadata*)stack->top - 1)->size = n;
universe@185 84 return ptr;
universe@185 85 }
universe@182 86 } else {
universe@185 87 if (ucx_stack_align(((struct ucx_stack_metadata*)ptr - 1)->size) <
universe@185 88 ucx_stack_align(n)) {
universe@182 89 void *nptr = ucx_stack_malloc(stack, n);
universe@182 90 if (nptr) {
universe@185 91 memcpy(nptr, ptr, n);
universe@182 92 ucx_stack_free(stack, ptr);
universe@185 93
universe@182 94 return nptr;
universe@182 95 } else {
universe@182 96 return NULL;
olaf@14 97 }
universe@182 98 } else {
universe@185 99 ((struct ucx_stack_metadata*)ptr - 1)->size = n;
universe@182 100 return ptr;
olaf@13 101 }
olaf@13 102 }
olaf@13 103 }
olaf@13 104
universe@182 105 void ucx_stack_free(UcxStack *stack, void *ptr) {
universe@185 106 if (ptr == stack->top) {
universe@185 107 stack->top = ((struct ucx_stack_metadata*) stack->top - 1)->prev;
universe@182 108 } else {
universe@185 109 struct ucx_stack_metadata *next = (struct ucx_stack_metadata*)(
universe@185 110 (char*)ptr +
universe@185 111 ucx_stack_align(((struct ucx_stack_metadata*) ptr - 1)->size)
universe@185 112 );
universe@185 113 next->prev = ((struct ucx_stack_metadata*) ptr - 1)->prev;
olaf@113 114 }
olaf@113 115 }
olaf@113 116
universe@185 117 void ucx_stack_popn(UcxStack *stack, void *dest, size_t n) {
universe@185 118 if (ucx_stack_empty(stack)) {
universe@185 119 return;
universe@185 120 }
universe@185 121
universe@185 122 size_t len = ucx_stack_topsize(stack);
universe@185 123 if (len > n) {
universe@185 124 len = n;
universe@185 125 }
universe@185 126
universe@185 127 memcpy(dest, stack->top, len);
universe@185 128
universe@185 129 ucx_stack_free(stack, stack->top);
olaf@13 130 }
olaf@13 131
universe@185 132 size_t ucx_stack_avail(UcxStack *stack) {
universe@185 133 size_t avail = ((stack->top ? (stack->size
universe@185 134 - (stack->top - stack->space)
universe@185 135 - ucx_stack_align(ucx_stack_topsize(stack)))
universe@185 136 : stack->size));
universe@185 137
universe@185 138 if (avail > sizeof(struct ucx_stack_metadata)) {
universe@185 139 return avail - sizeof(struct ucx_stack_metadata);
universe@185 140 } else {
universe@185 141 return 0;
universe@185 142 }
olaf@13 143 }

mercurial