countbits

count leading 0 bits in hex strings
git clone git://jb55.com/countbits
Log | Files | Refs | README

main.c (2062B)


      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 
      5 static inline int char_to_hex(unsigned char *val, char c)
      6 {
      7 	if (c >= '0' && c <= '9') {
      8 		*val = c - '0';
      9 		return 1;
     10 	}
     11  	if (c >= 'a' && c <= 'f') {
     12 		*val = c - 'a' + 10;
     13 		return 1;
     14 	}
     15  	if (c >= 'A' && c <= 'F') {
     16 		*val = c - 'A' + 10;
     17 		return 1;
     18 	}
     19 	return 0;
     20 }
     21 
     22 static inline int hex_decode(const char *str, size_t slen, void *buf, size_t bufsize)
     23 {
     24 	unsigned char v1, v2;
     25 	unsigned char *p = buf;
     26 
     27 	while (slen > 1) {
     28 		if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1]))
     29 			return 0;
     30 		if (!bufsize)
     31 			return 0;
     32 		*(p++) = (v1 << 4) | v2;
     33 		str += 2;
     34 		slen -= 2;
     35 		bufsize--;
     36 	}
     37 	return slen == 0 && bufsize == 0;
     38 }
     39 
     40 static inline size_t hex_str_size(size_t bytes)
     41 {
     42 	return 2 * bytes + 1;
     43 }
     44 
     45 static inline char hexchar(unsigned int val)
     46 {
     47 	if (val < 10)
     48 		return '0' + val;
     49 	if (val < 16)
     50 		return 'a' + val - 10;
     51 	abort();
     52 }
     53 
     54 static inline int hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize)
     55 {
     56 	size_t i;
     57 
     58 	if (destsize < hex_str_size(bufsize)) {
     59 		fprintf(stderr, "hexencode: destsize(%zu) < hex_str_size(%zu)\n", destsize, hex_str_size(bufsize));
     60 		return 0;
     61 	}
     62 
     63 	for (i = 0; i < bufsize; i++) {
     64 		unsigned int c = ((const unsigned char *)buf)[i];
     65 		*(dest++) = hexchar(c >> 4);
     66 		*(dest++) = hexchar(c & 0xF);
     67 	}
     68 	*dest = '\0';
     69 
     70 	return 1;
     71 }
     72 
     73 
     74 static inline int zero_bits(unsigned char b)
     75 {
     76 	int n = 0;
     77 
     78 	if (b == 0)
     79 		return 8;
     80 
     81 	while (b >>= 1)
     82 		n++;
     83 
     84 	return 7-n;
     85 }
     86 
     87 /* find the number of leading zero bits in a hash */
     88 static int count_leading_zero_bits(unsigned char *hash, int len)
     89 {
     90 	int bits, total, i;
     91 
     92 	for (i = 0, total = 0; i < len; i++) {
     93 		bits = zero_bits(hash[i]);
     94 		total += bits;
     95 		if (bits != 8)
     96 			break;
     97 	}
     98 	return total;
     99 }
    100 
    101 int main(int argc, const char *argv[])
    102 {
    103 	unsigned char buf[4096];
    104 	const char *hex;
    105 	int bits, len;
    106 
    107 	if (argc < 1)
    108 		return 1;
    109 
    110 	hex = argv[1];
    111 	len = strlen(hex);
    112 
    113 	if (!hex_decode(hex, len, buf, len/2))
    114 		return 2;
    115 
    116 	bits = count_leading_zero_bits(buf, len / 2);
    117 	printf("%d\n", bits);
    118 	return 0;
    119 }