您的位置:首页 > 编程语言

c标准库源代码之 memcpy/memcmp/memset

2011-01-09 10:35 204 查看
void *
memcpy (dstpp, srcpp, len)
void *dstpp;
const void *srcpp;
size_t len;
{
unsigned long int dstp = (long int) dstpp;
unsigned long int srcp = (long int) srcpp;

/* Copy from the beginning to the end.  */

/* If there not too few bytes to copy, use word copy.  */
if (len >= OP_T_THRES)
{
/* Copy just a few bytes to make DSTP aligned.  */
len -= (-dstp) % OPSIZ;
BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);

/* Copy whole pages from SRCP to DSTP by virtual address manipulation,
as much as possible.  */

PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);

/* Copy from SRCP to DSTP taking advantage of the known alignment of
DSTP.  Number of bytes remaining is put in the third argument,
i.e. in LEN.  This number may vary from machine to machine.  */

WORD_COPY_FWD (dstp, srcp, len, len);

/* Fall out and copy the tail.  */
}

/* There are just a few bytes to copy.  Use byte memory operations.  */
BYTE_COPY_FWD (dstp, srcp, len);

return dstpp;
}


int
memcmp (s1, s2, len)
const __ptr_t s1;
const __ptr_t s2;
size_t len;
{
op_t a0;
op_t b0;
long int srcp1 = (long int) s1;
long int srcp2 = (long int) s2;
op_t res;

if (len >= OP_T_THRES)
{
/* There are at least some bytes to compare.  No need to test
for LEN == 0 in this alignment loop.  */
while (srcp2 % OPSIZ != 0)
{
a0 = ((byte *) srcp1)[0];
b0 = ((byte *) srcp2)[0];
srcp1 += 1;
srcp2 += 1;
res = a0 - b0;
if (res != 0)
return res;
len -= 1;
}

/* SRCP2 is now aligned for memory operations on `op_t'.
SRCP1 alignment determines if we can do a simple,
aligned compare or need to shuffle bits.  */

if (srcp1 % OPSIZ == 0)
res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ);
else
res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ);
if (res != 0)
return res;

/* Number of bytes remaining in the interval [0..OPSIZ-1].  */
srcp1 += len & -OPSIZ;
srcp2 += len & -OPSIZ;
len %= OPSIZ;
}

/* There are just a few bytes to compare.  Use byte memory operations.  */
while (len != 0)
{
a0 = ((byte *) srcp1)[0];
b0 = ((byte *) srcp2)[0];
srcp1 += 1;
srcp2 += 1;
res = a0 - b0;
if (res != 0)
return res;
len -= 1;
}

return 0;
}


void *
memset (dstpp, c, len)
void *dstpp;
int c;
size_t len;
{
long int dstp = (long int) dstpp;

if (len >= 8)
{
size_t xlen;
op_t cccc;

cccc = (unsigned char) c;
cccc |= cccc << 8;
cccc |= cccc << 16;
if (OPSIZ > 4)
/* Do the shift in two steps to avoid warning if long has 32 bits.  */
cccc |= (cccc << 16) << 16;

/* There are at least some bytes to set.
No need to test for LEN == 0 in this alignment loop.  */
while (dstp % OPSIZ != 0)
{
((byte *) dstp)[0] = c;
dstp += 1;
len -= 1;
}

/* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
xlen = len / (OPSIZ * 8);
while (xlen > 0)
{
((op_t *) dstp)[0] = cccc;
((op_t *) dstp)[1] = cccc;
((op_t *) dstp)[2] = cccc;
((op_t *) dstp)[3] = cccc;
((op_t *) dstp)[4] = cccc;
((op_t *) dstp)[5] = cccc;
((op_t *) dstp)[6] = cccc;
((op_t *) dstp)[7] = cccc;
dstp += 8 * OPSIZ;
xlen -= 1;
}
len %= OPSIZ * 8;

/* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
xlen = len / OPSIZ;
while (xlen > 0)
{
((op_t *) dstp)[0] = cccc;
dstp += OPSIZ;
xlen -= 1;
}
len %= OPSIZ;
}

/* Write the last few bytes.  */
while (len > 0)
{
((byte *) dstp)[0] = c;
dstp += 1;
len -= 1;
}

return dstpp;
}


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/onezeros/archive/2010/07/08/5720903.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: