Beispiel #1
0
        /// <summary>
        /// This method validates the state sliding window.
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TMatch"></typeparam>
        /// <param name="state">The match collection state.</param>
        /// <param name="deQueue"></param>
        /// <returns>Returns the updated match state.</returns>
        private static MatchCollectionState <TSource, TMatch> ValidateCollectionSlidingWindow <TSource, TMatch>(
            MatchCollectionState <TSource, TMatch> state
            , bool deQueue)
        {
            //Remove the first item from the collection.
            if (deQueue)
            {
                state.SlidingWindow.Dequeue();
                state.Length++;
                state.Length -= state.SlidingWindow.Count;
            }
#if (DEBUG)
            MatchStateDebugLog(state, "Recurse");
#endif
            //Ok, check whether the queue is empty. This can happen when the queue only contained
            //1 item and was called recursively.
            if (state.SlidingWindow.Count == 0)
            {
                state.Status = MatchTerminatorStatus.NotSet;
                return(state);
            }

            Queue <TSource> window = state.SlidingWindow;

            state.CurrentEnumerator.Reset();
            state.CurrentEnumerator.MoveNext();
            state.SlidingWindow = new Queue <TSource>();
            //OK, we recursively call the window to allow the queue to
            //be processed.

            return(window.MatchCollection(state));
        }
Beispiel #2
0
        /// <summary>
        /// This is the match method. This method maps the incoming buffer to the match parameters.
        /// </summary>
        /// <param name="buffer">The byte buffer.</param>
        /// <param name="offset">The byte offset/</param>
        /// <param name="count">The number of bytes that can be read.</param>
        /// <param name="length">The length of the bytes read.</param>
        /// <returns>Returns true if a match has been found.</returns>
        public virtual bool Match(byte[] buffer, int offset, int count, out int length, out long?bodyLength)
        {
            if (!Initialized)
            {
                throw new NotSupportedException("Match is not supported without Initialization.");
            }

            //Get the current start position so that we can calculate the offset later.
            int lengthStart = mState.Length;

            //OK, match against the specified buffer range.
            mState = buffer
                     .Range(offset, count)
                     .MatchCollection(mState);

            //OK, calculate the number of bytes scanned.
            length = mState.Length - lengthStart;

            //OK, do we have a match?
            if (mState.Status.HasValue && (mState.Status.Value & MatchTerminatorStatus.Success) > 0)
            {
                //Yes, so calculate the actual body length.
                bodyLength = mState.MatchPosition - mState.Start;
                return(true);
            }

            //OK, we don't have a match.
            bodyLength = null;

            return(false);
        }
Beispiel #3
0
        /// <summary>
        /// This method matches the source enumeration against the state collection, this is to allow pattern
        /// matching over multiple byte blocks.
        /// </summary>
        /// <typeparam name="TSource">The source type.</typeparam>
        /// <typeparam name="TMatch">The match type.</typeparam>
        /// <param name="source">The enumerable source.</param>
        /// <param name="state">The incoming match state.</param>
        /// <returns>Returns the updated match state.</returns>
        public static MatchCollectionState <TSource, TMatch> MatchCollection <TSource, TMatch>(
            this IEnumerable <TSource> source
            , MatchCollectionState <TSource, TMatch> state)
        {
            IEnumerator <TSource> sourceEnum = source.GetEnumerator();

            sourceEnum.MoveNext();
            return(sourceEnum.MatchCollection(state));
        }
        private static void MatchStateDebugLog <TSource, TMatch>(MatchCollectionState <TSource, TMatch> state, string type)
        {
            if (state.DebugTrace)
            {
                state.DebugTraceCollection.Add(
                    string.Format("{0} <- {1} Q={2}, ({3})"
                                  , type
                                  , state.DebugTraceRecursion
                                  , state.SlidingWindow == null ? "null" : state.SlidingWindow.Count.ToString()
                                  , !state.Status.HasValue ? "null" : state.Status.Value.ToString())
                    );
            }

            state.DebugTraceRecursion--;
        }
