ossp-pkg/str/str_memory.c
/*
** OSSP str - String Handling
** Copyright (c) 1999-2005 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 1999-2005 The OSSP Project <http://www.ossp.org/>
**
** This file is part of OSSP str, a string handling and manipulation
** library which can be found at http://www.ossp.org/pkg/lib/str/.
**
** 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.
**
** str_mem.c: raw memory functions
*/
#include "str_p.h"
#define _str_mem_alloc malloc
#define _str_mem_realloc realloc
#define _str_mem_free free
static void *
_str_mem_dup(
void *mem,
size_t bytes)
{
void *dmem;
if (mem == NULL)
return NULL;
if ((dmem = str_mem_alloc(bytes)) == NULL)
return NULL;
str_mem_move(dmem, mem, bytes);
return dmem;
}
#ifdef HAVE_MEMSET
#define _str_mem_set memset
#else
static void *
_str_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;
}
#endif
#ifdef HAVE_MEMMOVE
#define _str_mem_move memmove
#else
static void *
_str_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;
}
#endif
static void *
_str_mem_rev(
void *src,
size_t bytes)
{
register unsigned char *p1;
register unsigned char *p2;
register unsigned char c;
p1 = (unsigned char *)src;
p2 = (unsigned char *)src + bytes;
while (p1 < p2)
c = *p1, *p1++ = *p2, *p2-- = c;
return src;
}
#ifdef HAVE_MEMCHR
#define _str_mem_char memchr
#else
static void *
_str_mem_char(
const void *src,
int c,
size_t bytes)
{
register const unsigned char *cp;
if (bytes != 0) {
cp = src;
do {
if (*cp++ == (unsigned char)c)
return ((void *)(cp - 1));
} while (--bytes != 0);
}
return NULL;
}
#endif
static void *
_str_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) &&
str_mem_cmp(&begin[1], (const char *)needle + 1, needle_len - 1) == 0)
return (void *)begin;
return NULL;
}
#ifdef HAVE_MEMCMP
#define _str_mem_cmp memcmp
#else
static int
_str_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;
}
#endif
/* the API consists only of indirection pointers */
void *(*str_mem_alloc)(size_t) = _str_mem_alloc;
void *(*str_mem_realloc)(void *, size_t) = _str_mem_realloc;
void (*str_mem_free)(void *) = _str_mem_free;
void *(*str_mem_dup)(void *, size_t) = _str_mem_dup;
void *(*str_mem_set)(void *, int, size_t) = _str_mem_set;
void *(*str_mem_move)(void *, const void *, size_t) = _str_mem_move;
void *(*str_mem_rev)(void *, size_t) = _str_mem_rev;
void *(*str_mem_char)(const void *, int, size_t) = _str_mem_char;
void *(*str_mem_mem)(const void *, size_t, const void *, size_t) = _str_mem_mem;
int (*str_mem_cmp)(const void *, const void *, size_t) = _str_mem_cmp;