// File: ivanzamanov[P]kmeans/src/common/matcher.cpp
// Function: build_matcher(char const*, matcher*&)
bool build_matcher(const char* string, matcher* &result) {
	// The result
	result = new matcher();
	unsigned int n = 0;
	// strlen
	while(*(string + n) != 0) {
		n++;
	}
	// Save the string and it's lenght
	// Not sure why...
	result->n = n;
	result->string = new char[n + 1];
	result->string[n] = 0;

	// While copying the string, find and save
	// the min and max chars to reduce
	// memory footprint
	char min_char = 0;
	char max_char = 0;
	for(unsigned int k = 0; k < n; k++) {
		char c = string[k];
		result->string[k] = c;
		if(min_char > c) {
			min_char = c;
		}
		if(max_char < c) {
			max_char = c;
		}
	}
	unsigned int range = max_char - min_char + 1;
	result->min_char = min_char;
	result->max_char = max_char;
	// Transitions table
	result->table = new unsigned int*[n + 1];
	for (unsigned int i = 0; i < n + 1; i++) {
		result->table[i] = new unsigned int[range];
	}

	unsigned int** table = result->table;
	for (unsigned int i = 0; i < n+1; i++) {
		for (unsigned int j = 0; j < range; j++) {
			table[i][j] = 0;
		}
	}
	
	// Will hold the sink state for each character
	// So we won't need to go back every time and search
	unsigned int* sinks = new unsigned int[range];
	for(unsigned int i = 0; i < range; i++) {
		sinks[i] = 0;
	}

	// Populate transitions
	for (unsigned int i = 0; i < n+1; i++) {
		unsigned int c = (unsigned int) result->string[i];
		// Sink back to the first state which has
		// a transition with this char for all previous
		// characters
		// Always a transition to the next state
		// with the current char
		// This is the new sink state for this char
		sinks[c] = i+1;
		for (unsigned int j = 0; j < range; j++) {
			table[i][j] = sinks[j];
		}
	}
	delete sinks;
	return 1;
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movl $0x18, %edi
callq 0x10b0
movq %rax, %rdi
movq %rdi, 0x10(%rsp)
xorl %esi, %esi
movl $0x18, %edx
callq 0x1080
movq 0x10(%rsp), %rcx
movq 0x58(%rsp), %rax
movq %rcx, (%rax)
movl $0x0, 0x54(%rsp)
movq 0x60(%rsp), %rax
movl 0x54(%rsp), %ecx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
je 0x1770
movl 0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x54(%rsp)
jmp 0x1751
movl 0x54(%rsp), %ecx
movq 0x58(%rsp), %rax
movq (%rax), %rax
movl %ecx, 0x8(%rax)
movl 0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, %eax
movl %eax, %edi
callq 0x1030
movq %rax, %rcx
movq 0x58(%rsp), %rax
movq (%rax), %rax
movq %rcx, (%rax)
movq 0x58(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movl 0x54(%rsp), %ecx
movb $0x0, (%rax,%rcx)
movb $0x0, 0x53(%rsp)
movb $0x0, 0x52(%rsp)
movl $0x0, 0x4c(%rsp)
movl 0x4c(%rsp), %eax
cmpl 0x54(%rsp), %eax
jae 0x182d
movq 0x60(%rsp), %rax
movl 0x4c(%rsp), %ecx
movb (%rax,%rcx), %al
movb %al, 0x4b(%rsp)
movb 0x4b(%rsp), %dl
movq 0x58(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movl 0x4c(%rsp), %ecx
movb %dl, (%rax,%rcx)
movsbl 0x53(%rsp), %eax
movsbl 0x4b(%rsp), %ecx
cmpl %ecx, %eax
jle 0x1808
movb 0x4b(%rsp), %al
movb %al, 0x53(%rsp)
movsbl 0x52(%rsp), %eax
movsbl 0x4b(%rsp), %ecx
cmpl %ecx, %eax
jge 0x181e
movb 0x4b(%rsp), %al
movb %al, 0x52(%rsp)
jmp 0x1820
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x17c2
movsbl 0x52(%rsp), %eax
movsbl 0x53(%rsp), %ecx
subl %ecx, %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
movb 0x53(%rsp), %cl
movq 0x58(%rsp), %rax
movq (%rax), %rax
movb %cl, 0xc(%rax)
movb 0x52(%rsp), %cl
movq 0x58(%rsp), %rax
movq (%rax), %rax
movb %cl, 0xd(%rax)
movl 0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, %eax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x1030
movq %rax, %rcx
movq 0x58(%rsp), %rax
movq (%rax), %rax
movq %rcx, 0x10(%rax)
movl $0x0, 0x40(%rsp)
movl 0x40(%rsp), %eax
movl 0x54(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jae 0x18f7
movl 0x44(%rsp), %eax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x1030
movq %rax, %rdx
movq 0x58(%rsp), %rax
movq (%rax), %rax
movq 0x10(%rax), %rax
movl 0x40(%rsp), %ecx
movq %rdx, (%rax,%rcx,8)
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x189f
movq 0x58(%rsp), %rax
movq (%rax), %rax
movq 0x10(%rax), %rax
movq %rax, 0x38(%rsp)
movl $0x0, 0x34(%rsp)
movl 0x34(%rsp), %eax
movl 0x54(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jae 0x1965
movl $0x0, 0x30(%rsp)
movl 0x30(%rsp), %eax
cmpl 0x44(%rsp), %eax
jae 0x1956
movq 0x38(%rsp), %rax
movl 0x34(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movl 0x30(%rsp), %ecx
movl $0x0, (%rax,%rcx,4)
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x1927
jmp 0x1958
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0x1910
movl 0x44(%rsp), %eax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x1030
movq %rax, 0x28(%rsp)
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x44(%rsp), %eax
jae 0x19be
movq 0x28(%rsp), %rax
movl 0x24(%rsp), %ecx
movl $0x0, (%rax,%rcx,4)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x1997
movl $0x0, 0x20(%rsp)
movl 0x20(%rsp), %eax
movl 0x54(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jae 0x1a50
movq 0x58(%rsp), %rax
movq (%rax), %rax
movq (%rax), %rax
movl 0x20(%rsp), %ecx
movsbl (%rax,%rcx), %eax
movl %eax, 0x1c(%rsp)
movl 0x20(%rsp), %edx
addl $0x1, %edx
movq 0x28(%rsp), %rax
movl 0x1c(%rsp), %ecx
movl %edx, (%rax,%rcx,4)
movl $0x0, 0x18(%rsp)
movl 0x18(%rsp), %eax
cmpl 0x44(%rsp), %eax
jae 0x1a3e
movq 0x28(%rsp), %rax
movl 0x18(%rsp), %ecx
movl (%rax,%rcx,4), %edx
movq 0x38(%rsp), %rax
movl 0x20(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movl 0x18(%rsp), %ecx
movl %edx, (%rax,%rcx,4)
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x1a07
jmp 0x1a40
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0x19c6
movq 0x28(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x1a6a
movq 0x8(%rsp), %rdi
callq 0x10a0
movb $0x1, %al
andb $0x1, %al
addq $0x68, %rsp
retq
nopw %cs:(%rax,%rax)