/* 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;
}
Example #2
0
/* 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;
}
Example #3
0
/* 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;
}
Example #5
0
/* 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;
}
Example #8
0
/* 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);
        }
    }
}