wsutil: Add a memrchr implementation

Use the system memrchr if found, otherwise use a very basic
non optimized implementation
This commit is contained in:
John Thacker 2023-10-11 08:43:35 -04:00 committed by AndersBroman
parent 6c424b610d
commit 0cec46bb25
5 changed files with 46 additions and 0 deletions

View File

@ -104,6 +104,7 @@ if(UNIX)
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
check_symbol_exists("memmem" "string.h" HAVE_MEMMEM)
check_symbol_exists("memrchr" "string.h" HAVE_MEMRCHR)
check_symbol_exists("strerrorname_np" "string.h" HAVE_STRERRORNAME_NP)
check_symbol_exists("strptime" "time.h" HAVE_STRPTIME)
check_symbol_exists("vasprintf" "stdio.h" HAVE_VASPRINTF)

View File

@ -280,6 +280,9 @@
/* Define if you have the 'memmem' function. */
#cmakedefine HAVE_MEMMEM 1
/* Define if you have the 'memrchr' function. */
#cmakedefine HAVE_MEMRCHR 1
/* Define if you have the 'strerrorname_np' function. */
#cmakedefine HAVE_STRERRORNAME_NP 1

View File

@ -490,6 +490,7 @@ libwsutil.so.0 libwsutil0 #MINVER#
ws_memmem@Base 3.7.0
ws_mempbrk_compile@Base 1.99.4
ws_mempbrk_exec@Base 1.99.4
ws_memrchr@Base 4.3.0rc0
ws_optarg@Base 3.5.1
ws_opterr@Base 3.5.1
ws_optind@Base 3.5.1

View File

@ -339,6 +339,36 @@ ws_ascii_strcasestr(const char *haystack, const char *needle)
return NULL;
}
/* Return the last occurrence of ch in the n bytes of haystack.
* If not found or n is 0, return NULL. */
const uint8_t *
ws_memrchr(const void *_haystack, int ch, size_t n)
{
#ifdef HAVE_MEMRCHR
return memrchr(_haystack, ch, n);
#else
/* A generic implementation. This could be optimized considerably,
* e.g. by fetching a word at a time.
*/
if (n == 0) {
return NULL;
}
const uint8_t *haystack = _haystack;
const uint8_t *p;
uint8_t c = (uint8_t)ch;
const uint8_t *const end = haystack + n - 1;
for (p = end; p >= haystack; --p) {
if (*p == c) {
return p;
}
}
return NULL;
#endif /* HAVE_MEMRCHR */
}
#define FORMAT_SIZE_UNIT_MASK 0x00ff
#define FORMAT_SIZE_PFX_MASK 0xff00

View File

@ -182,6 +182,17 @@ bool isdigit_string(const unsigned char *str);
WS_DLL_PUBLIC
const char *ws_ascii_strcasestr(const char *haystack, const char *needle);
/** Like the memchr() function, except it scans backwards from the end.
*
* @param haystack Pointer to the bytes of memory to search
* @param ch The character to search
* @param n The length of bytes to search from the end
* @return A pointer to the last occurrence of "ch" in "haystack".
* If "ch" isn't found or "n" is 0, returns NULL.
*/
WS_DLL_PUBLIC
const uint8_t *ws_memrchr(const void *haystack, int ch, size_t n);
WS_DLL_PUBLIC
char *ws_escape_string(wmem_allocator_t *alloc, const char *string, bool add_quotes);