/*-
 * Copyright (c) 1990, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Chris Torek.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS 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 REGENTS OR 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.
 */
#include "config.h"

#ifdef SHOW_SCCSIDS
static char sccsid[] = "@(#)memcmp.c	8.1 (Berkeley) 6/4/93";
static char sccsid[] = "@(#)memset.c	8.1 (Berkeley) 6/4/93";
static char sccsid[] = "@(#)memcpy.c	8.1 (Berkeley) 6/4/93";
static char sccsid[] = "@(#)memmove.c	8.1 (Berkeley) 6/4/93";
#endif

#include <sys/types.h>

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif

#ifndef HAVE_MEMCMP
/* Compare memory regions. */
int memcmp(s1, s2, n)
    const void *s1, *s2;
    size_t n;
{
    register const unsigned char *p1 = s1, *p2 = s2;
    for (; n != 0; n--) if (*p1++ != *p2++) return (*--p1 - *--p2);
    return (0);
}
#endif

#ifndef HAVE_MEMMOVE
/* Copy a block of memory, handling overlap. */
void *memmove(dst, src, length)
    void *dst;
    const void *src;
    register size_t length;
{
    bcopy((const char *)src, (char *)dst, length);
    return(dst);
}
#endif

#define	wsize	sizeof(u_int)
#define	wmask	(wsize - 1)

#ifndef HAVE_MEMSET
void *memset(dst0, c0, length)
    void *dst0;
    register int c0;
    register size_t length;
{
    register size_t t;
    register u_int c;
    register u_char *dst;
    
    dst = dst0;
    /* If not enough words, just fill bytes.  A length >= 2 words            */
    /* guarantees that at least one of them is `complete' after              */
    /* any necessary alignment.  For instance:                               */
    /*                                                                       */
    /* |-----------|-----------|-----------|                                 */
    /* |00|01|02|03|04|05|06|07|08|09|0A|00|                                 */
    /*           ^---------------------^                                     */
    /*           dst            dst+length-1                                 */
    /*                                                                       */
    /* but we use a minimum of 3 here since the overhead of the code         */
    /* to do word writes is substantial.                                     */
    if (length < 3 * wsize) {
	while (length != 0) {
	    *dst++ = c0;
	    --length;
	}
	return (dst0);
    }

    if ((c = (u_char)c0) != 0) {	/* Fill the word.                    */
#ifndef UINT_MAX
	UINT_MAX must be defined, try 0xFFFFFFFF;
#endif
	c = (c << 8) | c;		/* u_int is 16 bits.                 */
#if UINT_MAX > 65535
	c = (c << 16) | c;		/* u_int is 32 bits.                 */
#endif
#if UINT_MAX > 2147483647
	c = (c << 32) | c;		/* u_int is 64 bits.                 */
#endif
    }

    /* Align destination by filling in bytes.                                */
    if ((t = (int)dst & wmask) != 0) {
	for (t = wsize-t, length -= t; t; t--) {
	    *dst++ = c0;
	}
    }

    /* Fill words.  Length was >= 2*words so we know t >= 1 here.            */
    for (t = length / wsize; t; t--) {
	*(u_int *)dst = c;
	dst += wsize;
    } 

    /* Mop up trailing bytes, if any.                                        */
    for (t = length & wmask; t; t--) {
	*dst++ = c0;
    }

    return (dst0);
}
#endif
