OSSP CVS Repository

ossp - ossp-pkg/act/act_mem.c
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/act/act_mem.c
/*
**  OSSP act - Abstract Container Types
**  Copyright (c) 1999-2003 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 1999-2003 The OSSP Project <http://www.ossp.org/>
**
**  This file is part of OSSP act, an abstract container type library
**  which can be found at http://www.ossp.org/pkg/lib/act/.
**
**  Permission to use, copy, modify, and distribute this software for
**  any purpose with or without fee is hereby granted, provided that
**  the above copyright notice and this permission notice appear in all
**  copies.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
**  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
**  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
**  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
**  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
**  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
**  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
**  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
**  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
**  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
**  SUCH DAMAGE.
**
**  act_mem.c: memory handling (implementation)
*/

#include <stdlib.h>
#include <string.h>

#include "act_p.h"

/* the API consists only of indirection pointers */
void *(*act_mem_alloc)(size_t)                                   = malloc;
void *(*act_mem_realloc)(void *, size_t)                         = realloc;
void  (*act_mem_free)(void *)                                    = free;
void *(*act_mem_dup)(void *, size_t)                             = _act_mem_dup;
void *(*act_mem_set)(void *, int, size_t)                        = _act_mem_set;
void *(*act_mem_move)(void *, const void *, size_t)              = _act_mem_move;
void *(*act_mem_mem)(const void *, size_t, const void *, size_t) = _act_mem_mem;
void *(*act_mem_char)(const void *, unsigned char, size_t)       = _act_mem_char;
int   (*act_mem_cmp)(const void *, const void *, size_t)         = _act_mem_cmp;

/*
 * Align a size to the next larger or equal size which is likely to have the
 * longest *relevant* CPU-specific memory word alignment restrictions.
 */
size_t act_mem_align(size_t size)
{
    union mem_word {
        void  *mw_vp;
        void (*mw_fp)(void);
        char  *mw_cp;
        long   mw_l;
        double mw_d;
    };
    return ((1+((size-1) / sizeof(union mem_word))) * sizeof(union mem_word));
}

/* the initialization function for the memory part */
intern int act_mem_init(void)
{
#ifdef HAVE_MEMSET
    act_mem_set  = memset;
#endif
#ifdef HAVE_MEMMOVE
    act_mem_move = memmove;
#endif
#ifdef HAVE_MEMCMP
    act_mem_cmp  = memcmp;
#endif
    return TRUE;
}

/* the destruction function for the memory part */
intern int act_mem_kill(void)
{
    act_mem_set  = _act_mem_set;
    act_mem_move = _act_mem_move;
    act_mem_cmp  = _act_mem_cmp;
    return TRUE;
}

/* local version of a memdup function */
intern void *_act_mem_dup(void *mem, size_t bytes)
{
    void *dmem;

    if (mem == NULL)
        return NULL;
    if ((dmem = act_mem_alloc(bytes)) == NULL)
        return NULL;
    act_mem_move(dmem, mem, bytes);
    return dmem;
}

/* local fallback version of POSIX memset(3) */
intern void *_act_mem_set(void *dst0, int c0, size_t bytes)
{
    register size_t t;
    register unsigned int c;
    register unsigned char *dst;
    const int word_size = sizeof(unsigned int);
    const int word_mask = (sizeof(unsigned int) - 1);

    dst = dst0;

    /* if not enough words for a reasonable speedup, just fill bytes */
    if (bytes < 3 * word_size) {
        while (bytes != 0) {
            *dst++ = c0;
            --bytes;
        }
        return dst0;
    }

    /* fill the whole stamping word */
    if ((c = (unsigned char)c0) != 0) {
        c = c | (c << 8);
#if (SIZEOF_INT > 2)
        c = c | (c << 16);
#endif
#if (SIZEOF_INT > 4)
        c = c | (c << 32);
#endif
    }

    /* align destination by filling in bytes */
    if ((t = (long)dst & word_mask) != 0) {
        t = word_size - t;
        bytes -= t;
        do {
            *dst++ = c0;
        } while (--t != 0);
    }

    /* now fill with words. length was >= 2*words so we know t >= 1 here */
    t = bytes / word_size;
    do {
        *(unsigned int *)dst = c;
        dst += word_size;
    } while (--t != 0);

    /* finish with trailing bytes, if there are bytes left */
    t = bytes & word_mask;
    if (t != 0) {
        do {
            *dst++ = c0;
        } while (--t != 0);
    }

    return dst0;
}

