// File: salleaffaire[P]MXFParser/klv.cpp
// Function: klv_parser::get_klv_item(klv_item&, bit_extractor&)
bool klv_parser::get_klv_item(klv_item &klvi, bit_extractor &be) {
   bool rval = true;
   
   // Read Key
   // ------------------------------------------------------------------------------
   // Test for enough byte for a LU Key
   if (be.get_bytes_left() >= 16) {
      for (int i=0;i<16;++i) {
         klvi.mKey[i] = be.get_bits(8);
      }
   }
   else {
      std::cout << "Need 16 bytes for a KLV Key but only " << be.get_bytes_left()
                << " bytes left in the file." << std::endl;
      rval = false;
   }
   
   uint8_t l0;
   if (rval && (be.get_bytes_left() >= 1)) {
      // Read Length (BER encoded)
      l0 = be.get_bits(8);
   }
   else {
      std::cout << "Need 1 byte for a BER first byte file is empty" << std::endl;
      rval = false;
   }
   
   if (rval) {
      // Short form
      if (!(l0 & 0x80)) {
         klvi.mLength = l0;
      } 
      // Long form
      else {
         int num_of_octets = l0 & 0x7F;
         if (be.get_bytes_left() >= num_of_octets) {
            if (num_of_octets > 4) {
               std::cout << " Error : This library doesn't support BER long form with number of octets "
                         << "bigger than 4." << std::endl;
            }
            int i;
            klvi.mLength = 0;
            for (i=num_of_octets-1;i>=0;--i) {
               uint32_t o = be.get_bits(8);
               klvi.mLength |= (o << (i*8));
            }
         }
         else {
            std::cout << "Need " << num_of_octets
                      << " bytes for a KLV Length BER but only " << be.get_bytes_left()
                      << " bytes left in the file." << std::endl;
            rval = false;
         }
      }
      
   }
   
   if (rval && (be.get_bytes_left() >= klvi.mLength)) {
      klvi.mValue = be.get_buffer();
      be.skip_n_bytes(klvi.mLength);
   }
   else {
      std::cout << "Need " << klvi.mLength
                << " bytes for a KLV Value but only " << be.get_bytes_left()
                << " bytes left in the file." << std::endl;
      rval = false;
   }

   if (rval)  {
      klvi.parse_value();
   }
   
   return rval;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movb $0x1, -0x19(%rbp)
movq -0x18(%rbp), %rdi
callq 0x5170
cmpl $0x10, %eax
jb 0x3f85
movl $0x0, -0x20(%rbp)
cmpl $0x10, -0x20(%rbp)
jge 0x3f83
movq -0x18(%rbp), %rdi
movl $0x8, %esi
callq 0x51c0
movb %al, -0x31(%rbp)
movq -0x10(%rbp), %rdi
movl -0x20(%rbp), %eax
movzbl %al, %esi
callq 0x5030
movb -0x31(%rbp), %cl
movb %cl, (%rax)
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x3f4d
jmp 0x3fd2
movq 0xd04c(%rip), %rdi      # 0x10fd8
leaq 0x8267(%rip), %rsi      # 0xc1fa
callq 0x31f0
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rdi
callq 0x5170
movq -0x40(%rbp), %rdi
movl %eax, %esi
callq 0x32d0
movq %rax, %rdi
leaq 0x8266(%rip), %rsi      # 0xc220
callq 0x31f0
movq %rax, %rdi
movq 0xcfef(%rip), %rsi      # 0x10fb8
callq 0x3230
movb $0x0, -0x19(%rbp)
testb $0x1, -0x19(%rbp)
je 0x3ff9
movq -0x18(%rbp), %rdi
callq 0x5170
cmpl $0x1, %eax
jb 0x3ff9
movq -0x18(%rbp), %rdi
movl $0x8, %esi
callq 0x51c0
movb %al, -0x21(%rbp)
jmp 0x401f
movq 0xcfd8(%rip), %rdi      # 0x10fd8
leaq 0x8232(%rip), %rsi      # 0xc239
callq 0x31f0
movq %rax, %rdi
movq 0xcfa2(%rip), %rsi      # 0x10fb8
callq 0x3230
movb $0x0, -0x19(%rbp)
testb $0x1, -0x19(%rbp)
je 0x4154
movzbl -0x21(%rbp), %eax
andl $0x80, %eax
cmpl $0x0, %eax
jne 0x4047
movzbl -0x21(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x10(%rax)
jmp 0x4152
movzbl -0x21(%rbp), %eax
andl $0x7f, %eax
movl %eax, -0x28(%rbp)
movq -0x18(%rbp), %rdi
callq 0x5170
cmpl -0x28(%rbp), %eax
jb 0x40e9
cmpl $0x4, -0x28(%rbp)
jle 0x409a
movq 0xcf68(%rip), %rdi      # 0x10fd8
leaq 0x81f1(%rip), %rsi      # 0xc268
callq 0x31f0
movq %rax, %rdi
leaq 0x822d(%rip), %rsi      # 0xc2b3
callq 0x31f0
movq %rax, %rdi
movq 0xcf23(%rip), %rsi      # 0x10fb8
callq 0x3230
movq -0x10(%rbp), %rax
movl $0x0, 0x10(%rax)
movl -0x28(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jl 0x40e7
movq -0x18(%rbp), %rdi
movl $0x8, %esi
callq 0x51c0
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
movl -0x2c(%rbp), %ecx
shll $0x3, %ecx
shll %cl, %eax
movl %eax, %ecx
movq -0x10(%rbp), %rax
orl 0x10(%rax), %ecx
movl %ecx, 0x10(%rax)
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x40ae
jmp 0x4150
movq 0xcee8(%rip), %rdi      # 0x10fd8
leaq 0x81cb(%rip), %rsi      # 0xc2c2
callq 0x31f0
movq %rax, %rdi
movl -0x28(%rbp), %esi
callq 0x3360
movq %rax, %rdi
leaq 0x81b7(%rip), %rsi      # 0xc2c8
callq 0x31f0
movq %rax, -0x48(%rbp)
movq -0x18(%rbp), %rdi
callq 0x5170
movq -0x48(%rbp), %rdi
movl %eax, %esi
callq 0x32d0
movq %rax, %rdi
leaq 0x80e8(%rip), %rsi      # 0xc220
callq 0x31f0
movq %rax, %rdi
movq 0xce71(%rip), %rsi      # 0x10fb8
callq 0x3230
movb $0x0, -0x19(%rbp)
jmp 0x4152
jmp 0x4154
testb $0x1, -0x19(%rbp)
je 0x4192
movq -0x18(%rbp), %rdi
callq 0x5170
movq -0x10(%rbp), %rcx
cmpl 0x10(%rcx), %eax
jb 0x4192
movq -0x18(%rbp), %rdi
callq 0x5200
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x5220
jmp 0x41fd
movq 0xce3f(%rip), %rdi      # 0x10fd8
leaq 0x8122(%rip), %rsi      # 0xc2c2
callq 0x31f0
movq %rax, %rdi
movq -0x10(%rbp), %rax
movl 0x10(%rax), %esi
callq 0x32d0
movq %rax, %rdi
leaq 0x8130(%rip), %rsi      # 0xc2ee
callq 0x31f0
movq %rax, -0x50(%rbp)
movq -0x18(%rbp), %rdi
callq 0x5170
movq -0x50(%rbp), %rdi
movl %eax, %esi
callq 0x32d0
movq %rax, %rdi
leaq 0x803b(%rip), %rsi      # 0xc220
callq 0x31f0
movq %rax, %rdi
movq 0xcdc4(%rip), %rsi      # 0x10fb8
callq 0x3230
movb $0x0, -0x19(%rbp)
testb $0x1, -0x19(%rbp)
je 0x420c
movq -0x10(%rbp), %rdi
callq 0x3c00
movb -0x19(%rbp), %al
andb $0x1, %al
addq $0x50, %rsp
popq %rbp
retq
nopw (%rax,%rax)