// File: /workspace/github_c_makefile_star2_O1/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, %r14
movq %rsi, %r15
movq %rdi, %r12
cmpq $0x4001, %rsi           # imm = 0x4001
movl $0x4000, %edi           # imm = 0x4000
cmovaeq %rsi, %rdi
movq %rdi, (%rsp)
callq 0x2170
testq %rax, %rax
je 0x311e
movq %rax, %rbp
leaq 0x38(%rsp), %rdi
movl $0x0, 0x8(%rdi)
xorl %eax, %eax
movq %rax, (%rdi)
xorps %xmm0, %xmm0
movups %xmm0, 0x40(%rdi)
movq %rax, 0x50(%rdi)
leaq 0x12a2(%rip), %rsi      # 0x426b
movl $0x70, %edx
callq 0x21b0
movl $0x1, %ecx
testl %eax, %eax
jne 0x314c
movq %r12, 0x10(%rsp)
movq %r14, 0x18(%rsp)
movq %rbx, 0x8(%rsp)
movl $0x3, %r12d
movq %rbp, %r13
movq %r15, 0x20(%rsp)
movq %r15, %rdx
xorl %r15d, %r15d
movq (%rsp), %r14
movl $0x2000, %eax           # imm = 0x2000
movl $0x2000, %ecx           # imm = 0x2000
cmpq $0x2000, %rdx           # imm = 0x2000
ja 0x3028
testq %rdx, %rdx
je 0x3160
movl %edx, %ecx
movq %rdx, %rax
movl %ecx, 0x40(%rsp)
movq 0x10(%rsp), %rcx
movq %rcx, 0x38(%rsp)
addq %rax, %rcx
movq %rcx, 0x10(%rsp)
movq (%rsp), %rbx
movq %rdx, 0x30(%rsp)
testq %rdx, %rdx
je 0x30ad
cmpq $0x3fff, %r14           # imm = 0x3FFF
ja 0x30ad
movq %r15, 0x28(%rsp)
movl %r12d, %r15d
shll $0xd, %r15d
movq %rbx, (%rsp)
addq %r15, %rbx
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x21a0
movq %rbp, %rcx
movq %rax, %rbp
testq %rax, %rax
je 0x308d
subl %ecx, %r13d
addq %r15, %r14
addq %rbp, %r13
leal (%r12,%r12,2), %r12d
jmp 0x309f
leaq 0x11de(%rip), %rdi      # 0x4272
xorl %eax, %eax
callq 0x2080
movq (%rsp), %rbx
testq %rbp, %rbp
movq 0x28(%rsp), %r15
je 0x312f
movl $0x2000, 0x58(%rsp)     # imm = 0x2000
movq %r13, 0x50(%rsp)
leaq 0x38(%rsp), %rdi
xorl %esi, %esi
callq 0x2030
leal 0x4(%rax), %ecx
cmpl $0x2, %ecx
jb 0x313d
cmpl $0x2, %eax
je 0x313d
cmpl $-0x2, %eax
je 0x31cb
movl 0x58(%rsp), %ecx
movl $0x2000, %edx           # imm = 0x2000
subl %ecx, %edx
addq %rdx, %r13
addq %rdx, %r15
subq %rdx, %r14
testl %ecx, %ecx
movq 0x30(%rsp), %rdx
je 0x3047
movq %rbx, (%rsp)
xorl %ebx, %ebx
subq $0x2000, %rdx           # imm = 0x2000
movl $0x0, %ecx
cmovbq %rcx, %rdx
cmpl $0x1, %eax
jne 0x3007
jmp 0x3171
movq %rbx, 0x8(%rsp)
leaq 0x1351(%rip), %rdi      # 0x447b
callq 0x2040
movq 0x8(%rsp), %rax
movq $0x0, (%rax)
jmp 0x3147
leaq 0x38(%rsp), %rdi
callq 0x2150
movl $0x1, %ecx
movl %ecx, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x132a(%rip), %rdi      # 0x4491
callq 0x2040
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
leaq 0x38(%rsp), %rdi
callq 0x2150
movq 0x20(%rsp), %rsi
cmpq %rsi, %r15
jae 0x3196
leaq 0x11ee(%rip), %rdi      # 0x437a
movq %r15, %rdx
xorl %eax, %eax
callq 0x2080
movq %rbp, %rdi
movq %r15, %rsi
callq 0x21a0
testq %rax, %rax
je 0x31ba
movq 0x18(%rsp), %rcx
movq %rax, (%rcx)
movq 0x8(%rsp), %rax
movq %r15, (%rax)
movl %ebx, %ecx
jmp 0x314c
leaq 0x1167(%rip), %rdi      # 0x4328
callq 0x21d0
jmp 0x312f
leaq 0x10bf(%rip), %rdi      # 0x4291
leaq 0x10ce(%rip), %rsi      # 0x42a7
leaq 0x1159(%rip), %rcx      # 0x4339
movl $0x481, %edx            # imm = 0x481
callq 0x2090
nop