So you want a hex-to-hex conversion from unsigned to signed 2's complement. Did you realize you can just go digit by digit? Every digit in the input string plus its counterpart in the output string equals 0xf
, except the last, where it's 0x10
. Any kind of bigint arithmetic is overkill for this problem.
Demo in C (note: this doesn't strip leading zeros)
#include <stdio.h>
#include <string.h>
static int fromhex(char dig)
{
return dig >= '0' && dig <= '9' ? dig - '0' :
dig >= 'A' && dig <= 'F' ? dig - 'A' + 10 :
dig >= 'a' && dig <= 'f' ? dig - 'a' + 10 :
-1;
}
int main(int argc, char **argv)
{
if(argc!=2 ||
strlen(argv[1])!=40 ||
strspn(argv[1], "0123456789abcdefABCDEF")!=40)
{
fprintf(stderr, "Usage: %s sha1hex\n", argv[0]);
return 1;
}
if(strchr("01234567", argv[1][0])) {
puts(argv[1]);
} else {
int i;
putchar('-');
for(i=0;i<39;++i)
printf("%x", 15 - fromhex(argv[1][i]));
printf("%x\n", 16 - fromhex(argv[1][i]));
}
return 0;
}