// File: trisolaris233[P]httpc/src/request_parser.hpp
// Function: httpc::RequestParser::ResultType httpc::RequestParser::ParseRequest<char>(httpc::Request&, char)
ResultType ParseRequest(
                Request& request_, CharT chr) {
            // there is a problem with the original parsing function
            // the case is that when request line is like this "GET HTTP/1.1"
            // is also available on many broswers, but error will occurs on
            // the original one.
            switch(parse_enum_) {
                case kStart:
                    if (!is_char(chr) || is_ctl(chr) || is_tspecial(chr)) {
                        return kBad;
                    } else {
                        request_.method.push_back(chr);
                        parse_enum_ = kHTTPMethod;
                        return kIndeterminate;
                    }

                case kHTTPMethod:
                    if (chr == ' ') {
                        parse_enum_ = kURI;
                        return kIndeterminate;
                    } else if (!is_char(chr) || is_ctl(chr) || is_tspecial(chr)) {
                        return kBad;
                    } else {
                        request_.method.push_back(chr);
                        return kIndeterminate;
                    }

                case kURI:
                    if (chr == ' ') {
                        parse_enum_ = kH;
                        return kIndeterminate;
                    } else if (is_ctl(chr)) {
                        return kBad;
                    } else {
                        request_.uri.Append(chr);
                        return kIndeterminate;
                    }

                case kH:
                    if (chr == 'H') {
                        parse_enum_ = kT1;
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kT1:
                    if (chr == 'T') {
                        parse_enum_ = kT2;
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }
                    
                case kT2:
                    if (chr == 'T') {
                        parse_enum_ = kP;
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kP:
                    if (chr == 'P') {
                        parse_enum_ = kSlash;
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kSlash:
                    if (chr == '/') {
                        parse_enum_ = kMajorVersion;
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kMajorVersion:
                    if (chr == '.') {
                        power_ = 1;
                        parse_enum_ = kMinorVersion;
                        return kIndeterminate;
                    } else if (std::isdigit(chr)) {
                        request_.http_major_version += power_ * static_cast<int>(chr - 0x30);
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kMinorVersion:
                    if (chr == '\r') {
                        parse_enum_ = kFirstLF;
                        return kIndeterminate;
                    } else if (std::isdigit(chr)) {
                        request_.http_minor_version += power_ * static_cast<int>(chr - 0x30);
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kFirstLF:
                    if (chr == '\n') {
                        parse_enum_ = kHeaderLineStart;
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kHeaderLineStart:
                    if (chr == '\r') {
                        parse_enum_ = kExceptingNewLineEnding;
                        return kIndeterminate;
                    } else if (!request_.headers.empty() && (chr == ' ' || chr == '\t')) {
                        parse_enum_ = kHeaderLws;
                        return kIndeterminate;
                    } else if (!is_char(chr) || is_ctl(chr) || is_tspecial(chr)) {
                        return kBad;
                    } else {
                        request_.headers.push_back(Header());
                        request_.headers.back().field.push_back(chr);
                        parse_enum_ = kHeaderName;
                        return kIndeterminate;
                    }

                case kHeaderLws:
                    if (chr == '\r') {
                        parse_enum_ = kExceptingNormalNewLine;
                        return kIndeterminate;
                    } else if (chr == ' ' || chr == '\t') {
                        return kIndeterminate;
                    } else if (is_ctl(chr)) {
                        return kBad;
                    } else {
                        parse_enum_ = kHeaderValue;
                        request_.headers.back().value.push_back(chr);
                        return kIndeterminate;;
                    }

                case kHeaderName:
                    if (chr == ':') {
                        parse_enum_ = kSpaceBeforeHeaderValue;
                        return kIndeterminate;
                    } else if (!is_char(chr) || is_ctl(chr) || is_tspecial(chr)) {
                        return kBad;
                    } else {
                        request_.headers.back().field.push_back(chr);
                        return kIndeterminate;
                    }

                case kSpaceBeforeHeaderValue:
                    if (chr == ' ') {
                        parse_enum_ = kHeaderValue;
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kHeaderValue:
                    if (chr == '\r') {
                        parse_enum_ = kExceptingNormalNewLine;
                        return kIndeterminate;
                    } else if (is_ctl(chr)) {
                        return kBad;
                    } else {
                        request_.headers.back().value.push_back(chr);
                        return kIndeterminate;
                    }

                case kExceptingNormalNewLine:
                    if (chr == '\n') {
                        parse_enum_ = kHeaderLineStart;
                        return kIndeterminate;
                    } else {
                        return kBad;
                    }

                case kExceptingNewLineEnding:
                    return chr == '\n' ? kGood : kBad;
                    
                
                default:
                    return kBad;
            }
        }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movb %dl, %al
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movb %al, -0x19(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x80(%rbp)
movl 0x20(%rax), %eax
movq %rax, -0x78(%rbp)
subq $0x12, %rax
ja 0x31c10
movq -0x78(%rbp), %rax
leaq 0x27a60(%rip), %rcx     # 0x5905c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movsbl -0x19(%rbp), %edi
callq 0x55300
testb $0x1, %al
jne 0x31614
jmp 0x31630
movsbl -0x19(%rbp), %edi
callq 0x55330
testb $0x1, %al
jne 0x31630
movsbl -0x19(%rbp), %edi
callq 0x55360
testb $0x1, %al
jne 0x31630
jmp 0x3163c
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movq -0x18(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0xa5d0
movq -0x80(%rbp), %rax
movl $0x1, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x20, %eax
jne 0x31680
movq -0x80(%rbp), %rax
movl $0x2, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edi
callq 0x55300
testb $0x1, %al
jne 0x3168f
jmp 0x316ab
movsbl -0x19(%rbp), %edi
callq 0x55330
testb $0x1, %al
jne 0x316ab
movsbl -0x19(%rbp), %edi
callq 0x55360
testb $0x1, %al
jne 0x316ab
jmp 0x316b7
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movq -0x18(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0xa5d0
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x20, %eax
jne 0x316f0
movq -0x80(%rbp), %rax
movl $0x3, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edi
callq 0x55330
testb $0x1, %al
jne 0x316ff
jmp 0x3170b
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movq -0x18(%rbp), %rdi
addq $0x20, %rdi
leaq -0x19(%rbp), %rsi
callq 0x31e90
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x48, %eax
jne 0x31748
movq -0x80(%rbp), %rax
movl $0x4, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x54, %eax
jne 0x31774
movq -0x80(%rbp), %rax
movl $0x5, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x54, %eax
jne 0x317a0
movq -0x80(%rbp), %rax
movl $0x6, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x50, %eax
jne 0x317cc
movq -0x80(%rbp), %rax
movl $0x7, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x2f, %eax
jne 0x317f8
movq -0x80(%rbp), %rax
movl $0x8, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x2e, %eax
jne 0x3182b
movq -0x80(%rbp), %rax
movl $0x1, 0x28(%rax)
movl $0xa, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edi
callq 0xa610
cmpl $0x0, %eax
je 0x31866
movq -0x80(%rbp), %rax
movl 0x28(%rax), %ecx
movsbl -0x19(%rbp), %eax
subl $0x30, %eax
imull %eax, %ecx
movq -0x18(%rbp), %rax
addl 0x90(%rax), %ecx
movl %ecx, 0x90(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0xd, %eax
jne 0x31892
movq -0x80(%rbp), %rax
movl $0xb, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edi
callq 0xa610
cmpl $0x0, %eax
je 0x318cd
movq -0x80(%rbp), %rax
movl 0x28(%rax), %ecx
movsbl -0x19(%rbp), %eax
subl $0x30, %eax
imull %eax, %ecx
movq -0x18(%rbp), %rax
addl 0x94(%rax), %ecx
movl %ecx, 0x94(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0xa, %eax
jne 0x318f9
movq -0x80(%rbp), %rax
movl $0xc, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0xd, %eax
jne 0x31925
movq -0x80(%rbp), %rax
movl $0x12, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movq -0x18(%rbp), %rdi
addq $0x98, %rdi
callq 0x31ec0
testb $0x1, %al
jne 0x31962
movsbl -0x19(%rbp), %eax
cmpl $0x20, %eax
je 0x3194b
movsbl -0x19(%rbp), %eax
cmpl $0x9, %eax
jne 0x31962
movq -0x80(%rbp), %rax
movl $0xf, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edi
callq 0x55300
testb $0x1, %al
jne 0x31971
jmp 0x3198d
movsbl -0x19(%rbp), %edi
callq 0x55330
testb $0x1, %al
jne 0x3198d
movsbl -0x19(%rbp), %edi
callq 0x55360
testb $0x1, %al
jne 0x3198d
jmp 0x31999
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movq -0x18(%rbp), %rax
addq $0x98, %rax
movq %rax, -0x90(%rbp)
xorps %xmm0, %xmm0
movaps %xmm0, -0x30(%rbp)
movaps %xmm0, -0x40(%rbp)
movaps %xmm0, -0x50(%rbp)
movaps %xmm0, -0x60(%rbp)
leaq -0x60(%rbp), %rdi
movq %rdi, -0x88(%rbp)
callq 0x31f30
movq -0x90(%rbp), %rdi
movq -0x88(%rbp), %rsi
callq 0x31f00
jmp 0x319e2
leaq -0x60(%rbp), %rdi
callq 0x12ce0
movq -0x18(%rbp), %rdi
addq $0x98, %rdi
callq 0x132f0
movq %rax, %rdi
movsbl -0x19(%rbp), %esi
callq 0xa5d0
movq -0x80(%rbp), %rax
movl $0xd, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x12ce0
jmp 0x31c23
movsbl -0x19(%rbp), %eax
cmpl $0xd, %eax
jne 0x31a58
movq -0x80(%rbp), %rax
movl $0x11, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x20, %eax
je 0x31a6a
movsbl -0x19(%rbp), %eax
cmpl $0x9, %eax
jne 0x31a76
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edi
callq 0x55330
testb $0x1, %al
jne 0x31a85
jmp 0x31a91
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movq -0x80(%rbp), %rax
movl $0xe, 0x20(%rax)
movq -0x18(%rbp), %rdi
addq $0x98, %rdi
callq 0x132f0
movq %rax, %rdi
addq $0x20, %rdi
movsbl -0x19(%rbp), %esi
callq 0xa5d0
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x3a, %eax
jne 0x31ae8
movq -0x80(%rbp), %rax
movl $0x10, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edi
callq 0x55300
testb $0x1, %al
jne 0x31af7
jmp 0x31b13
movsbl -0x19(%rbp), %edi
callq 0x55330
testb $0x1, %al
jne 0x31b13
movsbl -0x19(%rbp), %edi
callq 0x55360
testb $0x1, %al
jne 0x31b13
jmp 0x31b1f
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movq -0x18(%rbp), %rdi
addq $0x98, %rdi
callq 0x132f0
movq %rax, %rdi
movsbl -0x19(%rbp), %esi
callq 0xa5d0
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0x20, %eax
jne 0x31b67
movq -0x80(%rbp), %rax
movl $0xe, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0xd, %eax
jne 0x31b93
movq -0x80(%rbp), %rax
movl $0x11, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edi
callq 0x55330
testb $0x1, %al
jne 0x31ba2
jmp 0x31bab
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movq -0x18(%rbp), %rdi
addq $0x98, %rdi
callq 0x132f0
movq %rax, %rdi
addq $0x20, %rdi
movsbl -0x19(%rbp), %esi
callq 0xa5d0
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %eax
cmpl $0xa, %eax
jne 0x31bf1
movq -0x80(%rbp), %rax
movl $0xc, 0x20(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
jmp 0x31c17
movsbl -0x19(%rbp), %edx
movl $0x1, %eax
xorl %ecx, %ecx
cmpl $0xa, %edx
cmovel %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x31c17
movl $0x1, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
movq -0x68(%rbp), %rdi
callq 0xab10
nopl (%rax)