// File: attractivechaos[P]udb2/stb/./stb.h
// Function: stb_write
void stb_write(char *data, int data_len)
{
   stb_uint i;

   // @TODO: fast path for filling the buffer and doing nothing else
   //   if (xtb.valid + data_len < xtb.size)

   xtb.total_bytes += data_len;

   while (data_len) {
      // fill buffer
      if (xtb.valid < xtb.size) {
         int amt = xtb.size - xtb.valid;
         if (data_len < amt) amt = data_len;
         memcpy(xtb.buffer + xtb.valid, data, amt);
         data_len -= amt;
         data     += amt;
         xtb.valid += amt;
      }
      if (xtb.valid < xtb.size)
         return;

      // at this point, the buffer is full

      // if we can process some data, go for it; make sure
      // we leave an 'fsize's worth of data, though
      if (xtb.start + xtb.fsize < xtb.valid) {
         int amount = (xtb.valid - xtb.fsize) - xtb.start;
         int n;
         assert(amount > 0);
         n = stb_compress_chunk(xtb.buffer, xtb.buffer + xtb.start, xtb.buffer + xtb.valid,
                                amount, &xtb.pending_literals, xtb.chash, xtb.hashmask);
         xtb.start += n;
      }

      assert(xtb.start + xtb.fsize >= xtb.valid);
      // at this point, our future size is too small, so we
      // need to flush some history. we, in fact, flush exactly
      // one window's worth of history

      {
         int flush = xtb.window;
         assert(xtb.start >= flush);
         assert(xtb.valid >= flush);

         // if 'pending literals' extends back into the shift region,
         // write them out
         if (xtb.start - xtb.pending_literals < flush) {
            outliterals(xtb.buffer + xtb.start - xtb.pending_literals, xtb.pending_literals);
            xtb.pending_literals = 0;
         }

         // now shift the window
         memmove(xtb.buffer, xtb.buffer + flush, xtb.valid - flush);
         xtb.start -= flush;
         xtb.valid -= flush;
   
         for (i=0; i <= xtb.hashmask; ++i)
            if (xtb.chash[i] < xtb.buffer + flush)
               xtb.chash[i] = NULL;
            else
               xtb.chash[i] -= flush;
      }
      // and now that we've made room for more data, go back to the top
   }
}

