// File: onai[P]npio/./npio.h
// Function: npio_save_header_mem(void*, unsigned long, npio_Array const*, void**)
static inline int npio_save_header_mem(void* p, size_t sz, const npio_Array* array
  , void **out)
{
  size_t i, hdr_len;
  char* hdr_buf = (char*) p;
  char* hdr_end = hdr_buf + sz;
  char* hdr = hdr_buf;

  /* This is the absolute minimum space for the header the way we write it. */
  if (sz < 64)
    return ERANGE;

  memcpy(hdr, "\x93NUMPY\x1\x0", 8);
  hdr = hdr_buf + 8 + 2; /* leave 2 bytes for header_len, to be filled later*/
  hdr += sprintf(hdr, "{\"descr\": \"%c%c%d\", "
    , array->little_endian ? '<' : '>'
    , array->floating_point ? 'f' : array->is_signed ? 'i' : 'u'
    , array->bit_width / 8);
  /* There is no way hdr can overflow at this point! */

  hdr += sprintf(hdr, "\"fortran_order\": %s, "
    , array->fortran_order ? "True" : "False");
  /* Again, no need to check for overflow here. */

  hdr += sprintf(hdr, "\"shape\": (");
  for (i = 0; i < array->dim; ++i)
  {
    hdr += snprintf(hdr, hdr_end - hdr, "%ld, ", array->shape[i]);
    if (hdr >= hdr_end - 3)
      return ERANGE;
  }
  hdr += sprintf(hdr, ")} ");  /* hence the -3 above. */

  /* insert pad spaces */
  while (hdr < hdr_end && ((hdr - hdr_end) % 16))
    *hdr++ = ' ';

  /* check that we still have space */
  if ((hdr - hdr_end) % 16)
    return ERANGE;

  /* terminate with a \n.  The npy specification is vague on this. One
  interpretation is that the \n can occur first and then be followed by
  spaces, but that causes "IndentationError: unexpected indent" from the
  python loader. */
  hdr[-1] = '\n';

  /* Fill in the header_len field */
  hdr_len = hdr - hdr_buf - 10;
  hdr_buf[8] = hdr_len & 0xff;
  hdr_buf[9] = hdr_len >> 8;

  *out = hdr;
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
addq -0x18(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x50(%rbp)
cmpq $0x40, -0x18(%rbp)
jae 0x1667
movl $0x22, -0x4(%rbp)
jmp 0x18e4
movq -0x50(%rbp), %rax
movq 0x1a43(%rip), %rcx      # 0x30b5
movq %rcx, (%rax)
movq -0x40(%rbp), %rax
addq $0x8, %rax
addq $0x2, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x20(%rbp), %rax
movl 0x34(%rax), %ecx
movb $0x3c, %al
movb $0x3e, %dl
movb %dl, -0x52(%rbp)
cmpl $0x0, %ecx
movb %al, -0x51(%rbp)
jne 0x16a9
movb -0x52(%rbp), %al
movb %al, -0x51(%rbp)
movb -0x51(%rbp), %al
movsbl %al, %eax
movl %eax, -0x64(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x0, 0x38(%rax)
je 0x16c3
movb $0x66, %al
movb %al, -0x65(%rbp)
jmp 0x16e5
movq -0x20(%rbp), %rax
movl 0x3c(%rax), %ecx
movb $0x69, %al
movb $0x75, %dl
movb %dl, -0x67(%rbp)
cmpl $0x0, %ecx
movb %al, -0x66(%rbp)
jne 0x16df
movb -0x67(%rbp), %al
movb %al, -0x66(%rbp)
movb -0x66(%rbp), %al
movb %al, -0x65(%rbp)
movq -0x60(%rbp), %rdi
movb -0x65(%rbp), %al
movsbl %al, %ecx
movq -0x20(%rbp), %rax
movl 0x40(%rax), %eax
movl $0x8, %esi
cltd
idivl %esi
movl -0x64(%rbp), %edx
movl %eax, %r8d
leaq 0x195f(%rip), %rsi      # 0x306a
movb $0x0, %al
callq 0x1040
movl %eax, %ecx
movq -0x50(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
movq -0x20(%rbp), %rax
movl 0x30(%rax), %ecx
leaq 0x1966(%rip), %rdx      # 0x309a
leaq 0x195a(%rip), %rax      # 0x3095
cmpl $0x0, %ecx
cmovneq %rax, %rdx
leaq 0x1936(%rip), %rsi      # 0x307f
movb $0x0, %al
callq 0x1040
movl %eax, %ecx
movq -0x50(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
leaq 0x1935(%rip), %rsi      # 0x30a0
movb $0x0, %al
callq 0x1040
movl %eax, %ecx
movq -0x50(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq $0x0, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq -0x20(%rbp), %rcx
cmpq 0x18(%rcx), %rax
jae 0x1802
movq -0x50(%rbp), %rdi
movq -0x48(%rbp), %rsi
movq -0x50(%rbp), %rax
subq %rax, %rsi
movq -0x20(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x30(%rbp), %rcx
movq (%rax,%rcx,8), %rcx
leaq 0x18ed(%rip), %rdx      # 0x30ab
movb $0x0, %al
callq 0x1100
movl %eax, %ecx
movq -0x50(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
addq $-0x3, %rcx
cmpq %rcx, %rax
jb 0x17f2
movl $0x22, -0x4(%rbp)
jmp 0x18e4
jmp 0x17f4
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
jmp 0x178a
movq -0x50(%rbp), %rdi
leaq 0x18a4(%rip), %rsi      # 0x30b1
movb $0x0, %al
callq 0x1040
movl %eax, %ecx
movq -0x50(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rcx
xorl %eax, %eax
cmpq -0x48(%rbp), %rcx
movb %al, -0x68(%rbp)
jae 0x1852
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
subq %rcx, %rax
movl $0x10, %ecx
cqto
idivq %rcx
cmpq $0x0, %rdx
setne %al
movb %al, -0x68(%rbp)
movb -0x68(%rbp), %al
testb $0x1, %al
jne 0x185b
jmp 0x186f
movq -0x50(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x50(%rbp)
movb $0x20, (%rax)
jmp 0x1824
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
subq %rcx, %rax
movl $0x10, %ecx
cqto
idivq %rcx
cmpq $0x0, %rdx
je 0x1893
movl $0x22, -0x4(%rbp)
jmp 0x18e4
movq -0x50(%rbp), %rax
movb $0xa, -0x1(%rax)
movq -0x50(%rbp), %rax
movq -0x40(%rbp), %rcx
subq %rcx, %rax
subq $0xa, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
andq $0xff, %rax
movb %al, %cl
movq -0x40(%rbp), %rax
movb %cl, 0x8(%rax)
movq -0x38(%rbp), %rax
shrq $0x8, %rax
movb %al, %cl
movq -0x40(%rbp), %rax
movb %cl, 0x9(%rax)
movq -0x50(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)