// File: cpearce[P]OggIndex/src/SkeletonEncoder.cpp
// Function: SkeletonEncoder::UpdateFisbone(ogg_packet*)
ogg_packet*
SkeletonEncoder::UpdateFisbone(ogg_packet* original) {
  assert(IsFisbonePacket(original));

  ogg_uint32_t serialno = LEUint32(original->packet + FISBONE_SERIALNO_OFFSET);
  Decoder* decoder = FindTrack(serialno);
  if (!decoder) {
    cerr << "ERROR: incoming fisbone packet for stream " << serialno << " is unknown" << endl;
    return 0;
  }
  FisboneInfo info = decoder->GetFisboneInfo();

  // Extract the message header fields, ensure we include the all compulsory
  // fields. These are: Content-Type, Role, Name.
  const char* x = (const char*)(original->packet + FISBONE_HEADER_OFFSET);
  string header(x, original->bytes - FISBONE_HEADER_OFFSET);
  vector<string> headers;
  Tokenize(header, headers, "\r\n");

  bool hasContentType = false;
  bool hasRole = false;
  bool hasName = false;
  for (unsigned i=0; i<headers.size(); i++) {
    string::size_type colon = headers[i].find_first_of(":");
    if (colon == string::npos) {
      continue;
    }
    string id = headers[i].substr(0, colon);
    ToLower(id);
    if (id.compare("content-type") == 0) {
      hasContentType = true;
    } else if (id.compare("name") == 0) {
      hasName = true;
    } else if (id.compare("role") == 0) {
      hasRole = true;
    }
  }

  unsigned size = original->bytes;

  if (!hasContentType)
    size += strlen("Content-Type: ") + info.mContentType.size() + 2;
  if (!hasName)
    size += strlen("Name: ") + info.mName.size() + 2;
  if (!hasRole)
    size += strlen("Role: ") + info.mRole.size() + 2;

  ogg_packet* packet = new ogg_packet();
  memcpy(packet, original, sizeof(ogg_packet));
  packet->packet = new unsigned char[size];
  packet->bytes = size;

  // Copy stuff up to headers
  memcpy(packet->packet, original->packet, FISBONE_HEADER_OFFSET);

  unsigned char* h = packet->packet + FISBONE_HEADER_OFFSET;

  // Write any existing headers.
  memcpy(h, original->packet+FISBONE_HEADER_OFFSET, original->bytes - FISBONE_HEADER_OFFSET);
  h += original->bytes - FISBONE_HEADER_OFFSET;

  if (!hasContentType) {
    // Write a content type...
    string s = "Content-Type: " + info.mContentType + "\r\n";
    memcpy(h, s.c_str(), s.size());
    h += s.size();
  }
  if (!hasName) {
    // Write a name...
    string s = "Name: " + info.mName + "\r\n";
    memcpy(h, s.c_str(), s.size());
    h += s.size();
  }
  if (!hasRole) {
    // Write a role...
    string s = "Role: " + info.mRole + "\r\n";
    memcpy(h, s.c_str(), s.size());
    h += s.size();
  }
  assert(h == packet->packet + packet->bytes);
  return packet;
}

