[comp.os.minix] memcpy

tholm@uvicctr.UUCP (Terrence W. Holm) (09/14/88)

EFTH MINIX report #40  - September 1988 -  memcpy(3) & friends


There follows an implementation of memcpy(3), memccpy(3),
memchr(3), memcmp(3) and memset(3) for MINIX. Please consider
this public domain software. "man" pages are included.

----------------------------------------------------------
echo x - memccpy.3
gres '^X' '' > memccpy.3 << '/'
XSUBROUTINES
X    memccpy(3)		- memory copy, until specified character
X
XINVOCATION
X    #include <memory.h>
X
X    char *memccpy( to, from, chr, count )
X      char *to;
X      char *from;
X      int   chr;
X      int   count;
X
XEXPLANATION
X    <count> characters are copied from the memory pointed to by
X    <from> to the memory pointed to by <to>. If the character <chr>
X    is encountered then the copy stops, after <chr> is copied.
X
XRESULTS
X    NULL : <chr> was not found.
X    o/w  : Points to the character after <chr> in <from> vector.
/
echo x - memccpy.c
gres '^X' '' > memccpy.c << '/'
X/*  memccpy(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X#define  NULL  (char *) 0
X
X
Xchar *memccpy( to, from, chr, count )
X  char *to;
X  char *from;
X  int   chr;
X  int   count;
X
X  {
X  while( --count >= 0 )
X    if ( (*to++ = *from++) == chr )
X	return( from );
X
X  return( NULL );
X  }
/
echo x - memchr.3
gres '^X' '' > memchr.3 << '/'
XSUBROUTINES
X    memchr(3)		- memory search
X
XINVOCATION
X    #include <memory.h>
X
X    char *memchr( vector, chr, count )
X      char *vector;
X      int   chr;
X      int   count;
X
XEXPLANATION
X    Memchr(3) looks for the character <chr> within the first
X    <count> characters of <vector>.
X
XRESULTS
X    NULL : <chr> was not found.
X    o/w  : Points to <chr> in <vector>.
X
XREFERENCES
X    strchr(3)
/
echo x - memchr.c
gres '^X' '' > memchr.c << '/'
X/*  memchr(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X#define  NULL  (char *) 0
X
X
Xchar *memchr( vector, chr, count )
X  char *vector;
X  int   chr;
X  int   count;
X
X  {
X  while( --count >= 0 )
X    if ( *vector++ == chr )
X	return( vector - 1 );
X
X  return( NULL );
X  }
/
echo x - memcmp.3
gres '^X' '' > memcmp.3 << '/'
XSUBROUTINES
X    memcmp(3)		- memory compare
X
XINVOCATION
X    int memcmp( vector1, vector2, count )
X      char *vector1;
X      char *vector2;
X      int   count;
X
XEXPLANATION
X    Memcmp(3) uses character comparison to determine if
X    the data pointed to by <vector1> is less, equal or
X    greater than the data pointed to by <vector2>. Up to
X    <count> characters are compared.
X
XRESULTS
X    <0 : <vector1> is less than <vector2>
X    =0 : <vector1> is equal to <vector2>
X    >0 : <vector1> is greater than <vector2>
X
XREFERENCES
X    bcmp(3), strcmp(3)
/
echo x - memcmp.c
gres '^X' '' > memcmp.c << '/'
X/*  memcmp(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X
Xint memcmp( vector1, vector2, count )
X  char *vector1;
X  char *vector2;
X  int   count;
X
X  {
X  register int cmp;
X
X  if ( vector1 == vector2 )
X    return( 0 );
X
X  while( --count >= 0 )
X    if ( cmp = *vector1++ - *vector2++ )
X	return( cmp );
X
X  return( 0 );
X  }
/
echo x - memcpy.3
gres '^X' '' > memcpy.3 << '/'
XSUBROUTINES
X    memcpy(3)		- memory copy
X
XINVOCATION
X    #include <memory.h>
X
X    char *memcpy( to, from, count )
X      char *to;
X      char *from;
X      int   count;
X
XEXPLANATION
X    <count> characters are copied from the memory pointed
X    to by <from> to the memory pointed to by <to>. If the
X    location <to> is within the <from> vector, then
X    the copy is done backwards to save the <from> vector
X    from being trampled.
X
XRESULTS
X    Returns <to>.
X
XREFERENCES
X    bcopy(3), strcpy(3)
/
echo x - memcpy.c
gres '^X' '' > memcpy.c << '/'
X/*  memcpy(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X
Xchar *memcpy( to, from, count )
X  char *to;
X  char *from;
X  int   count;
X
X  {
X  int word_count = count / sizeof(int);
X  int byte_count = count & ( sizeof(int) - 1 );
X  char *temp_to  = to;
X  
X  if ( to > from  &&  to < from + count )
X    {
X    /*  Must copy backwards  */
X    from += count;
X    to   += count;
X
X    while( --byte_count >= 0 )
X      *--to = *--from;
X
X    while( --word_count >= 0 )
X      *--((int *) to) = *--((int *) from);
X    }
X  else
X    {
X    while( --word_count >= 0 )
X      *((int *) to)++ = *((int *) from)++;
X
X    while( --byte_count >= 0 )
X      *to++ = *from++;
X    }
X
X  return( temp_to );
X  }
/
echo x - memory.h
gres '^X' '' > memory.h << '/'
X/*  memory.h  */
X
Xchar *memcpy();
Xchar *memccpy();
Xchar *memchr();
Xchar *memset();
Xint   memcmp();
/
echo x - memset.3
gres '^X' '' > memset.3 << '/'
XSUBROUTINES
X    memset(3)		- memory initialize
X
XINVOCATION
X    #include <memory.h>
X
X    char *memset( vector, chr, count )
X      char *vector;
X      int   chr;
X      int   count;
X
XEXPLANATION
X    The first <count> characters of <vector> are set to <chr>.
X
XRESULTS
X    Returns <vector>.
X
XREFERENCES
X    bzero(3)
/
echo x - memset.c
gres '^X' '' > memset.c << '/'
X/*  memset(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X
Xchar *memset( vector, chr, count )
X  char *vector;
X  int   chr;
X  int   count;
X
X  {
X  register char *memory = vector;
X
X  while( --count >= 0 )
X    *memory++ = chr;
X
X  return( vector );
X  }
/
----------------------------------------------------------

		Edwin L. Froese
		  uw-beaver!ubc-cs!mprg!handel!froese

		Terrence W. Holm
		  uw-beaver!uvicctr!tholm

chip@vector.UUCP (Chip Rosenthal) (09/15/88)

In article <496@uvicctr.UUCP> tholm@uvicctr.UUCP (Terrence W. Holm) writes:
>There follows an implementation of memcpy(3), memccpy(3),
>memchr(3), memcmp(3) and memset(3) for MINIX. Please consider
>this public domain software. "man" pages are included.

It might worth playing some games with these.  I would think that memcpy()
is one of the cases where you are willing to give a little ugliness for
performance.

There was a recent discussion in comp.lang.c about using "Duff's Device"
for loop-unrolling in a portable way.  Tom Duff himself talked about the
origins of this in <8144@alice.UUCP>.  It might be interesting to look
at this way of doing memcpy().  (I've archived a copy of Tom's message
in case anybody is interested.)
-- 
Chip Rosenthal     chip@vector.UUCP | I've been a wizard since my childhood.
Dallas Semiconductor   214-450-0486 | And I've earned some respect for my art.

tholm@uvicctr.UUCP (Terrence W. Holm) (09/19/88)

> From: chip@vector.UUCP (Chip Rosenthal)
> 
> In article <496@uvicctr.UUCP> tholm@uvicctr.UUCP (Terrence W. Holm) writes:
> >There follows an implementation of memcpy(3), memccpy(3),
> >memchr(3), memcmp(3) and memset(3) for MINIX. Please consider
> 
> It might worth playing some games with these.  I would think that memcpy()
> is one of the cases where you are willing to give a little ugliness for
> performance.

Yes, I agree. But you must have noticed that my mission is to supply
MINIX with a useful, documented library, not to waste time with small
performance details - which are mute once we consider the whole
picture.

If you want to really help the MINIX community, I can supply you with
a list of more important topics.

> 
> There was a recent discussion in comp.lang.c about using "Duff's Device"

Yes, I teach all my 1st years to write code this way :-) :-)

                                    Terrence W. Holm

tholm@uvicctr.UUCP (Terrence W. Holm) (11/23/88)

EFTH MINIX report #59  - November 1988 -  memcpy(3), etc. for MINIX-ST


My previous posting of memcpy(3), etc. could copy int's at
an odd address. This does not work on an MC68000 system.
The following fixes the problem, (and also runs faster
on 80286 machines when the data is word aligned).

----------------------------------------------------------
echo x - bcmp.c
gres '^X' '' > bcmp.c << '/'
X/*  bcmp(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X
Xint bcmp( vector1, vector2, count )
X  register char *vector1;
X  register char *vector2;
X  int   count;
X
X  {
X  register int long_count;
X  register int byte_count;
X
X  if ( vector1 == vector2 )
X    return( 0 );
X
X  /*  Only compare longs if both are on an  */
X  /*  even byte boundary.		    */
X
X  if ( ((int) vector1 & 1)  ||  ((int) vector2 & 1) )
X    {
X    long_count = 0;
X    byte_count = count;
X    }
X  else
X    {
X    long_count = count >> 2;	/*  Assumes sizeof(long) is 4  */
X    byte_count = count & 03;
X    }
X
X
X  while( --long_count >= 0 )
X    if (  *((long *) vector1)++ != *((long *) vector2)++ )
X	return( 1 );
X
X  while( --byte_count >= 0 )
X    if (  *vector1++ != *vector2++ )
X	return( 1 );
X
X  return( 0 );
X  }
/
echo x - bcopy.c
gres '^X' '' > bcopy.c << '/'
X/*  bcopy(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X
Xbcopy( from, to, count )
X  register char *from;
X  register char *to;
X  int   count;
X
X  {
X  register int long_count;
X  register int byte_count;
X
X  /*  Only copy longs if both source and destination  */
X  /*  are on an even byte boundary.		      */
X
X  if ( ((int) to & 1)  ||  ((int) from & 1) )
X    {
X    long_count = 0;
X    byte_count = count;
X    }
X  else
X    {
X    long_count = count >> 2;	/*  Assumes sizeof(long) is 4  */
X    byte_count = count & 03;
X    }
X
X  
X  if ( to > from  &&  to < from + count )
X    {
X    /*  Must copy backwards  */
X    from += count;
X    to   += count;
X
X    while( --byte_count >= 0 )
X      *--to = *--from;
X
X    while( --long_count >= 0 )
X      *--((long *) to) = *--((long *) from);
X    }
X  else
X    {
X    while( --long_count >= 0 )
X      *((long *) to)++ = *((long *) from)++;
X
X    while( --byte_count >= 0 )
X      *to++ = *from++;
X    }
X  }
/
echo x - bzero.c
gres '^X' '' > bzero.c << '/'
X/*  bzero(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X
Xbzero( vector, count )
X  register char *vector;
X  int count;
X
X  {
X  register int long_count;
X  register int byte_count;
X
X  /*  Only use longs if on an even byte boundary  */
X
X  if ( (int) vector & 1 )
X    {
X    long_count = 0;
X    byte_count = count;
X    }
X  else
X    {
X    long_count = count >> 2;	/*  Assumes sizeof(long) is 4  */
X    byte_count = count & 03;
X    }
X
X  while( --long_count >= 0 )
X    *((long *) vector)++ = 0L;
X
X  while( --byte_count >= 0 )
X    *vector++ = 0;
X  }
/
echo x - memcpy.c
gres '^X' '' > memcpy.c << '/'
X/*  memcpy(3)
X *
X *  Author: Terrence W. Holm          Sep. 1988
X */
X
X
Xchar *memcpy( to, from, count )
X  register char *to;
X  register char *from;
X  int   count;
X
X  {
X  char *temp_to = to;
X  register int long_count;
X  register int byte_count;
X
X  /*  Only copy longs if both source and destination  */
X  /*  are on an even byte boundary.		      */
X
X  if ( ((int) to & 1)  ||  ((int) from & 1) )
X    {
X    long_count = 0;
X    byte_count = count;
X    }
X  else
X    {
X    long_count = count >> 2;	/*  Assumes sizeof(long) is 4  */
X    byte_count = count & 03;
X    }
X
X  
X  if ( to > from  &&  to < from + count )
X    {
X    /*  Must copy backwards  */
X    from += count;
X    to   += count;
X
X    while( --byte_count >= 0 )
X      *--to = *--from;
X
X    while( --long_count >= 0 )
X      *--((long *) to) = *--((long *) from);
X    }
X  else
X    {
X    while( --long_count >= 0 )
X      *((long *) to)++ = *((long *) from)++;
X
X    while( --byte_count >= 0 )
X      *to++ = *from++;
X    }
X
X  return( temp_to );
X  }
/
----------------------------------------------------------

		Terrence W. Holm
		  uunet!uw-beaver!uvicctr!tholm
		  tholm%uvunix.bitnet
		  tholm%sirius.UVic.ca@relay.ubc.ca