summaryrefslogtreecommitdiffstats
path: root/utils/midpoint.c
blob: 1a2e6f38862e1288dd89578b4b7b238b57fc0d8d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <dht.c>
#include <error.h>
#define S0(x) (x ? x : "")

/**
 * converts a hexadecimal string to bytes
 *
 * b and h may not overlap, unless they are the same address
 *
 * @param b	[out]	array of bytes to write to with capacity l
 * @param h	[in]	array of hex to read from with 2l hex digits
 * @param l	[in]	length of output array
 */

void hex2bin (unsigned char * b, const char * h, int l) {
	for (int i = 0; i < l; i++) {
		char ms = *h++;
		char ls = *h++;
		b[i] = (ms >= 'a' ? ms - 'a' + 10 : (ms >= 'A' ? ms - 'A' + 10 : ms - '0')) << 4;
		b[i] |= (ls >= 'a' ? ls - 'a' + 10 : (ls >= 'A' ? ls - 'A' + 10 : ls - '0'));
	}
}

int main (int argc, char ** argv) {
	if (argc < 3)
		error_at_line(1, 0, __FILE__, __LINE__, "%s <bin|add|subtract|divide|midpoint> <a> [b]", S0(argv[0]));
	if (argv[1][0] == 'b' || argv[1][0] == 'B') {
		unsigned char a[strlen(argv[2])/2+1];
		a[strlen(argv[2])/2] = '\0';
		hex2bin(a, argv[2], strlen(argv[2])/2);
		if (strlen(argv[2]) != 40 || (argv[2] && strlen(argv[2]) != 40)) {
			printf("%s\n", a);
			return 0;
		}
		return 0;
	}
	if (strlen(argv[2]) != 40)
		error_at_line(3, 0, __FILE__, __LINE__, "strlen(a) != 40 && !bin");
	if (argv[1][0] == 'd' || argv[1][0] == 'D') {
		unsigned char a[20];
		hex2bin(a, argv[2], 20);
		divide(a);
		char out[41];
		out[40] = '\0';
		bin2hex(out, a, 20);
		printf("%s\n", out);
		return 0;
	}
	if (!argv[3])
		error_at_line(2, 0, __FILE__, __LINE__, "!b && !bin && !divide");
	if (strlen(argv[3]) != 40)
		error_at_line(3, 0, __FILE__, __LINE__, "strlen(b) != 40 && !bin && !divide");
	unsigned char a[20];
	unsigned char b[20];
	hex2bin(a, argv[2], 20);
	hex2bin(b, argv[3], 20);
	char out[41];
	out[40] = '\0';
	unsigned char r[20];
	if (argv[1][0] == 'a' || argv[1][0] == 'A') {
		memcpy(r, a, 20);
		add(r, b);
	} else if (argv[1][0] == 's' || argv[1][0] == 'S') {
		memcpy(r, a, 20);
		subtract(r, b);
	} else {
		midpoint(r, a, b);
	}
	bin2hex(out, r, 20);
	printf("%s\n", out);
}