18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#include <linux/slab.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci/*
68c2ecf20Sopenharmony_ci * Merge two NULL-terminated pointer arrays into a newly allocated
78c2ecf20Sopenharmony_ci * array, which is also NULL-terminated. Nomenclature is inspired by
88c2ecf20Sopenharmony_ci * memset_p() and memcat() found elsewhere in the kernel source tree.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_civoid **__memcat_p(void **a, void **b)
118c2ecf20Sopenharmony_ci{
128c2ecf20Sopenharmony_ci	void **p = a, **new;
138c2ecf20Sopenharmony_ci	int nr;
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci	/* count the elements in both arrays */
168c2ecf20Sopenharmony_ci	for (nr = 0, p = a; *p; nr++, p++)
178c2ecf20Sopenharmony_ci		;
188c2ecf20Sopenharmony_ci	for (p = b; *p; nr++, p++)
198c2ecf20Sopenharmony_ci		;
208c2ecf20Sopenharmony_ci	/* one for the NULL-terminator */
218c2ecf20Sopenharmony_ci	nr++;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	new = kmalloc_array(nr, sizeof(void *), GFP_KERNEL);
248c2ecf20Sopenharmony_ci	if (!new)
258c2ecf20Sopenharmony_ci		return NULL;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci	/* nr -> last index; p points to NULL in b[] */
288c2ecf20Sopenharmony_ci	for (nr--; nr >= 0; nr--, p = p == b ? &a[nr] : p - 1)
298c2ecf20Sopenharmony_ci		new[nr] = *p;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	return new;
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__memcat_p);
348c2ecf20Sopenharmony_ci
35