summaryrefslogtreecommitdiff
path: root/hex.c
blob: 7bb440e7940212809006b21da96971b7dcda936e (plain)
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include "git-compat-util.h"
#include "hash.h"
#include "hex.h"

const signed char hexval_table[256] = {
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 00-07 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 08-0f */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 10-17 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 18-1f */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 20-27 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 28-2f */
	  0,  1,  2,  3,  4,  5,  6,  7,		/* 30-37 */
	  8,  9, -1, -1, -1, -1, -1, -1,		/* 38-3f */
	 -1, 10, 11, 12, 13, 14, 15, -1,		/* 40-47 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 48-4f */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 50-57 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 58-5f */
	 -1, 10, 11, 12, 13, 14, 15, -1,		/* 60-67 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 68-67 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 70-77 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 78-7f */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 80-87 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 88-8f */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 90-97 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* 98-9f */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* a0-a7 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* a8-af */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* b0-b7 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* b8-bf */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* c0-c7 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* c8-cf */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* d0-d7 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* d8-df */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* e0-e7 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* e8-ef */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* f0-f7 */
	 -1, -1, -1, -1, -1, -1, -1, -1,		/* f8-ff */
};

int hex_to_bytes(unsigned char *binary, const char *hex, size_t len)
{
	for (; len; len--, hex += 2) {
		unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]);

		if (val & ~0xff)
			return -1;
		*binary++ = val;
	}
	return 0;
}

static int get_hash_hex_algop(const char *hex, unsigned char *hash,
			      const struct git_hash_algo *algop)
{
	int i;
	for (i = 0; i < algop->rawsz; i++) {
		int val = hex2chr(hex);
		if (val < 0)
			return -1;
		*hash++ = val;
		hex += 2;
	}
	return 0;
}

int get_sha1_hex(const char *hex, unsigned char *sha1)
{
	return get_hash_hex_algop(hex, sha1, the_hash_algo);
}

int get_oid_hex_algop(const char *hex, struct object_id *oid,
		      const struct git_hash_algo *algop)
{
	int ret = get_hash_hex_algop(hex, oid->hash, algop);
	if (!ret)
		oid_set_algo(oid, algop);
	return ret;
}

/*
 * NOTE: This function relies on hash algorithms being in order from shortest
 * length to longest length.
 */
int get_oid_hex_any(const char *hex, struct object_id *oid)
{
	int i;
	for (i = GIT_HASH_NALGOS - 1; i > 0; i--) {
		if (!get_oid_hex_algop(hex, oid, &hash_algos[i]))
			return i;
	}
	return GIT_HASH_UNKNOWN;
}

int get_oid_hex(const char *hex, struct object_id *oid)
{
	return get_oid_hex_algop(hex, oid, the_hash_algo);
}

int parse_oid_hex_algop(const char *hex, struct object_id *oid,
			const char **end,
			const struct git_hash_algo *algop)
{
	int ret = get_oid_hex_algop(hex, oid, algop);
	if (!ret)
		*end = hex + algop->hexsz;
	return ret;
}

int parse_oid_hex_any(const char *hex, struct object_id *oid, const char **end)
{
	int ret = get_oid_hex_any(hex, oid);
	if (ret)
		*end = hex + hash_algos[ret].hexsz;
	return ret;
}

int parse_oid_hex(const char *hex, struct object_id *oid, const char **end)
{
	return parse_oid_hex_algop(hex, oid, end, the_hash_algo);
}

char *hash_to_hex_algop_r(char *buffer, const unsigned char *hash,
			  const struct git_hash_algo *algop)
{
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	/*
	 * Our struct object_id has been memset to 0, so default to printing
	 * using the default hash.
	 */
	if (algop == &hash_algos[0])
		algop = the_hash_algo;

	for (i = 0; i < algop->rawsz; i++) {
		unsigned int val = *hash++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}

char *oid_to_hex_r(char *buffer, const struct object_id *oid)
{
	return hash_to_hex_algop_r(buffer, oid->hash, &hash_algos[oid->algo]);
}

char *hash_to_hex_algop(const unsigned char *hash, const struct git_hash_algo *algop)
{
	static int bufno;
	static char hexbuffer[4][GIT_MAX_HEXSZ + 1];
	bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
	return hash_to_hex_algop_r(hexbuffer[bufno], hash, algop);
}

char *hash_to_hex(const unsigned char *hash)
{
	return hash_to_hex_algop(hash, the_hash_algo);
}

char *oid_to_hex(const struct object_id *oid)
{
	return hash_to_hex_algop(oid->hash, &hash_algos[oid->algo]);
}