]>
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 | ||
14 | #include <stdio.h> | |
15 | #include <string.h> | |
cf0fbc49 | 16 | |
d5a89d7d KS |
17 | #include "strxcpyx.h" |
18 | ||
e70151c9 YW |
19 | size_t strnpcpy_full(char **dest, size_t size, const char *src, size_t len, bool *ret_truncated) { |
20 | bool truncated = false; | |
21 | ||
f91049d5 VC |
22 | assert(dest); |
23 | assert(src); | |
24 | ||
e70151c9 YW |
25 | if (size == 0) { |
26 | if (ret_truncated) | |
27 | *ret_truncated = len > 0; | |
9e5bd85a | 28 | return 0; |
e70151c9 | 29 | } |
9e5bd85a | 30 | |
d5a89d7d KS |
31 | if (len >= size) { |
32 | if (size > 1) | |
33 | *dest = mempcpy(*dest, src, size-1); | |
34 | size = 0; | |
e70151c9 | 35 | truncated = true; |
68619204 LP |
36 | } else if (len > 0) { |
37 | *dest = mempcpy(*dest, src, len); | |
38 | size -= len; | |
d5a89d7d | 39 | } |
68619204 | 40 | |
e70151c9 YW |
41 | if (ret_truncated) |
42 | *ret_truncated = truncated; | |
43 | ||
d5a89d7d KS |
44 | *dest[0] = '\0'; |
45 | return size; | |
46 | } | |
47 | ||
e70151c9 | 48 | size_t strpcpy_full(char **dest, size_t size, const char *src, bool *ret_truncated) { |
7e4831d2 YW |
49 | assert(dest); |
50 | assert(src); | |
51 | ||
e70151c9 | 52 | return strnpcpy_full(dest, size, src, strlen(src), ret_truncated); |
7e4831d2 YW |
53 | } |
54 | ||
e70151c9 YW |
55 | size_t strpcpyf_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) { |
56 | bool truncated = false; | |
d5a89d7d KS |
57 | va_list va; |
58 | int i; | |
59 | ||
f91049d5 VC |
60 | assert(dest); |
61 | assert(src); | |
62 | ||
d5a89d7d KS |
63 | va_start(va, src); |
64 | i = vsnprintf(*dest, size, src, va); | |
e70151c9 YW |
65 | va_end(va); |
66 | ||
67 | if (i < (int) size) { | |
d5a89d7d KS |
68 | *dest += i; |
69 | size -= i; | |
e70151c9 | 70 | } else { |
d5a89d7d | 71 | size = 0; |
e70151c9 YW |
72 | truncated = i > 0; |
73 | } | |
74 | ||
75 | if (ret_truncated) | |
76 | *ret_truncated = truncated; | |
77 | ||
d5a89d7d KS |
78 | return size; |
79 | } | |
80 | ||
e70151c9 YW |
81 | size_t strpcpyl_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) { |
82 | bool truncated = false; | |
d5a89d7d KS |
83 | va_list va; |
84 | ||
f91049d5 VC |
85 | assert(dest); |
86 | assert(src); | |
87 | ||
d5a89d7d KS |
88 | va_start(va, src); |
89 | do { | |
e70151c9 YW |
90 | bool t; |
91 | ||
92 | size = strpcpy_full(dest, size, src, &t); | |
93 | truncated = truncated || t; | |
d5a89d7d | 94 | src = va_arg(va, char *); |
68619204 | 95 | } while (src); |
d5a89d7d | 96 | va_end(va); |
e70151c9 YW |
97 | |
98 | if (ret_truncated) | |
99 | *ret_truncated = truncated; | |
d5a89d7d KS |
100 | return size; |
101 | } | |
102 | ||
e70151c9 | 103 | size_t strnscpy_full(char *dest, size_t size, const char *src, size_t len, bool *ret_truncated) { |
d5a89d7d KS |
104 | char *s; |
105 | ||
f91049d5 VC |
106 | assert(dest); |
107 | assert(src); | |
108 | ||
d5a89d7d | 109 | s = dest; |
e70151c9 | 110 | return strnpcpy_full(&s, size, src, len, ret_truncated); |
7e4831d2 YW |
111 | } |
112 | ||
e70151c9 | 113 | size_t strscpy_full(char *dest, size_t size, const char *src, bool *ret_truncated) { |
7e4831d2 YW |
114 | assert(dest); |
115 | assert(src); | |
116 | ||
e70151c9 | 117 | return strnscpy_full(dest, size, src, strlen(src), ret_truncated); |
d5a89d7d KS |
118 | } |
119 | ||
e70151c9 YW |
120 | size_t strscpyl_full(char *dest, size_t size, bool *ret_truncated, const char *src, ...) { |
121 | bool truncated = false; | |
d5a89d7d KS |
122 | va_list va; |
123 | char *s; | |
124 | ||
f91049d5 VC |
125 | assert(dest); |
126 | assert(src); | |
127 | ||
d5a89d7d KS |
128 | va_start(va, src); |
129 | s = dest; | |
130 | do { | |
e70151c9 YW |
131 | bool t; |
132 | ||
133 | size = strpcpy_full(&s, size, src, &t); | |
134 | truncated = truncated || t; | |
d5a89d7d | 135 | src = va_arg(va, char *); |
68619204 | 136 | } while (src); |
d5a89d7d KS |
137 | va_end(va); |
138 | ||
e70151c9 YW |
139 | if (ret_truncated) |
140 | *ret_truncated = truncated; | |
141 | ||
d5a89d7d KS |
142 | return size; |
143 | } |