[ccan] [PATCH 1/2] Add new 'bytestring' module

David Gibson david at gibson.dropbear.id.au
Thu Jun 21 20:32:55 EST 2012


This patch adds a new 'bytestring' module which manipulates bytestrings
consisting of a const char pointer and length.  This makes for more
convenient handling of subsections of a large fixed data buffer or buffers.

Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
---
 ccan/bytestring/LICENSE                          |    1 +
 ccan/bytestring/_info                            |   41 +++++++++++
 ccan/bytestring/bytestring.h                     |   81 ++++++++++++++++++++++
 ccan/bytestring/test/compile_fail-BYTESTRING-2.c |   15 ++++
 ccan/bytestring/test/compile_fail-BYTESTRING.c   |   18 +++++
 ccan/bytestring/test/run.c                       |   35 ++++++++++
 6 files changed, 191 insertions(+)
 create mode 120000 ccan/bytestring/LICENSE
 create mode 100644 ccan/bytestring/_info
 create mode 100644 ccan/bytestring/bytestring.h
 create mode 100644 ccan/bytestring/test/compile_fail-BYTESTRING-2.c
 create mode 100644 ccan/bytestring/test/compile_fail-BYTESTRING.c
 create mode 100644 ccan/bytestring/test/run.c

diff --git a/ccan/bytestring/LICENSE b/ccan/bytestring/LICENSE
new file mode 120000
index 0000000..dc314ec
--- /dev/null
+++ b/ccan/bytestring/LICENSE
@@ -0,0 +1 @@
+../../licenses/LGPL-2.1
\ No newline at end of file
diff --git a/ccan/bytestring/_info b/ccan/bytestring/_info
new file mode 100644
index 0000000..5b08491
--- /dev/null
+++ b/ccan/bytestring/_info
@@ -0,0 +1,41 @@
+#include <string.h>
+#include "config.h"
+
+/**
+ * bytestring - simple bytestring handling
+ *
+ * This code handles manipulation of "bytestrings" represented as a
+ * structure containing a pointer and length.  Bytestrings are not
+ * NUL-terminated, and may include internal \0 characters.  The main
+ * use case is for referencing sub-sections of a large data buffer
+ * without the inconvenience of manually passing (and returning) both
+ * pointer and length all the time.
+ *
+ * Because of this use case, the bytestrings are treated as having
+ * immutable contents (we use a const char pointer).  The caller code
+ * is responsible for ensuring that the lifetime of the data
+ * referenced by the bytestrings is long enough not to leave
+ * bytestring structures with a dangling pointer.
+ *
+ * Example:
+ *	const char buf[] = "ABCDEFGH";
+ *	struct bytestring abcd = BYTESTRING("ABCD");
+ *
+ *	assert(bytestring_eq(bytestring(buf, 4), abcd));
+ *
+ * License: LGPL (v2.1 or any later version)
+ * Author: David Gibson <david at gibson.dropbear.id.au>
+ */
+int main(int argc, char *argv[])
+{
+	/* Expect exactly one argument */
+	if (argc != 2)
+		return 1;
+
+	if (strcmp(argv[1], "depends") == 0) {
+		printf("ccan/array_size\n");
+		return 0;
+	}
+
+	return 1;
+}
diff --git a/ccan/bytestring/bytestring.h b/ccan/bytestring/bytestring.h
new file mode 100644
index 0000000..ee4087d
--- /dev/null
+++ b/ccan/bytestring/bytestring.h
@@ -0,0 +1,81 @@
+/* Licensed under LGPLv2+ - see LICENSE file for details */
+#ifndef CCAN_BYTESTRING_H_
+#define CCAN_BYTESTRING_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <ccan/array_size/array_size.h>
+
+struct bytestring {
+	const char *ptr;
+	size_t len;
+};
+
+/**
+ * bytestring - construct a new bytestring
+ * @p: pointer to the content of the bytestring
+ * @l: length of the bytestring
+ *
+ * Builds a new bytestring starting at p, of length l.
+ *
+ * Example:
+ *	char x[5] = "abcde";
+ *	struct bytestring bs = bytestring(x, 5);
+ *	assert(bs.len == 5);
+ */
+static inline struct bytestring bytestring(const char *p, size_t l)
+{
+	struct bytestring bs = {
+		.ptr = p,
+		.len = l,
+	};
+
+	return bs;
+}
+
+#define bytestring_NULL		bytestring(NULL, 0)
+
+/**
+ * BYTESTRING - construct a bytestring from a string literal
+ * @s: string literal
+ *
+ * Builds a new bytestring containing the given literal string, not
+ * including the terminating \0 (but including any internal \0s).
+ *
+ * Example:
+ *	assert(BYTESTRING("abc\0def").len == 7);
+ */
+#define BYTESTRING(s) (bytestring((s), ARRAY_SIZE(s) - 1))
+
+
+/**
+ * bytestring_from_string - construct a bytestring from a NUL terminated string
+ * @s: NUL-terminated string pointer
+ *
+ * Builds a new bytestring containing the given NUL-terminated string,
+ * up to, but not including, the terminating \0.
+ *
+ * Example:
+ *	assert(bytestring_from_string("abc\0def").len == 3);
+ */
+static inline struct bytestring bytestring_from_string(const char *s)
+{
+	return bytestring(s, strlen(s));
+}
+
+/**
+ * bytestring_eq - test if bytestrings have identical content
+ * @a, @b: bytestrings
+ *
+ * Returns 1 if the given bytestrings have identical length and
+ * content, 0 otherwise.
+ */
+static inline bool bytestring_eq(struct bytestring a, struct bytestring b)
+{
+	return (a.len == b.len)
+		&& (memcmp(a.ptr, b.ptr, a.len) == 0);
+}
+
+#endif /* CCAN_BYTESTRING_H_ */
diff --git a/ccan/bytestring/test/compile_fail-BYTESTRING-2.c b/ccan/bytestring/test/compile_fail-BYTESTRING-2.c
new file mode 100644
index 0000000..7ab06f8
--- /dev/null
+++ b/ccan/bytestring/test/compile_fail-BYTESTRING-2.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+#include <ccan/bytestring/bytestring.h>
+
+int main(int argc, char *argv[])
+{
+	struct bytestring bs;
+	const char *x = "abcde";
+
+#ifdef FAIL
+	bs = BYTESTRING(x);
+#endif
+	printf("%zd %s\n", bs.len, x);
+	return 0;
+}
diff --git a/ccan/bytestring/test/compile_fail-BYTESTRING.c b/ccan/bytestring/test/compile_fail-BYTESTRING.c
new file mode 100644
index 0000000..f3fcb20
--- /dev/null
+++ b/ccan/bytestring/test/compile_fail-BYTESTRING.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+#include <ccan/bytestring/bytestring.h>
+
+int main(int argc, char *argv[])
+{
+	struct bytestring bs;
+
+	bs = BYTESTRING(
+#ifdef FAIL
+		argv[0]
+#else
+		"literal"
+#endif
+);
+	printf("%zd\n", bs.len);
+	return 0;
+}
diff --git a/ccan/bytestring/test/run.c b/ccan/bytestring/test/run.c
new file mode 100644
index 0000000..49c16a6
--- /dev/null
+++ b/ccan/bytestring/test/run.c
@@ -0,0 +1,35 @@
+#include <ccan/bytestring/bytestring.h>
+#include <ccan/tap/tap.h>
+
+#define TEST_STRING	"test string"
+#define TEST_STRING_2	"abc\0def"
+
+const char str1[] = TEST_STRING;
+const char *str2 = TEST_STRING;
+
+int main(void)
+{
+	struct bytestring bs, bs1, bs2, bs3, bs4;
+
+	/* This is how many tests you plan to run */
+	plan_tests(6);
+
+	bs = bytestring(str1, sizeof(str1) - 1);
+	ok1(bs.ptr == str1);
+	ok1(bs.len == (sizeof(str1) - 1));
+
+	bs1 = BYTESTRING(TEST_STRING);
+	ok1(bytestring_eq(bs, bs1));
+
+	bs2 = BYTESTRING(TEST_STRING_2);
+	ok1(bs2.len == 7);
+
+	bs3 = bytestring_from_string(str2);
+	ok1(bytestring_eq(bs3, bs));
+
+	bs4 = bytestring_from_string(TEST_STRING_2);
+	ok1(bs4.len == 3);
+
+	/* This exits depending on whether all tests passed */
+	return exit_status();
+}
-- 
1.7.10



More information about the ccan mailing list