Commit fc3a762c authored by Rusty Russell's avatar Rusty Russell

str/hex: to-from hexstring conversion routines.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 64b0c5cd
../../../licenses/CC0
\ No newline at end of file
#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;
}
/* 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;
}
/* 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 */
#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();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment