/* ** OSSP str - String Handling ** Copyright (c) 1999-2005 Ralf S. Engelschall ** Copyright (c) 1999-2005 The OSSP Project ** ** 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;