source: trunk/libs/newlib/src/newlib/libc/string/memccpy.c @ 543

Last change on this file since 543 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 3.6 KB
Line 
1/*
2FUNCTION
3        <<memccpy>>---copy memory regions with end-token check
4
5SYNOPSIS
6        #include <string.h>
7        void* memccpy(void *restrict <[out]>, const void *restrict <[in]>,
8                      int <[endchar]>, size_t <[n]>);
9
10DESCRIPTION
11        This function copies up to <[n]> bytes from the memory region
12        pointed to by <[in]> to the memory region pointed to by
13        <[out]>.  If a byte matching the <[endchar]> is encountered,
14        the byte is copied and copying stops.
15
16        If the regions overlap, the behavior is undefined.
17
18RETURNS
19        <<memccpy>> returns a pointer to the first byte following the
20        <[endchar]> in the <[out]> region.  If no byte matching
21        <[endchar]> was copied, then <<NULL>> is returned.
22
23PORTABILITY
24<<memccpy>> is a GNU extension.
25
26<<memccpy>> requires no supporting OS subroutines.
27
28        */
29
30#include <_ansi.h>
31#include <stddef.h>
32#include <string.h>
33#include <limits.h>
34
35/* Nonzero if either X or Y is not aligned on a "long" boundary.  */
36#define UNALIGNED(X, Y) \
37  (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
38
39/* How many bytes are copied each iteration of the word copy loop.  */
40#define LITTLEBLOCKSIZE (sizeof (long))
41
42/* Threshhold for punting to the byte copier.  */
43#define TOO_SMALL(LEN)  ((LEN) < LITTLEBLOCKSIZE)
44
45/* Macros for detecting endchar */
46#if LONG_MAX == 2147483647L
47#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
48#else
49#if LONG_MAX == 9223372036854775807L
50/* Nonzero if X (a long int) contains a NULL byte. */
51#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
52#else
53#error long int is not a 32bit or 64bit type.
54#endif
55#endif
56
57
58void *
59memccpy (void *__restrict dst0,
60        const void *__restrict src0,
61        int endchar0,
62        size_t len0)
63{
64
65#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
66  void *ptr = NULL;
67  char *dst = (char *) dst0;
68  char *src = (char *) src0;
69  char endchar = endchar0 & 0xff;
70
71  while (len0--)
72    {
73      if ((*dst++ = *src++) == endchar)
74        {
75          ptr = dst;
76          break;
77        }
78    }
79
80  return ptr;
81#else
82  void *ptr = NULL;
83  char *dst = dst0;
84  const char *src = src0;
85  long *aligned_dst;
86  const long *aligned_src;
87  char endchar = endchar0 & 0xff;
88
89  /* If the size is small, or either SRC or DST is unaligned,
90     then punt into the byte copy loop.  This should be rare.  */
91  if (!TOO_SMALL(len0) && !UNALIGNED (src, dst))
92    {
93      unsigned int i;
94      unsigned long mask = 0;
95
96      aligned_dst = (long*)dst;
97      aligned_src = (long*)src;
98
99      /* The fast code reads the ASCII one word at a time and only
100         performs the bytewise search on word-sized segments if they
101         contain the search character, which is detected by XORing
102         the word-sized segment with a word-sized block of the search
103         character and then detecting for the presence of NULL in the
104         result.  */
105      for (i = 0; i < LITTLEBLOCKSIZE; i++)
106        mask = (mask << 8) + endchar;
107
108
109      /* Copy one long word at a time if possible.  */
110      while (len0 >= LITTLEBLOCKSIZE)
111        {
112          unsigned long buffer = (unsigned long)(*aligned_src);
113          buffer ^=  mask;
114          if (DETECTNULL (buffer))
115            break; /* endchar is found, go byte by byte from here */
116          *aligned_dst++ = *aligned_src++;
117          len0 -= LITTLEBLOCKSIZE;
118        }
119
120       /* Pick up any residual with a byte copier.  */
121      dst = (char*)aligned_dst;
122      src = (char*)aligned_src;
123    }
124
125  while (len0--)
126    {
127      if ((*dst++ = *src++) == endchar)
128        {
129          ptr = dst;
130          break;
131        }
132    }
133
134  return ptr;
135#endif /* not PREFER_SIZE_OVER_SPEED */
136}
Note: See TracBrowser for help on using the repository browser.