X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Fbytestring%2Fbytestring.h;h=62141bea41149a30bd61214e8804d50c23e4c971;hb=f1e31c66572ef5997e08a1ecadf2e45b2fb04532;hp=ee4087d44cb4c9dc864e632973e917cafb768ea9;hpb=8253b9dd5d279793e267ed5dfcc4c0f2cfbaeb83;p=ccan diff --git a/ccan/bytestring/bytestring.h b/ccan/bytestring/bytestring.h index ee4087d4..62141bea 100644 --- a/ccan/bytestring/bytestring.h +++ b/ccan/bytestring/bytestring.h @@ -2,11 +2,15 @@ #ifndef CCAN_BYTESTRING_H_ #define CCAN_BYTESTRING_H_ +#include "config.h" + #include #include #include +#include #include +#include struct bytestring { const char *ptr; @@ -62,6 +66,8 @@ static inline struct bytestring bytestring(const char *p, size_t l) */ static inline struct bytestring bytestring_from_string(const char *s) { + if (!s) + return bytestring_NULL; return bytestring(s, strlen(s)); } @@ -78,4 +84,120 @@ static inline bool bytestring_eq(struct bytestring a, struct bytestring b) && (memcmp(a.ptr, b.ptr, a.len) == 0); } +/** + * bytestring_byte - get a byte from a bytestring + * @s: bytestring + * @n: index + * + * Return the @n-th byte from @s. Aborts (via assert) if @n is out of + * range for the length of @s. + */ +static inline char bytestring_byte(struct bytestring s, size_t n) +{ + assert(n < s.len); + return s.ptr[n]; +} + +/** + * bytestring_slice - extract a substring from a bytestring + * @s: bytestring + * @start, @end: indexes + * + * Return a sub-bytestring of @s, starting at byte index @start, and + * running to, but not including byte @end. If @end is before start, + * returns a zero-length bytestring. If @start is out of range, + * return a zero length bytestring at the end of @s. + * + * Note that this doesn't copy or allocate anything - the returned + * bytestring occupies (some of) the same memory as the given + * bytestring. + */ +static inline struct bytestring bytestring_slice(struct bytestring s, + size_t start, size_t end) +{ + if (start > s.len) + start = s.len; + if (end > s.len) + end = s.len; + if (end < start) + end = start; + + return bytestring(s.ptr + start, end - start); +} + +/** + * bytestring_starts - test if the start of one bytestring matches another + * @s, @prefix: bytestrings + * + * Returns true if @prefix appears as a substring at the beginning of + * @s, false otherwise. + */ +static inline bool bytestring_starts(struct bytestring s, + struct bytestring prefix) +{ + return (s.len >= prefix.len) && (memcmp(s.ptr, + prefix.ptr, prefix.len) == 0); +} + +/** + * bytestring_ends - test if the end of one bytestring matches another + * @s, @suffix: bytestrings + * + * Returns true if @suffix appears as a substring at the end of @s, + * false otherwise. + */ +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); +} + +/** + * bytestring_index - locate character in bytestring + * @haystack: a bytestring + * @needle: a character or byte value + * + * Returns a pointer to the first occurrence of @needle within + * @haystack, or NULL if @needle does not appear in @haystack. + */ +static inline const char *bytestring_index(struct bytestring haystack, + char needle) +{ + return memchr(haystack.ptr, needle, haystack.len); +} + +/** + * bytestring_rindex - locate character in bytestring + * @haystack: a bytestring + * @needle: a character or byte value + * + * Returns a pointer to the last occurrence of @needle within + * @haystack, or NULL if @needle does not appear in @haystack. + */ +static inline const char *bytestring_rindex(struct bytestring haystack, + char needle) +{ + return memrchr(haystack.ptr, needle, haystack.len); +} + +/* + * bytestring_bytestring - search for a bytestring in another bytestring + * @haystack, @needle: bytestrings + * + * Returns a bytestring corresponding to the first occurrence of + * @needle in @haystack, or bytestring_NULL if @needle is not found + * within @haystack. + */ +static inline struct bytestring bytestring_bytestring(struct bytestring haystack, + struct bytestring needle) +{ + const char *p = memmem(haystack.ptr, haystack.len, + needle.ptr, needle.len); + if (p) + return bytestring(p, needle.len); + else + return bytestring_NULL; +} + #endif /* CCAN_BYTESTRING_H_ */