xref: /illumos-gate/usr/src/lib/libc/port/i18n/wcslcat.c (revision 71f3ceb939e47627273608fb7ea4b3aa1c3b37e7)
1*71f3ceb9SRobert Mustacchi /*
2*71f3ceb9SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*71f3ceb9SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*71f3ceb9SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*71f3ceb9SRobert Mustacchi  * 1.0 of the CDDL.
6*71f3ceb9SRobert Mustacchi  *
7*71f3ceb9SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*71f3ceb9SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*71f3ceb9SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*71f3ceb9SRobert Mustacchi  */
11*71f3ceb9SRobert Mustacchi 
12*71f3ceb9SRobert Mustacchi /*
13*71f3ceb9SRobert Mustacchi  * Copyright 2025 Oxide Computer Company
14*71f3ceb9SRobert Mustacchi  */
15*71f3ceb9SRobert Mustacchi 
16*71f3ceb9SRobert Mustacchi /*
17*71f3ceb9SRobert Mustacchi  * Wide character version of strlcat(3C). This appends up to dstlen - 1 wide
18*71f3ceb9SRobert Mustacchi  * characters to dst, taking into account any string that already is present
19*71f3ceb9SRobert Mustacchi  * there. The resulting string is always terminated with a NULL wide-character
20*71f3ceb9SRobert Mustacchi  * unless the dst buffer is already full of data with no terminator. The number
21*71f3ceb9SRobert Mustacchi  * of wide characters that would be in the fully concatenated string is
22*71f3ceb9SRobert Mustacchi  * returned.
23*71f3ceb9SRobert Mustacchi  */
24*71f3ceb9SRobert Mustacchi 
25*71f3ceb9SRobert Mustacchi #include "lint.h"
26*71f3ceb9SRobert Mustacchi #include <wchar.h>
27*71f3ceb9SRobert Mustacchi #include <sys/sysmacros.h>
28*71f3ceb9SRobert Mustacchi 
29*71f3ceb9SRobert Mustacchi size_t
wcslcat(wchar_t * restrict dst,const wchar_t * restrict src,size_t dstlen)30*71f3ceb9SRobert Mustacchi wcslcat(wchar_t *restrict dst, const wchar_t *restrict src, size_t dstlen)
31*71f3ceb9SRobert Mustacchi {
32*71f3ceb9SRobert Mustacchi 	size_t srclen = wcslen(src);
33*71f3ceb9SRobert Mustacchi 	size_t dstoff = wcsnlen(dst, dstlen);
34*71f3ceb9SRobert Mustacchi 	size_t nwcs;
35*71f3ceb9SRobert Mustacchi 
36*71f3ceb9SRobert Mustacchi 	/*
37*71f3ceb9SRobert Mustacchi 	 * If there is no space in the destination buffer for the source string,
38*71f3ceb9SRobert Mustacchi 	 * then do not do anything. We check both for the case where there is no
39*71f3ceb9SRobert Mustacchi 	 * valid NUL in dst (dstoff == dstlen) or where there is one, which
40*71f3ceb9SRobert Mustacchi 	 * means that there is nothing to actually copy. It's also possible that
41*71f3ceb9SRobert Mustacchi 	 * there was never any space to begin with.
42*71f3ceb9SRobert Mustacchi 	 */
43*71f3ceb9SRobert Mustacchi 	if (dstlen == 0 || dstoff >= dstlen - 1) {
44*71f3ceb9SRobert Mustacchi 		return (srclen + dstoff);
45*71f3ceb9SRobert Mustacchi 	}
46*71f3ceb9SRobert Mustacchi 
47*71f3ceb9SRobert Mustacchi 	nwcs = MIN(dstlen - 1 - dstoff, srclen);
48*71f3ceb9SRobert Mustacchi 	(void) wmemcpy(dst + dstoff, src, nwcs);
49*71f3ceb9SRobert Mustacchi 	dst[nwcs + dstoff] = L'\0';
50*71f3ceb9SRobert Mustacchi 	return (srclen + dstoff);
51*71f3ceb9SRobert Mustacchi }
52