// File: /workspace/github_c_makefile_star2_O1/OnionIoT[P]lv_example/lvgl/src/lv_draw/lv_img_cache.c
// Function: lv_img_cache_open
lv_img_cache_entry_t * lv_img_cache_open(const void * src, const lv_style_t * style)
{
    if(entry_cnt == 0) {
        LV_LOG_WARN("lv_img_cache_open: the cache size is 0");
        return NULL;
    }

    lv_img_cache_entry_t * cache = LV_GC_ROOT(_lv_img_cache_array);

    /*Decrement all lifes. Make the entries older*/
    uint16_t i;
    for(i = 0; i < entry_cnt; i++) {
        if(cache[i].life > INT32_MIN + LV_IMG_CACHE_AGING) {
            cache[i].life -= LV_IMG_CACHE_AGING;
        }
    }

    /*Is the image cached?*/
    lv_img_cache_entry_t * cached_src = NULL;
    for(i = 0; i < entry_cnt; i++) {
        bool match = false;
        lv_img_src_t src_type = lv_img_src_get_type(cache[i].dec_dsc.src);
        if(src_type == LV_IMG_SRC_VARIABLE) {
            if(cache[i].dec_dsc.src == src) match = true;
        } else if(src_type == LV_IMG_SRC_FILE) {
            if(strcmp(cache[i].dec_dsc.src, src) == 0) match = true;
        }

        if(match) {
            /* If opened increment its life.
             * Image difficult to open should live longer to keep avoid frequent their recaching.
             * Therefore increase `life` with `time_to_open`*/
            cached_src = &cache[i];
            cached_src->life += cached_src->dec_dsc.time_to_open * LV_IMG_CACHE_LIFE_GAIN;
            if(cached_src->life > LV_IMG_CACHE_LIFE_LIMIT) cached_src->life = LV_IMG_CACHE_LIFE_LIMIT;
            LV_LOG_TRACE("image draw: image found in the cache");
            break;
        }
    }

    /*The image is not cached then cache it now*/
    if(cached_src == NULL) {
        /*Find an entry to reuse. Select the entry with the least life*/
        cached_src = &cache[0];
        for(i = 1; i < entry_cnt; i++) {
            if(cache[i].life < cached_src->life) {
                cached_src = &cache[i];
            }
        }

        /*Close the decoder to reuse if it was opened (has a valid source)*/
        if(cached_src->dec_dsc.src) {
            lv_img_decoder_close(&cached_src->dec_dsc);
            LV_LOG_INFO("image draw: cache miss, close and reuse an entry");
        } else {
            LV_LOG_INFO("image draw: cache miss, cached to an empty entry");
        }

        /*Open the image and measure the time to open*/
        uint32_t t_start;
        t_start                          = lv_tick_get();
        cached_src->dec_dsc.time_to_open = 0;
        lv_res_t open_res                = lv_img_decoder_open(&cached_src->dec_dsc, src, style);
        if(open_res == LV_RES_INV) {
            LV_LOG_WARN("Image draw cannot open the image resource");
            lv_img_decoder_close(&cached_src->dec_dsc);
            memset(&cached_src->dec_dsc, 0, sizeof(lv_img_decoder_dsc_t));
            memset(cached_src, 0, sizeof(lv_img_cache_entry_t));
            cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its use  */
            return NULL;
        }

        cached_src->life = 0;

        /*If `time_to_open` was not set in the open function set it here*/
        if(cached_src->dec_dsc.time_to_open == 0) {
            cached_src->dec_dsc.time_to_open = lv_tick_elaps(t_start);
        }

        if(cached_src->dec_dsc.time_to_open == 0) cached_src->dec_dsc.time_to_open = 1;
    }

    return cached_src;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movzwl 0x33812(%rip), %eax     # 0x71af4
testq %rax, %rax
je 0x3e45b
movq %rdi, %r14
movq %rsi, (%rsp)
leaq 0x2a2a7(%rip), %rcx     # 0x685a0
movq (%rcx), %r12
shll $0x3, %eax
leaq (%rax,%rax,8), %rax
xorl %ecx, %ecx
movl 0x40(%r12,%rcx), %edx
cmpl $0x80000002, %edx       # imm = 0x80000002
jl 0x3e319
decl %edx
movl %edx, 0x40(%r12,%rcx)
addq $0x48, %rcx
cmpq %rcx, %rax
jne 0x3e305
cmpw $0x0, 0x337ca(%rip)     # 0x71af4
je 0x3e39b
xorl %r13d, %r13d
movq %r12, %r15
xorl %ebx, %ebx
movq 0x8(%r15), %rdi
callq 0x3c49f
movb $0x1, %bpl
cmpb $0x1, %al
je 0x3e351
movzbl %al, %eax
testl %eax, %eax
jne 0x3e381
cmpq %r14, 0x8(%r15)
jmp 0x3e35f
movq 0x8(%r15), %rdi
movq %r14, %rsi
callq 0x20e0
testl %eax, %eax
sete %al
testb %al, %al
je 0x3e381
movl 0x40(%r15), %eax
addl 0x28(%r15), %eax
movl $0x3e8, %ecx            # imm = 0x3E8
cmpl %ecx, %eax
cmovgel %ecx, %eax
movl %eax, 0x40(%r15)
xorl %ebp, %ebp
movq %r15, %rbx
testb %bpl, %bpl
je 0x3e39d
incq %r13
movzwl 0x33764(%rip), %eax     # 0x71af4
addq $0x48, %r15
cmpq %rax, %r13
jb 0x3e334
jmp 0x3e39d
xorl %ebx, %ebx
testq %rbx, %rbx
jne 0x3e45d
movzwl 0x33747(%rip), %eax     # 0x71af4
cmpq $0x2, %rax
jb 0x3e3d9
leaq 0x48(%r12), %rcx
decq %rax
movl 0x40(%rcx), %edx
movq %rcx, %rbx
cmpl 0x40(%r12), %edx
jl 0x3e3cb
movq %r12, %rbx
addq $0x48, %rcx
movq %rbx, %r12
decq %rax
jne 0x3e3bb
jmp 0x3e3dc
movq %r12, %rbx
cmpq $0x0, 0x8(%rbx)
je 0x3e3eb
movq %rbx, %rdi
callq 0x3e27e
callq 0x883e
movl %eax, %ebp
movl $0x0, 0x28(%rbx)
movq %rbx, %rdi
movq %r14, %rsi
movq (%rsp), %rdx
callq 0x3e162
testb %al, %al
je 0x3e432
movl $0x0, 0x40(%rbx)
cmpl $0x0, 0x28(%rbx)
jne 0x3e423
movl %ebp, %edi
callq 0x8855
movl %eax, 0x28(%rbx)
cmpl $0x0, 0x28(%rbx)
jne 0x3e45d
movl $0x1, 0x28(%rbx)
jmp 0x3e45d
movq %rbx, %rdi
callq 0x3e27e
xorps %xmm0, %xmm0
movups %xmm0, 0x30(%rbx)
movups %xmm0, 0x20(%rbx)
movups %xmm0, 0x10(%rbx)
movups %xmm0, (%rbx)
movq $0x0, 0x40(%rbx)
movl $0x80000000, 0x40(%rbx) # imm = 0x80000000
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq