// File: /workspace/github_cpp_makefile_star2_O3/williewillus[P]panda_scratchpad/src/wrapper/DiskMod.cpp
// Function: wrapper::DiskMod::Deserialize(std::shared_ptr<char>, wrapper::DiskMod&)
int DiskMod::Deserialize(shared_ptr<char> data, DiskMod &res) {
  res.Reset();

  // Skip the first uint64 which is the size of this region. This is a blind
  // deserialization of the object!
  char *data_ptr = data.get();
  data_ptr += sizeof(uint64_t);

  uint16_t mod_type;
  uint16_t mod_opts;
  memcpy(&mod_type, data_ptr, sizeof(uint16_t));
  data_ptr += sizeof(uint16_t);
  res.mod_type = (DiskMod::ModType) be16toh(mod_type);

  memcpy(&mod_opts, data_ptr, sizeof(uint16_t));
  data_ptr += sizeof(uint16_t);
  res.mod_opts = (DiskMod::ModOpts) be16toh(mod_opts);

  if (res.mod_type == DiskMod::kCheckpointMod ||
    res.mod_type == DiskMod::kSyncMod) {
    // No more left to do here.
    return 0;
  }

  // Small buffer to read characters into so we aren't adding to a string one
  // character at a time until the end of the string.
  const unsigned int tmp_size = 128;
  char tmp[tmp_size];
  memset(tmp, 0, tmp_size);
  unsigned int chars_read = 0;
  while (data_ptr[0] != '\0') {
    // We still haven't seen a null terminator, so read another character.
    tmp[chars_read] = data_ptr[0];
    ++chars_read;
    if (chars_read == tmp_size - 1) {
      // Fall into this at one character short so that we have an automatic null
      // terminator
      res.path += tmp;
      chars_read = 0;
      // Required because we just add the char[] to the string and we don't want
      // extra junk. An alternative would be to make sure you always had a null
      // terminator the character after the one that was just assigned.
      memset(tmp, 0, tmp_size);
    }
    ++data_ptr;
  }
  // Add the remaining data that is in tmp.
  res.path += tmp;
  // Move past the null terminating character.
  ++data_ptr;

  res.directory_mod = (bool) data_ptr[0];
  ++data_ptr;

  if (res.mod_type == DiskMod::kFsyncMod ||
      res.mod_type == DiskMod::kCreateMod) {
    return 0;
  }

  uint64_t file_mod_location;
  uint64_t file_mod_len;
  memcpy(&file_mod_location, data_ptr, sizeof(uint64_t));
  data_ptr += sizeof(uint64_t);
  file_mod_location = be64toh(file_mod_location);
  res.file_mod_location = file_mod_location;

  memcpy(&file_mod_len, data_ptr, sizeof(uint64_t));
  data_ptr += sizeof(uint64_t);
  file_mod_len = be64toh(file_mod_len);
  res.file_mod_len = file_mod_len;

  // Some mods have file length and location, but no actual data associated with
  // them.
  if (res.mod_type == DiskMod::kSyncFileRangeMod ||
      res.mod_opts == DiskMod::kFallocateOpt ||
      res.mod_opts == DiskMod::kFallocateKeepSizeOpt ||
      res.mod_opts == DiskMod::kPunchHoleKeepSizeOpt ||
      res.mod_opts == DiskMod::kCollapseRangeOpt ||
      res.mod_opts == DiskMod::kZeroRangeOpt ||
      res.mod_opts == DiskMod::kZeroRangeKeepSizeOpt ||
      res.mod_opts == DiskMod::kInsertRangeOpt) {
    return 0;
  }

  if (res.file_mod_len > 0) {
    // Read the data for this mod.
    res.file_mod_data.reset(new (std::nothrow) char[res.file_mod_len],
        [](char *c) {delete[] c;});
    if (res.file_mod_data.get() == nullptr) {
      return -1;
    }
    memcpy(res.file_mod_data.get(), data_ptr, res.file_mod_len);
  }

  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x80, %rsp
movq %rsi, %rbx
movq %rdi, %r14
movq %rsi, %rdi
callq 0x9d38
movq (%r14), %r14
movzwl 0x8(%r14), %eax
rolw $0x8, %ax
movzwl %ax, %eax
movl %eax, 0x20(%rbx)
movzwl 0xa(%r14), %ecx
rolw $0x8, %cx
movzwl %cx, %ecx
movl %ecx, 0x24(%rbx)
xorl %r15d, %r15d
cmpw $0x6, %ax
je 0x9cf2
cmpl $0x8, %eax
je 0x9cf2
xorps %xmm0, %xmm0
movaps %xmm0, -0x30(%rbp)
movaps %xmm0, -0x40(%rbp)
movaps %xmm0, -0x50(%rbp)
movaps %xmm0, -0x60(%rbp)
movaps %xmm0, -0x70(%rbp)
movaps %xmm0, -0x80(%rbp)
movaps %xmm0, -0x90(%rbp)
movaps %xmm0, -0xa0(%rbp)
movb 0xc(%r14), %cl
addq $0xc, %r14
testb %cl, %cl
je 0x9c06
xorl %eax, %eax
leaq -0xa0(%rbp), %r15
movl %eax, %edx
movb %cl, -0xa0(%rbp,%rdx)
incl %eax
cmpl $0x7f, %eax
jne 0x9bfb
movq %rbx, %rdi
movq %r15, %rsi
callq 0x5860
xorps %xmm0, %xmm0
movaps %xmm0, -0xa0(%rbp)
movaps %xmm0, -0x90(%rbp)
movaps %xmm0, -0x80(%rbp)
movaps %xmm0, -0x70(%rbp)
movaps %xmm0, -0x60(%rbp)
movaps %xmm0, -0x50(%rbp)
movaps %xmm0, -0x40(%rbp)
movaps %xmm0, -0x30(%rbp)
xorl %eax, %eax
movb 0x1(%r14), %cl
incq %r14
testb %cl, %cl
jne 0x9bb5
leaq -0xa0(%rbp), %rsi
movq %rbx, %rdi
callq 0x5860
cmpb $0x0, 0x1(%r14)
setne 0xb8(%rbx)
movl 0x20(%rbx), %eax
xorl %r15d, %r15d
testl %eax, %eax
je 0x9cf2
cmpl $0x7, %eax
je 0x9cf2
movq 0x2(%r14), %rcx
bswapq %rcx
movq %rcx, 0xd0(%rbx)
movq 0xa(%r14), %rcx
movq %rcx, %rdi
bswapq %rdi
movq %rdi, 0xd8(%rbx)
cmpl $0x9, %eax
je 0x9cf2
testq %rcx, %rcx
je 0x9cf2
movl 0x24(%rbx), %eax
addl $-0x2, %eax
cmpl $0x7, %eax
jb 0x9cf2
movq 0x1230d(%rip), %rsi     # 0x1bf88
callq 0x5720
movq %rax, %r12
movl $0x18, %edi
callq 0x54a0
movabsq $0x100000001, %rcx      # imm = 0x100000001
movq %rcx, 0x8(%rax)
leaq 0x11ba6(%rip), %rcx     # 0x1b848
movq %rcx, (%rax)
movq %r12, 0x10(%rax)
movq %r12, 0xc0(%rbx)
movq 0xc8(%rbx), %rdi
movq %rax, 0xc8(%rbx)
testq %rdi, %rdi
je 0x9ccf
callq 0x8a78
movq 0xc0(%rbx), %r12
testq %r12, %r12
je 0x9cec
addq $0x12, %r14
movq 0xd8(%rbx), %rdx
movq %r12, %rdi
movq %r14, %rsi
callq 0x53b0
jmp 0x9cf2
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
movl %r15d, %eax
addq $0x80, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rdi
callq 0x51d0
testq %r12, %r12
je 0x9d1a
movq %r12, %rdi
callq 0x5540
callq 0x5640
movq %rax, %rbx
callq 0x5710
movq %rbx, %rdi
callq 0x57c0
movq %rax, %rdi
callq 0x7f7a
nop