A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd

add memccpy.c

Not sure if this is worth the added bin size yet but I will
see where I can use it to try and make it worth it

Change-Id: Icc299d3986172ff224a14be48da3bf065d728a66

authored by

William Wilgus and committed by
William Wilgus
b25a9d8f 034b6d5b

+139 -5
+3 -1
apps/debug_menu.c
··· 1627 1627 if (len >= name_sz) len = name_sz-1; 1628 1628 slen += len; 1629 1629 } 1630 - snprintf(str+slen, size-slen, "%s", buf); 1630 + 1631 + if (!memccpy (str+slen, buf, '\0', size-slen)) 1632 + (str+slen)[size-slen - 1] = '\0'; 1631 1633 } 1632 1634 1633 1635 return 1; /* ok */
+7 -2
apps/playlist_viewer.c
··· 516 516 { 517 517 char selected_track[MAX_PATH]; 518 518 close_playlist_viewer(); 519 - snprintf(selected_track, sizeof(selected_track), "%s", current_track->name); 519 + 520 + if (!memccpy (selected_track, current_track->name, '\0', sizeof(selected_track))) 521 + selected_track[sizeof(selected_track) - 1] = '\0'; 522 + 520 523 521 524 return (filetype_list_viewers(selected_track) == 522 525 PLUGIN_USB_CONNECTED ? PV_ONPLAY_USB_CLOSED : PV_ONPLAY_CLOSED); ··· 528 531 { 529 532 char selected_track[MAX_PATH]; 530 533 close_playlist_viewer(); 531 - snprintf(selected_track, sizeof(selected_track), "%s", current_track->name); 534 + 535 + if (!memccpy (selected_track, current_track->name, '\0', sizeof(selected_track))) 536 + selected_track[sizeof(selected_track) - 1] = '\0'; 532 537 533 538 return (filetype_load_plugin((void *)"pictureflow", selected_track) == 534 539 PLUGIN_USB_CONNECTED ? PV_ONPLAY_USB_CLOSED : PV_ONPLAY_CLOSED);
+8 -2
apps/screens.c
··· 561 561 case LANG_ID3_COMMENT: 562 562 if (!id3->comment) 563 563 return NULL; 564 - snprintf(buffer, buffer_len, "%s", id3->comment); 564 + 565 + if (!memccpy (buffer, id3->comment, '\0', buffer_len)) 566 + buffer[buffer_len - 1] = '\0'; 567 + 565 568 val=buffer; 566 569 if(say_it && val) 567 570 talk_spell(val, true); ··· 608 611 case LANG_FORMAT: 609 612 if (id3->codectype >= AFMT_NUM_CODECS) 610 613 return NULL; 611 - snprintf(buffer, buffer_len, "%s", audio_formats[id3->codectype].label); 614 + 615 + if (!memccpy (buffer, audio_formats[id3->codectype].label, '\0', buffer_len)) 616 + buffer[buffer_len - 1] = '\0'; 617 + 612 618 val=buffer; 613 619 if(say_it) 614 620 talk_spell(val, true);
+1
firmware/SOURCES
··· 262 262 libc/sprintf.c 263 263 #endif 264 264 265 + libc/memccpy.c 265 266 libc/memchr.c 266 267 libc/memcmp.c 267 268
+1
firmware/libc/include/string.h
··· 20 20 _PTR _EXFUN(memchr,(const _PTR, int, size_t)); 21 21 int _EXFUN(memcmp,(const _PTR, const _PTR, size_t)); 22 22 _PTR _EXFUN(memcpy,(_PTR, const _PTR, size_t)); 23 + _PTR _EXFUN(memccpy,(_PTR, const _PTR, int, size_t)); 23 24 _PTR _EXFUN(mempcpy,(_PTR, const _PTR, size_t)); 24 25 _PTR _EXFUN(memmove,(_PTR, const _PTR, size_t)); 25 26 _PTR _EXFUN(memset,(_PTR, int, size_t));
+119
firmware/libc/memccpy.c
··· 1 + /* 2 + FUNCTION 3 + <<memccpy>>---copy memory regions with end-token check 4 + ANSI_SYNOPSIS 5 + #include <string.h> 6 + void* memccpy(void *restrict <[out]>, const void *restrict <[in]>, 7 + int <[endchar]>, size_t <[n]>); 8 + TRAD_SYNOPSIS 9 + void *memccpy(<[out]>, <[in]>, <[endchar]>, <[n]> 10 + void *<[out]>; 11 + void *<[in]>; 12 + int <[endchar]>; 13 + size_t <[n]>; 14 + DESCRIPTION 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. 20 + RETURNS 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. 24 + PORTABILITY 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 + }