lighttpd的buffer.c中有个int buffer_append_long_hex(buffer *b, unsigend long value),作用是把value转换成16进制字符串表示,并附加到buffer后面。
我提取了转换的操作,原理是这样的:
char hex_char[] = "0123456789abcdef";
char *h2x (char *buf, unsigned long value)
{
int shift = 0; /* 表示value 的二进制表示到底有多少位 */
unsigned long copy = value;
char *org = buf;
/* 获得value在16进制时的位数,保存在shift中 */
while (copy) {
copy >>= 4;
shift++;
}
/* 如果shift==0, 其实就是value == 0 */
if (shift == 0)
{
shift++;
}
/* 如果shift是奇数,我们要加1补成偶数,比如1234的16进制表示是0x4D2, 我们要把它扩展成0x04D2 */
if (shift & 0x01)
{
shift++;
}
/* 16进制的每一位数字都包含4个bit,所以乘4得到二进制表示的位数 */
shift <<= 2;
while (shift > 0) {
shift -= 4;
/* 每次把需要的16进制位数移到最低的4位,并且&0x0F保证它落在数组中 */
*(buf++) = hex_char[(value >> shift) & 0x0F];
}
*buf = '\0';
return org;
}
可能说得还是不太清楚,举例来说,10进制1234的16进制表示是0x04D2,二进制表示则为 0000 0100 1101 0010,这段代码通过查表,把0000转成’0’,0100转成’4’……