protected virtual void PostElementParse(ref List <Match> .Enumerator tokens, AppenderValue appenderValue, string aggregate = null)
 {
     tokens.MoveNext();
 }
        protected virtual AppenderValue NewAppenderValue()
        {
            var v = new AppenderValue();

            return(v);
        }
 protected virtual void AssignValueField(AppenderValue currentValue, string fieldName, double d, string sNum, string sValue)
 {
 }
 protected void AddValue(AppenderValue currentValue)
 {
     _values.Add(currentValue);
 }
        protected virtual void ParseTokens(ref List <Match> .Enumerator enumerator, string renderedMessage)
        {
            string name, sNum = string.Empty, rest = "";
            int?   jsonDepth = 0, ignoreBelow = null, includeAt = null;

            var collectedTokens = new List <int>();

            AppenderValue currentValue = null;

            var matches = new List <Match>();

            while (enumerator.MoveNext())
            {
                matches.Add(enumerator.Current);
            }

            var tokens = matches.GetEnumerator();

            tokens.MoveNext();
            while (tokens.Current != null)
            {
                if (!string.IsNullOrEmpty(tokens.Current.Groups["lbrace"].Value))
                {
                    jsonDepth++;

                    tokens.MoveNext();
                    if (currentValue != null && includeAt == null)
                    {
                        includeAt = jsonDepth;
                    }


                    continue;
                }

                if (!string.IsNullOrEmpty(tokens.Current.Groups["rbrace"].Value))
                {
                    jsonDepth--;

                    tokens.MoveNext();
                    if (currentValue != null && jsonDepth < includeAt)
                    {
                        includeAt = null;
                        _values.Add(currentValue);
                        currentValue = null;
                    }


                    continue;
                }


                if (ignoreBelow != null && jsonDepth > ignoreBelow)
                {
                    tokens.MoveNext();
                    continue;
                }

                if (!string.IsNullOrEmpty(name = tokens.Current.Groups["name"].Value))
                {
                    if (!IsSupportedName(name))
                    {
                        tokens.MoveNext();
                        ignoreBelow = jsonDepth;
                        continue;
                    }

                    collectedTokens.Add(tokens.Current.Index);

                    ignoreBelow = null;

                    if (currentValue != null && includeAt == null)
                    {
                        currentValue = null;
                    }

                    if (currentValue == null)
                    {
                        currentValue      = NewAppenderValue();
                        currentValue.Name = name;
                    }

                    if (includeAt != null && (IsSupportedValueField(name) || name.Equals("value", StringComparison.OrdinalIgnoreCase)))
                    {
                        tokens.MoveNext();

                        sNum = string.IsNullOrEmpty(tokens.Current.Groups["float"].Value)
                            ? tokens.Current.Groups["int"].Value
                            : tokens.Current.Groups["float"].Value;

                        var sValue = tokens.Current.Groups["word"].Value;

                        if (string.IsNullOrEmpty(sNum) && string.IsNullOrEmpty(sValue))
                        {
                            tokens.MoveNext();
                            continue;
                        }

                        double d;

                        if (!Double.TryParse(sNum, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out d))
                        {
                            if (string.IsNullOrEmpty(sValue))
                            {
                                tokens.MoveNext();
                                continue;
                            }

                            Double.TryParse(sValue.Trim("\" ".ToCharArray()), NumberStyles.AllowDecimalPoint,
                                            CultureInfo.InvariantCulture, out d);
                        }


                        if (name.Equals("value", StringComparison.OrdinalIgnoreCase))
                        {
                            currentValue.dValue = d;
                            currentValue.sValue = string.IsNullOrEmpty(sValue) ? sNum : sValue;

                            collectedTokens.Add(tokens.Current.Index);
                            PostElementParse(ref tokens, currentValue);

                            continue;
                        }

                        AssignValueField(currentValue, name, d, sNum, sValue);
                        collectedTokens.Add(tokens.Current.Index);
                        tokens.MoveNext();
                        continue;
                    }

                    if (ShouldLocalParse(name))
                    {
                        LocalParse(ref tokens);
                    }
                    else if (name.StartsWith("Timestamp", StringComparison.InvariantCultureIgnoreCase))
                    {
                        DateTimeOffset time;
                        int            length;
                        var            start = tokens.Current.Index + name.Length + 1;
                        if (ExtractTime(renderedMessage.Substring(start), out time, out length))
                        {
                            _values.Add(new AppenderValue
                            {
                                Name = "Timestamp",
                                Time = time
                            });

                            collectedTokens.Add(tokens.Current.Index);
                            tokens.MoveNext();
                            do
                            {
                                if (tokens.Current != null)
                                {
                                    collectedTokens.Add(tokens.Current.Index);
                                }
                            } while (tokens.MoveNext() && tokens.Current.Index < start + length);
                        }

                        tokens.MoveNext();
                    }
                    else
                    {
                        if (!tokens.MoveNext())
                        {
                            continue;
                        }

                        if (!string.IsNullOrEmpty(tokens.Current.Groups["lbrace"].Value))
                        {
                            continue;
                        }

                        sNum = string.IsNullOrEmpty(tokens.Current.Groups["float"].Value)
                            ? tokens.Current.Groups["int"].Value
                            : tokens.Current.Groups["float"].Value;

                        var sValue = tokens.Current.Groups["word"].Value;

                        var strings = sValue.Split(' ');
                        if (strings.Count() > 1 && string.IsNullOrEmpty(sNum))
                        {
                            sNum = strings[0];
                        }

                        if (string.IsNullOrEmpty(sNum) && string.IsNullOrEmpty(sValue))
                        {
                            tokens.MoveNext();
                            continue;
                        }

                        double d;

                        if (!Double.TryParse(sNum, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out d))
                        {
                            if (string.IsNullOrEmpty(sValue))
                            {
                                tokens.MoveNext();
                                continue;
                            }

                            Double.TryParse(sValue.Trim('"'), NumberStyles.AllowDecimalPoint,
                                            CultureInfo.InvariantCulture, out d);
                        }


                        currentValue.dValue = d;
                        currentValue.sValue = string.IsNullOrEmpty(sValue) ? sNum : sValue;

                        var aggregate = strings.Skip(1).Aggregate("", (a, b) => a + b);

                        if (tokens.Current != null)
                        {
                            collectedTokens.Add(tokens.Current.Index);
                        }
                        PostElementParse(ref tokens, currentValue, aggregate);

                        AddValue(currentValue);
                        currentValue = null;
                    }
                }
                else
                {
                    tokens.MoveNext();
                }
            }

            collectedTokens = collectedTokens.Distinct().ToList();

            tokens = matches.GetEnumerator();

            int?startRest = 0;
            var rest2     = "";

            while (tokens.MoveNext())
            {
                if (!collectedTokens.Contains(tokens.Current.Index))
                {
                    startRest = startRest ?? tokens.Current.Index;
                }
                else
                {
                    if (startRest != null)
                    {
                        rest2 += renderedMessage.Substring(startRest.Value, tokens.Current.Index - startRest.Value);
                    }
                    startRest = null;
                }
            }

            if (startRest != null)
            {
                rest2 += renderedMessage.Substring(startRest.Value, renderedMessage.Length - startRest.Value);
            }

            rest2 = rest2.Replace(" {} ", " ").Replace("{}", "");
            rest  = rest2;

            AddValue(new AppenderValue {
                Name = "__cav_rest", sValue = rest.Trim()
            });
        }
 protected abstract bool FillName(AppenderValue value);