/* #line 150 "./ragel/tsip_parser_message.rl" */

    public static TSIP_Message Parse(byte[] content, Boolean extractContent)
    {
        TSK_RagelState state = TSK_RagelState.Init(content);

        byte[]       data    = content;
        TSIP_Message message = null;

        // Ragel init
        TSIP_ParserMessage.Init(ref state);

        // State mechine execution
        message = TSIP_ParserMessage.Execute(ref state, extractContent);

        // Check result
        if (message != null && state.CS <
/* #line 196 "../Parsers/TSIP_ParserMessage.cs" */
            37
/* #line 164 "./ragel/tsip_parser_message.rl" */
            )
        {
            message.Dispose();
            message = null;
        }
        return(message);
    }
    private static void Init(ref TSK_RagelState state)
    {
        int cs = 0;

        // Ragel machine initialization

/* #line 213 "../Parsers/TSIP_ParserMessage.cs" */
        {
            cs = tsip_machine_parser_message_start;
        }

/* #line 178 "./ragel/tsip_parser_message.rl" */

        state.CS = cs;
    }
    private static void EoH(ref TSK_RagelState state, ref TSIP_Message message, Boolean extractContent)
    {
        int cs  = state.CS;
        int p   = state.P;
        int pe  = state.PE;
        int eof = state.EOF;

        if (extractContent && message != null)
        {
            int clen = (int)(message.ContentLength != null ? message.ContentLength.Length : 0);
            if ((p + clen) < pe && message.Content == null)
            {
                byte[] content = new byte[clen];
                Buffer.BlockCopy(state.Data, p + 1, content, 0, clen);
                message.AddContent(null, content);
                p = (p + clen);
            }
            else
            {
                p = (pe - 1);
            }
        }
    }
 // Check if we have ",CRLF" ==> See WWW-Authenticate header
 // As :>CRLF is preceded by any+ ==> p will be at least (start + 1)
 // p point to CR
 private static Boolean PrevNotComma(TSK_RagelState state, int p)
 {
     return((state.PE <= p) || ((char)state.Data[p - 1] != ','));
 }
    private static TSIP_Message Execute(ref TSK_RagelState state, Boolean extractContent)
    {
        int cs  = state.CS;
        int p   = state.P;
        int pe  = state.PE;
        int eof = state.EOF;

        byte[]       data    = state.Data;
        TSIP_Message message = null;


/* #line 233 "../Parsers/TSIP_ParserMessage.cs" */
        {
            sbyte _klen;
            byte  _trans;
            int   _widec;
            sbyte _acts;
            sbyte _nacts;
            byte  _keys;

            if (p == pe)
            {
                goto _test_eof;
            }
            if (cs == 0)
            {
                goto _out;
            }
_resume:
            _widec = data[p];
            _klen  = _tsip_machine_parser_message_cond_lengths[cs];
            _keys  = (byte)(_tsip_machine_parser_message_cond_offsets[cs] * 2);
            if (_klen > 0)
            {
                short _lower = _keys;
                short _mid;
                short _upper = (short)(_keys + (_klen << 1) - 2);
                while (true)
                {
                    if (_upper < _lower)
                    {
                        break;
                    }

                    _mid = (short)(_lower + (((_upper - _lower) >> 1) & ~1));
                    if (_widec < _tsip_machine_parser_message_cond_keys[_mid])
                    {
                        _upper = (short)(_mid - 2);
                    }
                    else if (_widec > _tsip_machine_parser_message_cond_keys[_mid + 1])
                    {
                        _lower = (short)(_mid + 2);
                    }
                    else
                    {
                        switch (_tsip_machine_parser_message_cond_spaces[_tsip_machine_parser_message_cond_offsets[cs] + ((_mid - _keys) >> 1)])
                        {
                        case 0: {
                            _widec = (int)(65536u + (data[p] - 0u));
                            if (
/* #line 29 "./ragel/tsip_parser_message.rl" */

                                PrevNotComma(state, p)
                                )
                            {
                                _widec += 65536;
                            }
                            break;
                        }

                        default: break;
                        }
                        break;
                    }
                }
            }

            _keys  = _tsip_machine_parser_message_key_offsets[cs];
            _trans = (byte)_tsip_machine_parser_message_index_offsets[cs];

            _klen = _tsip_machine_parser_message_single_lengths[cs];
            if (_klen > 0)
            {
                short _lower = _keys;
                short _mid;
                short _upper = (short)(_keys + _klen - 1);
                while (true)
                {
                    if (_upper < _lower)
                    {
                        break;
                    }

                    _mid = (short)(_lower + ((_upper - _lower) >> 1));
                    if (_widec < _tsip_machine_parser_message_trans_keys[_mid])
                    {
                        _upper = (short)(_mid - 1);
                    }
                    else if (_widec > _tsip_machine_parser_message_trans_keys[_mid])
                    {
                        _lower = (short)(_mid + 1);
                    }
                    else
                    {
                        _trans += (byte)(_mid - _keys);
                        goto _match;
                    }
                }
                _keys  += (byte)_klen;
                _trans += (byte)_klen;
            }

            _klen = _tsip_machine_parser_message_range_lengths[cs];
            if (_klen > 0)
            {
                short _lower = _keys;
                short _mid;
                short _upper = (short)(_keys + (_klen << 1) - 2);
                while (true)
                {
                    if (_upper < _lower)
                    {
                        break;
                    }

                    _mid = (short)(_lower + (((_upper - _lower) >> 1) & ~1));
                    if (_widec < _tsip_machine_parser_message_trans_keys[_mid])
                    {
                        _upper = (short)(_mid - 2);
                    }
                    else if (_widec > _tsip_machine_parser_message_trans_keys[_mid + 1])
                    {
                        _lower = (short)(_mid + 2);
                    }
                    else
                    {
                        _trans += (byte)((_mid - _keys) >> 1);
                        goto _match;
                    }
                }
                _trans += (byte)_klen;
            }

_match:
            _trans = (byte)_tsip_machine_parser_message_indicies[_trans];
            cs     = _tsip_machine_parser_message_trans_targs[_trans];

            if (_tsip_machine_parser_message_trans_actions[_trans] == 0)
            {
                goto _again;
            }

            _acts  = _tsip_machine_parser_message_trans_actions[_trans];
            _nacts = _tsip_machine_parser_message_actions[_acts++];
            while (_nacts-- > 0)
            {
                switch (_tsip_machine_parser_message_actions[_acts++])
                {
                case 0:
/* #line 30 "./ragel/tsip_parser_message.rl" */
                {
                    state.TagStart = p;
                }
                break;

                case 1:
/* #line 36 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);
                    String method = Encoding.UTF8.GetString(data, state.TagStart, len);
                    if (message == null)
                    {
                        message = new TSIP_Request(method, null, null, null, null, 0);
                    }
                    else
                    {
                        state.CS = tsip_machine_parser_message_error;
                    }
                }
                break;

                case 2:
/* #line 53 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);
                    if ((message as TSIP_Request).Uri == null)
                    {
                        (message as TSIP_Request).Uri = TSIP_ParserUri.Parse(Encoding.UTF8.GetString(state.Data, state.TagStart, len));
                    }
                }
                break;

                case 3:
/* #line 65 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);

                    if (message == null)
                    {
                        message = new TSIP_Response(0, null, null);
                    }
                    message.Version = Encoding.UTF8.GetString(state.Data, state.TagStart, len);
                }
                break;

                case 4:
/* #line 79 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);

                    if (message == null)
                    {
                        message = new TSIP_Response(0, null, null);
                    }

                    UInt16 statusCode = 0;
                    if (UInt16.TryParse(Encoding.UTF8.GetString(state.Data, state.TagStart, len), out statusCode))
                    {
                        (message as TSIP_Response).StatusCode = statusCode;
                    }
                }
                break;

                case 5:
/* #line 98 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);
                    (message as TSIP_Response).ReasonPhrase = Encoding.UTF8.GetString(state.Data, state.TagStart, len);
                }
                break;

                case 6:
/* #line 107 "./ragel/tsip_parser_message.rl" */
                {
                    int len;
                    state.TagEnd = p;
                    len          = (int)(state.TagEnd - state.TagStart);

                    if (!TSIP_ParserHeader.Parse(state, ref message))
                    {
                        TSK_Debug.Error("Failed to parse header at {0}", state.TagStart);
                    }
                }
                break;

                case 7:
/* #line 119 "./ragel/tsip_parser_message.rl" */
                {
                    state.CS  = cs;
                    state.P   = p;
                    state.PE  = pe;
                    state.EOF = eof;

                    TSIP_ParserMessage.EoH(ref state, ref message, extractContent);

                    cs  = state.CS;
                    p   = state.P;
                    pe  = state.PE;
                    eof = state.EOF;
                }
                break;

/* #line 447 "../Parsers/TSIP_ParserMessage.cs" */
                default: break;
                }
            }

_again:
            if (cs == 0)
            {
                goto _out;
            }
            if (++p != pe)
            {
                goto _resume;
            }
            _test_eof : {}
            _out      : {}
        }

/* #line 192 "./ragel/tsip_parser_message.rl" */

        state.CS  = cs;
        state.P   = p;
        state.PE  = pe;
        state.EOF = eof;

        return(message);
    }