/* local fallback version of POSIX memmove(3) */
intern void *_act_mem_move(void *dst, const void *src, size_t bytes)
{
    register unsigned char *dst_p;
    register const unsigned char *src_p;

    if (src == NULL || dst == NULL)
        return NULL;
    src_p = src;
    dst_p = dst;
    if (dst > src) {
        /* must go high to low */
        src_p += bytes;
        dst_p += bytes;
        while (bytes-- > 0)
            *--dst_p = *--src_p;
    }
    else if (dst < src) {
        /* must go low to high */
        while (bytes-- > 0)
            *dst_p++ = *src_p++;
    }
    return dst;
}

/* local fallback version of POSIX memchr(3) */
intern void *_act_mem_char(const void *src, unsigned char c, size_t bytes)
{
    register const unsigned char *cp;

    if (bytes != 0) {
        cp = src;
        do {
            if (*cp++ == c)
                return ((void *)(cp - 1));
        } while (--bytes != 0);
    }
    return NULL;
}

/* additional function: memmem(3) like */
intern void *
_act_mem_mem(
    const void *haystack, size_t haystack_len,
    const void *needle,   size_t needle_len)
{
    register const char *begin;
    register const char *last_possible;

    if (needle_len == 0)
        /* The first occurrence of the empty string is deemed to occur at
           the end of the string. */
        return (void *)&((const char *)haystack)[haystack_len - 1];
    last_possible = (const char *)haystack + haystack_len - needle_len;
    for (begin = (const char *)haystack; begin <= last_possible; begin++)
        if (   *begin == *((const char *)needle)
            && act_mem_cmp(&begin[1], (const char *)needle + 1, needle_len - 1) == 0)
            return (void *)begin;
    return NULL;
}

/* local fallback version of POSIX memcmp(3) */
intern int _act_mem_cmp(const void *src1, const void *src2, size_t bytes)
{
    register const unsigned char *cp1;
    register const unsigned char *cp2;

    if (bytes != 0) {
        cp1 = src1;
        cp2 = src2;
        do {
            if (*cp1++ != *cp2++)
                return (*--cp1 - *--cp2);
        } while (--bytes != 0);
    }
    return 0;
}

/* special utility function: a variant of act_mem_alloc() via a context */
void *act_mem_alloc_ctx(act_ctx_t *ctx, size_t size)
{
    void *fct = NULL;
    void *ctxarg = NULL;
    int ctxuse = FALSE;
    void *rv = NULL;

    if (ctx == NULL)
        return NULL;
    act_ctx_get(ctx, ACT_CTX_MEM_ALLOC, &fct);
    if (fct == NULL)
        fct = (void *)act_mem_alloc;
    else {
        act_ctx_get(ctx, ACT_CTX_MEM_CTXUSE, &ctxuse);
        if (ctxuse)
            act_ctx_get(ctx, ACT_CTX_MEM_CTXARG, &ctxarg);
    }
    if (ctxuse)
        rv = ((act_mem_alloc_ctx_t)fct)(ctxarg, size);
    else
        rv = ((act_mem_alloc_t)fct)(size);
    return rv;
}

/* special utility function: a variant of act_mem_realloc() via a context */
void *act_mem_realloc_ctx(act_ctx_t *ctx, void *ptr, size_t size)
{
    void *fct = NULL;
    void *ctxarg = NULL;
    int ctxuse = FALSE;
    void *rv = NULL;

    if (ctx == NULL)
        return NULL;
    act_ctx_get(ctx, ACT_CTX_MEM_REALLOC, &fct);
    if (fct == NULL)
        fct = (void *)act_mem_realloc;
    else {
        act_ctx_get(ctx, ACT_CTX_MEM_CTXUSE, &ctxuse);
        if (ctxuse)
            act_ctx_get(ctx, ACT_CTX_MEM_CTXARG, &ctxarg);
    }
    if (ctxuse)
        rv = ((act_mem_realloc_ctx_t)fct)(ctxarg, ptr, size);
    else
        rv = ((act_mem_realloc_t)fct)(ptr, size);
    return rv;
}

/* special utility function: a variant of act_mem_free() via a context */
void act_mem_free_ctx(act_ctx_t *ctx, void *ptr)
{
    void *fct = NULL;
    void *ctxarg = NULL;
    int ctxuse = FALSE;

    if (ctx == NULL)
        return;
    act_ctx_get(ctx, ACT_CTX_MEM_FREE, &fct);
    if (fct == NULL)
        fct = (void *)act_mem_free;
    else {
        act_ctx_get(ctx, ACT_CTX_MEM_CTXUSE, &ctxuse);
        if (ctxuse)
            act_ctx_get(ctx, ACT_CTX_MEM_CTXARG, &ctxarg);
    }
    if (ctxuse)
        ((act_mem_free_ctx_t)fct)(ctxarg, ptr);
    else
        ((act_mem_free_t)fct)(ptr);
    return;
}


CVSTrac 2.0.1