mem: extend with a few additional helpers similar to existing string-only functions
v4 cover mem: extend with a few additional helpers similar to existing string-only functions
since v3:
- fix memeq() return value
- add memends_str() helper
since v2:
- switch all the macros to static inline to avoid multiple evaluations of args
- add patch adding PURE_FUNCTION attributes
since v1:
- drop a patch that David pulled in
- add extra macro parens
- add blank lines after defintions
- covert memcchr's while loop to a for.
- change examples for mempbrkm and mempbrk to use '\0' in places
- fix spelling
- use memeq() even where we know the mem lengths are equal in memstarts()
- add a reviewed-by to the 2nd patch, no other changes to that patch.
--
This is essentially a rebased version of a patch I sent out quite some time ago.
At the time, David indicated that it would probably make sense for bytestring to call the plain mem-versions of these functions, so I've included a helper to do that as well (and 1 patch to help ccanlint for bytestring pass a bit better).
The selection of mem* functions is entirely based on which ones I need for some code I was writing, and they are in no way complete (notably, they include mem variants of strpbrk instead of strspn variants as used in bytestring). I expect the missing functions can be added as people find a need for them.
Cody P Schafer (4):
mem: add mem helper functions
bytestring: use newly added mem helpers
mem: mark all functions as PURE
mem: add memends_str() helper for symmetry
ccan/bytestring/bytestring.h | 9 +-- ccan/mem/_info | 1 + ccan/mem/mem.c | 24 ++++++ ccan/mem/mem.h | 185 +++++++++++++++++++++++++++++++++++++++++++ ccan/mem/test/api.c | 41 +++++++++- 5 files changed, 253 insertions(+), 7 deletions(-)
Signature · 6 lines
2.5.1 _______________________________________________ ccan mailing list [email protected] https://lists.ozlabs.org/listinfo/ccan
PATCH v4 1/4 mem: add mem helper functions
--- ccan/mem/mem.c | 24 ++++++++ ccan/mem/mem.h | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ccan/mem/test/api.c | 37 ++++++++++++- 3 files changed, 217 insertions(+), 1 deletion(-)
ccan/mem/mem.c +24 -0
@@ -40,3 +40,27 @@ void *memrchr(const void *s, int c, size_t n)return NULL ; }#endif + +void *mempbrkm (const void *data_,size_t len,const void *accept_,size_t accept_len) +{ +const char *data = data_, *accept = accept_; +size_t i, j; + +for (i =0 ; i < len; i++) +for (j =0 ; j < accept_len; j++) +if (accept[j] == data[i]) +return (void *)&data[i]; +return NULL ; +} + +void *memcchr (void const *data,int c,size_t data_len) +{ +char const *p = data; +size_t i; + +for (i =0 ; i < data_len; i++) +if (p[i] != c) +return (void *)&p[i]; + +return NULL ; +}
ccan/mem/mem.h +157 -0
167 lines not on this page · raw message
ccan/mem/test/api.c +36 -1
@@ -8,9 +8,11 @@ int main(void)char haystack2[] ="ab\0ab\0ab\0ab" ;char needle1[] ="ab" ;char needle2[] ="d\0e" ; +char scan1[] ="aaaab" ; +char scan2[] ="\0\0\0b" ;/* This is how many tests you plan to run */ -plan_tests (19 ); +plan_tests (42 );ok1 (memmem (haystack1,sizeof (haystack1), needle1,2 ) == haystack1);ok1 (memmem (haystack1,sizeof (haystack1), needle1,3 ) ==NULL );
@@ -37,6 +39,39 @@ int main(void)ok1 (memrchr (needle1,'\0' ,2 ) ==NULL ); +#define S (x) (x), sizeof(x) - 1 +ok1 (mempbrkm (S (haystack1),S ("\0efgh" )) == haystack1 +4 ); +ok1 (mempbrkm (S (haystack1),S ("jklmn" )) ==NULL ); +ok1 (mempbrkm (S (haystack1),S ("sd\0a" )) == haystack1 +0 ); + +ok1 (mempbrk (haystack1,sizeof (haystack1),"bcd\0a" ) == haystack1 +1 ); +ok1 (mempbrk (haystack1,sizeof (haystack1),"\0" ) ==NULL ); + +ok1 (memcchr (scan1,'a' ,sizeof (scan1)) == scan1 +4 ); +ok1 (memcchr (scan1,'b' ,sizeof (scan1)) == scan1); +ok1 (memcchr (scan2,'\0' ,sizeof (scan2)) == scan2 +3 ); +ok1 (memcchr (scan2,'\0' ,sizeof (scan2) -2 ) ==NULL ); + +ok1 (memeq (haystack1,sizeof (haystack1), haystack1,sizeof (haystack1))); +ok1 (!memeq (haystack1,sizeof (haystack1), haystack2,sizeof (haystack2))); + +ok1 (memeqstr (scan1,sizeof (scan1) -1 , scan1)); +ok1 (!memeqstr (scan1,sizeof (scan1), scan1)); +ok1 (!memeqstr (scan1,sizeof (scan1),"aaaa" )); + +ok1 (memstarts (S ("a\0bcdef" ),S ("a\0bc" ))); +ok1 (!memstarts (S ("a\0bcdef" ),S ("a\0bcG" ))); +ok1 (!memstarts (S ("a\0bcdef" ),S ("a\0bcdefg" ))); + +ok1 (memstarts_str (scan1,sizeof (scan1), scan1)); +ok1 (!memstarts_str (scan1,sizeof (scan1),"ab" )); + +ok1 (memends (S ("abcdef" ),S ("abcdef" ))); +ok1 (!memends (S ("abcdef" ),S ("abcdefg" ))); +ok1 (!memends (S ("a\0bcdef" ),S ("a\0b" ))); +ok1 (memends (S ("a\0bcdef" ),S ("ef" ))); + +/* This exits depending on whether all tests passed */ return exit_status (); }
Signature · 6 lines
2.5.1 _______________________________________________ ccan mailing list [email protected] https://lists.ozlabs.org/listinfo/ccan
PATCH v4 2/4 bytestring: use newly added mem helpers
In reply to Cody P Schafer--- ccan/bytestring/bytestring.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
ccan/bytestring/bytestring.h +3 -6
@@ -94,8 +94,7 @@ static inline struct bytestring bytestring_from_string(const char *s)*/ static inline bool bytestring_eq (struct bytestring a,struct bytestring b) { -return (a.len == b.len) - && (memcmp (a.ptr, b.ptr, a.len) ==0 ); +return memeq (a.ptr, a.len, b.ptr, b.len); }/**
@@ -149,8 +148,7 @@ static inline struct bytestring bytestring_slice(struct bytestring s,static inline bool bytestring_starts (struct bytestring s,struct bytestring prefix) { -return (s.len >= prefix.len) && (memcmp (s.ptr, - prefix.ptr, prefix.len) ==0 ); +return memstarts (s.ptr, s.len, prefix.ptr, prefix.len); }/**
@@ -163,8 +161,7 @@ static inline bool bytestring_starts(struct bytestring s,static inline bool bytestring_ends (struct bytestring s,struct bytestring suffix) { -return (s.len >= suffix.len) && (memcmp (s.ptr + s.len - suffix.len, - suffix.ptr, suffix.len) ==0 ); +return memends (s.ptr, s.len, suffix.ptr, suffix.len); }/**
Signature · 6 lines
2.5.1 _______________________________________________ ccan mailing list [email protected] https://lists.ozlabs.org/listinfo/ccan
PATCH v4 3/4 mem: mark all functions as PURE
In reply to Cody P SchaferThis might allow compilers that support the anotation to make better choices when optimizing, and all these functions meet the requirements for being marked pure.
--- ccan/mem/_info | 1 + ccan/mem/mem.h | 11 +++++++++++ 2 files changed, 12 insertions(+)
ccan/mem/_info +1 -0
@@ -18,6 +18,7 @@ int main(int argc, char *argv[]) return 1; if (strcmp(argv[1], "depends") == 0) { + printf("ccan/compiler"); return 0; }
ccan/mem/mem.h +11 -0
@@ -3,16 +3,19 @@#define CCAN_MEM_H #include "config.h" +#include <ccan/compiler/compiler.h> #include <string.h> #include <stdbool.h> #if !HAVE_MEMMEM +PURE_FUNCTION void *memmem(const void *haystack, size_t haystacklen,const void *needle,size_t needlelen);#endif #if !HAVE_MEMRCHR +PURE_FUNCTION void *memrchr(const void *s, int c, size_t n);#endif
@@ -37,6 +40,7 @@ void *memrchr(const void *s, int c, size_t n);* } * */ +PURE_FUNCTION void *mempbrkm(const void *data, size_t len, const void *accept, size_t accept_len);/**
@@ -57,6 +61,7 @@ void *mempbrkm(const void *data, size_t len, const void *accept, size_t accept_l* printf("Nada\n"); * } */ +PURE_FUNCTION static inline char *mempbrk(const void *data, size_t len, const char *accept) {return mempbrkm (data, len, accept,strlen (accept));
@@ -81,6 +86,7 @@ static inline char *mempbrk(const void *data, size_t len, const char *accept)* printf("Found %c after trimming spaces\n", *r); * } */ +PURE_FUNCTION void *memcchr(void const *data, int c, size_t data_len);/**
@@ -95,6 +101,7 @@ void *memcchr(void const *data, int c, size_t data_len);* printf("memory blocks are the same!\n"); * } */ +PURE_FUNCTION static inline bool memeq(const void *a, size_t al, const void *b, size_t bl) {return al == bl && !memcmp (a, b, bl);
@@ -114,6 +121,7 @@ static inline bool memeq(const void *a, size_t al, const void *b, size_t bl)* printf("somebytes starts with otherbytes!\n"); * } */ +PURE_FUNCTION static inline bool memstarts(void const *data, size_t data_len,void const *prefix,size_t prefix_len) {
@@ -135,6 +143,7 @@ static inline bool memstarts(void const *data, size_t data_len,* printf("somebytes == 'foo'!\n"); * } */ +PURE_FUNCTION static inline bool memeqstr(const void *data, size_t length, const char *string) {return memeq (data, length, string,strlen (string));
@@ -151,6 +160,7 @@ static inline bool memeqstr(const void *data, size_t length, const char *string)* printf("somebytes starts with 'It'\n"); * } */ +PURE_FUNCTION static inline bool memstarts_str(const void *a, size_t al, const char *s) {return memstarts (a, al, s,strlen (s));
@@ -166,6 +176,7 @@ static inline bool memstarts_str(const void *a, size_t al, const char *s)* Returns true if @suffix appears as a substring at the end of @s, * false otherwise. */ +PURE_FUNCTION static inline bool memends(const void *s, size_t s_len, const void *suffix, size_t suffix_len) { return (s_len >= suffix_len) && (memcmp((const char *)s + s_len - suffix_len,
Signature · 6 lines
2.5.1 _______________________________________________ ccan mailing list [email protected] https://lists.ozlabs.org/listinfo/ccan
PATCH v4 4/4 mem: add memends_str() helper for symmetry
In reply to Cody P Schafer--- ccan/mem/mem.h | 17 +++++++++++++++++ ccan/mem/test/api.c | 6 +++++- 2 files changed, 22 insertions(+), 1 deletion(-)
ccan/mem/mem.h +17 -0
@@ -183,4 +183,21 @@ static inline bool memends(const void *s, size_t s_len, const void *suffix, size suffix, suffix_len) == 0); } +/** +* memends_str - Does this byte array end with a string suffix? +* @a: byte array +* @al: length in bytes +* @s: string suffix +* +* Example: +* if (memends_str(somebytes, bytes_len, "It")) { +* printf("somebytes ends with with 'It'\n"); +* } +*/ +PURE_FUNCTION +static inline bool memends_str(const void *a, size_t al, const char *s) +{ +return memends (a, al, s,strlen (s)); +} +#endif /* CCAN_MEM_H */
ccan/mem/test/api.c +5 -1
@@ -12,7 +12,7 @@ int main(void)char scan2[] ="\0\0\0b" ;/* This is how many tests you plan to run */ -plan_tests (42 ); +plan_tests (46 );ok1 (memmem (haystack1,sizeof (haystack1), needle1,2 ) == haystack1);ok1 (memmem (haystack1,sizeof (haystack1), needle1,3 ) ==NULL );
@@ -71,6 +71,10 @@ int main(void)ok1 (!memends (S ("a\0bcdef" ),S ("a\0b" )));ok1 (memends (S ("a\0bcdef" ),S ("ef" ))); +ok1 (memends_str (S ("abcdef" ),"abcdef" )); +ok1 (!memends_str (S ("abcde\0f" ),"d\0f" )); +ok1 (!memends_str (S ("a\0bcdef" ),"a" )); +ok1 (memends_str (S ("a\0bcdef" ),"ef" ));/* This exits depending on whether all tests passed */ return exit_status ();
Signature · 6 lines
2.5.1 _______________________________________________ ccan mailing list [email protected] https://lists.ozlabs.org/listinfo/ccan
Quoted 12 lines · Cody P Schafer
since v3:
- fix
memeq()return value
- addmemends_str()helpersince v2:
- switch all the macros to static inline to avoid multiple evaluations of args
- add patch addingPURE_FUNCTIONattributessince v1:
Quoted 8 lines
- drop a patch that David pulled in
- add extra macro parens
- add blank lines after defintions
- covert memcchr's while loop to a for.
- change examples for mempbrkm and mempbrk to use '\0' in places
- fix spelling
- usememeq()even where we know the mem lengths are equal inmemstarts()
- add a reviewed-by to the 2nd patch, no other changes to that patch.
Looks good, I've applied this to the repository.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
_______________________________________________
ccan mailing list
[email protected]
https://lists.ozlabs.org/listinfo/ccan