Browse Source

str/hex: to-from hexstring conversion routines.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 11 years ago
parent
commit
fc3a762c66
5 changed files with 225 additions and 0 deletions
  1. 1 0
      ccan/str/hex/LICENSE
  2. 39 0
      ccan/str/hex/_info
  3. 70 0
      ccan/str/hex/hex.c
  4. 73 0
      ccan/str/hex/hex.h
  5. 42 0
      ccan/str/hex/test/run.c

+ 1 - 0
ccan/str/hex/LICENSE

@@ -0,0 +1 @@
+../../../licenses/CC0

+ 39 - 0
ccan/str/hex/_info

@@ -0,0 +1,39 @@
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * str/hex - hex-to-string conversions and vice-versa
+ *
+ * This code contains simple routines for hexidecimal strings.
+ *
+ * License: CC0 (Public domain)
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ *
+ * Example:
+ *	int main(int argc, char *argv[])
+ *	{
+ *		int i;
+ *
+ *		for (i = 1; i < argc; i++) {
+ *			char str[hex_str_size(strlen(argv[i]))];
+ *
+ *			hex_encode(str, sizeof(str), argv[i], strlen(argv[i]));
+ *			printf("%s ", str);
+ *		}
+ *		printf("\n");
+ *		return 0;
+ *	}
+ */
+int main(int argc, char *argv[])
+{
+	/* Expect exactly one argument */
+	if (argc != 2)
+		return 1;
+
+	if (strcmp(argv[1], "depends") == 0) {
+		return 0;
+	}
+
+	return 1;
+}

+ 70 - 0
ccan/str/hex/hex.c

@@ -0,0 +1,70 @@
+/* CC0 license (public domain) - see LICENSE file for details */
+#include <ccan/str/hex/hex.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static bool char_to_hex(unsigned char *val, char c)
+{
+	if (c >= '0' && c <= '9') {
+		*val = c - '0';
+		return true;
+	}
+ 	if (c >= 'a' && c <= 'f') {
+		*val = c - 'a' + 10;
+		return true;
+	}
+ 	if (c >= 'A' && c <= 'F') {
+		*val = c - 'A' + 10;
+		return true;
+	}
+	return false;
+}
+
+bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize)
+{
+	unsigned char v1, v2;
+	unsigned char *p = buf;
+
+	while (slen > 1) {
+		if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1]))
+			return false;
+		if (!bufsize)
+			return false;
+		*(p++) = (v1 << 4) | v2;
+		str += 2;
+		slen -= 2;
+		bufsize--;
+	}
+	return slen == 0 && bufsize == 0;
+}
+
+static char hexchar(unsigned int val)
+{
+	if (val < 10)
+		return '0' + val;
+	if (val < 16)
+		return 'a' + val - 10;
+	abort();
+}
+
+bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize)
+{
+	size_t used = 0;
+
+	if (destsize < 1)
+		return false;
+
+	while (used < bufsize) {
+		unsigned int c = ((const unsigned char *)buf)[used];
+		if (destsize < 3)
+			return false;
+		*(dest++) = hexchar(c >> 4);
+		*(dest++) = hexchar(c & 0xF);
+		used++;
+		destsize -= 2;
+	}
+	*dest = '\0';
+
+	return used + 1;
+}

+ 73 - 0
ccan/str/hex/hex.h

