aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--libsimple/mem.h20
-rw-r--r--man0/libsimple.h.07
-rw-r--r--man3/libsimple_memelem.31
-rw-r--r--man3/libsimple_memelemscan.387
-rw-r--r--man3/libsimple_memscan.34
l---------man3/memelemscan.3libsimple1
-rw-r--r--memelem.c3
-rw-r--r--memelemscan.c94
-rw-r--r--memrelem.c3
10 files changed, 216 insertions, 5 deletions
diff --git a/Makefile b/Makefile
index 3428753..5944817 100644
--- a/Makefile
+++ b/Makefile
@@ -67,6 +67,7 @@ OBJ =\
memcasestarts.o\
memdup.o\
memelem.o\
+ memelemscan.o\
memends.o\
memeqlen.o\
memisutf8.o\
diff --git a/libsimple/mem.h b/libsimple/mem.h
index dacc78c..67834bc 100644
--- a/libsimple/mem.h
+++ b/libsimple/mem.h
@@ -269,6 +269,26 @@ void *libsimple_memelem(const void *, size_t, const void *, size_t);
/**
+ * Finds the first element in an array, the comparison is case-sensitive
+ *
+ * @param haystack The array of bytes to search
+ * @param nhaystack The length of `haystack`, divided by `needle`
+ * @param needle The substring to search for
+ * @param nneedle The length of `needle`
+ * @return `haystack` with a minimal offset such that,
+ * `!memcmp(r, needle, nneedle)` where `r` is the
+ * returned pointer and such that `(r - haystack) % nneedle == 0`,
+ * `(void *)&((char *)haystack)[nhaystack * nneedle]`
+ * if no such offset exists
+ */
+_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__)))
+void *libsimple_memelemscan(const void *, size_t, const void *, size_t);
+#ifndef memelemscan
+# define memelemscan libsimple_memelemscan
+#endif
+
+
+/**
* Finds the last element in an array, the comparison is case-sensitive
*
* @param haystack The array of bytes to search
diff --git a/man0/libsimple.h.0 b/man0/libsimple.h.0
index 7cb93dd..d3c018d 100644
--- a/man0/libsimple.h.0
+++ b/man0/libsimple.h.0
@@ -542,6 +542,13 @@ that operate on multibyte units
rather than simple bytes.
.TP
+.BR libsimple_memelemscan (3)
+Version of
+.BR memscan (3)
+that operate on multibyte units
+rather than simple bytes.
+
+.TP
.BR libsimple_memends (3),
.RS 0
.BR libsimple_memcaseends (3)
diff --git a/man3/libsimple_memelem.3 b/man3/libsimple_memelem.3
index 833e246..6eb3c0b 100644
--- a/man3/libsimple_memelem.3
+++ b/man3/libsimple_memelem.3
@@ -79,6 +79,7 @@ None.
.SH BUGS
None.
.SH SEE ALSO
+.BR libsimple_memelemscan (3),
.BR libsimple_memrelem (3),
.BR libsimple_memmem (3),
.BR memchr (3)
diff --git a/man3/libsimple_memelemscan.3 b/man3/libsimple_memelemscan.3
new file mode 100644
index 0000000..de70105
--- /dev/null
+++ b/man3/libsimple_memelemscan.3
@@ -0,0 +1,87 @@
+.TH LIBSIMPLE_MEMELEMSCAN 3 2018-11-17 libsimple
+.SH NAME
+libsimple_memelemscan \- find aligned byte string in memory
+.SH SYNOPSIS
+.nf
+#include <libsimple.h>
+
+void *libsimple_memelemscan(const void *\fIhaystack\fP, size_t \fInhaystack\fP, const void *\fIneedle\fP, size_t \fInneedle\fP);
+
+#ifndef memelemscan
+# define memelemscan libsimple_memelemscan
+#endif
+.fi
+.PP
+Link with
+.IR \-lsimple .
+.SH DESCRIPTION
+The
+.BR libsimple_memelemscan ()
+function scans the memory segment
+.IR haystack ,
+with the size
+.IR nhaystack*nneedle ,
+for the first occurence of the byte string
+.I needle
+with the size
+.IR nneedle ,
+and with an offset equivalent to zero modulo
+.IR nneedle .
+If no such character exist in the memory
+segment, the memory segment's end is returned.
+.PP
+The comparison is case-sensitive.
+.SH RETURN VALUE
+The
+.BR libsimple_memelemscan ()
+function returns the pointer
+.I s
+with a minimal offset such that
+.IR !memcmp(r,needle,nneedle) ,
+where
+.I r
+is the returned pointer, and such that
+the offset is equivalent to zero modulo
+.IR nneedle .
+If no such offset exists,
+.I (void *)&((char *)haystack)[nhaystack*nneedle]
+is returned.
+.SH ERRORS
+The
+.BR libsimple_memelemscan ()
+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_memelemscan ()
+T} Thread safety MT-Safe
+T{
+.BR libsimple_memelemscan ()
+T} Async-signal safety AS-Safe
+T{
+.BR libsimple_memelemscan ()
+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_memelem (3),
+.BR libsimple_memrelem (3),
+.BR libsimple_memmem (3),
+.BR libsimple_memchrscan (3)
diff --git a/man3/libsimple_memscan.3 b/man3/libsimple_memscan.3
index c9db7da..0c5d14a 100644
--- a/man3/libsimple_memscan.3
+++ b/man3/libsimple_memscan.3
@@ -25,6 +25,8 @@ for the first occurence of the byte
.I c
(it is converted to a
.BR char ).
+If no such character exist in the memory
+segment, the memory segment's end is returned.
.PP
The comparison is case-sensitive.
.SH RETURN VALUE
@@ -38,7 +40,7 @@ where
.I r
is the returned pointer.
If no such offset exists,
-.B NULL
+.I &r[n]
is returned.
.SH ERRORS
The
diff --git a/man3/memelemscan.3libsimple b/man3/memelemscan.3libsimple
new file mode 120000
index 0000000..3c612db
--- /dev/null
+++ b/man3/memelemscan.3libsimple
@@ -0,0 +1 @@
+libsimple_memelemscan.3 \ No newline at end of file
diff --git a/memelem.c b/memelem.c
index 43cb298..3881832 100644
--- a/memelem.c
+++ b/memelem.c
@@ -52,7 +52,6 @@ libsimple_memelem(const void *hay_, size_t hayn, const void *sub_, size_t subn)
next:;
}
break;
-
}
}
@@ -70,7 +69,7 @@ main(void)
assert(!strcmpnul(libsimple_memelem("12345634", 0, "", 0), "12345634"));
assert(!strcmpnul(libsimple_memelem("12345634", 8, "3", 1), "345634"));
- assert(!libsimple_memelem("12345634", 8, "x", 1));;
+ assert(!libsimple_memelem("12345634", 8, "x", 1));
assert(!strcmpnul(libsimple_memelem("13456342", 8, "3", 1), "3456342"));
assert(!libsimple_memelem("12345634", 0, "3", 1));
diff --git a/memelemscan.c b/memelemscan.c
new file mode 100644
index 0000000..744989b
--- /dev/null
+++ b/memelemscan.c
@@ -0,0 +1,94 @@
+/* See LICENSE file for copyright and license details. */
+#include "libsimple.h"
+#ifndef TEST
+
+
+void *
+libsimple_memelemscan(const void *hay_, size_t hayn, const void *sub_, size_t subn)
+{
+ if (!subn)
+ return (void *)hay_;
+
+ switch (subn) {
+ case 1:
+ return libsimple_memscan(hay_, *(char *)sub_, hayn);
+ case 2:
+ {
+ uint16_t *hay = (void *)hay_;
+ uint16_t sub = *(uint16_t *)sub_;
+ for (; hayn-- && *hay != sub; hay++);
+ return hay;
+ }
+ case 4:
+ {
+ uint32_t *hay = (void *)hay_;
+ uint32_t sub = *(uint32_t *)sub_;
+ for (; hayn-- && *hay != sub; hay++);
+ return hay;
+ }
+ case 8:
+ {
+ uint64_t *hay = (void *)hay_;
+ uint64_t sub = *(uint64_t *)sub_;
+ for (; hayn-- && *hay != sub; hay++);
+ return hay;
+ }
+ default:
+ {
+ char *hay = (void *)hay_;
+ const char *sub = sub_;
+ size_t i;
+ for (; hayn--; hay += subn) {
+ for (i = 0; i < subn; i++)
+ if (hay[i] != sub[i])
+ goto next;
+ return hay;
+ next:;
+ }
+ return hay;
+ }
+ }
+
+ return NULL;
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void)
+{
+ assert(!strcmpnul(libsimple_memelemscan("12345634", 8, "", 0), "12345634"));
+ assert(!strcmpnul(libsimple_memelemscan("12345634", 0, "", 0), "12345634"));
+
+ assert(!strcmpnul(libsimple_memelemscan("12345634", 8, "3", 1), "345634"));
+ assert(!strcmpnul(libsimple_memelemscan("12345634", 8, "x", 1), ""));
+ assert(!strcmpnul(libsimple_memelemscan("13456342", 8, "3", 1), "3456342"));
+ assert(!strcmpnul(libsimple_memelemscan("12345634", 0, "3", 1), "12345634"));
+
+ assert(!strcmpnul(libsimple_memelemscan("12345634", 4, "34", 2), "345634"));
+ assert(!strcmpnul(libsimple_memelemscan("12345634z", 4, "xx", 2), "z"));
+ assert(!strcmpnul(libsimple_memelemscan("13456342z", 4, "34", 2), "z"));
+ assert(!strcmpnul(libsimple_memelemscan("12345634z", 0, "34", 2), "12345634z"));
+
+ assert(!strcmpnul(libsimple_memelemscan("abcd1234abcd1234", 4, "1234", 4), "1234abcd1234"));
+ assert(!strcmpnul(libsimple_memelemscan("abcd1234abcd1234z", 4, "zzzz", 4), "z"));
+ assert(!strcmpnul(libsimple_memelemscan("cd1234abcd1234abz", 4, "1234", 4), "z"));
+ assert(!strcmpnul(libsimple_memelemscan("abcd1234abcd1234z", 0, "1234", 4), "abcd1234abcd1234z"));
+
+ assert(!strcmpnul(libsimple_memelemscan("abcdefgh12345678abcdefgh12345678", 4, "12345678", 8), "12345678abcdefgh12345678"));
+ assert(!strcmpnul(libsimple_memelemscan("abcdefgh12345678abcdefgh12345678z", 4, "zzzzzzzz", 8), "z"));
+ assert(!strcmpnul(libsimple_memelemscan("efgh12345678abcdefgh12345678abcdz", 4, "12345678", 8), "z"));
+ assert(!strcmpnul(libsimple_memelemscan("abcdefgh12345678abcdefgh12345678z", 0, "12345678", 8),
+ "abcdefgh12345678abcdefgh12345678z"));
+
+ assert(!strcmpnul(libsimple_memelemscan("abc123abc123", 4, "123", 3), "123abc123"));
+ assert(!strcmpnul(libsimple_memelemscan("abc123abc123z", 4, "zzz", 3), "z"));
+ assert(!strcmpnul(libsimple_memelemscan("bc123abc123az", 4, "123", 3), "z"));
+ assert(!strcmpnul(libsimple_memelemscan("abc123abc123z", 0, "123", 3), "abc123abc123z"));
+
+ return 0;
+}
+
+#endif
diff --git a/memrelem.c b/memrelem.c
index b1e69ba..8317e8e 100644
--- a/memrelem.c
+++ b/memrelem.c
@@ -60,7 +60,6 @@ libsimple_memrelem(const void *hay_, size_t hayn, const void *sub_, size_t subn)
next:;
}
break;
-
}
}
@@ -78,7 +77,7 @@ main(void)
assert(!strcmpnul(libsimple_memrelem("12345634", 0, "", 0), "12345634"));
assert(!strcmpnul(libsimple_memrelem("12345634", 8, "3", 1), "34"));
- assert(!libsimple_memrelem("12345634", 8, "x", 1));;
+ assert(!libsimple_memrelem("12345634", 8, "x", 1));
assert(!strcmpnul(libsimple_memrelem("13456342", 8, "3", 1), "342"));
assert(!libsimple_memrelem("12345634", 0, "3", 1));