// File: /workspace/github_c_makefile_star2_O2/ijleesw[P]data-compression/src/golomb/encode.c
// Function: zlib_decode
int
zlib_decode (void *input, unsigned long input_len, 
    void **output, unsigned long *output_len) 
{
  int ret;
  unsigned have;
  z_stream strm;
  //unsigned char in[CHUNK];
  //unsigned char out[CHUNK];
  unsigned char *in;
  unsigned char *out_head, *out;
  unsigned long bytes_left, bytes_written;
  unsigned long output_bytes, output_bytes_left;
  int buf_realloc_penalty = BUF_REALLOC_PENALTY;

  bytes_left = input_len;
  bytes_written = 0;
  in = (unsigned char*) input;

  /* allocate a reasonable amount of space */

  output_bytes = input_len > CHUNK_2 ? input_len : CHUNK_2;
  if ( !(out_head = (unsigned char*) malloc (output_bytes)) ) {
    printf ("decode: malloc failed\n");
    goto decode_error_save;
  }
  out = out_head;
  output_bytes_left = output_bytes;

  /* allocate inflate state */
  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;
  strm.avail_in = 0;
  strm.next_in = Z_NULL;
  ret = inflateInit(&strm);
  if (ret != Z_OK) {
    //return ret;
    return 1;
  }

  /* decompress until deflate stream ends or end of file */
  do {
    //strm.avail_in = fread(in, 1, CHUNK, source);
    if (bytes_left > CHUNK) {
      strm.avail_in = CHUNK;
      strm.next_in = in;
      in += CHUNK;
      //bytes_left -= CHUNK;
    } else if (bytes_left == 0) {
      printf ("hmm, shouldnt have come here?\n");
      break;
    } else {
      strm.avail_in = bytes_left;
      strm.next_in = in;
      in += bytes_left;
      //bytes_left = 0;
    }

    //printf ("decode: going ahead with %d bytes\n", strm.avail_in);
    //if (ferror(source)) {
      //(void)inflateEnd(&strm);
      //return Z_ERRNO;
    //}
    //if (strm.avail_in == 0)
      //break;
    //strm.next_in = in;

    /* run inflate() on input until output buffer not full */
    do {
      /* to make sure we have at least CHUNK bytes left in out buffer */
      //assert (bytes_written + CHUNK <= input_len);
      //printf ("curr size: %lu, in bytes left: %lu, out bytes left: %lu\n",
          //output_bytes, bytes_left, output_bytes_left);
      if (bytes_left && output_bytes_left < CHUNK_2) {
        unsigned extra = buf_realloc_penalty*CHUNK;
        unsigned offset = out - out_head;
        if (!(out_head = realloc (out_head, output_bytes + extra)) ) {
          printf ("allocing more bytes didnt work");
          goto decode_error_save;
        }
        output_bytes += extra;
        output_bytes_left += extra;
        out = out_head + offset;
        buf_realloc_penalty *= BUF_REALLOC_PENALTY;
      }
         
      strm.avail_out = CHUNK;
      strm.next_out = out;
      ret = inflate(&strm, Z_NO_FLUSH);
      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
      switch (ret) {
        case Z_NEED_DICT:
          ret = Z_DATA_ERROR;     /* and fall through */
        case Z_DATA_ERROR:
        case Z_MEM_ERROR:
          (void)inflateEnd(&strm);
          //return ret;
          return 1;
      }
      have = CHUNK - strm.avail_out;

      out += have;
      bytes_written += have;
      output_bytes_left -= have;

      //if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
        //(void)inflateEnd(&strm);
        //return Z_ERRNO;
      //}
    } while (strm.avail_out == 0);

    bytes_left = (bytes_left > CHUNK) ? (bytes_left - CHUNK) : 0;
      
    /* done when inflate() says it's done */
  } while (ret != Z_STREAM_END);

  /* clean up and return */
  (void)inflateEnd(&strm);

  /* prepare stuff to be returned */
  if (bytes_written < input_len)
    printf ("in decode: encoding sucks: input was %lu but "
        "output is %lu\n", input_len, bytes_written);

  if ( !(out_head = realloc (out_head, bytes_written)) )  {
    perror ("realloc failed: ");
    goto decode_error_save;
  }
  *output = out_head;
  *output_len = bytes_written;

  //return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
  return ret == Z_STREAM_END ? 0 : -1;

decode_error_save:
  if (out_head) free (out_head);
  *output_len = 0;
  return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %rcx, %rbx
movq %rdx, %r12
movq %rsi, %r13
movq %rdi, 0x10(%rsp)
cmpq $0x4001, %rsi           # imm = 0x4001
movl $0x4000, %r14d          # imm = 0x4000
cmovaeq %rsi, %r14
movq %r14, %rdi
callq 0x2170
pushq $0x1
popq %rbp
testq %rax, %rax
je 0x2ed9
movq %rax, (%rsp)
leaq 0x38(%rsp), %rdi
andl $0x0, 0x8(%rdi)
andq $0x0, (%rdi)
xorps %xmm0, %xmm0
movups %xmm0, 0x40(%rdi)
andq $0x0, 0x50(%rdi)
leaq 0x14c3(%rip), %rsi      # 0x426b
pushq $0x70
popq %rdx
callq 0x21b0
testl %eax, %eax
jne 0x2ef8
movq %r12, 0x20(%rsp)
movq %rbx, 0x8(%rsp)
pushq $0x3
popq %rbp
movq %r14, %rbx
xorl %r14d, %r14d
leaq 0x38(%rsp), %r15
movq (%rsp), %r12
movq %r13, 0x28(%rsp)
movq %r13, %rdx
movq %rbx, 0x18(%rsp)
movl $0x2000, %eax           # imm = 0x2000
movl $0x2000, %ecx           # imm = 0x2000
cmpq $0x2000, %rdx           # imm = 0x2000
ja 0x2e02
testq %rdx, %rdx
je 0x2f24
movl %edx, %ecx
movq %rdx, %rax
movq %rdx, 0x30(%rsp)
movl %ecx, 0x40(%rsp)
movq 0x10(%rsp), %rcx
movq %rcx, 0x38(%rsp)
addq %rax, %rcx
movq %rcx, 0x10(%rsp)
cmpq $0x3fff, %rbx           # imm = 0x3FFF
ja 0x2e6d
movq %r14, %r15
movq %rbp, %r14
shll $0xd, %ebp
movq 0x18(%rsp), %rsi
addq %rbp, %rsi
movq (%rsp), %r13
movq %r13, %rdi
movq %rsi, 0x18(%rsp)
callq 0x21a0
testq %rax, %rax
je 0x2f0c
subl %r13d, %r12d
addq %rbp, %rbx
addq %rax, %r12
leal (%r14,%r14,2), %r14d
movq %rax, (%rsp)
movq %r14, %rbp
movq %r15, %r14
leaq 0x38(%rsp), %r15
movl $0x2000, 0x58(%rsp)     # imm = 0x2000
movq %r12, 0x50(%rsp)
movq %r15, %rdi
xorl %esi, %esi
callq 0x2030
leal 0x4(%rax), %ecx
cmpl $0x2, %ecx
jb 0x2eeb
cmpl $0x2, %eax
je 0x2eeb
cmpl $-0x2, %eax
je 0x2f90
movl 0x58(%rsp), %ecx
movl $0x2000, %edx           # imm = 0x2000
subl %ecx, %edx
addq %rdx, %r12
addq %rdx, %r14
subq %rdx, %rbx
testl %ecx, %ecx
je 0x2e1d
xorl %r13d, %r13d
movq 0x30(%rsp), %rdx
subq $0x2000, %rdx           # imm = 0x2000
movl $0x0, %ecx
cmovbq %rcx, %rdx
cmpl $0x1, %eax
jne 0x2de1
jmp 0x2f34
leaq 0x159b(%rip), %rdi      # 0x447b
callq 0x2040
andq $0x0, (%rbx)
jmp 0x2ef8
leaq 0x38(%rsp), %rdi
callq 0x2150
pushq $0x1
popq %rbp
movl %ebp, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x135f(%rip), %rdi      # 0x4272
xorl %eax, %eax
callq 0x2080
movq 0x8(%rsp), %rbx
pushq $0x1
popq %rbp
jmp 0x2ee5
leaq 0x1566(%rip), %rdi      # 0x4491
callq 0x2040
pushq $-0x1
popq %r13
leaq 0x38(%rsp), %rdi
callq 0x2150
movq 0x28(%rsp), %rsi
cmpq %rsi, %r14
jae 0x2f59
leaq 0x142b(%rip), %rdi      # 0x437a
movq %r14, %rdx
xorl %eax, %eax
callq 0x2080
movq (%rsp), %rdi
movq %r14, %rsi
callq 0x21a0
testq %rax, %rax
je 0x2f82
movq 0x20(%rsp), %rcx
movq %rax, (%rcx)
movq 0x8(%rsp), %rax
movq %r14, (%rax)
movl %r13d, %ebp
jmp 0x2ef8
leaq 0x139f(%rip), %rdi      # 0x4328
callq 0x21d0
jmp 0x2f1a
leaq 0x12fa(%rip), %rdi      # 0x4291
leaq 0x1309(%rip), %rsi      # 0x42a7
leaq 0x1394(%rip), %rcx      # 0x4339
movl $0x481, %edx            # imm = 0x481
callq 0x2090