// Assembly:
subq $0x298, %rsp            # imm = 0x298
movq %rdi, 0x288(%rsp)
movq %rsi, 0x280(%rsp)
movq 0x288(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x280(%rsp), %rdi
callq 0x16950
testb $0x1, %al
jne 0x134c7
jmp 0x134c9
jmp 0x134e8
leaq 0xae70(%rip), %rdi      # 0x1e340
leaq 0xab0d(%rip), %rsi      # 0x1dfe4
movl $0x25a, %edx            # imm = 0x25A
leaq 0xae77(%rip), %rcx      # 0x1e35a
callq 0x5280
movq 0x280(%rsp), %rax
movq (%rax), %rdi
addq $0xc, %rdi
callq 0x168b0
movq 0x68(%rsp), %rdi
movl %eax, 0x27c(%rsp)
movl 0x27c(%rsp), %esi
callq 0x133f0
movq %rax, 0x270(%rsp)
cmpq $0x0, 0x270(%rsp)
jne 0x13578
movq 0x14ac2(%rip), %rdi     # 0x27ff0
leaq 0xae5e(%rip), %rsi      # 0x1e393
callq 0x53d0
movq %rax, %rdi
movl 0x27c(%rsp), %esi
callq 0x5560
movq %rax, %rdi
leaq 0xae6b(%rip), %rsi      # 0x1e3be
callq 0x53d0
movq %rax, %rdi
movq 0x14a5e(%rip), %rsi     # 0x27fc0
callq 0x5430
movq $0x0, 0x290(%rsp)
jmp 0x13d9c
movq 0x270(%rsp), %rsi
movq (%rsi), %rax
movq 0x40(%rax), %rax
leaq 0x1f0(%rsp), %rdi
callq *%rax
movq 0x280(%rsp), %rax
movq (%rax), %rax
addq $0x34, %rax
movq %rax, 0x1e8(%rsp)
movq 0x1e8(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x280(%rsp), %rax
movq 0x8(%rax), %rax
addq $-0x34, %rax
movq %rax, 0x58(%rsp)
leaq 0x1c7(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x57e0
movq 0x50(%rsp), %rsi
movq 0x58(%rsp), %rdx
movq 0x60(%rsp), %rcx
leaq 0x1c8(%rsp), %rdi
callq 0x5490
jmp 0x135fa
leaq 0x1c7(%rsp), %rdi
callq 0x5450
leaq 0x198(%rsp), %rdi
callq 0x14260
leaq 0x177(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x57e0
movq 0x48(%rsp), %rdx
leaq 0xad98(%rip), %rsi      # 0x1e3ca
leaq 0x178(%rsp), %rdi
callq 0x14270
jmp 0x13641
leaq 0x1c8(%rsp), %rdi
leaq 0x198(%rsp), %rsi
leaq 0x178(%rsp), %rdx
callq 0x16fc0
jmp 0x13660
leaq 0x178(%rsp), %rdi
callq 0x5260
leaq 0x177(%rsp), %rdi
callq 0x5450
movb $0x0, 0x176(%rsp)
movb $0x0, 0x175(%rsp)
movb $0x0, 0x174(%rsp)
movl $0x0, 0x170(%rsp)
movl 0x170(%rsp), %eax
movq %rax, 0x40(%rsp)
leaq 0x198(%rsp), %rdi
callq 0x14330
movq %rax, %rcx
movq 0x40(%rsp), %rax
cmpq %rcx, %rax
jae 0x1388a
movl 0x170(%rsp), %eax
movl %eax, %esi
leaq 0x198(%rsp), %rdi
callq 0x14350
movq %rax, %rdi
leaq 0xa4fc(%rip), %rsi      # 0x1dbe3
xorl %eax, %eax
movl %eax, %edx
callq 0x5200
movq %rax, 0x168(%rsp)
cmpq $-0x1, 0x168(%rsp)
jne 0x13777
jmp 0x13874
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1b8(%rsp)
movl %eax, 0x1b4(%rsp)
leaq 0x1c7(%rsp), %rdi
callq 0x5450
jmp 0x13d8d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1b8(%rsp)
movl %eax, 0x1b4(%rsp)
jmp 0x13765
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1b8(%rsp)
movl %eax, 0x1b4(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x5260
leaq 0x177(%rsp), %rdi
callq 0x5450
jmp 0x13d73
movl 0x170(%rsp), %eax
movl %eax, %esi
leaq 0x198(%rsp), %rdi
callq 0x14350
movq %rax, %rsi
movq 0x168(%rsp), %rcx
xorl %eax, %eax
movl %eax, %edx
leaq 0x148(%rsp), %rdi
callq 0x5410
jmp 0x137ab
leaq 0x148(%rsp), %rdi
callq 0x13dc0
jmp 0x137ba
leaq 0x148(%rsp), %rdi
leaq 0xac04(%rip), %rsi      # 0x1e3cd
callq 0x5110
cmpl $0x0, %eax
jne 0x1381f
movb $0x1, 0x176(%rsp)
jmp 0x13867
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1b8(%rsp)
movl %eax, 0x1b4(%rsp)
jmp 0x13d73
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1b8(%rsp)
movl %eax, 0x1b4(%rsp)
leaq 0x148(%rsp), %rdi
callq 0x5260
jmp 0x13d73
leaq 0x148(%rsp), %rdi
leaq 0xa778(%rip), %rsi      # 0x1dfa6
callq 0x5110
cmpl $0x0, %eax
jne 0x13842
movb $0x1, 0x174(%rsp)
jmp 0x13865
leaq 0x148(%rsp), %rdi
leaq 0xab89(%rip), %rsi      # 0x1e3da
callq 0x5110
cmpl $0x0, %eax
jne 0x13863
movb $0x1, 0x175(%rsp)
jmp 0x13865
jmp 0x13867
leaq 0x148(%rsp), %rdi
callq 0x5260
movl 0x170(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x170(%rsp)
jmp 0x1369d
movq 0x280(%rsp), %rax
movq 0x8(%rax), %rax
movl %eax, 0x144(%rsp)
testb $0x1, 0x176(%rsp)
jne 0x138d4
leaq 0x1f0(%rsp), %rdi
addq $0x20, %rdi
callq 0x52d0
movq %rax, %rcx
addq $0xe, %rcx
addq $0x2, %rcx
movl 0x144(%rsp), %eax
addq %rcx, %rax
movl %eax, 0x144(%rsp)
testb $0x1, 0x174(%rsp)
jne 0x1390b
leaq 0x1f0(%rsp), %rdi
addq $0x60, %rdi
callq 0x52d0
movq %rax, %rcx
addq $0x6, %rcx
addq $0x2, %rcx
movl 0x144(%rsp), %eax
addq %rcx, %rax
movl %eax, 0x144(%rsp)
testb $0x1, 0x175(%rsp)
jne 0x13942
leaq 0x1f0(%rsp), %rdi
addq $0x40, %rdi
callq 0x52d0
movq %rax, %rcx
addq $0x6, %rcx
addq $0x2, %rcx
movl 0x144(%rsp), %eax
addq %rcx, %rax
movl %eax, 0x144(%rsp)
movl $0x30, %edi
callq 0x53e0
movq %rax, 0x38(%rsp)
jmp 0x13953
movq 0x38(%rsp), %rax
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%rax)
movaps %xmm0, 0x10(%rax)
movaps %xmm0, (%rax)
movq %rax, 0x138(%rsp)
movq 0x138(%rsp), %rax
movq 0x280(%rsp), %rcx
movups (%rcx), %xmm0
movups 0x10(%rcx), %xmm1
movups 0x20(%rcx), %xmm2
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
movl 0x144(%rsp), %eax
movl %eax, %edi
callq 0x5030
movq %rax, 0x30(%rsp)
jmp 0x139a9
movq 0x30(%rsp), %rcx
movq 0x138(%rsp), %rax
movq %rcx, (%rax)
movl 0x144(%rsp), %eax
movl %eax, %ecx
movq 0x138(%rsp), %rax
movq %rcx, 0x8(%rax)
movq 0x138(%rsp), %rax
movq (%rax), %rdi
movq 0x280(%rsp), %rax
movq (%rax), %rsi
movl $0x34, %edx
callq 0x5340
movq 0x138(%rsp), %rax
movq (%rax), %rax
addq $0x34, %rax
movq %rax, 0x130(%rsp)
movq 0x130(%rsp), %rdi
movq 0x280(%rsp), %rax
movq (%rax), %rsi
addq $0x34, %rsi
movq 0x280(%rsp), %rax
movq 0x8(%rax), %rdx
subq $0x34, %rdx
callq 0x5340
movq 0x280(%rsp), %rax
movq 0x8(%rax), %rax
subq $0x34, %rax
addq 0x130(%rsp), %rax
movq %rax, 0x130(%rsp)
testb $0x1, 0x176(%rsp)
jne 0x13b38
leaq 0x210(%rsp), %rdx
leaq 0xa971(%rip), %rsi      # 0x1e3df
leaq 0xf0(%rsp), %rdi
callq 0x143c0
jmp 0x13a7d
leaq 0xa946(%rip), %rdx      # 0x1e3ca
leaq 0x110(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x14370
jmp 0x13a9b
leaq 0xf0(%rsp), %rdi
callq 0x5260
movq 0x130(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x5180
movq %rax, 0x28(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x52d0
movq 0x20(%rsp), %rdi
movq 0x28(%rsp), %rsi
movq %rax, %rdx
callq 0x5340
leaq 0x110(%rsp), %rdi
callq 0x52d0
addq 0x130(%rsp), %rax
movq %rax, 0x130(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x5260
jmp 0x13b38
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1b8(%rsp)
movl %eax, 0x1b4(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x5260
jmp 0x13d73
testb $0x1, 0x174(%rsp)
jne 0x13c1f
leaq 0x250(%rsp), %rdx
leaq 0xa899(%rip), %rsi      # 0x1e3ee
leaq 0xb0(%rsp), %rdi
callq 0x143c0
jmp 0x13b64
leaq 0xa85f(%rip), %rdx      # 0x1e3ca
leaq 0xd0(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x14370
jmp 0x13b82
leaq 0xb0(%rsp), %rdi
callq 0x5260
movq 0x130(%rsp), %rax
movq %rax, 0x10(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x5180
movq %rax, 0x18(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x52d0
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rsi
movq %rax, %rdx
callq 0x5340
leaq 0xd0(%rsp), %rdi
callq 0x52d0
addq 0x130(%rsp), %rax
movq %rax, 0x130(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x5260
jmp 0x13c1f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1b8(%rsp)
movl %eax, 0x1b4(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0x5260
jmp 0x13d73
testb $0x1, 0x175(%rsp)
jne 0x13cf5
leaq 0x230(%rsp), %rdx
leaq 0xa7b9(%rip), %rsi      # 0x1e3f5
leaq 0x70(%rsp), %rdi
callq 0x143c0
jmp 0x13c48
leaq 0xa77b(%rip), %rdx      # 0x1e3ca
leaq 0x90(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x14370
jmp 0x13c63
leaq 0x70(%rsp), %rdi
callq 0x5260
movq 0x130(%rsp), %rax
movq %rax, (%rsp)
leaq 0x90(%rsp), %rdi
callq 0x5180
movq %rax, 0x8(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x52d0
movq (%rsp), %rdi
movq 0x8(%rsp), %rsi
movq %rax, %rdx
callq 0x5340
leaq 0x90(%rsp), %rdi
callq 0x52d0
addq 0x130(%rsp), %rax
movq %rax, 0x130(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x5260
jmp 0x13cf5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1b8(%rsp)
movl %eax, 0x1b4(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x5260
jmp 0x13d73
movq 0x130(%rsp), %rax
movq 0x138(%rsp), %rcx
movq (%rcx), %rcx
movq 0x138(%rsp), %rdx
addq 0x8(%rdx), %rcx
cmpq %rcx, %rax
jne 0x13d1b
jmp 0x13d3a
leaq 0xa6da(%rip), %rdi      # 0x1e3fc
leaq 0xa2bb(%rip), %rsi      # 0x1dfe4
movl $0x2a7, %edx            # imm = 0x2A7
leaq 0xa625(%rip), %rcx      # 0x1e35a
callq 0x5280
movq 0x138(%rsp), %rax
movq %rax, 0x290(%rsp)
leaq 0x198(%rsp), %rdi
callq 0x144f0
leaq 0x1c8(%rsp), %rdi
callq 0x5260
leaq 0x1f0(%rsp), %rdi
callq 0xaf10
jmp 0x13d9c
leaq 0x198(%rsp), %rdi
callq 0x144f0
leaq 0x1c8(%rsp), %rdi
callq 0x5260
leaq 0x1f0(%rsp), %rdi
callq 0xaf10
jmp 0x13dac
movq 0x290(%rsp), %rax
addq $0x298, %rsp            # imm = 0x298
retq
movq 0x1b8(%rsp), %rdi
callq 0x57d0
nopl (%rax)