Beispiel #5
0
        /// <summary>
        /// This method matches the source enumeration against the state collection, this is to allow pattern
        /// matching over multiple byte blocks.
        /// </summary>
        /// <typeparam name="TSource">The source type.</typeparam>
        /// <typeparam name="TMatch">The match type.</typeparam>
        /// <param name="sourceEnum">The source enumeration data.</param>
        /// <param name="state">The incoming match state.</param>
        /// <returns>Returns the updated match state.</returns>
        public static MatchCollectionState <TSource, TMatch> MatchCollection <TSource, TMatch>(
            this IEnumerator <TSource> sourceEnum
            , MatchCollectionState <TSource, TMatch> state)
        {
            if (state == null)
            {
                throw new ArgumentNullException("state cannot be null.");
            }

#if (DEBUG)
            state.DebugTraceRecursion++;
#endif
            try
            {
#if (DEBUG)
                MatchStateDebugLog(state, "Entry");
#endif
                //Ok, have we already matched in which case return the current state unchanged.
                if (state.Status.HasValue && ((state.Status.Value & MatchTerminatorStatus.Success) > 0))
                {
                    return(state);
                }

                //Initialize the state.
                if (!state.Status.HasValue)
                {
                    state.Start  = state.Length;
                    state.Status = MatchTerminatorStatus.NotSet;
                }

                //OK, get the MatchTerminator current enumerator or create a new one if it is null.
                IEnumerator <MatchTerminator <TSource, TMatch> > currentEnum = state.ActualEnumerator;

                //Check whether there is any data from the sliding window and if so process it first.
                if (state.SlidingWindow.Count > 0 && state.Status == MatchTerminatorStatus.NotSet)
                {
                    state = ValidateCollectionSlidingWindow(state, false);
                }

                //If the sliding window data has completed the match, then exit
                if ((state.Status & MatchTerminatorStatus.Success) > 0)
                {
                    return(state);
                }

                //Ok, let's start the match.
                MatchTerminatorResult result;
                bool reset = false;
                do
                {
                    MatchTerminator <TSource, TMatch> term = currentEnum.Current;
                    result = term.Match(sourceEnum, state.SlidingWindow, state.Length - state.Start);

                    reset = (result.Status & MatchTerminatorStatus.Reset) > 0;
#if (DEBUG)
                    if (state.DebugTrace)
                    {
                        state.DebugTraceCollection.Add(
                            string.Format("Match ({0})={1} [{2:X}]", term.GetType().Name, result.Status, state.Length));
                    }
#endif
                    state.IsTerminator |= result.IsTerminator;

                    switch (result.Status)
                    {
                    case MatchTerminatorStatus.Fail:
                        term.Reset();
                        state.Length += result.Length - 1;    // +state.SlidingWindow.Count - 1;
                        if (state.SlidingWindow.Count > 0)
                        {
                            int oldLength = state.Length;
                            //Dispose of the first item, and process the queue.
                            state = ValidateCollectionSlidingWindow <TSource, TMatch>(state, true);
                            //Ok, we need to check whether we have a partial match in the enqueued bytes.
                            currentEnum = state.CurrentEnumerator;
                        }

                        if (state.Status != MatchTerminatorStatus.SuccessPartial)
                        {
                            currentEnum.Reset();
                        }

                        break;

                    case MatchTerminatorStatus.SuccessPartial:
                        //Ok, we have a partial match but have reached the end of sourceEnum, so return
                        //and wait for the next piece.
                        state.Status  = MatchTerminatorStatus.SuccessPartial;
                        state.Length += result.Length;
                        if (state.MatchPosition == -1)
                        {
                            state.MatchPosition = state.Length - state.SlidingWindow.Count;
                        }
                        return(state);

                    case MatchTerminatorStatus.NotSet:
                        //Ok, we have scanned to the end of the array and not found a match.
                        state.MatchPosition = -1;
                        state.Length       += result.Length;
                        return(state);

                    case MatchTerminatorStatus.SuccessNoLength:
                    case MatchTerminatorStatus.SuccessNoLengthReset:
                        term.Reset();
                        state.Length += result.Length;
                        if (state.MatchPosition == -1)
                        {
                            state.MatchPosition = state.Length - state.SlidingWindow.Count;
                        }

                        if (reset)
                        {
                            currentEnum.Reset();
                            currentEnum.MoveNext();
                        }


                        break;

                    case MatchTerminatorStatus.Success:
                    case MatchTerminatorStatus.SuccessReset:
                        term.Reset();
                        state.Length += result.Length;
                        if (state.MatchPosition == -1)
                        {
                            state.MatchPosition = state.Length - state.SlidingWindow.Count;
                        }

                        if (reset)
                        {
                            currentEnum.Reset();
                            currentEnum.MoveNext();
                        }
                        //Ok, we are successful, so we need to move on to the next step.

                        if (!result.CanContinue || reset)
                        {
                            //We have reached the end of the byte stream so we need to check whether we have
                            //actually terminated.
                            bool moreTerminatorParts = reset ? false : currentEnum.MoveNext();
                            if (!state.IsTerminator && moreTerminatorParts)
                            {
                                //OK, we only have a partial match as the terminator flag is not set and we have more parts
                                //of the terminator to process.
                                state.Status = MatchTerminatorStatus.SuccessPartial;
                            }
                            else
                            {
                                //Ok, either the termination flag is set, meaning the terminator chars match a specific character
                                //or there are no more parts of the terminator to match.
                                state.Status = MatchTerminatorStatus.Success;
                                state.SlidingWindow.Clear();
                            }

                            return(state);
                        }

                        break;

                    default:
                        throw new ArgumentOutOfRangeException("Unknown MatchTerminatorStatus value.");
                    }
                }while (result.CanContinue && currentEnum.MoveNext() && !reset);

                //OK, we have completed. Either we have failed or succeeded
                state.Status = result.Status;

                //OK, time to do some tidy up.
                if ((result.Status & MatchTerminatorStatus.Success) > 0)
                {
                    int extra = state.Length - state.MatchPosition;
                    state.SlidingWindow.DequeueRemove(extra);
                    state.CurrentEnumerator = null;
                }

                return(state);
            }
            finally
            {
#if (DEBUG)
                MatchStateDebugLog(state, "Exit");
#endif
            }
        }