OSSP CVS Repository

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

ossp-pkg/act/act_mem.c 1.6
/* ====================================================================
 * Copyright (c) 1999-2000 Ralf S. Engelschall. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``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 RALF S. ENGELSCHALL OR
 * ITS 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
*/

#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;

/* 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