[PATCH 2/2] mem: Add memswap() function

David Gibson <[email protected]>
Newsgroups org.ozlabs.lists.ccan
Message-ID <[email protected]>
Add a memswap() function to the mem module, which exchanges two (equal
sized, non-overlapping) memory regions.

Signed-off-by: David Gibson <[email protected]>
---
 ccan/mem/mem.c      | 21 +++++++++++++++++++++
 ccan/mem/mem.h      | 10 ++++++++++
 ccan/mem/test/api.c | 19 ++++++++++++++++++-
 3 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/ccan/mem/mem.c b/ccan/mem/mem.c
index 853f975..bab1a86 100644
--- a/ccan/mem/mem.c
+++ b/ccan/mem/mem.c
@@ -40,3 +40,24 @@ void *memrchr(const void *s, int c, size_t n)
 	return NULL;
 }
 #endif
+
+#define MEMSWAP_TMP_SIZE	256
+
+void memswap(void *a, void *b, size_t n)
+{
+	char *ap = a;
+	char *bp = b;
+	char tmp[MEMSWAP_TMP_SIZE];
+
+	while (n) {
+		size_t m = n > MEMSWAP_TMP_SIZE ? MEMSWAP_TMP_SIZE : n;
+
+		memcpy(tmp, bp, m);
+		memcpy(bp, ap, m);
+		memcpy(ap, tmp, m);
+
+		ap += m;
+		bp += m;
+		n -= m;
+	}
+}
diff --git a/ccan/mem/mem.h b/ccan/mem/mem.h
index dcb44b8..41120a4 100644
--- a/ccan/mem/mem.h
+++ b/ccan/mem/mem.h
@@ -15,4 +15,14 @@ void *memmem(const void *haystack, size_t haystacklen,
 void *memrchr(const void *s, int c, size_t n);
 #endif
 
+/**
+ * memswap - Exchange two memory regions
+ * @a: first region
+ * @b: second region
+ * @n: length of the regions
+ *
+ * Undefined results if the two memory regions overlap.
+ */
+void memswap(void *a, void *b, size_t n);
+
 #endif /* CCAN_MEM_H */
diff --git a/ccan/mem/test/api.c b/ccan/mem/test/api.c
index d97ab28..8885d48 100644
--- a/ccan/mem/test/api.c
+++ b/ccan/mem/test/api.c
@@ -1,15 +1,22 @@
+#include "config.h"
+
+#include <assert.h>
+
 #include <ccan/mem/mem.h>
 #include <ccan/tap/tap.h>
 
+#define SWAPSIZE	12
+
 int main(void)
 {
 	char haystack1[] = "abcd\0efgh";
 	char haystack2[] = "ab\0ab\0ab\0ab";
 	char needle1[] = "ab";
 	char needle2[] = "d\0e";
+	char tmp1[SWAPSIZE], tmp2[SWAPSIZE];
 
 	/* This is how many tests you plan to run */
-	plan_tests(19);
+	plan_tests(21);
 
 	ok1(memmem(haystack1, sizeof(haystack1), needle1, 2) == haystack1);
 	ok1(memmem(haystack1, sizeof(haystack1), needle1, 3) == NULL);
@@ -36,6 +43,16 @@ int main(void)
 
 	ok1(memrchr(needle1, '\0', 2) == NULL);
 
+	assert(sizeof(haystack1) <= SWAPSIZE);
+	assert(sizeof(haystack2) <= SWAPSIZE);
+	memset(tmp1, 0, sizeof(tmp1));
+	memset(tmp2, 0, sizeof(tmp2));
+	memcpy(tmp1, haystack1, sizeof(haystack1));
+	memcpy(tmp2, haystack2, sizeof(haystack2));
+	memswap(tmp1, tmp2, SWAPSIZE);
+	ok1(memcmp(tmp1, haystack2, sizeof(haystack2)) == 0);
+	ok1(memcmp(tmp2, haystack1, sizeof(haystack1)) == 0);
+
 	/* This exits depending on whether all tests passed */
 	return exit_status();
 }
-- 
2.4.3

_______________________________________________
ccan mailing list
[email protected]
https://lists.ozlabs.org/listinfo/ccan
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.