/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "nulstr-util.h"
#include "string-util.h"
#include "strv.h"

char** strv_parse_nulstr(const char *s, size_t l) {
        /* l is the length of the input data, which will be split at NULs into elements of the resulting
         * strv. Hence, the number of items in the resulting strv will be equal to one plus the number of NUL
         * bytes in the l bytes starting at s, unless s[l-1] is NUL, in which case the final empty string is
         * not stored in the resulting strv, and length is equal to the number of NUL bytes.
         *
         * Note that contrary to a normal nulstr which cannot contain empty strings, because the input data
         * is terminated by any two consequent NUL bytes, this parser accepts empty strings in s. */

        _cleanup_strv_free_ char **v = NULL;
        size_t c = 0, i = 0;

        assert(s || l <= 0);

        if (l <= 0)
                return new0(char*, 1);

        for (const char *p = s; p < s + l; p++)
                if (*p == 0)
                        c++;

        if (s[l-1] != 0)
                c++;

        v = new0(char*, c+1);
        if (!v)
                return NULL;

        for (const char *p = s; p < s + l; ) {
                const char *e;

                e = memchr(p, 0, s + l - p);

                v[i] = memdup_suffix0(p, e ? e - p : s + l - p);
                if (!v[i])
                        return NULL;

                i++;

                if (!e)
                        break;

                p = e + 1;
        }

        assert(i == c);

        return TAKE_PTR(v);
}

char** strv_split_nulstr(const char *s) {
        _cleanup_strv_free_ char **l = NULL;

        /* This parses a nulstr, without specification of size, and stops at an empty string. This cannot
         * parse nulstrs with embedded empty strings hence, as an empty string is an end marker. Use
         * strv_parse_nulstr() above to parse a nulstr with embedded empty strings (which however requires a
         * size to be specified) */

        NULSTR_FOREACH(i, s)
                if (strv_extend(&l, i) < 0)
                        return NULL;

        return l ? TAKE_PTR(l) : strv_new(NULL);
}

int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
        /* Builds a nulstr and returns it together with the size. An extra NUL byte will be appended (⚠️ but
         * not included in the size! ⚠️). This is done so that the nulstr can be used both in
         * strv_parse_nulstr() and in NULSTR_FOREACH()/strv_split_nulstr() contexts, i.e. with and without a
         * size parameter. In the former case we can include empty strings, in the latter case we cannot (as
         * that is the end marker).
         *
         * When NULSTR_FOREACH()/strv_split_nulstr() is used it is often assumed that the nulstr ends in two
         * NUL bytes (which it will, if not empty). To ensure that this assumption *always* holds, we'll
         * return a buffer with two NUL bytes in that case, but return a size of zero. */

        _cleanup_free_ char *m = NULL;
        size_t n = 0;

        assert(ret);
        assert(ret_size);

        STRV_FOREACH(i, l) {
                size_t z;

                z = strlen(*i);

                if (!GREEDY_REALLOC(m, n + z + 2))
                        return -ENOMEM;

                memcpy(m + n, *i, z + 1);
                n += z + 1;
        }

        if (!m) {
                /* return a buffer with an extra NUL, so that the assumption that we always have two trailing NULs holds */
                m = new0(char, 2);
                if (!m)
                        return -ENOMEM;

                n = 0;
        } else
                /* Make sure there is a second extra NUL at the end of resulting nulstr (not counted in return size) */
                m[n] = '\0';

        *ret = TAKE_PTR(m);
        *ret_size = n;

        return 0;
}

int set_make_nulstr(Set *s, char **ret, size_t *ret_size) {
        /* Use _cleanup_free_ instead of _cleanup_strv_free_ because we need to clean the strv only, not
         * the strings owned by the set. */
        _cleanup_free_ char **strv = NULL;

        assert(ret);
        assert(ret_size);

        strv = set_get_strv(s);
        if (!strv)
                return -ENOMEM;

        return strv_make_nulstr(strv, ret, ret_size);
}

const char* nulstr_get(const char *nulstr, const char *needle) {
        if (!nulstr)
                return NULL;

        NULSTR_FOREACH(i, nulstr)
                if (streq(i, needle))
                        return i;

        return NULL;
}
