// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/zipmap.c
// Function: zipmapLookupRaw
static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {

    // zm+1 略过 <zmlen> 属性，将 p 指向 zipmap 的首个节点
    unsigned char *p = zm+1, *k = NULL;
    unsigned int l,llen;

    // 遍历整个 zipmap 来寻找
    // T = O(N^2)
    while(*p != ZIPMAP_END) {
        unsigned char free;

        /* Match or skip the key */
        // 计算键的长度
        l = zipmapDecodeLength(p);
        // 计算编码键的长度所需的字节数
        llen = zipmapEncodeLength(NULL,l);
        // 对比 key
        // T = O(N)
        if (key != NULL && k == NULL && l == klen && !memcmp(p+llen,key,l)) {
            /* Only return when the user doesn't care
             * for the total length of the zipmap. */
            if (totlen != NULL) {
                // 如果调用者需要知道整个 zipmap 的长度，那么记录找到的指针到变量 k
                // 之后遍历时，程序只计算 zipmap 剩余节点的长度，不再用 memcmp 进行对比
                // 因为 k 已经不为 NULL 了
                k = p;
            } else {
                // 如果调用者不需要知道整个 zipmap 的长度，那么直接返回 p 
                return p;
            }
        }

        // 越过键节点，指向值节点
        p += llen+l;

        /* Skip the value as well */
        // 计算值的长度
        l = zipmapDecodeLength(p);
        // 计算编码值的长度所需的字节数，
        // 并移动指针 p ，越过该 <len> 属性，指向 <free> 属性
        p += zipmapEncodeLength(NULL,l);
        // 取出 <free> 属性的值
        free = p[0];
        // 略过值节点，指向下一节点
        p += l+1+free; /* +1 to skip the free byte */
    }

    // 计算并记录 zipmap 的空间长度
    // + 1 是将 ZIPMAP_END 也计算在内
    if (totlen != NULL) *totlen = (unsigned int)(p-zm)+1;

    // 返回找到 key 的指针
    return k;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq %rcx, -0x28(%rbp)
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
movq $0x0, -0x38(%rbp)
movq -0x30(%rbp), %rax
movzbl (%rax), %eax
cmpl $0xff, %eax
je 0x3033c
movq -0x30(%rbp), %rdi
callq 0x30660
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %esi
xorl %eax, %eax
movl %eax, %edi
callq 0x303f0
movl %eax, -0x40(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x302db
cmpq $0x0, -0x38(%rbp)
jne 0x302db
movl -0x3c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jne 0x302db
movq -0x30(%rbp), %rdi
movl -0x40(%rbp), %eax
addq %rax, %rdi
movq -0x18(%rbp), %rsi
movl -0x3c(%rbp), %eax
movl %eax, %edx
callq 0x1f950
cmpl $0x0, %eax
jne 0x302db
cmpq $0x0, -0x28(%rbp)
je 0x302cc
movq -0x30(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x302d9
movq -0x30(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x30361
jmp 0x302db
movl -0x40(%rbp), %ecx
addl -0x3c(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
callq 0x30660
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %esi
xorl %eax, %eax
movl %eax, %edi
callq 0x303f0
movl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movb (%rax), %al
movb %al, -0x41(%rbp)
movl -0x3c(%rbp), %ecx
addl $0x1, %ecx
movzbl -0x41(%rbp), %eax
addl %eax, %ecx
movq -0x30(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
jmp 0x3025b
cmpq $0x0, -0x28(%rbp)
je 0x30359
movq -0x30(%rbp), %rax
movq -0x10(%rbp), %rcx
subq %rcx, %rax
movl %eax, %ecx
addl $0x1, %ecx
movq -0x28(%rbp), %rax
movl %ecx, (%rax)
movq -0x38(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax,%rax)