123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- /* string.c - common string routines */
- /*
- * Copyright (c) 2014 Wind River Systems, Inc.
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <string.h>
- #include <stdint.h>
- #include <sys/types.h>
- extern void *memcpy32(void *d, const void *s, size_t n);
- extern void *memset32(void *d, int c, size_t n);
- /**
- *
- * @brief Copy a string
- *
- * @return pointer to destination buffer <d>
- */
- char *strcpy(char *_MLIBC_RESTRICT d, const char *_MLIBC_RESTRICT s)
- {
- char *dest = d;
- while (*s != '\0') {
- *d = *s;
- d++;
- s++;
- }
- *d = '\0';
- return dest;
- }
- /**
- *
- * @brief Copy part of a string
- *
- * @return pointer to destination buffer <d>
- */
- char *strncpy(char *_MLIBC_RESTRICT d, const char *_MLIBC_RESTRICT s, size_t n)
- {
- char *dest = d;
- while ((n > 0) && *s != '\0') {
- *d = *s;
- s++;
- d++;
- n--;
- }
- while (n > 0) {
- *d = '\0';
- d++;
- n--;
- }
- return dest;
- }
- /**
- *
- * @brief String scanning operation
- *
- * @return pointer to 1st instance of found byte, or NULL if not found
- */
- char *strchr(const char *s, int c)
- {
- char tmp = (char) c;
- while ((*s != tmp) && (*s != '\0')) {
- s++;
- }
- return (*s == tmp) ? (char *) s : NULL;
- }
- /**
- *
- * @brief String scanning operation
- *
- * @return pointer to last instance of found byte, or NULL if not found
- */
- char *strrchr(const char *s, int c)
- {
- char *match = NULL;
- do {
- if (*s == (char)c) {
- match = (char *)s;
- }
- } while (*s++);
- return match;
- }
- /**
- *
- * @brief Get string length
- *
- * @return number of bytes in string <s>
- */
- size_t strlen(const char *s)
- {
- size_t n = 0;
- while (*s != '\0') {
- s++;
- n++;
- }
- return n;
- }
- /**
- *
- * @brief Get fixed-size string length
- *
- * @return number of bytes in fixed-size string <s>
- */
- size_t strnlen(const char *s, size_t maxlen)
- {
- size_t n = 0;
- while (*s != '\0' && n < maxlen) {
- s++;
- n++;
- }
- return n;
- }
- /**
- *
- * @brief Compare two strings
- *
- * @return negative # if <s1> < <s2>, 0 if <s1> == <s2>, else positive #
- */
- int strcmp(const char *s1, const char *s2)
- {
- while ((*s1 == *s2) && (*s1 != '\0')) {
- s1++;
- s2++;
- }
- return *s1 - *s2;
- }
- /**
- *
- * @brief Compare part of two strings
- *
- * @return negative # if <s1> < <s2>, 0 if <s1> == <s2>, else positive #
- */
- int strncmp(const char *s1, const char *s2, size_t n)
- {
- while ((n > 0) && (*s1 == *s2) && (*s1 != '\0')) {
- s1++;
- s2++;
- n--;
- }
- return (n == 0) ? 0 : (*s1 - *s2);
- }
- /**
- * @brief Separate `str` by any char in `sep` and return NULL terminated
- * sections. Consecutive `sep` chars in `str` are treated as a single
- * separator.
- *
- * @return pointer to NULL terminated string or NULL on errors.
- */
- char *strtok_r(char *str, const char *sep, char **state)
- {
- char *start, *end;
- start = str ? str : *state;
- /* skip leading delimiters */
- while (*start && strchr(sep, *start)) {
- start++;
- }
- if (*start == '\0') {
- *state = start;
- return NULL;
- }
- /* look for token chars */
- end = start;
- while (*end && !strchr(sep, *end)) {
- end++;
- }
- if (*end != '\0') {
- *end = '\0';
- *state = end + 1;
- } else {
- *state = end;
- }
- return start;
- }
- char *strcat(char *_MLIBC_RESTRICT dest, const char *_MLIBC_RESTRICT src)
- {
- strcpy(dest + strlen(dest), src);
- return dest;
- }
- char *strncat(char *_MLIBC_RESTRICT dest, const char *_MLIBC_RESTRICT src,
- size_t n)
- {
- char *orig_dest = dest;
- size_t len = strlen(dest);
- dest += len;
- while ((n-- > 0) && (*src != '\0')) {
- *dest++ = *src++;
- }
- *dest = '\0';
- return orig_dest;
- }
- /**
- *
- * @brief Compare two memory areas
- *
- * @return negative # if <m1> < <m2>, 0 if <m1> == <m2>, else positive #
- */
- int memcmp(const void *m1, const void *m2, size_t n)
- {
- const char *c1 = m1;
- const char *c2 = m2;
- if (!n) {
- return 0;
- }
- while ((--n > 0) && (*c1 == *c2)) {
- c1++;
- c2++;
- }
- return *c1 - *c2;
- }
- /**
- *
- * @brief Copy bytes in memory with overlapping areas
- *
- * @return pointer to destination buffer <d>
- */
- void *memmove(void *d, const void *s, size_t n)
- {
- char *dest = d;
- const char *src = s;
- if ((size_t) (dest - src) < n) {
- /*
- * The <src> buffer overlaps with the start of the <dest> buffer.
- * Copy backwards to prevent the premature corruption of <src>.
- */
- while (n > 0) {
- n--;
- dest[n] = src[n];
- }
- } else {
- /* It is safe to perform a forward-copy */
- while (n > 0) {
- *dest = *src;
- dest++;
- src++;
- n--;
- }
- }
- return d;
- }
- /**
- *
- * @brief Copy bytes in memory
- *
- * @return pointer to start of destination buffer
- */
- void *memcpy(void *_MLIBC_RESTRICT d, const void *_MLIBC_RESTRICT s, size_t n)
- {
- /* attempt word-sized copying only if buffers have identical alignment */
- unsigned char *d_byte = (unsigned char *)d;
- const unsigned char *s_byte = (const unsigned char *)s;
- #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
- const uintptr_t mask = sizeof(mem_word_t) - 1;
- if ((((uintptr_t)d ^ (uintptr_t)s_byte) & mask) == 0) {
- /* do byte-sized copying until word-aligned or finished */
- while (((uintptr_t)d_byte) & mask) {
- if (n == 0) {
- return d;
- }
- *(d_byte++) = *(s_byte++);
- n--;
- }
- /* do cacheline-sized copying as long as possible */
- if (n >= 32) {
- unsigned int cnt = n / 32;
- unsigned int sz = cnt * 32;
- memcpy32(d_byte, s_byte, cnt);
- d_byte += sz;
- s_byte += sz;
- n -= sz;
- }
- /* do word-sized copying as long as possible */
- mem_word_t *d_word = (mem_word_t *)d_byte;
- const mem_word_t *s_word = (const mem_word_t *)s_byte;
- while (n >= sizeof(mem_word_t)) {
- *(d_word++) = *(s_word++);
- n -= sizeof(mem_word_t);
- }
- d_byte = (unsigned char *)d_word;
- s_byte = (unsigned char *)s_word;
- }
- #endif
- /* do byte-sized copying until finished */
- while (n > 0) {
- *(d_byte++) = *(s_byte++);
- n--;
- }
- return d;
- }
- /**
- *
- * @brief Set bytes in memory
- *
- * @return pointer to start of buffer
- */
- void *memset(void *buf, int c, size_t n)
- {
- /* do byte-sized initialization until word-aligned or finished */
- unsigned char *d_byte = (unsigned char *)buf;
- unsigned char c_byte = (unsigned char)c;
- #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
- while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) {
- if (n == 0) {
- return buf;
- }
- *(d_byte++) = c_byte;
- n--;
- }
- mem_word_t *d_word = (mem_word_t *)d_byte;
- mem_word_t c_word = (mem_word_t)c_byte;
- c_word |= c_word << 8;
- c_word |= c_word << 16;
- #if Z_MEM_WORD_T_WIDTH > 32
- c_word |= c_word << 32;
- #endif
- /* do cacheline-sized initialization as long as possible */
- if (n >= 32) {
- unsigned int cnt = n / 32;
- unsigned int sz = cnt * 32;
- memset32(d_word, c_word, cnt);
- d_word += sz / sizeof(mem_word_t);
- n -= sz;
- }
- /* do word-sized initialization as long as possible */
- while (n >= sizeof(mem_word_t)) {
- *(d_word++) = c_word;
- n -= sizeof(mem_word_t);
- }
- /* do byte-sized initialization until finished */
- d_byte = (unsigned char *)d_word;
- #endif
- while (n > 0) {
- *(d_byte++) = c_byte;
- n--;
- }
- return buf;
- }
- /**
- *
- * @brief Scan byte in memory
- *
- * @return pointer to start of found byte
- */
- void *memchr(const void *s, int c, size_t n)
- {
- if (n != 0) {
- const unsigned char *p = s;
- do {
- if (*p++ == (unsigned char)c) {
- return ((void *)(p - 1));
- }
- } while (--n != 0);
- }
- return NULL;
- }
|