@@ -0,0 +1,73 @@
+/* CC0 (Public domain) - see LICENSE file for details */
+#ifndef CCAN_HEX_H
+#define CCAN_HEX_H
+#include "config.h"
+#include <stdbool.h>
+#include <stdlib.h>
+
+/**
+ * hex_decode - Unpack a hex string.
+ * @str: the hexidecimal string
+ * @slen: the length of @str
+ * @buf: the buffer to write the data into
+ * @bufsize: the length of @buf
+ *
+ * Returns false if there are any characters which aren't 0-9, a-f or A-F,
+ * of the string wasn't the right length for @bufsize.
+ *
+ * Example:
+ *	unsigned char data[20];
+ *
+ *	if (!hex_decode(argv[1], strlen(argv[1]), data, 20))
+ *		printf("String is malformed!\n");
+ */
+bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize);
+
+/**
+ * hex_encode - Create a nul-terminated hex string
+ * @buf: the buffer to read the data from
+ * @bufsize: the length of @buf
+ * @dest: the string to fill
+ * @destsize: the max size of the string
+ *
+ * Returns true if the string, including terminator, fit in @destsize;
+ *
+ * Example:
+ *	unsigned char buf[] = { 0x1F, 0x2F };
+ *	char str[5];
+ *
+ *	if (!hex_encode(buf, sizeof(buf), str, sizeof(str)))
+ *		abort();
+ */
+bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize);
+
+/**
+ * hex_str_size - Calculate how big a nul-terminated hex string is
+ * @bytes: bytes of data to represent
+ *
+ * Example:
+ *	unsigned char buf[] = { 0x1F, 0x2F };
+ *	char str[hex_str_size(sizeof(buf))];
+ *
+ *	hex_encode(buf, sizeof(buf), str, sizeof(str));
+ */
+static inline size_t hex_str_size(size_t bytes)
+{
+	return 2 * bytes + 1;
+}
+
+/**
+ * hex_data_size - Calculate how many bytes of data in a hex string
+ * @strlen: the length of the string (with or without NUL)
+ *
+ * Example:
+ *	const char str[] = "1F2F";
+ *	unsigned char buf[hex_data_size(sizeof(str))];
+ *
+ *	hex_decode(str, strlen(str), buf, sizeof(buf));
+ */
+static inline size_t hex_data_size(size_t strlen)
+{
+	return strlen / 2;
+}
+#endif /* PETTYCOIN_HEX_H */

+ 42 - 0
ccan/str/hex/test/run.c

@@ -0,0 +1,42 @@
+#include <ccan/str/hex/hex.h>
+/* Include the C files directly. */
+#include <ccan/str/hex/hex.c>
+#include <ccan/tap/tap.h>
+#include <string.h>
+
+int main(void)
+{
+	const char teststr[] = "0123456789abcdefABCDEF";
+	const char bad_teststr[] = "0123456789abcdefABCDEF1O";
+	const unsigned char testdata[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
+					   0xcd, 0xef, 0xAB, 0xCD, 0xEF };
+	unsigned char data[11];
+	char str[23];
+	size_t i;
+	
+	plan_tests(10 + sizeof(str));
+	
+	ok1(hex_str_size(sizeof(testdata)) == sizeof(teststr));
+	/* This gives right result with or without nul included */
+	ok1(hex_data_size(strlen(teststr)) == sizeof(testdata));
+	ok1(hex_data_size(sizeof(teststr)) == sizeof(testdata));
+
+	ok1(hex_decode(teststr, strlen(teststr), data, sizeof(data)));
+	ok1(memcmp(data, testdata, sizeof(testdata)) == 0);
+	ok1(hex_encode(testdata, sizeof(testdata), str, sizeof(str)));
+	ok1(strcmp(str, "0123456789abcdefabcdef") == 0);
+
+	/* Bad char */
+	ok1(!hex_decode(bad_teststr, strlen(bad_teststr), data, sizeof(data)));
+	/* Bad hex string len */
+	ok1(!hex_decode(teststr, strlen(teststr) - 1, data, sizeof(data)));
+	/* Bad buffer len */
+	ok1(!hex_decode(teststr, strlen(teststr), data, sizeof(data) - 1));
+
+	/* Bad deststring size. */
+	for (i = 1; i <= sizeof(str); i++)
+		ok1(!hex_encode(testdata, sizeof(testdata), str, sizeof(str)-i));
+
+	/* This exits depending on whether all tests passed */
+	return exit_status();
+}