root/drivers/firmware/efi/libstub/string.c
// SPDX-License-Identifier: GPL-2.0
/*
 * Taken from:
 *  linux/lib/string.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>

#ifndef EFI_HAVE_STRLEN
/**
 * strlen - Find the length of a string
 * @s: The string to be sized
 */
size_t strlen(const char *s)
{
        const char *sc;

        for (sc = s; *sc != '\0'; ++sc)
                /* nothing */;
        return sc - s;
}
#endif

#ifndef EFI_HAVE_STRNLEN
/**
 * strnlen - Find the length of a length-limited string
 * @s: The string to be sized
 * @count: The maximum number of bytes to search
 */
size_t strnlen(const char *s, size_t count)
{
        const char *sc;

        for (sc = s; count-- && *sc != '\0'; ++sc)
                /* nothing */;
        return sc - s;
}
#endif

/**
 * strstr - Find the first substring in a %NUL terminated string
 * @s1: The string to be searched
 * @s2: The string to search for
 */
char *strstr(const char *s1, const char *s2)
{
        size_t l1, l2;

        l2 = strlen(s2);
        if (!l2)
                return (char *)s1;
        l1 = strlen(s1);
        while (l1 >= l2) {
                l1--;
                if (!memcmp(s1, s2, l2))
                        return (char *)s1;
                s1++;
        }
        return NULL;
}

#ifndef EFI_HAVE_STRCMP
/**
 * strcmp - Compare two strings
 * @cs: One string
 * @ct: Another string
 */
int strcmp(const char *cs, const char *ct)
{
        unsigned char c1, c2;

        while (1) {
                c1 = *cs++;
                c2 = *ct++;
                if (c1 != c2)
                        return c1 < c2 ? -1 : 1;
                if (!c1)
                        break;
        }
        return 0;
}
#endif

/**
 * strncmp - Compare two length-limited strings
 * @cs: One string
 * @ct: Another string
 * @count: The maximum number of bytes to compare
 */
int strncmp(const char *cs, const char *ct, size_t count)
{
        unsigned char c1, c2;

        while (count) {
                c1 = *cs++;
                c2 = *ct++;
                if (c1 != c2)
                        return c1 < c2 ? -1 : 1;
                if (!c1)
                        break;
                count--;
        }
        return 0;
}

/* Works only for digits and letters, but small and fast */
#define TOLOWER(x) ((x) | 0x20)

static unsigned int simple_guess_base(const char *cp)
{
        if (cp[0] == '0') {
                if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
                        return 16;
                else
                        return 8;
        } else {
                return 10;
        }
}

/**
 * simple_strtoull - convert a string to an unsigned long long
 * @cp: The start of the string
 * @endp: A pointer to the end of the parsed string will be placed here
 * @base: The number base to use
 */

unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
{
        unsigned long long result = 0;

        if (!base)
                base = simple_guess_base(cp);

        if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
                cp += 2;

        while (isxdigit(*cp)) {
                unsigned int value;

                value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
                if (value >= base)
                        break;
                result = result * base + value;
                cp++;
        }
        if (endp)
                *endp = (char *)cp;

        return result;
}

long simple_strtol(const char *cp, char **endp, unsigned int base)
{
        if (*cp == '-')
                return -simple_strtoull(cp + 1, endp, base);

        return simple_strtoull(cp, endp, base);
}

#ifdef CONFIG_EFI_PARAMS_FROM_FDT
#ifndef EFI_HAVE_STRRCHR
/**
 * strrchr - Find the last occurrence of a character in a string
 * @s: The string to be searched
 * @c: The character to search for
 */
char *strrchr(const char *s, int c)
{
        const char *last = NULL;
        do {
                if (*s == (char)c)
                        last = s;
        } while (*s++);
        return (char *)last;
}
#endif
#ifndef EFI_HAVE_MEMCHR
/**
 * memchr - Find a character in an area of memory.
 * @s: The memory area
 * @c: The byte to search for
 * @n: The size of the area.
 *
 * returns the address of the first occurrence of @c, or %NULL
 * if @c is not found
 */
void *memchr(const void *s, int c, size_t n)
{
        const unsigned char *p = s;
        while (n-- != 0) {
                if ((unsigned char)c == *p++) {
                        return (void *)(p - 1);
                }
        }
        return NULL;
}
#endif
#endif