// Assembly:
subq $0x28, %rsp
movq %rdi, 0x20(%rsp)
movl %esi, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
addl 0x11cfd(%rip), %eax     # 0x2c004
movl %eax, 0x11cf7(%rip)     # 0x2c004
cmpl $0x0, 0x1c(%rsp)
je 0x1a612
movl 0x11cce(%rip), %eax     # 0x2bfec
cmpl 0x11cc4(%rip), %eax     # 0x2bfe8
jge 0x1a39a
movl 0x11cbc(%rip), %eax     # 0x2bfe8
subl 0x11cba(%rip), %eax     # 0x2bfec
movl %eax, 0x14(%rsp)
movl 0x1c(%rsp), %eax
cmpl 0x14(%rsp), %eax
jge 0x1a348
movl 0x1c(%rsp), %eax
movl %eax, 0x14(%rsp)
movq 0x11c91(%rip), %rdi     # 0x2bfe0
movslq 0x11c96(%rip), %rax     # 0x2bfec
addq %rax, %rdi
movq 0x20(%rsp), %rsi
movslq 0x14(%rsp), %rdx
callq 0x2230
movl 0x14(%rsp), %ecx
movl 0x1c(%rsp), %eax
subl %ecx, %eax
movl %eax, 0x1c(%rsp)
movl 0x14(%rsp), %ecx
movq 0x20(%rsp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0x20(%rsp)
movl 0x14(%rsp), %eax
addl 0x11c58(%rip), %eax     # 0x2bfec
movl %eax, 0x11c52(%rip)     # 0x2bfec
movl 0x11c4c(%rip), %eax     # 0x2bfec
cmpl 0x11c42(%rip), %eax     # 0x2bfe8
jge 0x1a3ad
jmp 0x1a612
movl 0x11c3d(%rip), %eax     # 0x2bff0
addl 0x11c3f(%rip), %eax     # 0x2bff8
cmpl 0x11c2d(%rip), %eax     # 0x2bfec
jge 0x1a464
movl 0x11c21(%rip), %eax     # 0x2bfec
subl 0x11c27(%rip), %eax     # 0x2bff8
subl 0x11c19(%rip), %eax     # 0x2bff0
movl %eax, 0x10(%rsp)
cmpl $0x0, 0x10(%rsp)
jle 0x1a3e4
jmp 0x1a403
leaq 0x597c(%rip), %rdi      # 0x1fd67
leaq 0x4f97(%rip), %rsi      # 0x1f389
movl $0x29fa, %edx           # imm = 0x29FA
leaq 0x5974(%rip), %rcx      # 0x1fd72
callq 0x2140
movq 0x11bd6(%rip), %rdi     # 0x2bfe0
movq 0x11bcf(%rip), %rsi     # 0x2bfe0
movslq 0x11bd8(%rip), %rax     # 0x2bff0
addq %rax, %rsi
movq 0x11bbe(%rip), %rdx     # 0x2bfe0
movslq 0x11bc3(%rip), %rax     # 0x2bfec
addq %rax, %rdx
movl 0x10(%rsp), %ecx
movq 0x11bd1(%rip), %r9      # 0x2c008
movl 0x11bd3(%rip), %eax     # 0x2c010
leaq 0x11b9c(%rip), %r8      # 0x2bfe0
addq $0x1c, %r8
movl %eax, (%rsp)
callq 0x1a620
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
addl 0x11b92(%rip), %eax     # 0x2bff0
movl %eax, 0x11b8c(%rip)     # 0x2bff0
movl 0x11b86(%rip), %eax     # 0x2bff0
addl 0x11b88(%rip), %eax     # 0x2bff8
cmpl 0x11b76(%rip), %eax     # 0x2bfec
jl 0x1a47a
jmp 0x1a499
leaq 0x590d(%rip), %rdi      # 0x1fd8e
leaq 0x4f01(%rip), %rsi      # 0x1f389
movl $0x2a00, %edx           # imm = 0x2A00
leaq 0x58de(%rip), %rcx      # 0x1fd72
callq 0x2140
movl 0x11b55(%rip), %eax     # 0x2bff4
movl %eax, 0x8(%rsp)
movl 0x11b47(%rip), %eax     # 0x2bff0
cmpl 0x8(%rsp), %eax
jl 0x1a4b1
jmp 0x1a4d0
leaq 0x58f9(%rip), %rdi      # 0x1fdb1
leaq 0x4eca(%rip), %rsi      # 0x1f389
movl $0x2a07, %edx           # imm = 0x2A07
leaq 0x58a7(%rip), %rcx      # 0x1fd72
callq 0x2140
movl 0x11b16(%rip), %eax     # 0x2bfec
cmpl 0x8(%rsp), %eax
jl 0x1a4de
jmp 0x1a4fd
leaq 0x58df(%rip), %rdi      # 0x1fdc4
leaq 0x4e9d(%rip), %rsi      # 0x1f389
movl $0x2a08, %edx           # imm = 0x2A08
leaq 0x587a(%rip), %rcx      # 0x1fd72
callq 0x2140
movl 0x11aed(%rip), %eax     # 0x2bff0
subl 0x11af3(%rip), %eax     # 0x2bffc
cmpl 0x8(%rsp), %eax
jge 0x1a544
movq 0x11aca(%rip), %rdi     # 0x2bfe0
movslq 0x11ad3(%rip), %rax     # 0x2bff0
addq %rax, %rdi
movslq 0x11ad5(%rip), %rcx     # 0x2bffc
xorl %eax, %eax
subq %rcx, %rax
addq %rax, %rdi
movl 0x11ac7(%rip), %esi     # 0x2bffc
callq 0x1b010
movl $0x0, 0x11ab8(%rip)     # 0x2bffc
movq 0x11a95(%rip), %rdi     # 0x2bfe0
movq 0x11a8e(%rip), %rsi     # 0x2bfe0
movslq 0x8(%rsp), %rax
addq %rax, %rsi
movl 0x11a8c(%rip), %eax     # 0x2bfec
subl 0x8(%rsp), %eax
movslq %eax, %rdx
callq 0x22d0
movl 0x8(%rsp), %ecx
movl 0x11a7a(%rip), %eax     # 0x2bff0
subl %ecx, %eax
movl %eax, 0x11a72(%rip)     # 0x2bff0
movl 0x8(%rsp), %ecx
movl 0x11a64(%rip), %eax     # 0x2bfec
subl %ecx, %eax
movl %eax, 0x11a5c(%rip)     # 0x2bfec
movl $0x0, 0x18(%rsp)
movl 0x18(%rsp), %eax
cmpl 0x11a6e(%rip), %eax     # 0x2c010
ja 0x1a60d
movq 0x11a5d(%rip), %rax     # 0x2c008
movl 0x18(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq 0x11a26(%rip), %rcx     # 0x2bfe0
movslq 0x8(%rsp), %rdx
addq %rdx, %rcx
cmpq %rcx, %rax
jae 0x1a5dc
movq 0x11a3a(%rip), %rax     # 0x2c008
movl 0x18(%rsp), %ecx
movq $0x0, (%rax,%rcx,8)
jmp 0x1a5fe
movl 0x8(%rsp), %esi
movq 0x11a21(%rip), %rax     # 0x2c008
movl 0x18(%rsp), %ecx
movq (%rax,%rcx,8), %rdx
movslq %esi, %rdi
xorl %esi, %esi
subq %rdi, %rsi
addq %rsi, %rdx
movq %rdx, (%rax,%rcx,8)
jmp 0x1a600
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x1a598
jmp 0x1a30d
addq $0x28, %rsp
retq
nopw (%rax,%rax)