redis源码阅读之大小端转换
作者:
| 更新日期:大小端转换起始很简单,告诉你指定长度,然后翻转即可。
本文首发于公众号:天空的代码世界,微信号:tiankonguse
背景
redis是一个很不错的NOSQL数据库。
关于redis的使用文档, 可以参考这里.
关于redis大小端转换的源码可以参考这里
功能
一般需要进行大小端转换的有short
(16位), int
(32位), long long
(64位).
而下面这三个函数分别调用了对应的通用的转换函数。
uint16_t intrev16(uint16_t v) {
memrev16(&v);
return v;
}
uint32_t intrev32(uint32_t v) {
memrev32(&v);
return v;
}
uint64_t intrev64(uint64_t v) {
memrev64(&v);
return v;
}
转换
由于要转换的只有三个尺寸, 所以直接交换即可。
显然, 交换算法写成函数或者宏更好了。
void memrev16(void *p) {
unsigned char *x = p, t;
t = x[0];x[0] = x[1];x[1] = t;
}
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;
}
void memrev64(void *p) {
unsigned char *x = p, t;
t = x[0];x[0] = x[7];x[7] = t;
t = x[1];x[1] = x[6];x[6] = t;
t = x[2];x[2] = x[5];x[5] = t;
t = x[3];x[3] = x[4];x[4] = t;
}
写成宏后就会简单点。
#define SWAP(l, r, t) do{t = l;l = r;l = t;}while(0)
void memrev16(void *p) {
unsigned char *x = p, t;
SWAP(x[0], x[1], t);
}
void memrev32(void *p) {
unsigned char *x = p, t;
SWAP(x[0], x[3], t);
SWAP(x[1], x[2], t);
}
void memrev64(void *p) {
unsigned char *x = p, t;
SWAP(x[0], x[7], t);
SWAP(x[1], x[6], t);
SWAP(x[2], x[5], t);
SWAP(x[3], x[4], t);
}
虽然只有三个, 如果封装成通用的函数就更好了。
#define SWAP(l, r, t) do{t = l;l = r;l = t;}while(0)
void memrev(void *p, int size) {
unsigned char *x = p, t;
int l=0, r = size - 1;
while(l < r){
SWAP(x[l], x[r], t);
l++,r--;
}
}
void memrev16(void *p) {
memrev(p, 2);
}
void memrev32(void *p) {
memrev(p, 4);
}
void memrev64(void *p) {
memrev(p, 8);
}
本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。