0,0 → 1,107 |
/* |
FUNCTION |
<<mempcpy>>---copy memory regions and return end pointer |
|
ANSI_SYNOPSIS |
#include <string.h> |
void* mempcpy(void *<[out]>, const void *<[in]>, size_t <[n]>); |
|
TRAD_SYNOPSIS |
void *mempcpy(<[out]>, <[in]>, <[n]> |
void *<[out]>; |
void *<[in]>; |
size_t <[n]>; |
|
DESCRIPTION |
This function copies <[n]> bytes from the memory region |
pointed to by <[in]> to the memory region pointed to by |
<[out]>. |
|
If the regions overlap, the behavior is undefined. |
|
RETURNS |
<<mempcpy>> returns a pointer to the byte following the |
last byte copied to the <[out]> region. |
|
PORTABILITY |
<<mempcpy>> is a GNU extension. |
|
<<mempcpy>> requires no supporting OS subroutines. |
|
*/ |
|
#include <_ansi.h> |
#include <stddef.h> |
#include <limits.h> |
#include <string.h> |
|
/* Nonzero if either X or Y is not aligned on a "long" boundary. */ |
#define UNALIGNED(X, Y) \ |
(((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) |
|
/* How many bytes are copied each iteration of the 4X unrolled loop. */ |
#define BIGBLOCKSIZE (sizeof (long) << 2) |
|
/* How many bytes are copied each iteration of the word copy loop. */ |
#define LITTLEBLOCKSIZE (sizeof (long)) |
|
/* Threshhold for punting to the byte copier. */ |
#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) |
|
_PTR |
_DEFUN (mempcpy, (dst0, src0, len0), |
_PTR dst0 _AND |
_CONST _PTR src0 _AND |
size_t len0) |
{ |
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) |
char *dst = (char *) dst0; |
char *src = (char *) src0; |
|
while (len0--) |
{ |
*dst++ = *src++; |
} |
|
return dst; |
#else |
char *dst = dst0; |
_CONST char *src = src0; |
long *aligned_dst; |
_CONST long *aligned_src; |
|
/* If the size is small, or either SRC or DST is unaligned, |
then punt into the byte copy loop. This should be rare. */ |
if (!TOO_SMALL(len0) && !UNALIGNED (src, dst)) |
{ |
aligned_dst = (long*)dst; |
aligned_src = (long*)src; |
|
/* Copy 4X long words at a time if possible. */ |
while (len0 >= BIGBLOCKSIZE) |
{ |
*aligned_dst++ = *aligned_src++; |
*aligned_dst++ = *aligned_src++; |
*aligned_dst++ = *aligned_src++; |
*aligned_dst++ = *aligned_src++; |
len0 -= BIGBLOCKSIZE; |
} |
|
/* Copy one long word at a time if possible. */ |
while (len0 >= LITTLEBLOCKSIZE) |
{ |
*aligned_dst++ = *aligned_src++; |
len0 -= LITTLEBLOCKSIZE; |
} |
|
/* Pick up any residual with a byte copier. */ |
dst = (char*)aligned_dst; |
src = (char*)aligned_src; |
} |
|
while (len0--) |
*dst++ = *src++; |
|
return dst; |
#endif /* not PREFER_SIZE_OVER_SPEED */ |
} |