1 /* Copyright (C) 1992-2023 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
18 #define NO_MEMPCPY_STPCPY_REDIRECT
22 #include <string-fzb.h>
23 #include <string-misc.h>
29 # define STPCPY __stpcpy
32 static __always_inline
char *
33 write_byte_from_word (op_t
*dest
, op_t word
)
35 char *d
= (char *) dest
;
36 for (size_t i
= 0; i
< OPSIZ
; i
++, ++d
)
38 char c
= extractbyte (word
, i
);
46 static __always_inline
char *
47 stpcpy_aligned_loop (op_t
*restrict dst
, const op_t
*restrict src
)
58 return write_byte_from_word (dst
, word
);
61 static __always_inline
char *
62 stpcpy_unaligned_loop (op_t
*restrict dst
, const op_t
*restrict src
,
66 uintptr_t sh_1
= ofs
* CHAR_BIT
;
67 uintptr_t sh_2
= OPSIZ
* CHAR_BIT
- sh_1
;
69 op_t w2
= MERGE (w2a
, sh_1
, (op_t
)-1, sh_2
);
74 /* Unaligned loop. The invariant is that W2B, which is "ahead" of W1,
75 does not contain end-of-string. Therefore it is safe (and necessary)
76 to read another word from each while we do not have a difference. */
80 w2
= MERGE (w2a
, sh_1
, w2b
, sh_2
);
81 /* Check if there is zero on w2a. */
90 /* Align the final partial of P2. */
91 w2
= MERGE (w2b
, sh_1
, 0, sh_2
);
95 return write_byte_from_word (dst
, w2
);
99 /* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
101 STPCPY (char *dest
, const char *src
)
103 /* Copy just a few bytes to make DEST aligned. */
104 size_t len
= (-(uintptr_t) dest
) % OPSIZ
;
105 for (; len
!= 0; len
--, ++dest
)
113 /* DEST is now aligned to op_t, SRC may or may not be. */
114 uintptr_t ofs
= (uintptr_t) src
% OPSIZ
;
115 return ofs
== 0 ? stpcpy_aligned_loop ((op_t
*) dest
, (const op_t
*) src
)
116 : stpcpy_unaligned_loop ((op_t
*) dest
,
117 (const op_t
*) (src
- ofs
) , ofs
);
119 weak_alias (__stpcpy
, stpcpy
)
120 libc_hidden_def (__stpcpy
)
121 libc_hidden_builtin_def (stpcpy
)