// File: tsfn[P]doc2txt/src/doc_text.cpp
// Function: doc_text(Storage const&)
uchar *doc_text(const Storage &storage) {
  const uchar *wds;
  uint wds_size;
  if (!storage.stream("WordDocument", &wds, &wds_size)) {
    return NULL;
  }

  const uchar *pt = get_piece_table(storage);
  if (pt == NULL) {
    return NULL;
  }

  uint buf_size = 0; // 文本块的大小

  uint lcb = *(const uint *)(pt + 1);
  uint n = (lcb - 4) / 12;
  const uchar *pcd = pt + 5;
  for (uint i = 0; i < n; ++i) {
    uint start = *(const uint *)(pcd + i * 4);
    uint end = *(const uint *)(pcd + i * 4 + 4);
    if (start >= end) return NULL;
    uint fcCompressed = *(const uint *)(pcd + (n + 1) * 4 + i * 8 + 2);
    bool fCompressed = (fcCompressed >> 30) & 1;
    if (fCompressed) {
      uint cb = end - start;
      buf_size += cb * 2;
    } else {
      uint cb = (end - start) * 2;
      buf_size += cb;
    }
  }

  uchar *buf = (uchar *)malloc(buf_size + 4);
  uint ptr = 0;
  if (buf == NULL) return NULL;

  for (uint i = 0; i < n; ++i) {
    uint start = *(const uint *)(pcd + i * 4);
    uint end = *(const uint *)(pcd + i * 4 + 4);
    uint fcCompressed = *(const uint *)(pcd + (n + 1) * 4 + i * 8 + 2);
    bool fCompressed = (fcCompressed >> 30) & 1;
    if (fCompressed) {
      uint fc = (fcCompressed & ~(1U << 30)) / 2;
      uint cb = end - start;
      for (uint i = 0; i < cb; ++i) {
        if (fc + i < wds_size) {
          buf[ptr++] = wds[fc + i];
          buf[ptr++] = 0;
        }
      }
    } else {
      uint fc = fcCompressed;
      uint cb = (end - start) * 2;
      for (uint i = 0; i < cb; ++i) {
        buf[ptr++] = wds[fc + i];
      }
    }
  }
  return buf;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
leaq 0x303b(%rip), %rsi      # 0x6045
leaq -0x18(%rbp), %rdx
leaq -0x1c(%rbp), %rcx
callq 0x1e80
testb $0x1, %al
jne 0x3028
movq $0x0, -0x8(%rbp)
jmp 0x32fa
movq -0x10(%rbp), %rdi
callq 0x3310
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x3049
movq $0x0, -0x8(%rbp)
jmp 0x32fa
movl $0x0, -0x2c(%rbp)
movq -0x28(%rbp), %rax
movl 0x1(%rax), %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
subl $0x4, %eax
movl $0xc, %ecx
xorl %edx, %edx
divl %ecx
movl %eax, -0x34(%rbp)
movq -0x28(%rbp), %rax
addq $0x5, %rax
movq %rax, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x34(%rbp), %eax
jae 0x313a
movq -0x40(%rbp), %rax
movl -0x44(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl (%rax,%rcx), %eax
movl %eax, -0x48(%rbp)
movq -0x40(%rbp), %rax
movl -0x44(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl 0x4(%rax,%rcx), %eax
movl %eax, -0x4c(%rbp)
movl -0x48(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jb 0x30c5
movq $0x0, -0x8(%rbp)
jmp 0x32fa
movq -0x40(%rbp), %rax
movl -0x34(%rbp), %ecx
addl $0x1, %ecx
shll $0x2, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movl -0x44(%rbp), %ecx
shll $0x3, %ecx
movl %ecx, %ecx
movl 0x2(%rax,%rcx), %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %eax
shrl $0x1e, %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x51(%rbp)
testb $0x1, -0x51(%rbp)
je 0x3116
movl -0x4c(%rbp), %eax
subl -0x48(%rbp), %eax
movl %eax, -0x58(%rbp)
movl -0x58(%rbp), %eax
shll %eax
addl -0x2c(%rbp), %eax
movl %eax, -0x2c(%rbp)
jmp 0x312a
movl -0x4c(%rbp), %eax
subl -0x48(%rbp), %eax
shll %eax
movl %eax, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
addl -0x2c(%rbp), %eax
movl %eax, -0x2c(%rbp)
jmp 0x312c
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x307f
movl -0x2c(%rbp), %eax
addl $0x4, %eax
movl %eax, %eax
movl %eax, %edi
callq 0x1180
movq %rax, -0x68(%rbp)
movl $0x0, -0x6c(%rbp)
cmpq $0x0, -0x68(%rbp)
jne 0x3168
movq $0x0, -0x8(%rbp)
jmp 0x32fa
movl $0x0, -0x70(%rbp)
movl -0x70(%rbp), %eax
cmpl -0x34(%rbp), %eax
jae 0x32f2
movq -0x40(%rbp), %rax
movl -0x70(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl (%rax,%rcx), %eax
movl %eax, -0x74(%rbp)
movq -0x40(%rbp), %rax
movl -0x70(%rbp), %ecx
shll $0x2, %ecx
movl %ecx, %ecx
movl 0x4(%rax,%rcx), %eax
movl %eax, -0x78(%rbp)
movq -0x40(%rbp), %rax
movl -0x34(%rbp), %ecx
addl $0x1, %ecx
shll $0x2, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movl -0x70(%rbp), %ecx
shll $0x3, %ecx
movl %ecx, %ecx
movl 0x2(%rax,%rcx), %eax
movl %eax, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
shrl $0x1e, %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x7d(%rbp)
testb $0x1, -0x7d(%rbp)
je 0x3277
movl -0x7c(%rbp), %eax
andl $0xbfffffff, %eax       # imm = 0xBFFFFFFF
shrl %eax
movl %eax, -0x84(%rbp)
movl -0x78(%rbp), %eax
subl -0x74(%rbp), %eax
movl %eax, -0x88(%rbp)
movl $0x0, -0x8c(%rbp)
movl -0x8c(%rbp), %eax
cmpl -0x88(%rbp), %eax
jae 0x3275
movl -0x84(%rbp), %eax
addl -0x8c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jae 0x3262
movq -0x18(%rbp), %rax
movl -0x84(%rbp), %ecx
addl -0x8c(%rbp), %ecx
movl %ecx, %ecx
movb (%rax,%rcx), %dl
movq -0x68(%rbp), %rax
movl -0x6c(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x6c(%rbp)
movl %ecx, %ecx
movb %dl, (%rax,%rcx)
movq -0x68(%rbp), %rax
movl -0x6c(%rbp), %ecx
movl %ecx, %edx
addl $0x1, %edx
movl %edx, -0x6c(%rbp)
movl %ecx, %ecx
movb $0x0, (%rax,%rcx)
jmp 0x3264
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x3205
jmp 0x32e2
movl -0x7c(%rbp), %eax
movl %eax, -0x90(%rbp)
movl -0x78(%rbp), %eax
subl -0x74(%rbp), %eax
shll %eax
movl %eax, -0x94(%rbp)
movl $0x0, -0x98(%rbp)
movl -0x98(%rbp), %eax
cmpl -0x94(%rbp), %eax
jae 0x32e0
movq -0x18(%rbp), %rax
movl -0x90(%rbp), %ecx
addl -0x98(%rbp), %ecx
movl %ecx, %ecx
movb (%rax,%rcx), %dl
movq -0x68(%rbp), %rax
movl -0x6c(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x6c(%rbp)
movl %ecx, %ecx
movb %dl, (%rax,%rcx)
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x98(%rbp)
jmp 0x3298
jmp 0x32e2
jmp 0x32e4
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x316f
movq -0x68(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopw (%rax,%rax)