// File: /workspace/github_c_makefile_star2_O2/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 0x353da(%rip), %eax     # 0x6faf4
testq %rax, %rax
je 0x3a85c
movq %rsi, %r14
movq %rdi, %r15
leaq 0x2be70(%rip), %rcx     # 0x665a0
movq (%rcx), %rbx
imulq $0x48, %rax, %rcx
xorl %edx, %edx
cmpq %rdx, %rcx
je 0x3a756
movl 0x40(%rbx,%rdx), %esi
cmpl $0x80000002, %esi       # imm = 0x80000002
jl 0x3a750
decl %esi
movl %esi, 0x40(%rbx,%rdx)
addq $0x48, %rdx
jmp 0x3a739
xorl %r13d, %r13d
movq %rbx, %r12
movzwl %ax, %eax
cmpq %rax, %r13
jae 0x3a7aa
movq 0x8(%r12), %rdi
callq 0x389cd
cmpb $0x1, %al
je 0x3a785
movzbl %al, %eax
testl %eax, %eax
jne 0x3a79a
cmpq %r15, 0x8(%r12)
jne 0x3a79a
jmp 0x3a81b
movq 0x8(%r12), %rdi
movq %r15, %rsi
callq 0x20e0
testl %eax, %eax
je 0x3a81b
incq %r13
movzwl 0x35350(%rip), %eax     # 0x6faf4
addq $0x48, %r12
jmp 0x3a75c
leaq 0x48(%rbx), %rcx
pushq $0x1
popq %rdx
cmpq %rax, %rdx
jae 0x3a7d0
movl 0x40(%rcx), %edi
movq %rcx, %rsi
cmpl 0x40(%rbx), %edi
jl 0x3a7c4
movq %rbx, %rsi
incq %rdx
addq $0x48, %rcx
movq %rsi, %rbx
jmp 0x3a7b1
cmpq $0x0, 0x8(%rbx)
je 0x3a7df
movq %rbx, %rdi
callq 0x3a69b
callq 0x801a
movl %eax, %ebp
andl $0x0, 0x28(%rbx)
movq %rbx, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x3a587
testb %al, %al
je 0x3a836
andl $0x0, 0x40(%rbx)
cmpl $0x0, 0x28(%rbx)
jne 0x3a816
movl %ebp, %edi
callq 0x8031
cmpl $0x1, %eax
adcl $0x0, %eax
movl %eax, 0x28(%rbx)
movq %rbx, %r12
jmp 0x3a85f
movl 0x40(%r12), %eax
addl 0x28(%r12), %eax
movl $0x3e8, %ecx            # imm = 0x3E8
cmpl %ecx, %eax
cmovgel %ecx, %eax
movl %eax, 0x40(%r12)
jmp 0x3a85f
movq %rbx, %rdi
callq 0x3a69b
xorps %xmm0, %xmm0
movups %xmm0, 0x30(%rbx)
movups %xmm0, 0x20(%rbx)
andq $0x0, 0x40(%rbx)
movups %xmm0, 0x10(%rbx)
movups %xmm0, (%rbx)
movl $0x80000000, 0x40(%rbx) # imm = 0x80000000
xorl %r12d, %r12d
movq %r12, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq