// File: mhe[P]raytracerframework_cpp/lodepng.cpp
// Function: getTreeInflateDynamic(HuffmanTree*, HuffmanTree*, HuffmanTree*, unsigned char const*, unsigned long*, unsigned long)
static unsigned getTreeInflateDynamic(HuffmanTree* codetree, HuffmanTree* codetreeD, HuffmanTree* codelengthcodetree,
                                      const unsigned char* in, size_t* bp, size_t inlength)
{
  /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/
  /*C-code note: use no "return" between ctor and dtor of an uivector!*/
  unsigned error = 0;
  unsigned n, HLIT, HDIST, HCLEN, i;
  uivector bitlen;
  uivector bitlenD;
  uivector codelengthcode;
  
  if((*bp) >> 3 >= inlength - 2) { return 49; } /*the bit pointer is or will go past the memory*/

  HLIT =  readBitsFromStream(bp, in, 5) + 257; /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/
  HDIST = readBitsFromStream(bp, in, 5) + 1; /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/
  HCLEN = readBitsFromStream(bp, in, 4) + 4; /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/
  
  /*read the code length codes out of 3 * (amount of code length codes) bits*/
  uivector_init(&codelengthcode);
  if(!uivector_resize(&codelengthcode, NUM_CODE_LENGTH_CODES)) error = 9911;
  
  if(!error)
  {
    for(i = 0; i < NUM_CODE_LENGTH_CODES; i++)
    {
      if(i < HCLEN) codelengthcode.data[CLCL[i]] = readBitsFromStream(bp, in, 3);
      else codelengthcode.data[CLCL[i]] = 0; /*if not, it must stay 0*/
    }
    
    error = HuffmanTree_makeFromLengths(codelengthcodetree, codelengthcode.data, codelengthcode.size, 7);
  }

  uivector_cleanup(&codelengthcode);
  if(error) return error;
  
  /*now we can use this tree to read the lengths for the tree that this function will return*/
  uivector_init(&bitlen);
  uivector_resizev(&bitlen, NUM_DEFLATE_CODE_SYMBOLS, 0);
  uivector_init(&bitlenD);
  uivector_resizev(&bitlenD, NUM_DISTANCE_SYMBOLS, 0);
  i = 0;
  if(!bitlen.data || !bitlenD.data) error = 9912;
  else while(i < HLIT + HDIST) /*i is the current symbol we're reading in the part that contains the code lengths of lit/len codes and dist codes*/
  {
    unsigned code = huffmanDecodeSymbol(&error, in, bp, codelengthcodetree, inlength);
    if(error) break;
    
    if(code <= 15) /*a length code*/
    {
      if(i < HLIT) bitlen.data[i] = code;
      else bitlenD.data[i - HLIT] = code;
      i++;
    }
    else if(code == 16) /*repeat previous*/
    {
      unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/
      unsigned value; /*set value to the previous code*/
      
      if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/
      
      replength += readBitsFromStream(bp, in, 2);
      
      if((i - 1) < HLIT) value = bitlen.data[i - 1];
      else value = bitlenD.data[i - HLIT - 1];
      /*repeat this value in the next lengths*/
      for(n = 0; n < replength; n++)
      {
        if(i >= HLIT + HDIST) { error = 13; break; } /*error: i is larger than the amount of codes*/
        if(i < HLIT) bitlen.data[i] = value;
        else bitlenD.data[i - HLIT] = value;
        i++;
      }
    }
    else if(code == 17) /*repeat "0" 3-10 times*/
    {
      unsigned replength = 3; /*read in the bits that indicate repeat length*/
      if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/

      replength += readBitsFromStream(bp, in, 3);
      
      /*repeat this value in the next lengths*/
      for(n = 0; n < replength; n++)
      {
        if(i >= HLIT + HDIST) { error = 14; break; } /*error: i is larger than the amount of codes*/
        if(i < HLIT) bitlen.data[i] = 0;
        else bitlenD.data[i - HLIT] = 0;
        i++;
      }
    }
    else if(code == 18) /*repeat "0" 11-138 times*/
    {
      unsigned replength = 11; /*read in the bits that indicate repeat length*/
      if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/
      replength += readBitsFromStream(bp, in, 7);
      
      /*repeat this value in the next lengths*/
      for(n = 0; n < replength; n++)
      {
        if(i >= HLIT + HDIST) { error = 15; break; } /*error: i is larger than the amount of codes*/
        if(i < HLIT) bitlen.data[i] = 0;
        else bitlenD.data[i - HLIT] = 0;
        i++;
      }
    }
    else { error = 16; break; } /*error: somehow an unexisting code appeared. This can never happen.*/
  }
  
  if(!error && bitlen.data[256] == 0) { error = 64; } /*the length of the end code 256 must be larger than 0*/
  
  /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/
  if(!error) error = HuffmanTree_makeFromLengths(codetree, &bitlen.data[0], bitlen.size, 15);
  if(!error) error = HuffmanTree_makeFromLengths(codetreeD, &bitlenD.data[0], bitlenD.size, 15);
  
  uivector_cleanup(&bitlen);
  uivector_cleanup(&bitlenD);
  
  return error;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
movl $0x0, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movq (%rax), %rax
shrq $0x3, %rax
movq -0x38(%rbp), %rcx
subq $0x2, %rcx
cmpq %rcx, %rax
jb 0x2d02e
movl $0x31, -0x4(%rbp)
jmp 0x2d526
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x5, %edx
callq 0x2d640
addl $0x101, %eax            # imm = 0x101
movl %eax, -0x44(%rbp)
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x5, %edx
callq 0x2d640
addl $0x1, %eax
movl %eax, -0x48(%rbp)
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x4, %edx
callq 0x2d640
addl $0x4, %eax
movl %eax, -0x4c(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x2d6a0
leaq -0x98(%rbp), %rdi
movl $0x13, %esi
callq 0x2d870
cmpl $0x0, %eax
jne 0x2d0a1
movl $0x26b7, -0x3c(%rbp)    # imm = 0x26B7
cmpl $0x0, -0x3c(%rbp)
jne 0x2d138
movl $0x0, -0x50(%rbp)
cmpl $0x13, -0x50(%rbp)
jae 0x2d119
movl -0x50(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jae 0x2d0ef
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x3, %edx
callq 0x2d640
movl %eax, %edx
movq -0x98(%rbp), %rax
movl -0x50(%rbp), %ecx
movl %ecx, %esi
leaq 0x1e989(%rip), %rcx     # 0x4ba70
movl (%rcx,%rsi,4), %ecx
movl %edx, (%rax,%rcx,4)
jmp 0x2d10c
movq -0x98(%rbp), %rax
movl -0x50(%rbp), %ecx
movl %ecx, %edx
leaq 0x1e96e(%rip), %rcx     # 0x4ba70
movl (%rcx,%rdx,4), %ecx
movl $0x0, (%rax,%rcx,4)
jmp 0x2d10e
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x2d0b2
movq -0x20(%rbp), %rdi
movq -0x98(%rbp), %rsi
movq -0x90(%rbp), %rdx
movl $0x7, %ecx
callq 0x2d910
movl %eax, -0x3c(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x2d9b0
cmpl $0x0, -0x3c(%rbp)
je 0x2d155
movl -0x3c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x2d526
leaq -0x68(%rbp), %rdi
callq 0x2d6a0
leaq -0x68(%rbp), %rdi
movl $0x120, %esi            # imm = 0x120
xorl %edx, %edx
callq 0x2dbb0
leaq -0x80(%rbp), %rdi
callq 0x2d6a0
leaq -0x80(%rbp), %rdi
movl $0x20, %esi
xorl %edx, %edx
callq 0x2dbb0
movl $0x0, -0x50(%rbp)
cmpq $0x0, -0x68(%rbp)
je 0x2d19c
cmpq $0x0, -0x80(%rbp)
jne 0x2d1a8
movl $0x26b8, -0x3c(%rbp)    # imm = 0x26B8
jmp 0x2d4b6
jmp 0x2d1aa
movl -0x50(%rbp), %eax
movl -0x44(%rbp), %ecx
addl -0x48(%rbp), %ecx
cmpl %ecx, %eax
jae 0x2d4b4
movq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x38(%rbp), %r8
leaq -0x3c(%rbp), %rdi
callq 0x2d580
movl %eax, -0x9c(%rbp)
cmpl $0x0, -0x3c(%rbp)
je 0x2d1e5
jmp 0x2d4b4
cmpl $0xf, -0x9c(%rbp)
ja 0x2d22b
movl -0x50(%rbp), %eax
cmpl -0x44(%rbp), %eax
jae 0x2d208
movl -0x9c(%rbp), %edx
movq -0x68(%rbp), %rax
movl -0x50(%rbp), %ecx
movl %edx, (%rax,%rcx,4)
jmp 0x2d21d
movl -0x9c(%rbp), %edx
movq -0x80(%rbp), %rax
movl -0x50(%rbp), %ecx
subl -0x44(%rbp), %ecx
movl %ecx, %ecx
movl %edx, (%rax,%rcx,4)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x2d4af
cmpl $0x10, -0x9c(%rbp)
jne 0x2d327
movl $0x3, -0xa0(%rbp)
movq -0x30(%rbp), %rax
movq (%rax), %rax
shrq $0x3, %rax
cmpq -0x38(%rbp), %rax
jb 0x2d25f
movl $0x32, -0x3c(%rbp)
jmp 0x2d4b4
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x2, %edx
callq 0x2d640
addl -0xa0(%rbp), %eax
movl %eax, -0xa0(%rbp)
movl -0x50(%rbp), %eax
subl $0x1, %eax
cmpl -0x44(%rbp), %eax
jae 0x2d29f
movq -0x68(%rbp), %rax
movl -0x50(%rbp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movl (%rax,%rcx,4), %eax
movl %eax, -0xa4(%rbp)
jmp 0x2d2b7
movq -0x80(%rbp), %rax
movl -0x50(%rbp), %ecx
subl -0x44(%rbp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movl (%rax,%rcx,4), %eax
movl %eax, -0xa4(%rbp)
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0xa0(%rbp), %eax
jae 0x2d322
movl -0x50(%rbp), %eax
movl -0x44(%rbp), %ecx
addl -0x48(%rbp), %ecx
cmpl %ecx, %eax
jb 0x2d2df
movl $0xd, -0x3c(%rbp)
jmp 0x2d322
movl -0x50(%rbp), %eax
cmpl -0x44(%rbp), %eax
jae 0x2d2f9
movl -0xa4(%rbp), %edx
movq -0x68(%rbp), %rax
movl -0x50(%rbp), %ecx
movl %edx, (%rax,%rcx,4)
jmp 0x2d30e
movl -0xa4(%rbp), %edx
movq -0x80(%rbp), %rax
movl -0x50(%rbp), %ecx
subl -0x44(%rbp), %ecx
movl %ecx, %ecx
movl %edx, (%rax,%rcx,4)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x2d2be
jmp 0x2d4ad
cmpl $0x11, -0x9c(%rbp)
jne 0x2d3e5
movl $0x3, -0xa8(%rbp)
movq -0x30(%rbp), %rax
movq (%rax), %rax
shrq $0x3, %rax
cmpq -0x38(%rbp), %rax
jb 0x2d35b
movl $0x32, -0x3c(%rbp)
jmp 0x2d4b4
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x3, %edx
callq 0x2d640
addl -0xa8(%rbp), %eax
movl %eax, -0xa8(%rbp)
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0xa8(%rbp), %eax
jae 0x2d3e0
movl -0x50(%rbp), %eax
movl -0x44(%rbp), %ecx
addl -0x48(%rbp), %ecx
cmpl %ecx, %eax
jb 0x2d3a1
movl $0xe, -0x3c(%rbp)
jmp 0x2d3e0
movl -0x50(%rbp), %eax
cmpl -0x44(%rbp), %eax
jae 0x2d3b9
movq -0x68(%rbp), %rax
movl -0x50(%rbp), %ecx
movl $0x0, (%rax,%rcx,4)
jmp 0x2d3cc
movq -0x80(%rbp), %rax
movl -0x50(%rbp), %ecx
subl -0x44(%rbp), %ecx
movl %ecx, %ecx
movl $0x0, (%rax,%rcx,4)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x2d380
jmp 0x2d4ab
cmpl $0x12, -0x9c(%rbp)
jne 0x2d4a0
movl $0xb, -0xac(%rbp)
movq -0x30(%rbp), %rax
movq (%rax), %rax
shrq $0x3, %rax
cmpq -0x38(%rbp), %rax
jb 0x2d419
movl $0x32, -0x3c(%rbp)
jmp 0x2d4b4
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl $0x7, %edx
callq 0x2d640
addl -0xac(%rbp), %eax
movl %eax, -0xac(%rbp)
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0xac(%rbp), %eax
jae 0x2d49e
movl -0x50(%rbp), %eax
movl -0x44(%rbp), %ecx
addl -0x48(%rbp), %ecx
cmpl %ecx, %eax
jb 0x2d45f
movl $0xf, -0x3c(%rbp)
jmp 0x2d49e
movl -0x50(%rbp), %eax
cmpl -0x44(%rbp), %eax
jae 0x2d477
movq -0x68(%rbp), %rax
movl -0x50(%rbp), %ecx
movl $0x0, (%rax,%rcx,4)
jmp 0x2d48a
movq -0x80(%rbp), %rax
movl -0x50(%rbp), %ecx
subl -0x44(%rbp), %ecx
movl %ecx, %ecx
movl $0x0, (%rax,%rcx,4)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x2d43e
jmp 0x2d4a9
movl $0x10, -0x3c(%rbp)
jmp 0x2d4b4
jmp 0x2d4ab
jmp 0x2d4ad
jmp 0x2d4af
jmp 0x2d1aa
jmp 0x2d4b6
cmpl $0x0, -0x3c(%rbp)
jne 0x2d4d0
movq -0x68(%rbp), %rax
cmpl $0x0, 0x400(%rax)
jne 0x2d4d0
movl $0x40, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jne 0x2d4ef
movq -0x10(%rbp), %rdi
movq -0x68(%rbp), %rsi
movq -0x60(%rbp), %rdx
movl $0xf, %ecx
callq 0x2d910
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jne 0x2d50e
movq -0x18(%rbp), %rdi
movq -0x80(%rbp), %rsi
movq -0x78(%rbp), %rdx
movl $0xf, %ecx
callq 0x2d910
movl %eax, -0x3c(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x2d9b0
leaq -0x80(%rbp), %rdi
callq 0x2d9b0
movl -0x3c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)