Ejemplo n.º 1
0
        /// <summary>
        /// Возвращает набор индексов начала и конца всех вхождений искомого шаблона в указанной строке, начиная поиск с указанного индекса. 
        /// Подстрока считается совпавшей с шаблоном тогда и только тогда, если начинается с указанного токена, оканчивается указанным токеном, и между токенами 
        /// содержит указанные обязательные и необязательные символы. Если между токенами содержатся какие-либо другие символы, 
        /// или же не содержится хотя бы одного из обязательных символов, то такая подстрока отбраковывается.
        /// </summary>
        /// <param name="Input">Входная строка, в которой происходит поиск шаблона. Если NULL или пустая, будет выброшено исключение.</param>
        /// <param name="StartToken">Начальный токен, которым должен начинаться искомый шаблон. Если NULL или пустой, будет выброшено исключение.</param>
        /// <param name="EndToken">Конечный токен, которым должен заканчиваться искомый шаблон. Если NULL или пустой, будет выброшено исключение.</param>
        /// <param name="StartIndex">Позиция (индекс), с которой включительно начинается анализ строки. Если меньше 0, будет приведён к 0. 
        /// Если больше длины строки, будет выброшено исключение.</param>
        /// <param name="RequiredInnerSymbols">Массив обязательных символов, все из которых должны присутствовать между начальным и конечным токеном. 
        /// Дублирующие символы игнорируются, учитываются только уникальные. Если NULL или пустой, предполагается, что обязательных символов нет.</param>
        /// <param name="OptionalInnerSymbols">Массив допустимых символов, которые могут, но не обязательны присутствовать между начальным и конечным токеном. 
        /// Дублирующие символы игнорируются, учитываются только уникальные. Если NULL или пустой, предполагается, что обязательных символов нет.</param>
        /// <param name="CompareOptions">Опции сравнения строк между собой</param>
        /// <returns>Словарь, где один элемент представляет индексы одного найденного токена: ключ содержит индекс начала токена, а значение - индекс его конца. 
        /// Если ни одного токена не найдено, возвращается пустой словарь.</returns>
        public static Dictionary<Int32, Int32> IndexesOfTemplate(String Input, String StartToken, String EndToken, Int32 StartIndex,
            Char[] RequiredInnerSymbols, Char[] OptionalInnerSymbols, StringComparison CompareOptions)
        {
            if (Input.IsStringNullOrEmpty() == true) { throw new ArgumentException("Входная строка не может быть NULL или пустой", "Input"); }
            if (StartToken.IsStringNullOrEmpty() == true) throw new ArgumentException("Начальный токен не может быть NULL или пустой строкой", "StartToken");
            if (EndToken.IsStringNullOrEmpty() == true) throw new ArgumentException("Конечный токен не может быть NULL или пустой строкой", "EndToken");
            if (StartIndex >= Input.Length) { throw new ArgumentOutOfRangeException("StartIndex", StartIndex, String.Format("Позиция начала поиска '{0}' превышает длину строки '{1}'", StartIndex, Input.Length)); }
            if (StartIndex < 0) { StartIndex = 0; }
            Int32 comp_value = (Int32)CompareOptions;
            if (comp_value < 0 || comp_value > 5) { throw new InvalidEnumArgumentException("CompareOptions", comp_value, typeof(StringComparison)); }
            if (RequiredInnerSymbols.IsNullOrEmpty() == true && OptionalInnerSymbols.IsNullOrEmpty() == true)
            {
                throw new ArgumentException("Массивы обязательных и допустимых символов не могут быть одновременно NULL или пустыми. " +
                  String.Format("RequiredInnerSymbols: {0}, OptionalInnerSymbols: {1}.", RequiredInnerSymbols.ToStringS("NULL", "пустой"), OptionalInnerSymbols.ToStringS("NULL", "пустой")));
            }
            Dictionary<Int32, Int32> output = new Dictionary<int, int>();

            Int32 start_token_length = StartToken.Length;
            Int32 end_token_length = EndToken.Length;
            HashSet<Char> unique_RequiredInnerSymbols = RequiredInnerSymbols.IsNullOrEmpty() == true ? new HashSet<Char>() : new HashSet<Char>(RequiredInnerSymbols);
            HashSet<Char> unique_OptionalInnerSymbols = OptionalInnerSymbols.IsNullOrEmpty() == true ? new HashSet<Char>() : new HashSet<Char>(OptionalInnerSymbols);
            Int32 offset = StartIndex;
            Dictionary<Char, Boolean> temp_dict = unique_RequiredInnerSymbols.Any() == true ? unique_RequiredInnerSymbols.ToDictionary((Char item) => item, (Char item) => false) : null;

            while (true)
            {
                Int32 start_index = Input.IndexOf(StartToken, offset, CompareOptions);
                if (start_index < 0) { break; }
                offset = start_index + start_token_length;
                Int32 end_index = Input.IndexOf(EndToken, offset, CompareOptions);
                if (end_index < 0) { break; }
#if Debug
                    String temp_substring = Input.SubstringWithEnd(offset, end_index);
#endif
                Boolean fail = false;
                for (Int32 i = offset; i < end_index; i++)
                {
                    Char ch = Input[i];

                    if (ch.IsIn(unique_RequiredInnerSymbols) == false && ch.IsIn(unique_OptionalInnerSymbols) == false)
                    {
                        fail = true;
                        break;
                    }
                    if (unique_RequiredInnerSymbols.Any() == true && ch.IsIn(unique_RequiredInnerSymbols) == true)
                    {
                        temp_dict[ch] = true;
                    }
                }
                if (fail == true || (temp_dict != null && temp_dict.All(item => item.Value == true) == false))
                {
                    continue;
                }
                offset = end_index + end_token_length - 1;
                output.Add(start_index, offset);

            }
            return output;
        }