root/sys/dev/pci/drm/include/linux/string.h
/* Public domain. */

#ifndef _LINUX_STRING_H
#define _LINUX_STRING_H

#include <sys/types.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/stdint.h>
#include <sys/errno.h>

#include <linux/compiler.h>
#include <linux/err.h>

void *memchr_inv(const void *, int, size_t);

static inline bool
mem_is_zero(const void *b, size_t len)
{
        return (memchr_inv(b, 0, len) == NULL);
}

static inline void *
memset32(uint32_t *b, uint32_t c, size_t len)
{
        uint32_t *dst = b;
        while (len--)
                *dst++ = c;
        return b;
}

static inline void *
memset64(uint64_t *b, uint64_t c, size_t len)
{
        uint64_t *dst = b;
        while (len--)
                *dst++ = c;
        return b;
}

static inline void *
memset_p(void **p, void *v, size_t n)
{
#ifdef __LP64__
        return memset64((uint64_t *)p, (uintptr_t)v, n);
#else
        return memset32((uint32_t *)p, (uintptr_t)v, n);
#endif
}

static inline void *
kmemdup(const void *src, size_t len, int flags)
{
        void *p = malloc(len, M_DRM, flags);
        if (p)
                memcpy(p, src, len);
        return (p);
}

static inline void *
kmemdup_array(const void *src, size_t nemb, size_t size, int flags)
{
        void *p = mallocarray(nemb, size, M_DRM, flags);
        if (p)
                memcpy(p, src, nemb * size);
        return (p);
}

static inline void *
memdup_array_user(const void *src, size_t nemb, size_t size)
{
        void *p = mallocarray(nemb, size, M_DRM, M_WAITOK | M_CANFAIL);
        if (p == NULL)
                return ERR_PTR(-ENOMEM);

        if (copyin(src, p, nemb * size) != 0) {
                free(p, M_DRM, nemb * size);
                return ERR_PTR(-EFAULT);
        }
        return (p);
}

static inline void *
memdup_user(void *src, size_t size)
{
        char *p = malloc(size, M_DRM, M_WAITOK | M_CANFAIL);
        if (p == NULL)
                return ERR_PTR(-ENOMEM);

        if (copyin(src, p, size) != 0) {
                free(p, M_DRM, size);
                return ERR_PTR(-EFAULT);
        }
        return (p);
}

static inline void *
memdup_user_nul(const void *src, size_t size)
{
        char *p = malloc(size + 1, M_DRM, M_WAITOK | M_CANFAIL);
        if (p == NULL)
                return ERR_PTR(-ENOMEM);

        if (copyin(src, p, size) != 0) {
                free(p, M_DRM, size + 1);
                return ERR_PTR(-EFAULT);
        }
        p[size] = '\0';
        return (p);
}

static inline void *
kstrdup(const char *str, int flags)
{
        size_t len;
        char *p;

        if (str == NULL)
                return NULL;

        len = strlen(str) + 1;
        p = malloc(len, M_DRM, flags);
        if (p)
                memcpy(p, str, len);
        return (p);
}

static inline const char *
kstrdup_const(const char *str, int flags)
{
        return kstrdup(str, flags);
}

void kfree_const(const void *);

static inline int
match_string(const char * const *array,  size_t n, const char *str)
{
        int i;

        for (i = 0; i < n; i++) {
                if (array[i] == NULL)
                        break;
                if (!strcmp(array[i], str))     
                        return i;
        }

        return -EINVAL;
}

static inline ssize_t
strscpy(char *dst, const char *src, size_t dstsize)
{
        ssize_t r;
        r = strlcpy(dst, src, dstsize);
        if (dstsize == 0 || r >= dstsize)
                return -E2BIG;
        return r;
}

static inline ssize_t
strscpy_pad(char *dst, const char *src, size_t dstsize)
{
        memset(dst, 0, dstsize);
        return strscpy(dst, src, dstsize);
}

void *vmemdup_array_user(const void *, size_t, size_t);

#endif