blob: b230149f0bcc01f3c388f6cad92fbafbea6aeb18 [file] [log] [blame]
//
// 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_