// File: king1600[P]cordpp/src/base64.cc
// Function: cordpp::b64_decode(char const*)
char* cordpp::b64_decode(const char *src) {
  // The input is invalid or not properly padded
  const size_t src_len = std::strlen(src);
  if (src_len % 4 != 0)
    return nullptr;

  // instead of figuring out exactly how long the decoded string should be
  // allocate enough. at most this is an extra 2 bytes
  char *buffer = new char[(src_len * 3 >> 2) + 1];

  // decode content with lookup table
  size_t i;
  char *p = buffer;
  for(i = 0; i < src_len - 4; i += 4) {
    *p++ = (B64_LOOKUP[(uint8_t)src[i]] << 2 | B64_LOOKUP[(uint8_t)src[i+1]] >> 4) & 0xff;
    *p++ = (B64_LOOKUP[(uint8_t)src[i+1]] << 4 | B64_LOOKUP[(uint8_t)src[i+2]] >> 2) & 0xff;
    *p++ = (B64_LOOKUP[(uint8_t)src[i+2]] << 6 | B64_LOOKUP[(uint8_t)src[i+3]]) & 0xff;
  }

  // decode padding
  *p++ = (B64_LOOKUP[(uint8_t)src[i]] << 2 | B64_LOOKUP[(uint8_t)src[i+1]] >> 4) & 0xff;

  // decode rest of padding
  if (src[i+2] != '=') {
    *p++ = (B64_LOOKUP[(uint8_t)src[i+1]] << 4 | B64_LOOKUP[(uint8_t)src[i+2]] >> 2) & 0xff;
    if (src[i+3] != '=')
      *p++ = (B64_LOOKUP[(uint8_t)src[i+2]] << 6 | B64_LOOKUP[(uint8_t)src[i+3]]) & 0xff;
    else
      *p++ = B64_LOOKUP[(uint8_t)src[i+2]] << 6 & 0xff;
  } else {
    *p++ = B64_LOOKUP[(uint8_t)src[i+1]] << 4 & 0xff;
  }

  // add null terminator and return constructed buffer
  *p = '\0';
  return buffer;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0xc580
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
andq $0x3, %rax
cmpq $0x0, %rax
je 0x101a4
movq $0x0, -0x8(%rbp)
jmp 0x10485
imulq $0x3, -0x18(%rbp), %rdi
shrq $0x2, %rdi
addq $0x1, %rdi
callq 0xc640
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x30(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq -0x18(%rbp), %rcx
subq $0x4, %rcx
cmpq %rcx, %rax
jae 0x102e8
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x7ee6c(%rip), %rax     # 0x8f060
movzbl (%rax,%rcx), %eax
shll $0x2, %eax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movzbl 0x1(%rcx,%rdx), %ecx
movl %ecx, %edx
leaq 0x7ee4f(%rip), %rcx     # 0x8f060
movzbl (%rcx,%rdx), %ecx
sarl $0x4, %ecx
orl %ecx, %eax
andl $0xff, %eax
movb %al, %cl
movq -0x30(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb %cl, (%rax)
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movzbl 0x1(%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x7ee18(%rip), %rax     # 0x8f060
movzbl (%rax,%rcx), %eax
shll $0x4, %eax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movzbl 0x2(%rcx,%rdx), %ecx
movl %ecx, %edx
leaq 0x7edfb(%rip), %rcx     # 0x8f060
movzbl (%rcx,%rdx), %ecx
sarl $0x2, %ecx
orl %ecx, %eax
andl $0xff, %eax
movb %al, %cl
movq -0x30(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb %cl, (%rax)
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movzbl 0x2(%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x7edc4(%rip), %rax     # 0x8f060
movzbl (%rax,%rcx), %eax
shll $0x6, %eax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movzbl 0x3(%rcx,%rdx), %ecx
movl %ecx, %edx
leaq 0x7eda7(%rip), %rcx     # 0x8f060
movzbl (%rcx,%rdx), %ecx
orl %ecx, %eax
andl $0xff, %eax
movb %al, %cl
movq -0x30(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb %cl, (%rax)
movq -0x28(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x28(%rbp)
jmp 0x101ca
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x7ed63(%rip), %rax     # 0x8f060
movzbl (%rax,%rcx), %eax
shll $0x2, %eax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movzbl 0x1(%rcx,%rdx), %ecx
movl %ecx, %edx
leaq 0x7ed46(%rip), %rcx     # 0x8f060
movzbl (%rcx,%rdx), %ecx
sarl $0x4, %ecx
orl %ecx, %eax
andl $0xff, %eax
movb %al, %cl
movq -0x30(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb %cl, (%rax)
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movsbl 0x2(%rax,%rcx), %eax
cmpl $0x3d, %eax
je 0x10441
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movzbl 0x1(%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x7ecf9(%rip), %rax     # 0x8f060
movzbl (%rax,%rcx), %eax
shll $0x4, %eax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movzbl 0x2(%rcx,%rdx), %ecx
movl %ecx, %edx
leaq 0x7ecdc(%rip), %rcx     # 0x8f060
movzbl (%rcx,%rdx), %ecx
sarl $0x2, %ecx
orl %ecx, %eax
andl $0xff, %eax
movb %al, %cl
movq -0x30(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb %cl, (%rax)
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movsbl 0x3(%rax,%rcx), %eax
cmpl $0x3d, %eax
je 0x1040a
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movzbl 0x2(%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x7ec93(%rip), %rax     # 0x8f060
movzbl (%rax,%rcx), %eax
shll $0x6, %eax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movzbl 0x3(%rcx,%rdx), %ecx
movl %ecx, %edx
leaq 0x7ec76(%rip), %rcx     # 0x8f060
movzbl (%rcx,%rdx), %ecx
orl %ecx, %eax
andl $0xff, %eax
movb %al, %cl
movq -0x30(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb %cl, (%rax)
jmp 0x1043f
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movzbl 0x2(%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x7ec40(%rip), %rax     # 0x8f060
movzbl (%rax,%rcx), %eax
shll $0x6, %eax
andl $0xff, %eax
movb %al, %cl
movq -0x30(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb %cl, (%rax)
jmp 0x10476
movq -0x10(%rbp), %rax
movq -0x28(%rbp), %rcx
movzbl 0x1(%rax,%rcx), %eax
movl %eax, %ecx
leaq 0x7ec09(%rip), %rax     # 0x8f060
movzbl (%rax,%rcx), %eax
shll $0x4, %eax
andl $0xff, %eax
movb %al, %cl
movq -0x30(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb %cl, (%rax)
movq -0x30(%rbp), %rax
movb $0x0, (%rax)
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
nop