// File: /workspace/github_cpp_makefile_star2_O3/jorbs[P]stellar-keypair-tool/keypair.cpp
// Function: main
int main(int argc, char* argv[]) {
  if (argc == 1) {
    usage(argv[0]);
    return 1;
  }

  std::string term;
  int threadsCount = -1, c;
  bool (*matchFunction)(const std::string &input, const std::string &suffix);

  while ((c = getopt(argc, argv, "p:m:s:j:")) != -1) {
    switch (c) {
      case 'p':
        if (optarg[0] != 'g' && optarg[0] != 'G') {
          std::cout << "Prepending 'G' to the search term.\n";
          term = "G";
        }

        term += optarg;
        matchFunction = &hasPrefix;
        break;
      case 's':
        term = optarg;
        matchFunction = &hasSuffix;
        break;
      case 'm':
        term = optarg;
        matchFunction = &hasSubstr;
        break;
      case 'j':
        threadsCount = atoi(optarg);
        break;
      case '?':
      default:
        usage(argv[0]);
        return 0;
    }
  }

  if (threadsCount < 1) {
    threadsCount = getProcessingUnits();
  }

  std::transform(term.begin(), term.end(), term.begin(), ::toupper);

  char invalidChar = checkInvalidChar(term);

  if (invalidChar != -1) {
    std::cerr << "\"" << invalidChar << "\" is not allowed. The search term must be scoped to:\n\t"
              << base32Dictionary << std::endl;
    return 0;
  }

  if (sodium_init() == -1) {
    std::cerr << "Unable to init libsodium.\n";
    return 1;
  }

  std::cout << "Searching...\n";

  std::vector<std::thread> threads(threadsCount);
  auto start = std::chrono::system_clock::now();

  for (int i = 0; i < threadsCount; i++)
    threads[i] = std::thread(process, term, matchFunction);

  std::for_each(threads.begin(), threads.end(), [](std::thread &t) { t.join(); });

  auto end = std::chrono::system_clock::now();
  std::chrono::duration<double> elapsed_seconds = end - start;

  std::cout << count << " tries in "
            << elapsed_seconds.count() << "s using "
            << threadsCount << " threads.\n";

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rsi, %r14
cmpl $0x1, %edi
jne 0x29d8
movq (%r14), %rdi
callq 0x2669
movl $0x1, %ebx
jmp 0x2c22
movl %edi, %ebp
leaq 0x20(%rsp), %rax
movq %rax, -0x10(%rax)
movq $0x0, -0x8(%rax)
movb $0x0, (%rax)
movl $0xffffffff, 0x4(%rsp)  # imm = 0xFFFFFFFF
leaq 0x1613(%rip), %r15      # 0x4010
leaq 0x10(%rsp), %r12
movl %ebp, %edi
movq %r14, %rsi
leaq 0x16c5(%rip), %rdx      # 0x40d3
callq 0x2050
leal -0x6a(%rax), %ecx
cmpl $0x9, %ecx
ja 0x2b1f
movslq (%r15,%rcx,4), %rax
addq %r15, %rax
jmpq *%rax
movq 0x3591(%rip), %rax      # 0x5fc0
movq (%rax), %rbx
movq 0x18(%rsp), %r13
movq %rbx, %rdi
callq 0x2080
movq %r12, %rdi
xorl %esi, %esi
movq %r13, %rdx
movq %rbx, %rcx
movq %rax, %r8
callq 0x2200
leaq 0x4af(%rip), %rax       # 0x2f08
movq %rax, 0x8(%rsp)
jmp 0x2a02
movq 0x3559(%rip), %rax      # 0x5fc0
movq (%rax), %rbx
movq 0x18(%rsp), %r13
movq %rbx, %rdi
callq 0x2080
movq %r12, %rdi
xorl %esi, %esi
movq %r13, %rdx
movq %rbx, %rcx
movq %rax, %r8
callq 0x2200
leaq 0x3f9(%rip), %rax       # 0x2e8a
movq %rax, 0x8(%rsp)
jmp 0x2a02
movq 0x351e(%rip), %rax      # 0x5fc0
movq (%rax), %rsi
movzbl (%rsi), %eax
orl $0x20, %eax
cmpl $0x67, %eax
je 0x2aee
movl $0x23, %edx
movq 0x3514(%rip), %rdi      # 0x5fd0
leaq 0x1619(%rip), %rsi      # 0x40dc
callq 0x21b0
movq 0x18(%rsp), %rdx
movl $0x1, %r8d
movq %r12, %rdi
xorl %esi, %esi
leaq 0x1621(%rip), %rcx      # 0x4100
callq 0x2200
movq 0x34d5(%rip), %rax      # 0x5fc0
movq (%rax), %rsi
movq %r12, %rdi
callq 0x22d0
leaq 0x318(%rip), %rax       # 0x2e15
movq %rax, 0x8(%rsp)
jmp 0x2a02
movq 0x34b2(%rip), %rax      # 0x5fc0
movq (%rax), %rdi
callq 0x2210
movl %eax, 0x4(%rsp)
jmp 0x2a02
cmpl $-0x1, %eax
jne 0x2bfc
movl 0x4(%rsp), %ebp
testl %ebp, %ebp
jg 0x2b37
callq 0x24fc
movl %eax, %ebp
movq 0x18(%rsp), %rbx
testq %rbx, %rbx
je 0x2b5f
movq 0x10(%rsp), %r14
xorl %r15d, %r15d
movsbl (%r14,%r15), %edi
callq 0x22c0
movb %al, (%r14,%r15)
incq %r15
cmpq %r15, %rbx
jne 0x2b49
leaq 0x10(%rsp), %rdi
callq 0x24ac
cmpb $-0x1, %al
je 0x2c33
movl %eax, %ebx
movq 0x3476(%rip), %rdi      # 0x5ff0
leaq 0x1581(%rip), %rsi      # 0x4102
movl $0x1, %edx
callq 0x21b0
leaq 0x38(%rsp), %rsi
movb %bl, (%rsi)
movq 0x3457(%rip), %rdi      # 0x5ff0
movl $0x1, %edx
callq 0x21b0
movq %rax, %rbx
leaq 0x1557(%rip), %rsi      # 0x4104
movl $0x36, %edx
movq %rax, %rdi
callq 0x21b0
movq 0x35d7(%rip), %rsi      # 0x6198
movq 0x35d8(%rip), %rdx      # 0x61a0
movq %rbx, %rdi
callq 0x21b0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20e0
jmp 0x2c04
movq (%r14), %rdi
callq 0x2669
xorl %ebx, %ebx
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x2c22
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2180
movl %ebx, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x22a0
cmpl $-0x1, %eax
je 0x2d7b
movq 0x3388(%rip), %rdi      # 0x5fd0
leaq 0x1507(%rip), %rsi      # 0x4156
movl $0xd, %edx
callq 0x21b0
movl %ebp, %esi
leaq 0x38(%rsp), %rdi
leaq 0x30(%rsp), %rdx
callq 0x2f24
callq 0x2040
movq %rax, 0x50(%rsp)
cmpl $0x1, %ebp
movl %ebp, 0x4(%rsp)
adcl $0x0, %ebp
xorl %ebx, %ebx
leaq -0x5a4(%rip), %r14      # 0x26e3
leaq 0x30(%rsp), %r15
leaq 0x10(%rsp), %r12
leaq 0x8(%rsp), %r13
movq %r15, %rdi
movq %r14, %rsi
movq %r12, %rdx
movq %r13, %rcx
callq 0x2f92
movq 0x38(%rsp), %rax
cmpq $0x0, (%rax,%rbx,8)
jne 0x2d9d
movq 0x30(%rsp), %rcx
movq %rcx, (%rax,%rbx,8)
incq %rbx
cmpq %rbx, %rbp
jne 0x2c96
movq 0x38(%rsp), %r14
movq 0x40(%rsp), %rbx
cmpq %rbx, %r14
movl 0x4(%rsp), %ebp
je 0x2cec
movq %r14, %rdi
callq 0x2260
addq $0x8, %r14
cmpq %rbx, %r14
jne 0x2cdb
callq 0x2040
movq %rax, %r14
movl 0x34c2(%rip), %esi      # 0x61bc
movq 0x32cf(%rip), %rdi      # 0x5fd0
callq 0x2270
movq %rax, %r15
leaq 0x1454(%rip), %rsi      # 0x4164
movl $0xa, %edx
movq %rax, %rdi
callq 0x21b0
subq 0x50(%rsp), %r14
cvtsi2sd %r14, %xmm0
divsd 0x12d9(%rip), %xmm0     # 0x4008
movq %r15, %rdi
callq 0x2230
movq %rax, %rbx
leaq 0x142e(%rip), %rsi      # 0x416f
movl $0x8, %edx
movq %rax, %rdi
callq 0x21b0
movq %rbx, %rdi
movl %ebp, %esi
callq 0x2270
leaq 0x1419(%rip), %rsi      # 0x4178
movl $0xa, %edx
movq %rax, %rdi
callq 0x21b0
leaq 0x38(%rsp), %rdi
callq 0x302e
jmp 0x2c04
movl $0x1, %ebx
movq 0x3269(%rip), %rdi      # 0x5ff0
leaq 0x13ad(%rip), %rsi      # 0x413b
movl $0x1a, %edx
callq 0x21b0
jmp 0x2c06
callq 0x2060
jmp 0x2dbb
jmp 0x2dac
jmp 0x2dbb
jmp 0x2dac
jmp 0x2dbb
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x302e
jmp 0x2dbe
movq %rax, %rbx
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x2dda
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2180
movq %rbx, %rdi
callq 0x2290