/* This function is used to iterate through all the zipmap elements. * * 这个函数用于遍历 zipmap 的所有元素。 * * In the first call the first argument is the pointer to the zipmap + 1. * * 在第一次调用这个函数时, zm 参数的值为 zipmap + 1 * (也即是,指向 zipmap 的第一个节点) * * In the next calls what zipmapNext returns is used as first argument. * * 而在之后的调用中, zm 参数的值为之前调用 zipmapNext 时所返回的值。 * * Example: * * 示例: * * unsigned char *i = zipmapRewind(my_zipmap); * while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) { * printf("%d bytes key at $p\n", klen, key); * printf("%d bytes value at $p\n", vlen, value); * } * * T = O(1) */ unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) { // 已到达列表末尾,停止迭代 if (zm[0] == ZIPMAP_END) return NULL; // 取出键,并保存到 key 参数中 if (key) { *key = zm; *klen = zipmapDecodeLength(zm); *key += ZIPMAP_LEN_BYTES(*klen); } // 越过键 zm += zipmapRawKeyLength(zm); // 取出值,并保存到 value 参数中 if (value) { *value = zm+1; *vlen = zipmapDecodeLength(zm); *value += ZIPMAP_LEN_BYTES(*vlen); } // 越过值 zm += zipmapRawValueLength(zm); // 返回指向下一节点的指针 return zm; }
/* This function is used to iterate through all the zipmap elements. * In the first call the first argument is the pointer to the zipmap + 1. * In the next calls what zipmapNext returns is used as first argument. * Example: * * unsigned char *i = zipmapRewind(my_zipmap); * while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) { * printf("%d bytes key at $p\n", klen, key); * printf("%d bytes value at $p\n", vlen, value); * } */ unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) { if (zm[0] == ZIPMAP_END) return NULL; if (key) { *key = zm; *klen = zipmapDecodeLength(zm); *key += ZIPMAP_LEN_BYTES(*klen); } zm += zipmapRawKeyLength(zm); if (value) { *value = zm+1; *vlen = zipmapDecodeLength(zm); *value += ZIPMAP_LEN_BYTES(*vlen); } zm += zipmapRawValueLength(zm); return zm; }
/* Search a key and retrieve the pointer and len of the associated value. * If the key is found the function returns 1, otherwise 0. */ int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen) { unsigned char *p; if ((p = zipmapLookupRaw(zm,key,klen,NULL)) == NULL) return 0; p += zipmapRawKeyLength(p); *vlen = zipmapDecodeLength(p); *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1; return 1; }
/* zipmap的迭代器式遍历函数,典型用法如下: * * unsigned char *i = zipmapRewind(my_zipmap); * while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) { * printf("%d bytes key at $p\n", klen, key); * printf("%d bytes value at $p\n", vlen, value); * } */ unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) { // 如果达到尾部,直接返回NULL if (zm[0] == ZIPMAP_END) return NULL; // 获取key if (key) { *key = zm; *klen = zipmapDecodeLength(zm); *key += ZIPMAP_LEN_BYTES(*klen); } zm += zipmapRawKeyLength(zm); // 获取value if (value) { // +1是为了跳过free字段,该字段占用一个字节 *value = zm+1; *vlen = zipmapDecodeLength(zm); *value += ZIPMAP_LEN_BYTES(*vlen); } // 此时zm指向下一个键值对的首地址 zm += zipmapRawValueLength(zm); return zm; }
/* Encode the length 'l' writing it in 'p'. If p is NULL it just returns * the amount of bytes required to encode such a length. */ static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) { if (p == NULL) { return ZIPMAP_LEN_BYTES(len); } else { if (len < ZIPMAP_BIGLEN) { p[0] = len; return 1; } else { p[0] = ZIPMAP_BIGLEN; memcpy(p+1,&len,sizeof(len)); return 1+sizeof(len); } } }
/* 将长度len编码到p指针指向的内存空间 */ static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) { if (p == NULL) { return ZIPMAP_LEN_BYTES(len); } else { if (len < ZIPMAP_BIGLEN) { // 长度小于254,只需要1个字节表示 p[0] = len; return 1; } else { // 长度大于等于254,第一个字节赋值为254,接下来的4歌字节才是真正的长度值 p[0] = ZIPMAP_BIGLEN; memcpy(p+1,&len,sizeof(len)); memrev32ifbe(p+1); return 1+sizeof(len); } } }
/* Search a key and retrieve the pointer and len of the associated value. * If the key is found the function returns 1, otherwise 0. * * 在 zipmap 中按 key 进行查找, * 将值的指针保存到 *value 中,并将值的长度保存到 *vlen 中。 * * 成功找到值时函数返回 1 ,没找到则返回 0 。 * * T = O(N^2) */ int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen) { unsigned char *p; // 在 zipmap 中按 key 查找 // 没找到直接返回 0 // T = O(N^2) if ((p = zipmapLookupRaw(zm,key,klen,NULL)) == NULL) return 0; // 越过键,指向值 p += zipmapRawKeyLength(p); // 取出值的长度 *vlen = zipmapDecodeLength(p); // 将 *value 指向值, +1 为越过 <free> 属性 *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1; // 找到,返回 1 return 1; }
/* Search a key and retrieve the pointer and len of the associated value. * If the key is found the function returns 1, otherwise 0. */ int zipmapXGet(unsigned char **zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen, unsigned int timestamp) { unsigned char *p; if ((p = zipmapXLookupRaw(*zm,key,klen,NULL,NULL)) == NULL) return 0; p += zipmapRawKeyLength(p); unsigned int ts = *(unsigned int*)p; p += sizeof(unsigned int); *vlen = zipmapDecodeLength(p); *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1; if (ts < timestamp) { *vlen = 0; *value = NULL; return 0; } return 1; }
/* Encode the length 'l' writing it in 'p'. If p is NULL it just returns * the amount of bytes required to encode such a length. * * 编码长度 l ,将它写入到 p 中,然后返回编码 l 所需的字节数。 * 如果 p 是 NULL ,那么函数只返回编码 l 所需的字节数,不进行任何写入。 * * T = O(1) */ static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) { // 只返回编码所需的字节数 if (p == NULL) { return ZIPMAP_LEN_BYTES(len); // 编码,并写入,然后返回编码所需的字节数 } else { if (len < ZIPMAP_BIGLEN) { p[0] = len; return 1; } else { p[0] = ZIPMAP_BIGLEN; memcpy(p+1,&len,sizeof(len)); memrev32ifbe(p+1); return 1+sizeof(len); } } }