Пример #1
0
        /// <summary>
        /// Parse the specified characters and test against the scheme and it's children. Returns if it's
        /// requirements are satisfied.
        /// </summary>
        public unsafe override bool Next(char[] characters, int start, int end)
        {
            // if the result isn't going anywhere - skip
            if (!_extract.OnSectionSet && _extract.SubExtracts.Count == 0)
            {
                // no result method or sub extracts
                return(false);
            }

            // have the results of this parser been satisfied?
            if (_runSubParsers)
            {
                // yes, pass any characters to the sub-parsers
                foreach (Parse parser in _activeSubParsers)
                {
                    if (!parser.Next(characters, start, end))
                    {
                        _activeSubParsers.RemoveQuick(parser);
                        _runSubParsers = _activeSubParsers.Count > 0;
                    }
                }
            }

            // the ultimate result of this parse is whether a result is achieved and
            // passed to a return method or a sub extract method is similarly successful
            bool result = false;
            // the last index to be copied into the current section
            int lastIndex = start;

            // are there prefixes and suffixes?
            if (_prefixesSet && _suffixesSet)
            {
                // yes, both prefixes and suffixes

                // set the current index within the block
                Index = lastIndex - 1;

                // loop until the block is complete
                while (Index <= end)
                {
                    // are there prefixes or has a match been found?
                    if (Active)
                    {
                        // iterate characters in current block
                        while (++Index < end)
                        {
                            char character = characters[Index];

                            // if a suffix has been found
                            if (_suffixSearch.Next(character))
                            {
                                // if current section count + current block is greater than max allowed
                                if (_currentSection.Count + Index - lastIndex > _extract.MaxCharacters)
                                {
                                    // overflow - reset section stack
                                    Reset();

                                    // decrement the index to start searching for the prefix
                                    --Index;

                                    // revert to prefix search
                                    break;
                                }

                                ++Index;

                                // is the current section able to contain the next block of characters?
                                if (_currentSection.Capacity - _currentSection.Count < Index - lastIndex)
                                {
                                    // no, resize
                                    _currentSection.SetCapacity(_currentSection.Capacity + Index - lastIndex);
                                }

                                // append the block up to the current index
                                fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                                {
                                    Marshal.Copy(characters, lastIndex, (IntPtr)dst, Index - lastIndex);
                                }

                                // update the current section count
                                _currentSection.Count += Index - lastIndex;
                                // update the last index
                                --Index;
                                lastIndex = Index;

                                // if there are nested requirements
                                if (_reqParsersSet)
                                {
                                    // run required nested extracts
                                    foreach (Parse reqParser in _reqParsers)
                                    {
                                        // if required extract wasn't satisfied then not active
                                        Active &= reqParser.Next(_currentSection.Array, 0, _currentSection.Count);
                                    }
                                }

                                // if any requirements were fulfilled
                                if (Active)
                                {
                                    // if there are sub parsers
                                    if (_subParsersSet)
                                    {
                                        // begin running sub parsers
                                        for (int i = _subParsers.Count - 1; i >= 0; --i)
                                        {
                                            if (_subParsers[i].Next(_currentSection.Array, 0, _currentSection.Count))
                                            {
                                                _activeSubParsers.Add(_subParsers[i]);
                                            }
                                            else
                                            {
                                                _activeSubParsers.RemoveQuick(_subParsers[i]);
                                            }
                                        }
                                        _runSubParsers = _activeSubParsers.Count != 0;
                                    }

                                    // if section callback is set
                                    if (_extract.OnSectionSet)
                                    {
                                        // run complete section callback
                                        _extract.OnSection.Take();
                                        _extract.OnSection.Item.ArgA = _currentSection.ToArray();
                                        _extract.OnSection.Item.Run();
                                        _extract.OnSection.Release();
                                        result = true;
                                    }
                                }

                                // pop the last section and check max length
                                if (Sections.Count > 1 && Sections[Sections.Count - 1].Count + _currentSection.Count - 1 < _extract.MaxCharacters)
                                {
                                    // get the next session
                                    Sections.Remove(Sections.Count - 1);
                                    ArrayRig <char> nextSection = Sections[Sections.Count - 1];

                                    // will the next section contain the current sections characters?
                                    if (nextSection.Capacity - nextSection.Count < _currentSection.Count)
                                    {
                                        // no, resize
                                        nextSection.SetCapacity(nextSection.Capacity + _currentSection.Count);
                                    }

                                    // append the last section
                                    fixed(void *dst = &nextSection.Array[0])
                                    {
                                        Marshal.Copy(_currentSection.Array, 0, (IntPtr)dst, _currentSection.Count);
                                    }

                                    // update the next section count
                                    nextSection.Count += _currentSection.Count;

                                    // set current section
                                    _currentSection = nextSection;

                                    // flag for suffix search
                                    Active = true;
                                }
                                else
                                {
                                    // reset the section stack
                                    Reset();

                                    // decrement index
                                    --Index;

                                    // move back to prefix search
                                    break;
                                }
                            }

                            // has the prefix been found?
                            if (_prefixSearch.Next(character))
                            {
                                // nested prefix has been found

                                // check max length of current section
                                if (_currentSection.Count + Index - lastIndex > _extract.MaxCharacters)
                                {
                                    // overflow - reset the sections stack
                                    Reset();
                                }
                                else
                                {
                                    // add the current section to the stack
                                    Sections.Add(_currentSection);

                                    // initialize new nested section
                                    _currentSection = new ArrayRig <char>();
                                }

                                // get the prefix char array
                                char[] prefix = _prefixSearch.Values[0].ToCharArray();

                                // if the current section won't contain the prefix
                                if (_currentSection.Capacity - _currentSection.Count < prefix.Length)
                                {
                                    // resize
                                    _currentSection.SetCapacity(_currentSection.Capacity + prefix.Length);
                                }

                                // copy the prefix charcters to the current section
                                fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                                {
                                    Marshal.Copy(prefix, 0, (IntPtr)dst, prefix.Length);
                                }

                                // update the section count
                                _currentSection.Count += prefix.Length;
                            }
                        }

                        // if block is finished
                        if (Index == end - 1)
                        {
                            // check max length
                            if (_currentSection.Count + Index - lastIndex > _extract.MaxCharacters)
                            {
                                // overflow - reset
                                Reset();
                            }
                            else
                            {
                                // if the current section won't contain the block
                                if (_currentSection.Capacity - _currentSection.Count < Index - lastIndex)
                                {
                                    // resize
                                    _currentSection.SetCapacity(_currentSection.Capacity + Index - lastIndex);
                                }

                                // copy the block charcters to the current section
                                fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                                {
                                    Marshal.Copy(characters, lastIndex, (IntPtr)dst, Index - lastIndex);
                                }

                                // update the section count
                                _currentSection.Count += Index - lastIndex;
                                lastIndex              = Index;
                            }

                            // return the result of the current block
                            return(result);
                        }
                    }

                    // search for a prefix

                    // iterate chacters in current block
                    while (++Index < end)
                    {
                        char character = characters[Index];

                        // if a prefix has been found
                        if (_prefixSearch.Next(character))
                        {
                            // get the prefix char array
                            char[] prefix = _prefixSearch.Values[0].ToCharArray();

                            // is the current section collection large enough for the prefix?
                            if (_currentSection.Capacity < prefix.Length)
                            {
                                // no, resize
                                _currentSection.SetCapacity(_currentSection.Capacity + prefix.Length);
                            }

                            // copy the prefix charcters to the current section
                            fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                            {
                                Marshal.Copy(prefix, 0, (IntPtr)dst, prefix.Length);
                            }

                            // update the section count
                            _currentSection.Count += prefix.Length;
                            // update the last index
                            lastIndex = Index + 1;

                            // catch up the suffix search (for partially overlapping prefixes and suffixes)
                            foreach (char c in prefix)
                            {
                                _suffixSearch.Next(c);
                            }

                            // set to look for suffix
                            Active = true;

                            // go on to find a suffix
                            break;
                        }
                    }

                    // if block is finished
                    if (!Active)
                    {
                        return(result);
                    }
                }
            }
            else if (_prefixesSet)
            {
                // no, prefixes only

                // iterate chacters in current block
                while (++Index < end)
                {
                    char character = characters[Index];

                    // if a prefix has been found
                    if (_prefixSearch.Next(character))
                    {
                        // get the prefix
                        char[] prefix = _prefixSearch.Values[0].ToCharArray();

                        // is the parser already active?
                        if (Active)
                        {
                            // yes, a nested prefix has been found

                            // create a new section
                            var newSection = new ArrayRig <char>(_extract.MaxCharacters < prefix.Length ? prefix.Length : _extract.MaxCharacters);

                            // copy the prefix charcters to the new section
                            fixed(void *dst = &newSection.Array[0])
                            {
                                Marshal.Copy(prefix, 0, (IntPtr)dst, prefix.Length);
                            }

                            // update the new section count
                            newSection.Count += prefix.Length;

                            /////// copy the current block to the current sections

                            // is the current section going to be full?
                            while (_currentSection.Count + Index - lastIndex >= _extract.MaxCharacters)
                            {
                                /////// yes, complete the current section

                                // resize the current section if needed
                                if (_extract.MaxCharacters > _currentSection.Capacity)
                                {
                                    _currentSection.SetCapacity(_extract.MaxCharacters);
                                }

                                // are there null characters in the current section?
                                if (_extract.MaxCharacters > _currentSection.Count)
                                {
                                    // yes, append the block to the current section
                                    fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                                    {
                                        Marshal.Copy(characters, lastIndex, (IntPtr)dst, _extract.MaxCharacters - _currentSection.Count);
                                    }

                                    // update the current section count
                                    _currentSection.Count = _extract.MaxCharacters;
                                }

                                // are there requirements?
                                if (_reqParsersSet)
                                {
                                    // yes, run the required parsers
                                    foreach (Parse parser in _reqParsers)
                                    {
                                        result |= parser.Next(_currentSection.Array, 0, _currentSection.Count);
                                    }
                                }
                                else
                                {
                                    // no, the parse was successful
                                    result = true;
                                }

                                // have the requirements been fulfilled?
                                if (result)
                                {
                                    // are there sub parsers?
                                    if (_subParsersSet)
                                    {
                                        // yes, begin running sub parsers
                                        for (int i = _subParsers.Count - 1; i >= 0; --i)
                                        {
                                            if (_subParsers[i].Next(_currentSection.Array, 0, _currentSection.Count))
                                            {
                                                _activeSubParsers.Add(_subParsers[i]);
                                            }
                                            else
                                            {
                                                _activeSubParsers.RemoveQuick(_subParsers[i]);
                                            }
                                        }
                                        _runSubParsers = _activeSubParsers.Count != 0;
                                    }

                                    // is the section callback set?
                                    if (_extract.OnSectionSet)
                                    {
                                        // yes, run complete section callback
                                        _extract.OnSection.Take();
                                        _extract.OnSection.Item.ArgA = _currentSection.ToArray();
                                        _extract.OnSection.Item.Run();
                                        _extract.OnSection.Release();
                                        result = true;
                                    }
                                }

                                // are there more sections?
                                if (Sections.Count == 0)
                                {
                                    // no, exit the iteration
                                    _currentSection.Reset();
                                    break;
                                }
                                // yes, get the next section
                                _currentSection.Dispose();
                                _currentSection = Sections[0];
                                Sections.Remove(0);
                            }

                            // are there any partial sections apart from the new section?
                            if (_currentSection.Count != 0)
                            {
                                ////// yes, copy the current block to all other sections that will not be filled

                                // resize the current section if needed
                                if (_currentSection.Count + Index - lastIndex > _currentSection.Capacity)
                                {
                                    _currentSection.SetCapacity(_currentSection.Count + Index - lastIndex);
                                }

                                // append the block to the current section
                                fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                                {
                                    Marshal.Copy(characters, lastIndex, (IntPtr)dst, Index - lastIndex);
                                }

                                // update the section count
                                _currentSection.Count += Index - lastIndex;

                                // iterate all sections
                                foreach (ArrayRig <char> section in Sections)
                                {
                                    // append the block to each section
                                    fixed(void *dst = &section.Array[section.Count])
                                    {
                                        Marshal.Copy(characters, lastIndex, (IntPtr)dst, Index - lastIndex);
                                    }

                                    // update the section count
                                    section.Count += Index - lastIndex;
                                }

                                // add the new section
                                Sections.Add(newSection);
                            }
                            else
                            {
                                // no, the new section is the only section left
                                _currentSection = newSection;
                            }

                            // update the last index
                            lastIndex = Index;
                        }
                        else
                        {
                            // no, start the first section

                            // will the section contain the prefix?
                            if (prefix.Length > _currentSection.Capacity)
                            {
                                // nope, resize
                                _currentSection.SetCapacity(prefix.Length);
                            }

                            // copy the characters to the current section
                            fixed(void *dst = &_currentSection.Array[0])
                            {
                                Marshal.Copy(prefix, 0, (IntPtr)dst, prefix.Length);
                            }

                            // update the section count
                            _currentSection.Count = prefix.Length;

                            // update the last index
                            lastIndex = Index;
                        }

                        // set parser active
                        Active = true;
                    }
                }

                ////// copy the remaining characters to the current sections if any

                // is there a prefix and is the current section going to be filled by the current block?
                while (Active && _currentSection.Count + Index - lastIndex >= _extract.MaxCharacters)
                {
                    /////// yes, complete the current section

                    // resize the current section if needed
                    if (_extract.MaxCharacters > _currentSection.Capacity)
                    {
                        _currentSection.SetCapacity(_extract.MaxCharacters);
                    }

                    // is there space in the current section?
                    if (_extract.MaxCharacters > _currentSection.Count)
                    {
                        // yes, fill the block to the current section
                        fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                        {
                            Marshal.Copy(characters, lastIndex, (IntPtr)dst, _extract.MaxCharacters - _currentSection.Count);
                        }

                        // update the current section count
                        _currentSection.Count = _extract.MaxCharacters;
                    }

                    // are there requirements?
                    if (_reqParsersSet)
                    {
                        // yes, run the required parsers
                        foreach (Parse parser in _reqParsers)
                        {
                            result |= parser.Next(_currentSection.Array, 0, _currentSection.Count);
                        }
                    }
                    else
                    {
                        // no, the parse was successful
                        result = true;
                    }

                    // have the requirements been fulfilled?
                    if (result)
                    {
                        // are there sub parsers?
                        if (_subParsersSet)
                        {
                            // yes, begin running sub parsers
                            for (int i = _subParsers.Count - 1; i >= 0; --i)
                            {
                                if (_subParsers[i].Next(_currentSection.Array, 0, _currentSection.Count))
                                {
                                    _activeSubParsers.Add(_subParsers[i]);
                                }
                                else
                                {
                                    _activeSubParsers.RemoveQuick(_subParsers[i]);
                                }
                            }
                            _runSubParsers = _activeSubParsers.Count != 0;
                        }

                        // is the section callback set?
                        if (_extract.OnSectionSet)
                        {
                            // yes, run complete section callback
                            _extract.OnSection.Take();
                            _extract.OnSection.Item.ArgA = _currentSection.ToArray();
                            _extract.OnSection.Item.Run();
                            _extract.OnSection.Release();
                            result = true;
                        }
                    }

                    // are there more sections?
                    if (Sections.Count == 0)
                    {
                        // no, exit the iteration
                        _currentSection.Reset();
                        break;
                    }

                    // yes, get the next section
                    _currentSection.Dispose();
                    _currentSection = Sections[0];
                    Sections.Remove(0);
                }

                // are there any partial sections left?
                if (_currentSection.Count != 0)
                {
                    ////// yes, copy the current block to all other sections thatill not be filled w

                    // resize the current section if needed
                    if (_currentSection.Count + Index - lastIndex > _currentSection.Capacity)
                    {
                        _currentSection.SetCapacity(_currentSection.Count + Index - lastIndex);
                    }

                    // append the block to the current section
                    fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                    {
                        Marshal.Copy(characters, lastIndex, (IntPtr)dst, Index - lastIndex);
                    }

                    // update the section count
                    _currentSection.Count += Index - lastIndex;

                    // iterate all sections
                    foreach (ArrayRig <char> section in Sections)
                    {
                        // append the block to each section
                        fixed(void *dst = &section.Array[section.Count])
                        {
                            Marshal.Copy(characters, lastIndex, (IntPtr)dst, Index - lastIndex);
                        }

                        // update the section count
                        section.Count += Index - lastIndex;
                    }
                }
            }
            else if (_suffixesSet)
            {
                // no, suffixes only

                // iterate characters in current block
                while (++Index < end)
                {
                    char character = characters[Index];

                    // does the current character complete a suffix?
                    if (_suffixSearch.Next(character))
                    {
                        // yes, push current character block

                        // if current section count + current block is greater than max allowed
                        if (_currentSection.Count + Index - lastIndex > _extract.MaxCharacters)
                        {
                            // overflow - move the current section

                            // shift characters from the current section
                            fixed(void *dst = &_currentSection.Array[0])
                            {
                                Marshal.Copy(_currentSection.Array, Index - lastIndex, (IntPtr)dst, _currentSection.Count - Index - lastIndex);
                            }

                            // set the new count
                            _currentSection.Count = _currentSection.Count - Index - lastIndex;
                        }

                        // resize the current section if needed
                        if (_currentSection.Count + Index - lastIndex > _currentSection.Capacity)
                        {
                            _currentSection.SetCapacity(_currentSection.Count + Index - lastIndex);
                        }

                        // append the block up to the current index
                        fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                        {
                            Marshal.Copy(characters, lastIndex, (IntPtr)dst, Index - lastIndex);
                        }

                        // update the current section count
                        _currentSection.Count += Index - lastIndex;
                        // update the last index
                        lastIndex = Index;

                        // are there requirements?
                        if (_reqParsersSet)
                        {
                            // yes, run the required parsers
                            foreach (Parse parser in _reqParsers)
                            {
                                result |= parser.Next(_currentSection.Array, 0, _currentSection.Count);
                            }
                        }
                        else
                        {
                            result = true;
                        }

                        // have the requirements been fulfilled?
                        if (result)
                        {
                            // are there sub parsers?
                            if (_subParsersSet)
                            {
                                // yes, begin running sub parsers
                                for (int i = _subParsers.Count - 1; i >= 0; --i)
                                {
                                    if (_subParsers[i].Next(_currentSection.Array, 0, _currentSection.Count))
                                    {
                                        _activeSubParsers.Add(_subParsers[i]);
                                    }
                                    else
                                    {
                                        _activeSubParsers.RemoveQuick(_subParsers[i]);
                                    }
                                }
                                _runSubParsers = _activeSubParsers.Count != 0;
                            }

                            // is the section callback set?
                            if (_extract.OnSectionSet)
                            {
                                // yes, run complete section callback
                                _extract.OnSection.Take();
                                _extract.OnSection.Item.ArgA = _currentSection.ToArray();
                                _extract.OnSection.Item.Run();
                                _extract.OnSection.Release();
                                result = true;
                            }
                        }
                    }
                }

                // copy the current character block

                // if current section count + current block is greater than max allowed
                if (_currentSection.Count + Index - lastIndex > _extract.MaxCharacters)
                {
                    // overflow - move the current section

                    // shift characters in the current section
                    fixed(void *dst = &_currentSection.Array[0])
                    {
                        Marshal.Copy(_currentSection.Array, Index - lastIndex, (IntPtr)dst, _currentSection.Count - Index - lastIndex);
                    }

                    // set the new count
                    _currentSection.Count = _currentSection.Count - Index - lastIndex;
                }

                // resize the current section if needed
                if (_currentSection.Count + Index - lastIndex > _currentSection.Capacity)
                {
                    _currentSection.SetCapacity(_currentSection.Count + Index - lastIndex);
                }

                // append the block up to the current index
                fixed(void *dst = &_currentSection.Array[_currentSection.Count])
                {
                    Marshal.Copy(characters, lastIndex, (IntPtr)dst, Index - lastIndex);
                }

                // update the current section count
                _currentSection.Count += Index - lastIndex;
            }
            else
            {
                // no prefixes or suffixes

                // are there requirements?
                if (_reqParsersSet)
                {
                    // yes, check requirements
                    foreach (Parse parser in _reqParsers)
                    {
                        result |= parser.Next(characters, start, end);
                    }
                }
                else
                {
                    // no, the result is positive
                    result = true;
                }

                // is the parser becoming active?
                if (result && !Active)
                {
                    // yes, update state
                    Active = true;

                    // run sub parsers
                    if (!_runSubParsers)
                    {
                        _runSubParsers = true;
                        // iterate sub parsers
                        for (int i = _subParsers.Count - 1; i >= 0; --i)
                        {
                            if (_subParsers[i].Next(_currentSection.Array, 0, _currentSection.Count))
                            {
                                _activeSubParsers.Add(_subParsers[i]);
                            }
                            else
                            {
                                _activeSubParsers.RemoveQuick(_subParsers[i]);
                            }
                        }
                    }
                }
            }

            // return the result
            return(result);
        }