aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2018-10-21 20:12:31 +0200
committerMattias Andrée <maandree@kth.se>2018-10-21 20:12:31 +0200
commit2215a474e340c3f8f58efe35fc96d62693eacef7 (patch)
tree87505305fb28e285b02082f07cdb2760b53ff01d
parentAdd memcasechr (diff)
downloadlibsimple-2215a474e340c3f8f58efe35fc96d62693eacef7.tar.gz
libsimple-2215a474e340c3f8f58efe35fc96d62693eacef7.tar.bz2
libsimple-2215a474e340c3f8f58efe35fc96d62693eacef7.tar.xz
Add memcase{cmp,ends,starts,eq} and mem[r]casemem
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile5
-rw-r--r--libsimple.c12
-rw-r--r--libsimple/mem.h115
-rw-r--r--man/libsimple_memcasecmp.379
-rw-r--r--man/libsimple_memcaseends.381
-rw-r--r--man/libsimple_memcaseeq.375
-rw-r--r--man/libsimple_memcaseeqlen.31
-rw-r--r--man/libsimple_memcasemem.380
-rw-r--r--man/libsimple_memcasestarts.379
-rw-r--r--man/libsimple_memends.31
-rw-r--r--man/libsimple_memeq.33
-rw-r--r--man/libsimple_memeqlen.31
-rw-r--r--man/libsimple_memmem.31
-rw-r--r--man/libsimple_mempcpy.32
-rw-r--r--man/libsimple_mempset.32
-rw-r--r--man/libsimple_memrcasemem.380
-rw-r--r--man/libsimple_memrmem.31
-rw-r--r--man/libsimple_memstarts.31
-rw-r--r--man/libsimple_strcasecmpnul.34
-rw-r--r--memcasecmp.c57
-rw-r--r--memcaseends.c59
-rw-r--r--memcasemem.c58
-rw-r--r--memcasestarts.c58
-rw-r--r--memmem.c3
-rw-r--r--memrcasemem.c61
-rw-r--r--memrmem.c3
26 files changed, 905 insertions, 17 deletions
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
@@ -168,6 +160,24 @@ void *libsimple_memmem(const void *, size_t, const void *, size_t);
/**
+ * 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
*
* @param haystack The array of bytes to search
@@ -186,6 +196,24 @@ void *libsimple_memrmem(const void *, size_t, const void *, size_t);
/**
+ * 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
*
* @param haystack The array of bytes to search
@@ -240,6 +268,22 @@ int libsimple_memstarts(const void *, size_t, const void *, size_t);
/**
+ * 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
*
* @param s The array of bytes to check
@@ -256,6 +300,37 @@ int libsimple_memends(const void *, size_t, const void *, size_t);
/**
+ * 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
*
* @param a One of the arrays of bytes
@@ -272,6 +347,22 @@ static inline int libsimple_memeq(const void *__a, const void *__b, size_t __n)
/**
+ * 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
*
* @param d The array the bytes should be copied into
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 <libsimple.h>
+
+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 <libsimple.h>
+
+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 <libsimple.h>
+
+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 <libsimple.h>
+
+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 <libsimple.h>
+
+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 <libsimple.h>
-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 <libsimple.h>
-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 <libsimple.h>
-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 <libsimple.h>
+
+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;
}