]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
d5a89d7d KS |
2 | |
3 | /* | |
4 | * Concatenates/copies strings. In any case, terminates in all cases | |
9e5bd85a VC |
5 | * with '\0' and moves the @dest pointer forward to the added '\0'. |
6 | * Returns the remaining size, and 0 if the string was truncated. | |
7 | * | |
8 | * Due to the intended usage, these helpers silently noop invocations | |
9 | * having zero size. This is technically an exception to the above | |
10 | * statement "terminates in all cases". It's unexpected for such calls to | |
11 | * occur outside of a loop where this is the preferred behavior. | |
d5a89d7d KS |
12 | */ |
13 | ||
11c3a366 | 14 | #include <stdarg.h> |
d5a89d7d KS |
15 | #include <stdio.h> |
16 | #include <string.h> | |
cf0fbc49 | 17 | |
d5a89d7d KS |
18 | #include "strxcpyx.h" |
19 | ||
7e4831d2 | 20 | size_t strnpcpy(char **dest, size_t size, const char *src, size_t len) { |
f91049d5 VC |
21 | assert(dest); |
22 | assert(src); | |
23 | ||
9e5bd85a VC |
24 | if (size == 0) |
25 | return 0; | |
26 | ||
d5a89d7d KS |
27 | if (len >= size) { |
28 | if (size > 1) | |
29 | *dest = mempcpy(*dest, src, size-1); | |
30 | size = 0; | |
68619204 LP |
31 | } else if (len > 0) { |
32 | *dest = mempcpy(*dest, src, len); | |
33 | size -= len; | |
d5a89d7d | 34 | } |
68619204 | 35 | |
d5a89d7d KS |
36 | *dest[0] = '\0'; |
37 | return size; | |
38 | } | |
39 | ||
7e4831d2 YW |
40 | size_t strpcpy(char **dest, size_t size, const char *src) { |
41 | assert(dest); | |
42 | assert(src); | |
43 | ||
44 | return strnpcpy(dest, size, src, strlen(src)); | |
45 | } | |
46 | ||
f168c273 | 47 | size_t strpcpyf(char **dest, size_t size, const char *src, ...) { |
d5a89d7d KS |
48 | va_list va; |
49 | int i; | |
50 | ||
f91049d5 VC |
51 | assert(dest); |
52 | assert(src); | |
53 | ||
9e5bd85a VC |
54 | if (size == 0) |
55 | return 0; | |
56 | ||
d5a89d7d KS |
57 | va_start(va, src); |
58 | i = vsnprintf(*dest, size, src, va); | |
59 | if (i < (int)size) { | |
60 | *dest += i; | |
61 | size -= i; | |
68619204 | 62 | } else |
d5a89d7d | 63 | size = 0; |
d5a89d7d | 64 | va_end(va); |
d5a89d7d KS |
65 | return size; |
66 | } | |
67 | ||
f168c273 | 68 | size_t strpcpyl(char **dest, size_t size, const char *src, ...) { |
d5a89d7d KS |
69 | va_list va; |
70 | ||
f91049d5 VC |
71 | assert(dest); |
72 | assert(src); | |
73 | ||
d5a89d7d KS |
74 | va_start(va, src); |
75 | do { | |
76 | size = strpcpy(dest, size, src); | |
77 | src = va_arg(va, char *); | |
68619204 | 78 | } while (src); |
d5a89d7d KS |
79 | va_end(va); |
80 | return size; | |
81 | } | |
82 | ||
7e4831d2 | 83 | size_t strnscpy(char *dest, size_t size, const char *src, size_t len) { |
d5a89d7d KS |
84 | char *s; |
85 | ||
f91049d5 VC |
86 | assert(dest); |
87 | assert(src); | |
88 | ||
d5a89d7d | 89 | s = dest; |
7e4831d2 YW |
90 | return strnpcpy(&s, size, src, len); |
91 | } | |
92 | ||
93 | size_t strscpy(char *dest, size_t size, const char *src) { | |
94 | assert(dest); | |
95 | assert(src); | |
96 | ||
97 | return strnscpy(dest, size, src, strlen(src)); | |
d5a89d7d KS |
98 | } |
99 | ||
100 | size_t strscpyl(char *dest, size_t size, const char *src, ...) { | |
101 | va_list va; | |
102 | char *s; | |
103 | ||
f91049d5 VC |
104 | assert(dest); |
105 | assert(src); | |
106 | ||
d5a89d7d KS |
107 | va_start(va, src); |
108 | s = dest; | |
109 | do { | |
110 | size = strpcpy(&s, size, src); | |
111 | src = va_arg(va, char *); | |
68619204 | 112 | } while (src); |
d5a89d7d KS |
113 | va_end(va); |
114 | ||
115 | return size; | |
116 | } |