From 2215a474e340c3f8f58efe35fc96d62693eacef7 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 21 Oct 2018 20:12:31 +0200 Subject: Add memcase{cmp,ends,starts,eq} and mem[r]casemem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 5 ++ libsimple.c | 12 +++++ libsimple/mem.h | 115 +++++++++++++++++++++++++++++++++++++----- man/libsimple_memcasecmp.3 | 79 +++++++++++++++++++++++++++++ man/libsimple_memcaseends.3 | 81 +++++++++++++++++++++++++++++ man/libsimple_memcaseeq.3 | 75 +++++++++++++++++++++++++++ man/libsimple_memcaseeqlen.3 | 1 + man/libsimple_memcasemem.3 | 80 +++++++++++++++++++++++++++++ man/libsimple_memcasestarts.3 | 79 +++++++++++++++++++++++++++++ man/libsimple_memends.3 | 1 + man/libsimple_memeq.3 | 3 +- man/libsimple_memeqlen.3 | 1 + man/libsimple_memmem.3 | 1 + man/libsimple_mempcpy.3 | 2 +- man/libsimple_mempset.3 | 2 +- man/libsimple_memrcasemem.3 | 80 +++++++++++++++++++++++++++++ man/libsimple_memrmem.3 | 1 + man/libsimple_memstarts.3 | 1 + man/libsimple_strcasecmpnul.3 | 4 +- memcasecmp.c | 57 +++++++++++++++++++++ memcaseends.c | 59 ++++++++++++++++++++++ memcasemem.c | 58 +++++++++++++++++++++ memcasestarts.c | 58 +++++++++++++++++++++ memmem.c | 3 ++ memrcasemem.c | 61 ++++++++++++++++++++++ memrmem.c | 3 ++ 26 files changed, 905 insertions(+), 17 deletions(-) create mode 100644 man/libsimple_memcasecmp.3 create mode 100644 man/libsimple_memcaseends.3 create mode 100644 man/libsimple_memcaseeq.3 create mode 100644 man/libsimple_memcasemem.3 create mode 100644 man/libsimple_memcasestarts.3 create mode 100644 man/libsimple_memrcasemem.3 create mode 100644 memcasecmp.c create mode 100644 memcaseends.c create mode 100644 memcasemem.c create mode 100644 memcasestarts.c create mode 100644 memrcasemem.c diff --git a/Makefile b/Makefile index b0834c9..4749ada 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,11 @@ OBJ =\ envreallocn.o\ isutf8.o\ memcasechr.o\ + memcasecmp.o\ + memcaseends.o\ memcaseeqlen.o\ + memcasemem.o\ + memcasestarts.o\ memdup.o\ memelem.o\ memends.o\ @@ -69,6 +73,7 @@ OBJ =\ mempsetelem.o\ memrcasechr.o\ memrcaseeqlen.o\ + memrcasemem.o\ memrchr.o\ memrelem.o\ memreqlen.o\ diff --git a/libsimple.c b/libsimple.c index aecd0a3..4aa2368 100644 --- a/libsimple.c +++ b/libsimple.c @@ -1207,6 +1207,18 @@ main(void) assert(libsimple_memeq("abcxyz", "abcx23", 4)); assert(libsimple_memeq("1", "2", 0)); assert(!libsimple_memeq("1", "2", 1)); + assert(!libsimple_memeq("abc", "ABC", 3)); + assert(!libsimple_memeq("ABC", "abc", 3)); + assert(libsimple_memeq("ABC", "ABC", 3)); + + assert(libsimple_memcaseeq("abcxyz", "abc123", 3)); + assert(!libsimple_memcaseeq("abcxyz", "abc123", 4)); + assert(libsimple_memcaseeq("abcxyz", "abcx23", 4)); + assert(libsimple_memcaseeq("1", "2", 0)); + assert(!libsimple_memcaseeq("1", "2", 1)); + assert(libsimple_memcaseeq("abc", "ABC", 3)); + assert(libsimple_memcaseeq("ABC", "abc", 3)); + assert(libsimple_memcaseeq("ABC", "ABC", 3)); stpcpy(buf, "abc123"); assert(!strcmpnul(libsimple_mempset(buf, '.', 3), "123")); diff --git a/libsimple/mem.h b/libsimple/mem.h index 7ca2f41..7a7f7ce 100644 --- a/libsimple/mem.h +++ b/libsimple/mem.h @@ -1,14 +1,6 @@ /* See LICENSE file for copyright and license details. */ -/* TODO memcasemem */ -/* TODO memrcasemem */ -/* TODO memcasestarts */ -/* TODO memcaseends */ -/* TODO memcasecmp */ -/* TODO memcaseeq */ - - /** * Finds the first occurence of a byte value in an array of bytes, * the comparison is case-insensitive @@ -41,7 +33,7 @@ void *libsimple_memcasechr(const void *, int, size_t); * @return `s` with a miminal offset such that `*r == c`, * where `r` is the returned pointer */ -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __returns_nonnull__, __warn_unused_result__))) void *libsimple_rawmemchr(const void *, int); #ifndef rawmemchr # define rawmemchr libsimple_rawmemchr @@ -62,7 +54,7 @@ void *libsimple_rawmemchr(const void *, int); * @return `s` with a miminal offset such that `tolower(*r) == tolower(c)`, * where `r` is the returned pointer */ -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __returns_nonnull__, __warn_unused_result__))) void *libsimple_rawmemcasechr(const void *, int); #ifndef rawmemcasechr # define rawmemcasechr libsimple_rawmemcasechr @@ -120,7 +112,7 @@ void *libsimple_memrcasechr(const void *, int, size_t); * @return `s` with a maximal offset such that `*r == c`, * where `r` is the returned pointer */ -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __returns_nonnull__, __warn_unused_result__))) void *libsimple_rawmemrchr(const void *, int, size_t); #ifndef rawmemrchr # define rawmemrchr libsimple_rawmemrchr @@ -142,7 +134,7 @@ void *libsimple_rawmemrchr(const void *, int, size_t); * @return `s` with a maximal offset such that `tolower(*r) == tolower(c)`, * where `r` is the returned pointer */ -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __returns_nonnull__, __warn_unused_result__))) void *libsimple_rawmemrcasechr(const void *, int, size_t); #ifndef rawmemrcasechr # define rawmemrcasechr libsimple_rawmemrcasechr @@ -167,6 +159,24 @@ void *libsimple_memmem(const void *, size_t, const void *, size_t); #endif +/** + * Finds the first substring in an array of bytes, the comparison is case-insensitive + * + * @param haystack The array of bytes to search + * @param nhaystack The length of `haystack` + * @param needle The substring to search for + * @param nneedle The length of `needle` + * @return `haystack` with a minimal offset such that, + * `!memcasecmp(r, needle, nneedle)` where `r` is the + * returned pointer, `NULL` if no such offset exists + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +void *libsimple_memcasemem(const void *, size_t, const void *, size_t); +#ifndef memcasemem +# define memcasemem libsimple_memcasemem +#endif + + /** * Finds the last substring in an array of bytes, the comparison is case-sensitive * @@ -185,6 +195,24 @@ void *libsimple_memrmem(const void *, size_t, const void *, size_t); #endif +/** + * Finds the last substring in an array of bytes, the comparison is case-insensitive + * + * @param haystack The array of bytes to search + * @param nhaystack The length of `haystack` + * @param needle The substring to search for + * @param nneedle The length of `needle` + * @return `haystack` with a maximal offset such that, + * `!memcasecmp(r, needle, nneedle)` where `r` is the + * returned pointer, `NULL` if no such offset exists + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +void *libsimple_memrcasemem(const void *, size_t, const void *, size_t); +#ifndef memrcasemem +# define memrcasemem libsimple_memrcasemem +#endif + + /** * Finds the first element in an array, the comparison is case-sensitive * @@ -239,6 +267,22 @@ int libsimple_memstarts(const void *, size_t, const void *, size_t); #endif +/** + * Checks the beginning of an array of bytes, the comparison is case-insensitive + * +ge * @param s The array of bytes to check + * @param n The length of `s` + * @param t The desired beginning of `s` + * @param m The length of `t` + * @return 1 if `s` begins with `t`, 0 otherwise + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +int libsimple_memcasestarts(const void *, size_t, const void *, size_t); +#ifndef memcasestarts +# define memcasestarts libsimple_memcasestarts +#endif + + /** * Checks the end of an array of bytes, the comparison is case-sensitive * @@ -255,6 +299,37 @@ int libsimple_memends(const void *, size_t, const void *, size_t); #endif +/** + * Checks the end of an array of bytes, the comparison is case-insensitive + * + * @param s The array of bytes to check + * @param n The length of `s` + * @param t The desired ending of `s` + * @param m The length of `t` + * @return 1 if `s` ends with `t`, 0 otherwise + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +int libsimple_memcaseends(const void *, size_t, const void *, size_t); +#ifndef memcaseends +# define memcaseends libsimple_memcaseends +#endif + + +/** + * Checks two arrays of bytes for equality, the comparison is case-insensitive + * + * @param a One of the arrays of bytes + * @param b The other arrays of bytes + * @param n The lengths of the arrays + * @return 1 if the arrays are equal, 0 otherwise + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +int libsimple_memcasecmp(const void *__a, const void *__b, size_t __n); +#ifndef memcasecmp +# define memcasecmp libsimple_memcasecmp +#endif + + /** * Checks two arrays of bytes for equality, the comparison is case-sensitive * @@ -271,6 +346,22 @@ static inline int libsimple_memeq(const void *__a, const void *__b, size_t __n) #endif +/** + * Checks two arrays of bytes for equality, the comparison is case-insensitive + * + * @param a One of the arrays of bytes + * @param b The other arrays of bytes + * @param n The lengths of the arrays + * @return 1 if the arrays are equal, 0 otherwise + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_memcaseeq(const void *__a, const void *__b, size_t __n) +{ return !memcasecmp(__a, __b, __n); } +#ifndef memcaseeq +# define memcaseeq libsimple_memcaseeq +#endif + + /** * Copies an array of bytes into another * diff --git a/man/libsimple_memcasecmp.3 b/man/libsimple_memcasecmp.3 new file mode 100644 index 0000000..9f93995 --- /dev/null +++ b/man/libsimple_memcasecmp.3 @@ -0,0 +1,79 @@ +.TH LIBSIMPLE_MEMCASECMP 3 2018-10-21 libsimple +.SH NAME +libsimple_memcasecmp \- compare two memory segments +.SH SYNOPSIS +.nf +#include + +static inline int libsimple_memcasecmp(const void *\fIa\fP, const void *\fIb\fP, size_t \fIn\fP); + +#ifndef memcasecmp +# define memcasecmp libsimple_memcasecmp +#endif +.fi +.PP +Link with +.IR \-lsimple . +.SH DESCRIPTION +The +.BR libsimple_memcasecmp () +function compares the first +.I n +bytes of +.I a +and +.IR b . +.PP +The comparison is case-insensitive and made as +if the strings were converted to lowercase and as +.IR "unsigned char *" s. +.SH RETURN VALUE +The +.BR libsimple_memcasecmp () +function returns a negative value if +.I a +is less than +.IR b , +a positive value if +.I a +is greater than +.IR b , +and 0 otherwise. +.SH ERRORS +The +.BR libsimple_memcasecmp () +function cannot fail. +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lb lb lb +l l l. +Interface Attribute Value +T{ +.BR libsimple_memcasecmp () +T} Thread safety MT-Safe +T{ +.BR libsimple_memcasecmp () +T} Async-signal safety AS-Safe +T{ +.BR libsimple_memcasecmp () +T} Async-cancel safety AC-Safe +.TE +.SH EXAMPLES +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH FUTURE DIRECTIONS +None. +.SH NOTES +None. +.SH BUGS +None. +.SH SEE ALSO +.BR libsimple_memcaseeq (3), +.BR libsimple_memcaseeqlen (3), +.BR memcmp (3) diff --git a/man/libsimple_memcaseends.3 b/man/libsimple_memcaseends.3 new file mode 100644 index 0000000..1cba467 --- /dev/null +++ b/man/libsimple_memcaseends.3 @@ -0,0 +1,81 @@ +.TH LIBSIMPLE_MEMCASEENDS 3 2018-10-21 libsimple +.SH NAME +libsimple_memcaseends \- checks end of memory +.SH SYNOPSIS +.nf +#include + +void *libsimple_memcaseends(const void *\fIs\fP, size_t \fIn\fP, const void *\fIt\fP, size_t \fIm\fP); + +#ifndef memcaseends +# define memcaseends libsimple_memcaseends +#endif +.fi +.PP +Link with +.IR \-lsimple . +.SH DESCRIPTION +The +.BR libsimple_memcaseends () +function checks whether the +.I n +is at least as great as +.I m +and that the +.I m +last bytes of +.IR s , +with the size +.IR n , +is the same as the +.I m +first bytes of +.IR t . +.PP +The comparison is case-insensitive. +.SH RETURN VALUE +The +.BR libsimple_memcaseends () +function returns 1 if +.I s +ends with +.IR t , +otherwise it returns 0. +.SH ERRORS +The +.BR libsimple_memcaseends () +function cannot fail. +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lb lb lb +l l l. +Interface Attribute Value +T{ +.BR libsimple_memcaseends () +T} Thread safety MT-Safe +T{ +.BR libsimple_memcaseends () +T} Async-signal safety AS-Safe +T{ +.BR libsimple_memcaseends () +T} Async-cancel safety AC-Safe +.TE +.SH EXAMPLES +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH FUTURE DIRECTIONS +None. +.SH NOTES +None. +.SH BUGS +None. +.SH SEE ALSO +.BR libsimple_memends (3), +.BR libsimple_memcasestarts (3), +.BR libsimple_memrcasemem (3) diff --git a/man/libsimple_memcaseeq.3 b/man/libsimple_memcaseeq.3 new file mode 100644 index 0000000..314fd63 --- /dev/null +++ b/man/libsimple_memcaseeq.3 @@ -0,0 +1,75 @@ +.TH LIBSIMPLE_MEMCASEEQ 3 2018-10-21 libsimple +.SH NAME +libsimple_memcaseeq \- check two memory segments for equality +.SH SYNOPSIS +.nf +#include + +static inline int libsimple_memcaseeq(const void *\fIa\fP, const void *\fIb\fP, size_t \fIn\fP); + +#ifndef memcaseeq +# define memcaseeq libsimple_memcaseeq +#endif +.fi +.PP +Link with +.IR \-lsimple . +.SH DESCRIPTION +The +.BR libsimple_memcaseeq () +function checks whether the first +.I n +bytes of +.I a +and +.I b +are equal. +.PP +The comparison is case-insensitive. +.SH RETURN VALUE +The +.BR libsimple_memcaseeq () +function returns 1 one if +.I a +and +.I b +are equal, with the possible exception if +their case, otherwise it returns 0. +.SH ERRORS +The +.BR libsimple_memcaseeq () +function cannot fail. +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lb lb lb +l l l. +Interface Attribute Value +T{ +.BR libsimple_memcaseeq () +T} Thread safety MT-Safe +T{ +.BR libsimple_memcaseeq () +T} Async-signal safety AS-Safe +T{ +.BR libsimple_memcaseeq () +T} Async-cancel safety AC-Safe +.TE +.SH EXAMPLES +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH FUTURE DIRECTIONS +None. +.SH NOTES +None. +.SH BUGS +None. +.SH SEE ALSO +.BR libsimple_memeq (3), +.BR libsimple_memcaseeqlen (3), +.BR libsimple_memcasecmp (3) diff --git a/man/libsimple_memcaseeqlen.3 b/man/libsimple_memcaseeqlen.3 index 8cad3ca..410da7d 100644 --- a/man/libsimple_memcaseeqlen.3 +++ b/man/libsimple_memcaseeqlen.3 @@ -71,5 +71,6 @@ None. .SH BUGS None. .SH SEE ALSO +.BR libsimple_memcaseeq (3), .BR libsimple_memeqlen (3), .BR libsimple_memrcaseeqlen (3) diff --git a/man/libsimple_memcasemem.3 b/man/libsimple_memcasemem.3 new file mode 100644 index 0000000..1b22e9b --- /dev/null +++ b/man/libsimple_memcasemem.3 @@ -0,0 +1,80 @@ +.TH LIBSIMPLE_MEMCASEMEM 3 2018-10-21 libsimple +.SH NAME +libsimple_memcasemem \- find byte string in memory +.SH SYNOPSIS +.nf +#include + +void *libsimple_memcasemem(const void *\fIhaystack\fP, size_t \fInhaystack\fP, const void *\fIneedle\fP, size_t \fInneedle\fP); + +#ifndef memcasemem +# define memcasemem libsimple_memcasemem +#endif +.fi +.PP +Link with +.IR \-lsimple . +.SH DESCRIPTION +The +.BR libsimple_memcasemem () +function scans the memory segment +.IR haystack , +with the size +.IR nhaystack , +for the first occurence of the byte string +.I needle +with the size +.IR nneedle . +.PP +The comparison is case-insensitive. +.SH RETURN VALUE +The +.BR libsimple_memcasemem () +function returns the pointer +.I s +with a minimal offset such that +.IR !memcasecmp(r,needle,nneedle) , +where +.I r +is the returned pointer. +If no such offset exists, +.B NULL +is returned. +.SH ERRORS +The +.BR libsimple_memcasemem () +function cannot fail. +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lb lb lb +l l l. +Interface Attribute Value +T{ +.BR libsimple_memcasemem () +T} Thread safety MT-Safe +T{ +.BR libsimple_memcasemem () +T} Async-signal safety AS-Safe +T{ +.BR libsimple_memcasemem () +T} Async-cancel safety AC-Safe +.TE +.SH EXAMPLES +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH FUTURE DIRECTIONS +None. +.SH NOTES +None. +.SH BUGS +None. +.SH SEE ALSO +.BR libsimple_memmem (3), +.BR libsimple_memrcasemem (3), +.BR libsimple_memcasechr (3) diff --git a/man/libsimple_memcasestarts.3 b/man/libsimple_memcasestarts.3 new file mode 100644 index 0000000..b89c0f3 --- /dev/null +++ b/man/libsimple_memcasestarts.3 @@ -0,0 +1,79 @@ +.TH LIBSIMPLE_MEMCASESTARTS 3 2018-10-21 libsimple +.SH NAME +libsimple_memcasestarts \- checks beginning of memory +.SH SYNOPSIS +.nf +#include + +void *libsimple_memcasestarts(const void *\fIs\fP, size_t \fIn\fP, const void *\fIt\fP, size_t \fIm\fP); + +#ifndef memcasestarts +# define memcasestarts libsimple_memcasestarts +#endif +.fi +.PP +Link with +.IR \-lsimple . +.SH DESCRIPTION +The +.BR libsimple_memcasestarts () +function checks whether the +.I n +is at least as great as +.I m +and that the +.I m +first bytes of +.I s +is the same as the +.I m +first bytes of +.IR t . +.PP +The comparison is case-insensitive. +.SH RETURN VALUE +The +.BR libsimple_memcasestarts () +function returns 1 if +.I s +begins with +.IR t , +otherwise it returns 0. +.SH ERRORS +The +.BR libsimple_memcasestarts () +function cannot fail. +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lb lb lb +l l l. +Interface Attribute Value +T{ +.BR libsimple_memcasestarts () +T} Thread safety MT-Safe +T{ +.BR libsimple_memcasestarts () +T} Async-signal safety AS-Safe +T{ +.BR libsimple_memcasestarts () +T} Async-cancel safety AC-Safe +.TE +.SH EXAMPLES +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH FUTURE DIRECTIONS +None. +.SH NOTES +None. +.SH BUGS +None. +.SH SEE ALSO +.BR libsimple_memstarts (3), +.BR libsimple_memcaseends (3), +.BR libsimple_memcasemem (3) diff --git a/man/libsimple_memends.3 b/man/libsimple_memends.3 index 201788e..ab0d9c5 100644 --- a/man/libsimple_memends.3 +++ b/man/libsimple_memends.3 @@ -76,5 +76,6 @@ None. .SH BUGS None. .SH SEE ALSO +.BR libsimple_memcaseends (3), .BR libsimple_memstarts (3), .BR libsimple_memrmem (3) diff --git a/man/libsimple_memeq.3 b/man/libsimple_memeq.3 index 0b9ce1e..d0c2a99 100644 --- a/man/libsimple_memeq.3 +++ b/man/libsimple_memeq.3 @@ -5,7 +5,7 @@ libsimple_memeq \- check two memory segments for equality .nf #include -void *libsimple_memeq(const void *\fIa\fP, const void *\fIb\fP, size_t \fIn\fP); +static inline int libsimple_memeq(const void *\fIa\fP, const void *\fIb\fP, size_t \fIn\fP); #ifndef memeq # define memeq libsimple_memeq @@ -69,5 +69,6 @@ None. .SH BUGS None. .SH SEE ALSO +.BR libsimple_memcaseeq (3), .BR libsimple_memeqlen (3), .BR memcmp (3) diff --git a/man/libsimple_memeqlen.3 b/man/libsimple_memeqlen.3 index 6ef9121..277e382 100644 --- a/man/libsimple_memeqlen.3 +++ b/man/libsimple_memeqlen.3 @@ -71,5 +71,6 @@ None. .SH BUGS None. .SH SEE ALSO +.BR libsimple_memeq (3), .BR libsimple_memcaseeqlen (3), .BR libsimple_memreqlen (3) diff --git a/man/libsimple_memmem.3 b/man/libsimple_memmem.3 index 05f9f37..4c1a628 100644 --- a/man/libsimple_memmem.3 +++ b/man/libsimple_memmem.3 @@ -75,6 +75,7 @@ None. .SH BUGS None. .SH SEE ALSO +.BR libsimple_memrcasemem (3), .BR libsimple_memrmem (3), .BR libsimple_memelem (3), .BR memchr (3) diff --git a/man/libsimple_mempcpy.3 b/man/libsimple_mempcpy.3 index 26531b5..2953e47 100644 --- a/man/libsimple_mempcpy.3 +++ b/man/libsimple_mempcpy.3 @@ -5,7 +5,7 @@ libsimple_mempcpy \- copy an array of bytes into another .nf #include -void *libsimple_mempcpy(void *\fIdest\fP, const void *\fIsrc\fP, size_t \fIn\fP); +static inline void *libsimple_mempcpy(void *\fIdest\fP, const void *\fIsrc\fP, size_t \fIn\fP); #ifndef mempcpy # define mempcpy libsimple_mempcpy diff --git a/man/libsimple_mempset.3 b/man/libsimple_mempset.3 index f75e424..c88257b 100644 --- a/man/libsimple_mempset.3 +++ b/man/libsimple_mempset.3 @@ -5,7 +5,7 @@ libsimple_mempset \- fill an array of bytes .nf #include -void *libsimple_mempset(void *\fIs\fP, int \fIc\fP, size_t \fIn\fP); +static inline void *libsimple_mempset(void *\fIs\fP, int \fIc\fP, size_t \fIn\fP); #ifndef mempset # define mempset libsimple_mempset diff --git a/man/libsimple_memrcasemem.3 b/man/libsimple_memrcasemem.3 new file mode 100644 index 0000000..712cb03 --- /dev/null +++ b/man/libsimple_memrcasemem.3 @@ -0,0 +1,80 @@ +.TH LIBSIMPLE_MEMRCASEMEM 3 2018-10-21 libsimple +.SH NAME +libsimple_memrcasemem \- find byte string in memory +.SH SYNOPSIS +.nf +#include + +void *libsimple_memrcasemem(const void *\fIhaystack\fP, size_t \fInhaystack\fP, const void *\fIneedle\fP, size_t \fInneedle\fP); + +#ifndef memrcasemem +# define memrcasemem libsimple_memrcasemem +#endif +.fi +.PP +Link with +.IR \-lsimple . +.SH DESCRIPTION +The +.BR libsimple_memrcasemem () +function scans the memory segment +.IR haystack , +with the size +.IR nhaystack , +for the last occurence of the byte string +.I needle +with the size +.IR nneedle . +.PP +The comparison is case-insensitive. +.SH RETURN VALUE +The +.BR libsimple_memrcasemem () +function returns the pointer +.I s +with a maximal offset such that +.IR !memcasecmp(r,needle,nneedle) , +where +.I r +is the returned pointer. +If no such offset exists, +.B NULL +is returned. +.SH ERRORS +The +.BR libsimple_memrcasemem () +function cannot fail. +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lb lb lb +l l l. +Interface Attribute Value +T{ +.BR libsimple_memrcasemem () +T} Thread safety MT-Safe +T{ +.BR libsimple_memrcasemem () +T} Async-signal safety AS-Safe +T{ +.BR libsimple_memrcasemem () +T} Async-cancel safety AC-Safe +.TE +.SH EXAMPLES +None. +.SH APPLICATION USAGE +None. +.SH RATIONALE +None. +.SH FUTURE DIRECTIONS +None. +.SH NOTES +None. +.SH BUGS +None. +.SH SEE ALSO +.BR libsimple_memrmem (3), +.BR libsimple_memcasemem (3), +.BR libsimple_memrcasechr (3) diff --git a/man/libsimple_memrmem.3 b/man/libsimple_memrmem.3 index f7d9945..c08d577 100644 --- a/man/libsimple_memrmem.3 +++ b/man/libsimple_memrmem.3 @@ -75,6 +75,7 @@ None. .SH BUGS None. .SH SEE ALSO +.BR libsimple_memcasemem (3), .BR libsimple_memmem (3), .BR libsimple_memrelem (3), .BR libsimple_memrchr (3) diff --git a/man/libsimple_memstarts.3 b/man/libsimple_memstarts.3 index f031837..9cc4cbf 100644 --- a/man/libsimple_memstarts.3 +++ b/man/libsimple_memstarts.3 @@ -74,5 +74,6 @@ None. .SH BUGS None. .SH SEE ALSO +.BR libsimple_memcasestarts (3), .BR libsimple_memends (3), .BR libsimple_memmem (3) diff --git a/man/libsimple_strcasecmpnul.3 b/man/libsimple_strcasecmpnul.3 index e07b551..197cac7 100644 --- a/man/libsimple_strcasecmpnul.3 +++ b/man/libsimple_strcasecmpnul.3 @@ -29,8 +29,8 @@ If one of the strings begins with the other string but is longer, the longer string is treated as greater than the shorter string. .PP -The comparison is case-insensitive and made as if the -strings were converted to lowercase and as +The comparison is case-insensitive and made as +if the strings were converted to lowercase and as .IR "unsigned char *" s. .SH RETURN VALUE The diff --git a/memcasecmp.c b/memcasecmp.c new file mode 100644 index 0000000..efc9b47 --- /dev/null +++ b/memcasecmp.c @@ -0,0 +1,57 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +int +libsimple_memcasecmp(const void *a_, const void *b_, size_t n) +{ + char *a = *(char **)(void *)&a_; + char *b = *(char **)(void *)&b_; + size_t i = 0; + for (; i < n && tolower(a[i]) == tolower(b[i]); i++); + if (i == n) + return 0; + return (tolower(a[i]) & 255) - (tolower(b[i]) & 255); +} + + +#else +#include "test.h" + +int +main(void) +{ + assert(libsimple_memcasecmp("x", "y", 0) == 0); + assert(libsimple_memcasecmp("x", "x", 1) == 0); + assert(libsimple_memcasecmp("x", "y", 1) < 0); + assert(libsimple_memcasecmp("y", "x", 1) > 0); + assert(libsimple_memcasecmp("x", "X", 1) == 0); + assert(libsimple_memcasecmp("x", "Y", 1) < 0); + assert(libsimple_memcasecmp("y", "X", 1) > 0); + assert(libsimple_memcasecmp("X", "x", 1) == 0); + assert(libsimple_memcasecmp("X", "y", 1) < 0); + assert(libsimple_memcasecmp("Y", "x", 1) > 0); + assert(libsimple_memcasecmp("X", "X", 1) == 0); + assert(libsimple_memcasecmp("X", "Y", 1) < 0); + assert(libsimple_memcasecmp("Y", "X", 1) > 0); + assert(libsimple_memcasecmp("\x00", "\xFF", 1) < 0); + assert(libsimple_memcasecmp("\xFF", "\x00", 1) > 0); + assert(libsimple_memcasecmp("\x00", "\x00", 1) == 0); + assert(libsimple_memcasecmp("\xFF", "\xFF", 1) == 0); + assert(libsimple_memcasecmp("abc", "abc", 3) == 0); + assert(libsimple_memcasecmp("abc", "abd", 3) < 0); + assert(libsimple_memcasecmp("abd", "abc", 3) > 0); + assert(libsimple_memcasecmp("abc", "ABC", 3) == 0); + assert(libsimple_memcasecmp("abc", "ABD", 3) < 0); + assert(libsimple_memcasecmp("abd", "ABC", 3) > 0); + assert(libsimple_memcasecmp("ABC", "abc", 3) == 0); + assert(libsimple_memcasecmp("ABC", "abd", 3) < 0); + assert(libsimple_memcasecmp("ABD", "abc", 3) > 0); + assert(libsimple_memcasecmp("ABC", "ABC", 3) == 0); + assert(libsimple_memcasecmp("ABC", "ABD", 3) < 0); + assert(libsimple_memcasecmp("ABD", "ABC", 3) > 0); + return 0; +} + +#endif diff --git a/memcaseends.c b/memcaseends.c new file mode 100644 index 0000000..0a673f7 --- /dev/null +++ b/memcaseends.c @@ -0,0 +1,59 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +int +libsimple_memcaseends(const void *s_, size_t n, const void *t_, size_t m) +{ + const char *s = s_, *t = t_; + if (n < m) + return 0; + while (n--, m--) + if (tolower(s[n]) != tolower(t[m])) + return 0; + return 1; +} + + +#else +#include "test.h" + +int +main(void) +{ + assert(libsimple_memcaseends("", 0, "", 0) == 1); + assert(libsimple_memcaseends("test", 4, "", 0) == 1); + assert(libsimple_memcaseends("", 0, "test", 4) == 0); + assert(libsimple_memcaseends("test", 4, "test", 4) == 1); + assert(libsimple_memcaseends("test", 4, "test", 5) == 0); + assert(libsimple_memcaseends("test", 4, "testx", 5) == 0); + assert(libsimple_memcaseends("test", 4, "est", 3) == 1); + assert(libsimple_memcaseends("test", 4, "st", 2) == 1); + assert(libsimple_memcaseends("test", 4, "t", 1) == 1); + assert(libsimple_memcaseends("test", 4, "x", 1) == 0); + assert(libsimple_memcaseends("test", 4, "xx", 2) == 0); + + assert(libsimple_memcaseends("TEST", 4, "", 0) == 1); + assert(libsimple_memcaseends("TEST", 4, "test", 4) == 1); + assert(libsimple_memcaseends("TEST", 4, "test", 5) == 0); + assert(libsimple_memcaseends("TEST", 4, "testx", 5) == 0); + assert(libsimple_memcaseends("TEST", 4, "est", 3) == 1); + assert(libsimple_memcaseends("TEST", 4, "st", 2) == 1); + assert(libsimple_memcaseends("TEST", 4, "t", 1) == 1); + assert(libsimple_memcaseends("TEST", 4, "x", 1) == 0); + assert(libsimple_memcaseends("TEST", 4, "xx", 2) == 0); + + assert(libsimple_memcaseends("", 0, "TEST", 4) == 0); + assert(libsimple_memcaseends("test", 4, "TEST", 4) == 1); + assert(libsimple_memcaseends("test", 4, "TEST", 5) == 0); + assert(libsimple_memcaseends("test", 4, "TESTX", 5) == 0); + assert(libsimple_memcaseends("test", 4, "EST", 3) == 1); + assert(libsimple_memcaseends("test", 4, "ST", 2) == 1); + assert(libsimple_memcaseends("test", 4, "T", 1) == 1); + assert(libsimple_memcaseends("test", 4, "X", 1) == 0); + assert(libsimple_memcaseends("test", 4, "XX", 2) == 0); + return 0; +} + +#endif diff --git a/memcasemem.c b/memcasemem.c new file mode 100644 index 0000000..244042b --- /dev/null +++ b/memcasemem.c @@ -0,0 +1,58 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void * +libsimple_memcasemem(const void *hay_, size_t hayn, const void *sub_, size_t subn) +{ + char *hay = (void *)hay_, *end; + const char *sub = sub_; + + if (!subn) + return hay; + if (hayn < subn) + return NULL; + if (subn == 1) + return libsimple_memcasechr(hay, *sub, hayn); + + for (end = &hay[hayn - subn + 1]; hay != end; hay++) + if (tolower(*hay) == tolower(*sub) && !libsimple_memcasecmp(hay, sub, subn)) + return hay; + + return NULL; +} + + +#else +#include "test.h" + +int +main(void) +{ + assert(!strcmpnul(libsimple_memcasemem("test", 4, "test", 4), "test")); + assert(!strcmpnul(libsimple_memcasemem("", 0, "", 0), "")); + assert(!strcmpnul(libsimple_memcasemem("test", 4, "", 0), "test")); + assert(!libsimple_memcasemem("", 0, "test", 4)); + assert(!libsimple_memcasemem("t", 1, "test", 4)); + assert(!strcmpnul(libsimple_memcasemem("test", 4, "t", 1), "test")); + assert(!strcmpnul(libsimple_memcasemem("test", 4, "e", 1), "est")); + assert(!strcmpnul(libsimple_memcasemem("test", 4, "s", 1), "st")); + assert(!libsimple_memcasemem("test", 4, "x", 1)); + assert(!strcmpnul(libsimple_memcasemem("test", 4, "te", 2), "test")); + assert(!strcmpnul(libsimple_memcasemem("test", 4, "es", 2), "est")); + assert(!strcmpnul(libsimple_memcasemem("test", 4, "st", 2), "st")); + assert(!strcmpnul(libsimple_memcasemem("test", 5, "t", 2), "t")); + assert(!libsimple_memcasemem("test", 4, "xx", 2)); + assert(!strcmpnul(libsimple_memcasemem("abc", 3, "c", 1), "c")); + assert(!strcmpnul(libsimple_memcasemem("abc", 3, "bc", 2), "bc")); + assert(!strcmpnul(libsimple_memcasemem("abc", 3, "abc", 3), "abc")); + assert(!libsimple_memcasemem("abc", 3, "abc", 4)); + assert(!strcmpnul(libsimple_memcasemem("abcabc", 6, "bc", 2), "bcabc")); + assert(!strcmpnul(libsimple_memcasemem("abcabc", 6, "BC", 2), "bcabc")); + assert(!strcmpnul(libsimple_memcasemem("ABCABC", 6, "bc", 2), "BCABC")); + assert(!strcmpnul(libsimple_memcasemem("ABCABC", 6, "BC", 2), "BCABC")); + return 0; +} + +#endif diff --git a/memcasestarts.c b/memcasestarts.c new file mode 100644 index 0000000..f9c30ee --- /dev/null +++ b/memcasestarts.c @@ -0,0 +1,58 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +int +libsimple_memcasestarts(const void *s_, size_t n, const void *t_, size_t m) +{ + const char *s = s_, *t = t_; + size_t i = 0; + if (n < m) + return 0; + while (i < m && tolower(s[i]) == tolower(t[i])) i++; + return i == m; +} + + +#else +#include "test.h" + +int +main(void) +{ + assert(libsimple_memcasestarts("", 0, "", 0) == 1); + assert(libsimple_memcasestarts("test", 4, "", 0) == 1); + assert(libsimple_memcasestarts("", 0, "test", 4) == 0); + assert(libsimple_memcasestarts("test", 4, "test", 4) == 1); + assert(libsimple_memcasestarts("test", 4, "test", 5) == 0); + assert(libsimple_memcasestarts("test", 4, "testx", 5) == 0); + assert(libsimple_memcasestarts("test", 4, "tes", 3) == 1); + assert(libsimple_memcasestarts("test", 4, "te", 2) == 1); + assert(libsimple_memcasestarts("test", 4, "t", 1) == 1); + assert(libsimple_memcasestarts("test", 4, "x", 1) == 0); + assert(libsimple_memcasestarts("test", 4, "xx", 2) == 0); + + assert(libsimple_memcasestarts("TEST", 4, "", 0) == 1); + assert(libsimple_memcasestarts("TEST", 4, "test", 4) == 1); + assert(libsimple_memcasestarts("TEST", 4, "test", 5) == 0); + assert(libsimple_memcasestarts("TEST", 4, "testx", 5) == 0); + assert(libsimple_memcasestarts("TEST", 4, "tes", 3) == 1); + assert(libsimple_memcasestarts("TEST", 4, "te", 2) == 1); + assert(libsimple_memcasestarts("TEST", 4, "t", 1) == 1); + assert(libsimple_memcasestarts("TEST", 4, "x", 1) == 0); + assert(libsimple_memcasestarts("TEST", 4, "xx", 2) == 0); + + assert(libsimple_memcasestarts("", 0, "TEST", 4) == 0); + assert(libsimple_memcasestarts("test", 4, "TEST", 4) == 1); + assert(libsimple_memcasestarts("test", 4, "TEST", 5) == 0); + assert(libsimple_memcasestarts("test", 4, "TESTX", 5) == 0); + assert(libsimple_memcasestarts("test", 4, "TES", 3) == 1); + assert(libsimple_memcasestarts("test", 4, "TE", 2) == 1); + assert(libsimple_memcasestarts("test", 4, "T", 1) == 1); + assert(libsimple_memcasestarts("test", 4, "X", 1) == 0); + assert(libsimple_memcasestarts("test", 4, "XX", 2) == 0); + return 0; +} + +#endif diff --git a/memmem.c b/memmem.c index dda13c8..2cee286 100644 --- a/memmem.c +++ b/memmem.c @@ -49,6 +49,9 @@ main(void) assert(!strcmpnul(libsimple_memmem("abc", 3, "abc", 3), "abc")); assert(!libsimple_memmem("abc", 3, "abc", 4)); assert(!strcmpnul(libsimple_memmem("abcabc", 6, "bc", 2), "bcabc")); + assert(!strcmpnul(libsimple_memmem("ABCABC", 6, "BC", 2), "BCABC")); + assert(!libsimple_memmem("ABCDEF", 6, "bc", 2)); + assert(!libsimple_memmem("abcdef", 6, "BC", 2)); return 0; } diff --git a/memrcasemem.c b/memrcasemem.c new file mode 100644 index 0000000..e7672f9 --- /dev/null +++ b/memrcasemem.c @@ -0,0 +1,61 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void * +libsimple_memrcasemem(const void *hay_, size_t hayn, const void *sub_, size_t subn) +{ + char *hay = (void *)hay_, *start; + const char *sub = sub_; + + if (!subn) + return &hay[hayn]; + if (hayn < subn) + return NULL; + if (subn == 1) + return libsimple_memrcasechr(hay, *sub, hayn); + + start = hay; + hay = &hay[hayn - subn]; + do { + if (tolower(*hay) == tolower(*sub) && !libsimple_memcasecmp(hay, sub, subn)) + return hay; + } while (hay-- != start); + + return NULL; +} + + +#else +#include "test.h" + +int +main(void) +{ + assert(!strcmpnul(libsimple_memrcasemem("test", 4, "test", 4), "test")); + assert(!strcmpnul(libsimple_memrcasemem("", 0, "", 0), "")); + assert(!strcmpnul(libsimple_memrcasemem("test", 4, "", 0), "")); + assert(!libsimple_memrcasemem("", 0, "test", 4)); + assert(!libsimple_memrcasemem("t", 1, "test", 4)); + assert(!strcmpnul(libsimple_memrcasemem("test", 4, "t", 1), "t")); + assert(!strcmpnul(libsimple_memrcasemem("test", 4, "e", 1), "est")); + assert(!strcmpnul(libsimple_memrcasemem("test", 4, "s", 1), "st")); + assert(!libsimple_memrcasemem("test", 4, "x", 1)); + assert(!strcmpnul(libsimple_memrcasemem("test", 4, "te", 2), "test")); + assert(!strcmpnul(libsimple_memrcasemem("test", 4, "es", 2), "est")); + assert(!strcmpnul(libsimple_memrcasemem("test", 4, "st", 2), "st")); + assert(!strcmpnul(libsimple_memrcasemem("test", 5, "t", 2), "t")); + assert(!libsimple_memrcasemem("test", 4, "xx", 2)); + assert(!strcmpnul(libsimple_memrcasemem("abc", 3, "c", 1), "c")); + assert(!strcmpnul(libsimple_memrcasemem("abc", 3, "bc", 2), "bc")); + assert(!strcmpnul(libsimple_memrcasemem("abc", 3, "abc", 3), "abc")); + assert(!libsimple_memrcasemem("abc", 3, "abc", 4)); + assert(!strcmpnul(libsimple_memrcasemem("abcabc", 6, "bc", 2), "bc")); + assert(!strcmpnul(libsimple_memrcasemem("abcabc", 6, "BC", 2), "bc")); + assert(!strcmpnul(libsimple_memrcasemem("ABCABC", 6, "bc", 2), "BC")); + assert(!strcmpnul(libsimple_memrcasemem("ABCABC", 6, "BC", 2), "BC")); + return 0; +} + +#endif diff --git a/memrmem.c b/memrmem.c index 92521bd..3968e73 100644 --- a/memrmem.c +++ b/memrmem.c @@ -52,6 +52,9 @@ main(void) assert(!strcmpnul(libsimple_memrmem("abc", 3, "abc", 3), "abc")); assert(!libsimple_memrmem("abc", 3, "abc", 4)); assert(!strcmpnul(libsimple_memrmem("abcabc", 6, "bc", 2), "bc")); + assert(!strcmpnul(libsimple_memrmem("ABCABC", 6, "BC", 2), "BC")); + assert(!libsimple_memrmem("ABCDEF", 6, "bc", 2)); + assert(!libsimple_memrmem("abcdef", 6, "BC", 2)); return 0; } -- cgit v1.2.3-70-g09d2