// File: devinsmith[P]qvdreader/QvdFile.cpp
// Function: QvdFile::parseXmlHeader(char const*)
bool QvdFile::parseXmlHeader(const char *filename)
{
  const char *endQvdTableHeader = "</QvdTableHeader>";
  xmlParserCtxtPtr ctxt;

  ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, filename);

  // Read XML content of the file.
  int done;
  do {
    size_t len = readBytes();
    done = len < sizeof(_buf); // Did we reach end of file?

    // Unfortunately the Qvd file format includes an XML based
    // header followed by raw binary data.
    // We know that it occurs after </QvdTableHeader> so we need
    // to scan our read buffer each time to see if we have that tag.
    //
    // If we do, we alter the length read, set a pointer to the data just
    // after the tag and proceed to finish reading the XML portion of the
    // file.

    char *end;
    if ((end = strstr(_buf, endQvdTableHeader)) != NULL) {
      end += strlen(endQvdTableHeader);
      // For the XML portion, the dataPtrStart marks the end of the XML
      // and the start of raw data to be parsed later on.
      //
      // We treat this as an "End of File" situation for expat.
      _dataPtrStart = end;
      _bufLen = len;
      len = end - _buf;
      _bufLen -= len;
      done = 1;
    }

    if (xmlParseChunk(ctxt, _buf, len, done) != 0) {
      fprintf(stderr, "An error occurred parsing the XML\n");
      return false;
#if 0
      fprintf(stderr, "%s at line %lu\n",
        XML_ErrorString(XML_GetErrorCode(parser)),
        XML_GetCurrentLineNumber(parser));
#endif
    }
  } while (!done);

  if (ctxt->myDoc == NULL || !ctxt->wellFormed) {
    // XML header is not well formed.
    return false;
  }

  xmlDoc *doc = ctxt->myDoc; /* the resulting document tree */
  xmlNode *root_element = xmlDocGetRootElement(doc);

  for (xmlNode *node = root_element; node; node = node->next) {
    if (node->type == XML_ELEMENT_NODE &&
        strcmp((char *)node->name, "QvdTableHeader") == 0) {
      _hdr.ParseXml(node);
    }
  }

  xmlFreeDoc(doc);
  xmlFreeParserCtxt(ctxt);
  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
leaq 0x5ef2(%rip), %rax      # 0x13151
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %r8
xorl %eax, %eax
movl %eax, %edx
xorl %ecx, %ecx
movq %rdx, %rdi
movq %rdx, %rsi
callq 0xa580
movq %rax, -0x28(%rbp)
movq -0x60(%rbp), %rdi
callq 0xb500
movq -0x60(%rbp), %rdi
movq %rax, -0x38(%rbp)
cmpq $0x2000, -0x38(%rbp)    # imm = 0x2000
setb %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x2c(%rbp)
addq $0x130, %rdi            # imm = 0x130
movq -0x20(%rbp), %rsi
callq 0xa200
movq %rax, -0x40(%rbp)
cmpq $0x0, %rax
je 0xd319
movq -0x20(%rbp), %rdi
callq 0xa4c0
movq %rax, %rcx
movq -0x60(%rbp), %rax
addq -0x40(%rbp), %rcx
movq %rcx, -0x40(%rbp)
movq -0x40(%rbp), %rcx
movq %rcx, 0x2130(%rax)
movq -0x38(%rbp), %rcx
movq %rcx, 0x2138(%rax)
movq -0x40(%rbp), %rcx
movq %rax, %rdx
addq $0x130, %rdx            # imm = 0x130
subq %rdx, %rcx
movq %rcx, -0x38(%rbp)
movq -0x38(%rbp), %rdx
movq 0x2138(%rax), %rcx
subq %rdx, %rcx
movq %rcx, 0x2138(%rax)
movl $0x1, -0x2c(%rbp)
movq -0x60(%rbp), %rsi
movq -0x28(%rbp), %rdi
addq $0x130, %rsi            # imm = 0x130
movq -0x38(%rbp), %rax
movl %eax, %edx
movl -0x2c(%rbp), %ecx
callq 0xa730
cmpl $0x0, %eax
je 0xd35c
movq 0xac96(%rip), %rax      # 0x17fd8
movq (%rax), %rdi
leaq 0x5e17(%rip), %rsi      # 0x13163
movb $0x0, %al
callq 0xaf80
movb $0x0, -0x1(%rbp)
jmp 0xd408
jmp 0xd35e
cmpl $0x0, -0x2c(%rbp)
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0xd27c
movq -0x28(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0xd384
movq -0x28(%rbp), %rax
cmpl $0x0, 0x18(%rax)
jne 0xd38a
movb $0x0, -0x1(%rbp)
jmp 0xd408
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
callq 0xb060
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
je 0xd3f2
movq -0x58(%rbp), %rax
cmpl $0x1, 0x8(%rax)
jne 0xd3e2
movq -0x58(%rbp), %rax
movq 0x10(%rax), %rdi
leaq 0x5dbb(%rip), %rsi      # 0x13186
callq 0xaf40
cmpl $0x0, %eax
jne 0xd3e2
movq -0x60(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0xa5a0
jmp 0xd3e4
movq -0x58(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x58(%rbp)
jmp 0xd3ab
movq -0x48(%rbp), %rdi
callq 0xb420
movq -0x28(%rbp), %rdi
callq 0xa620
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)