| // |
| // Copyright (C) 2001 and onwards Google, Inc. |
| // |
| // (Please see comments in strutil.h near the include of <asm/string.h> |
| // if you feel compelled to try to provide more efficient implementations |
| // of these routines.) |
| // |
| // These routines provide mem versions of standard C string routines, |
| // such a strpbrk. They function exactly the same as the str version, |
| // so if you wonder what they are, replace the word "mem" by |
| // "str" and check out the man page. I could return void*, as the |
| // strutil.h mem*() routines tend to do, but I return char* instead |
| // since this is by far the most common way these functions are called. |
| // |
| // The difference between the mem and str versions is the mem version |
| // takes a pointer and a length, rather than a NULL-terminated string. |
| // The memcase* routines defined here assume the locale is "C" |
| // (they use ascii_tolower instead of tolower). |
| // |
| // These routines are based on the BSD library. |
| // |
| // Here's a list of routines from string.h, and their mem analogues. |
| // Functions in lowercase are defined in string.h; those in UPPERCASE |
| // are defined here: |
| // |
| // strlen -- |
| // strcat strncat MEMCAT |
| // strcpy strncpy memcpy |
| // -- memccpy (very cool function, btw) |
| // -- memmove |
| // -- memset |
| // strcmp strncmp memcmp |
| // strcasecmp strncasecmp MEMCASECMP |
| // strchr memchr |
| // strcoll -- |
| // strxfrm -- |
| // strdup strndup MEMDUP |
| // strrchr MEMRCHR |
| // strspn MEMSPN |
| // strcspn MEMCSPN |
| // strpbrk MEMPBRK |
| // strstr MEMSTR MEMMEM |
| // (g)strcasestr MEMCASESTR MEMCASEMEM |
| // strtok -- |
| // strprefix MEMPREFIX (strprefix is from strutil.h) |
| // strcaseprefix MEMCASEPREFIX (strcaseprefix is from strutil.h) |
| // strsuffix MEMSUFFIX (strsuffix is from strutil.h) |
| // strcasesuffix MEMCASESUFFIX (strcasesuffix is from strutil.h) |
| // -- MEMIS |
| // -- MEMCASEIS |
| // strcount MEMCOUNT (strcount is from strutil.h) |
| |
| #ifndef STRINGS_MEMUTIL_H_ |
| #define STRINGS_MEMUTIL_H_ |
| |
| #include <stddef.h> |
| #include <string.h> // to get the POSIX mem*() routines |
| |
| #include "gutil/port.h" // disable some warnings on Windows |
| |
| inline char *memcat(char *dest, size_t destlen, |
| const char *src, size_t srclen) { |
| return reinterpret_cast<char*>(memcpy(dest + destlen, src, srclen)); |
| } |
| |
| int memcasecmp(const char *s1, const char *s2, size_t len); |
| char *memdup(const char *s, size_t slen); |
| char *memrchr(const char *s, int c, size_t slen); |
| size_t memspn(const char *s, size_t slen, const char *accept); |
| size_t memcspn(const char *s, size_t slen, const char *reject); |
| char *mempbrk(const char *s, size_t slen, const char *accept); |
| |
| // This is for internal use only. Don't call this directly |
| template<bool case_sensitive> |
| const char * int_memmatch(const char * phaystack, size_t haylen, |
| const char * pneedle, size_t neelen); |
| |
| // These are the guys you can call directly |
| inline const char * memstr(const char *phaystack, size_t haylen, |
| const char *pneedle) { |
| return int_memmatch<true>(phaystack, haylen, pneedle, strlen(pneedle)); |
| } |
| |
| inline const char * memcasestr(const char *phaystack, size_t haylen, |
| const char *pneedle) { |
| return int_memmatch<false>(phaystack, haylen, pneedle, strlen(pneedle)); |
| } |
| |
| inline const char * memmem(const char *phaystack, size_t haylen, |
| const char *pneedle, size_t needlelen) { |
| return int_memmatch<true>(phaystack, haylen, pneedle, needlelen); |
| } |
| |
| inline const char * memcasemem(const char *phaystack, size_t haylen, |
| const char *pneedle, size_t needlelen) { |
| return int_memmatch<false>(phaystack, haylen, pneedle, needlelen); |
| } |
| |
| // This is significantly faster for case-sensitive matches with very |
| // few possible matches. See unit test for benchmarks. |
| const char *memmatch(const char *phaystack, size_t haylen, |
| const char *pneedle, size_t neelen); |
| |
| // The ""'s catch people who don't pass in a literal for "str" |
| #define strliterallen(str) (sizeof("" str "")-1) |
| |
| // Must use a string literal for prefix. |
| #define memprefix(str, len, prefix) \ |
| ( (((len) >= strliterallen(prefix)) \ |
| && memcmp(str, prefix, strliterallen(prefix)) == 0) \ |
| ? str + strliterallen(prefix) \ |
| : NULL ) |
| |
| #define memcaseprefix(str, len, prefix) \ |
| ( (((len) >= strliterallen(prefix)) \ |
| && memcasecmp(str, prefix, strliterallen(prefix)) == 0) \ |
| ? str + strliterallen(prefix) \ |
| : NULL ) |
| |
| // Must use a string literal for suffix. |
| #define memsuffix(str, len, suffix) \ |
| ( (((len) >= strliterallen(suffix)) \ |
| && memcmp(str + (len) - strliterallen(suffix), suffix, \ |
| strliterallen(suffix)) == 0) \ |
| ? str + (len) - strliterallen(suffix) \ |
| : NULL ) |
| |
| #define memcasesuffix(str, len, suffix) \ |
| ( (((len) >= strliterallen(suffix)) \ |
| && memcasecmp(str + (len) - strliterallen(suffix), suffix, \ |
| strliterallen(suffix)) == 0) \ |
| ? str + (len) - strliterallen(suffix) \ |
| : NULL ) |
| |
| #define memis(str, len, literal) \ |
| ( (((len) == strliterallen(literal)) \ |
| && memcmp(str, literal, strliterallen(literal)) == 0) ) |
| |
| #define memcaseis(str, len, literal) \ |
| ( (((len) == strliterallen(literal)) \ |
| && memcasecmp(str, literal, strliterallen(literal)) == 0) ) |
| |
| |
| inline int memcount(const char* buf, size_t len, char c) { |
| int num = 0; |
| for (int i = 0; i < len; i++) { |
| if (buf[i] == c) |
| num++; |
| } |
| return num; |
| } |
| |
| #endif // STRINGS_MEMUTIL_H_ |