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