(二十四)— tool工具类(2)

最后更新于:2022-04-01 20:21:05

          在上篇文章中初步的分析了一下,Redis工具类文件中的一些用法,包括2个随机算法和循环冗余校验算法,今天,继续学习Redis中的其他的一些辅助工具类的用法。包括里面的大小端转换算法,sha算法在Redis中的实现和通用工具类算法util.c。        先来看看大小端转换算法,大小端学习过操作系统的人一定知道是什么意思,在不同的操作系统中,高位数字的存储方式存在,高位在前,低位在后,或是高位在后,低位在前,所以这里面就涉及到转换,根据不同的操作系统,有不同的转换方式,所以Redis在这方面就开放了这样一批的API; ~~~ /* 对于16位,32位,64位作大小端的转换 */ void memrev16(void *p); void memrev32(void *p); void memrev64(void *p); uint16_t intrev16(uint16_t v); uint32_t intrev32(uint32_t v); uint64_t intrev64(uint64_t v); ~~~ 挑出其中的一个API的实现: ~~~ /* Toggle the 32 bit unsigned integer pointed by *p from little endian to * big endian */ /* 32位需要4个字节,第0和第3个,第1和第2个字节作交换 */ void memrev32(void *p) { unsigned char *x = p, t; t = x[0]; x[0] = x[3]; x[3] = t; t = x[1]; x[1] = x[2]; x[2] = t; } ~~~ 总之就是做头尾部的交换。      下面在Redis中的加密算法的实现,采用的是SHA算法,/SHA:Secure Hash Algorithm安全散列算法,与MD5算法类似,也是属于单向加密算法,在加密长度上,做了很大的扩展,安全性也更高长度不超过2^64位的字符串或二进制流,经过SHA-1编码后,生成一个160位的二进制串 。在Redis中的C语言调用: ~~~ int main(int argc, char **argv) { SHA1_CTX ctx; unsigned char hash[20], buf[BUFSIZE]; int i; for(i=0;i= 3) { int start = pattern[0]; int end = pattern[2]; int c = string[0]; if (start > end) { int t = start; start = end; end = t; } if (nocase) { start = tolower(start); end = tolower(end); c = tolower(c); } pattern += 2; patternLen -= 2; if (c >= start && c <= end) match = 1; } else { if (!nocase) { if (pattern[0] == string[0]) match = 1; } else { if (tolower((int)pattern[0]) == tolower((int)string[0])) match = 1; } } pattern++; patternLen--; } if (not) match = !match; if (!match) return 0; /* no match */ string++; stringLen--; break; } case '\\': if (patternLen >= 2) { pattern++; patternLen--; } /* fall through */ default: /* 如果没有正则表达式的关键字符,则直接比较 */ if (!nocase) { if (pattern[0] != string[0]) //不相等,直接不匹配 return 0; /* no match */ } else { if (tolower((int)pattern[0]) != tolower((int)string[0])) return 0; /* no match */ } string++; stringLen--; break; } pattern++; patternLen--; if (stringLen == 0) { while(*pattern == '*') { pattern++; patternLen--; } break; } } if (patternLen == 0 && stringLen == 0) //如果匹配字符和模式字符匹配的长度都减少到0了,说明匹配成功了 return 1; return 0; } ~~~ 非常神奇的代码吧,从来没有想过去实现正则表达式原理的代码。还有一个方法是ll2string方法,数字转字符的方法,如果是我们平常的做法,就是除10取余,加上对应的数字字符,但是要转换的可是ll类型啊,长度非常长,效率会导致比较低,所以在Redis中作者,直接按除100算,2位,2位的赋值,而且用数字字符数字,做处理,直接按下标来赋值,避免了对余数的多次判断: ~~~ /* Convert a long long into a string. Returns the number of * characters needed to represent the number. * If the buffer is not big enough to store the string, 0 is returned. * * Based on the following article (that apparently does not provide a * novel approach but only publicizes an already used technique): * * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920 * * Modified in order to handle signed integers since the original code was * designed for unsigned integers. */ /* long long类型转化为string类型 */ int ll2string(char* dst, size_t dstlen, long long svalue) { static const char digits[201] = "0001020304050607080910111213141516171819" "2021222324252627282930313233343536373839" "4041424344454647484950515253545556575859" "6061626364656667686970717273747576777879" "8081828384858687888990919293949596979899"; int negative; unsigned long long value; /* The main loop works with 64bit unsigned integers for simplicity, so * we convert the number here and remember if it is negative. */ /* 在这里做正负号的判断处理 */ if (svalue < 0) { if (svalue != LLONG_MIN) { value = -svalue; } else { value = ((unsigned long long) LLONG_MAX)+1; } negative = 1; } else { value = svalue; negative = 0; } /* Check length. */ uint32_t const length = digits10(value)+negative; if (length >= dstlen) return 0; /* Null term. */ uint32_t next = length; dst[next] = '\0'; next--; while (value >= 100) { //做值的换算 int const i = (value % 100) * 2; value /= 100; //i所代表的余数值用digits字符数组中的对应数字代替了 dst[next] = digits[i + 1]; dst[next - 1] = digits[i]; next -= 2; } /* Handle last 1-2 digits. */ if (value < 10) { dst[next] = '0' + (uint32_t) value; } else { int i = (uint32_t) value * 2; dst[next] = digits[i + 1]; dst[next - 1] = digits[i]; } /* Add sign. */ if (negative) dst[0] = '-'; return length; } ~~~ digit[201]就是从00-99的数字字符,余数的赋值就通过这个数组,高效,方便,是提高了很多的速度。又发现了Redis代码中的一些亮点。
';