@@ -38,7 +38,7 @@ void *memmove(void *dest, const void *src, size_t n) {
38
38
39
39
#ifdef __wasm_simd128__
40
40
41
- // SIMD versions of some string.h functions.
41
+ // SIMD implementations of string.h functions.
42
42
43
43
__attribute__((weak ))
44
44
int memcmp (const void * v1 , const void * v2 , size_t n ) {
@@ -220,7 +220,7 @@ static int __strcmp_s(const char *s1, const char *s2) {
220
220
__attribute__((weak , always_inline ))
221
221
int strcmp (const char * s1 , const char * s2 ) {
222
222
// Skip the vector search when comparing against small literal strings.
223
- if (__builtin_constant_p (strlen (s2 ) && strlen (s2 ) < sizeof (v128_t ) )) {
223
+ if (__builtin_constant_p (strlen (s2 )) && strlen (s2 ) < sizeof (v128_t )) {
224
224
return __strcmp_s (s1 , s2 );
225
225
}
226
226
return __strcmp (s1 , s2 );
@@ -317,6 +317,9 @@ char *strrchr(const char *s, int c) {
317
317
if (__builtin_constant_p (c ) && (char )c == 0 ) {
318
318
return (char * )s + strlen (s );
319
319
}
320
+ // This could also be implemented in a single pass using strchr,
321
+ // advancing to the next match until no more matches are found.
322
+ // That would be suboptimal with lots of consecutive matches.
320
323
return (char * )memrchr (s , c , strlen (s ) + 1 );
321
324
}
322
325
@@ -416,10 +419,67 @@ size_t strcspn(const char *s, const char *c) {
416
419
return s - a ;
417
420
}
418
421
422
+ // Given the above SIMD implementations,
423
+ // these are best implemented as
424
+ // small wrappers over those functions.
425
+
426
+ // Simple wrappers from musl:
427
+ // - mempcpy
428
+ // - strcat
429
+ // - strdup
430
+ // - strndup
431
+ // - strnlen
432
+ // - strpbrk
433
+ // - strsep
434
+ // - strtok
435
+
436
+ __attribute__((weak , always_inline ))
437
+ void * memccpy (void * __restrict dest , const void * __restrict src , int c , size_t n ) {
438
+ const void * m = memchr (src , c , n );
439
+ if (m != NULL ) {
440
+ n = (char * )m - (char * )src + 1 ;
441
+ m = (char * )dest + n ;
442
+ }
443
+ memcpy (dest , src , n );
444
+ return (void * )m ;
445
+ }
446
+
447
+ __attribute__((weak , always_inline ))
448
+ char * stpcpy (char * __restrict dest , const char * __restrict src ) {
449
+ size_t slen = strlen (src );
450
+ memcpy (dest , src , slen + 1 );
451
+ return dest + slen ;
452
+ }
453
+
454
+ __attribute__((weak , always_inline ))
455
+ char * stpncpy (char * __restrict dest , const char * __restrict src , size_t n ) {
456
+ size_t strnlen (const char * s , size_t n );
457
+ size_t slen = strnlen (src , n );
458
+ memcpy (dest , src , slen );
459
+ memset (dest + slen , 0 , n - slen );
460
+ return dest + slen ;
461
+ }
462
+
463
+ __attribute__((weak , always_inline ))
464
+ char * strcpy (char * __restrict dest , const char * __restrict src ) {
465
+ stpcpy (dest , src );
466
+ return dest ;
467
+ }
468
+
469
+ __attribute__((weak , always_inline ))
470
+ char * strncpy (char * __restrict dest , const char * __restrict src , size_t n ) {
471
+ stpncpy (dest , src , n );
472
+ return dest ;
473
+ }
474
+
419
475
__attribute__((weak , always_inline ))
420
- char * strpbrk (const char * s , const char * b ) {
421
- s += strcspn (s , b );
422
- return * s ? (char * )s : 0 ;
476
+ char * strncat (char * __restrict dest , const char * __restrict src , size_t n ) {
477
+ size_t strnlen (const char * s , size_t n );
478
+ size_t dlen = strlen (dest );
479
+ size_t slen = strnlen (src , n );
480
+ memcpy (dest + dlen , src , slen );
481
+ dest [dlen + slen ] = 0 ;
482
+ return dest ;
423
483
}
424
484
425
485
#endif // __wasm_simd128__
0 commit comments