Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Модуль поиска по маске (более совершеный нежели дельфийский masks)

Delphi , Синтаксис , Текст и Строки

Модуль поиска по маске (более совершеный нежели дельфийский masks)

 
Code:
unit awMachMask; // © Alexandr Petrovich Sysoev
 
interface
 
uses Classes;
 
///////////////////////////////////////////////////// Работа со списком шаблонов
// Функции предназначены для сопоставления текстов (имен файлов) на
// соответствие заданному шаблону или списку шаблонов.
// Обычно используется для посторения простых фильтров, например аналогичных
// файловым фильтрам программы Total Commander.
//
// Каждый шаблон аналогичен шаблону имен файлов в MS-DOS и MS Windows,
// т.е. может включать "шаблонные" символы '*' и '?' и не может включать
// символ '|'.
// Любой шаблон может быть заключен в двойные кавычки ('''), при этом двойные
// кавычки имеющиеся в шаблоне должны быть удвоены. Если шаблон включает
// символы ';' или ' ' (пробел) то он обязательно должен быть заключен в
// двойные кавычки.
// В списке, шаблоны разделяются символом ';'.
// За первым списком шаблонов, может следовать символ '|', за которым может
// следовать второй список.
// Текст (имя файла) будет считаться соответствующим списку шаблонов только
// если он соответствует хотя бы одному шаблону из первого списка,
// и не соответствует ни одному шаблону из второго списка.
// Если первый список пуст, то подразумевается '*'
//
// Формальное описание синтаксиса списка шаблонов:
//
//    Полный список шаблонов      :: [<список включаемых шаблонов>]['|'<список исключаемых шаблонов>]
//    список включаемых шаблонов  :: <список шаблонов>
//    список исключаемых шаблонов :: <список шаблонов>
//    список шаблонов             :: <шаблон>[';'<шаблон>]
//    шаблон                      :: шаблон аналогичный шаблону имен файлов в
//                                   MS-DOS и MS Windows, т.е. может включать
//                                   "шаблонные" символы '*' и '?' и не может
//                                   включать символ '|'. Шаблон может быть
//                                   заключен в двойные кавычки (''') при этом
//                                   двойные кавычки имеющиеся в шаблоне должны
//                                   быть удвоены. Если шаблон включает символы
//                                   ';' или ' ' (пробел) то он
//                                   обязательно должен быть заключен в двойные
//                                   кавычки.
//
// Например:
//   '*.ini;*.wav'          - соответствует любым файлам с расшиениями 'ini'
//                            или 'wav'
//   '*.*|*.exe'            - соответствует любым файлам, кроме файлов с
//                            расширением 'EXE'
//   '*.mp3;*.wav|?.*;??.*' - соответствует любым файлам с расшиениями 'mp3'
//                            и 'wav' за исключением файлов у которых имя
//                            состоит из одного или двух символов.
//   '|awString.*'          - соответствует любым файлам за исключением файлов
//                            с именем awString и любым расширением.
//
 
Function IsMatchMask (aText, aMask :pChar ) :Boolean;                               overload;
Function IsMatchMask (aText, aMask :String; aFileNameMode :Boolean =True) :Boolean; overload;
// Выполняют сопоставление текста aText с одним шаблоном aMask.
// Возвращает True если сопоставление выполнено успешно, т.е. текст
// aText соответствует шаблону aMask.
// Если aFileNameModd=True, то объект используется для сопоставления
// имен файлов с шаблоном. А именно, в этом случае, если aText не
// содержит символа '.' то он добавляется в конец. Это необходимо для
// того, чтобы файлы без расширений соответствовали например шаблону '*.*'
 
Function IsMatchMaskList (aText, aMaskList :String; aFileNameMode :Boolean =True): Boolean;
// Выполняет сопоставление текста aText со списком шаблонов aMaskList.
// Возвращает True если сопоставление выполнено успешно, т.е. текст
// aText соответствует списку шаблонов aMaskList.
// Если aFileNameModd=True, то объект используется для сопоставления
// имен файлов с шаблоном. А именно, в этом случае, если aText не
// содержит символа '.' то он добавляется в конец. Это необходимо для
// того, чтобы файлы без расширений соответствовали например шаблону '*.*'
//
// Замечание, если требуется проверка сопоставления нескольких строк одному
// списку шаблонов, эффективнее будет воспользоваться объектом tMatchMaskList.
 
Type
tMatchMaskList = class(tObject)
   Private
     fMaskList      :String;
     fCaseSensitive :Boolean;
     fFileNameMode  :Boolean;
 
     fPrepared     :Boolean;
     fIncludeMasks :tStringList;
     fExcludeMasks :tStringList;
 
     procedure SetMaskList      (v :String );
     procedure SetCaseSensitive (v :Boolean);
 
   Public
     constructor Create (Const aMaskList :String ='');
       // Создает объект. Если задан параметр aMaskList, то он присваивается
       // свойству MaskList.
 
     destructor Destroy;    override;
       // Разрушает объект
 
     procedure PrepareMasks;
       // Осуществляет компиляцию списка шаблонов во внутреннюю структуру
       // используемую при сопоставлении текста.
       // Вызов данного метода не является обязательным и при необходимости
       // будет вызван автоматически.
 
     Function IsMatch (aText :String) :Boolean;
       // Выполняет сопоставление текста aText со списком шаблонов MaskList.
       // Возвращает True если сопоставление выполнено успешно, т.е. текст
       // aText соответствует списку шаблонов MaskList.
 
     Property MaskList      :String Read fMaskList        Write SetMaskList                     ;
       // Списко шаблонов используемый для сопоставления с текстом
 
     Property CaseSensitive :Boolean  Read fCaseSensitive   Write SetCaseSensitive   default False;
       // Если False (по умолчанию), то при сопоставлении текста будет
       // регистр символов не будет учитываться.
       // Иначе, если True, сопоставление будет проводиться с учетом регистра.
 
     Property FileNameMode :Boolean   Read fFileNameMode    Write fFileNameMode      default True;
       // Если True (по умолчанию), то объект используется для сопоставления
       // имен файлов с шаблоном. А именно, в этом случае, если aText не
       // содержит символа '.' то он добавляется в конец. Это необходимо для
       // того, чтобы файлы без расширений соответствовали например шаблону '*.*'
 
   End;
 
 
implementation
 
uses
SysUtils
;
 
Function IsMatchMask (aText, aMask :pChar ) :Boolean;            overload;
begin
Result := False;
While True  Do begin
   Case aMask^  of
     '*' :   // соответствует любому числу любых символов кроме конца строки
       begin
         // переместиться на очередной символ шаблона, при этом, подряд
         // идущие '*' эквивалентны одному, поэтому пропуск всех '*'
         repeat Inc(aMask);  Until (aMask^<>'*');
         // если за '*' следует любой символ кроме '?' то он должен совпасть
         // с символом в тексте. т.е. нужно пропустить все не совпадающие,
         // но не далее конца строки
         If aMask^ <> '?' then
           While (aText^ <> #0) And (aText^ <> aMask^)  Do Inc(aText);
 
         If aText^ <> #0 Then begin // не конец строки, значит совпал символ
           // '*' 'жадный' шаблон поэтому попробуем отдать совпавший символ
           // ему. т.е. проверить совпадение продолжения строки с шаблоном,
           // начиная с того-же '*'. если продолжение совпадает, то
           If IsMatchMask (aText+1, aMask-1)  Then Break;  // это СОВПАДЕНИЕ
           // продолжение не совпало, значит считаем что здесь закончилось
           // соответствие '*'. Продолжим сопоставление со следующего
           // символа шаблона
           Inc(aMask); Inc(aText);     //   иначе переходим к следующему символу
           End
         Else If (aMask^ = #0)  Then // конец строки и конец шаблона
           Break                       //     это СОВПАДЕНИЕ
         Else                          // конец строки но не конец шаблона
           Exit                        //     это НЕ СОВПАДЕНИЕ
       End;
 
     '?' :   // соответствует любому кроме конца строки
       If (aText^ = #0)  Then          // конец строки
         Exit                          //     это НЕ СОВПАДЕНИЕ
       Else begin                      // иначе
         Inc(aMask); Inc(aText);       //   иначе переходим к следующему символу
       End;
 
     Else     // символ в шаблоне должен совпасть с символом в строке
       If aMask^ <> aText^  Then      // символы не совпали -
         Exit                          //     это НЕ СОВПАДЕНИЕ
       Else begin                      // совпал очередной символ
         If (aMask^ = #0)  Then       //   совпавший символ последний -
           Break;                      //     это СОВПАДЕНИЕ
         Inc(aMask); Inc(aText);       //   иначе переходим к следующему символу
       End;
   End;
End;
Result := True;
End;
 
Function IsMatchMask (aText, aMask :String; aFileNameMode :Boolean =True) :Boolean;            overload;
begin
If aFileNameMode And (Pos('.',aText)=0)  then aText := aText+'.';
Result := IsMatchMask(pChar(aText),pChar(aMask));
End;
 
Function IsMatchMaskList (aText, aMaskList :String; aFileNameMode :Boolean =True) :Boolean;
begin
With tMatchMaskList.Create(aMaskList)  Do try
   FileNameMode := aFileNameMode;
   Result := IsMatch(aText);
finally
   Free;
End;
End;
 
 
/////////////////////////////////////////////////////////// tFileMask
 
 
procedure tMatchMaskList.SetMaskList (v :String );
begin
If fMaskList = v  Then Exit;
fMaskList := v;
fPrepared := False;
End;
 
 
procedure tMatchMaskList.SetCaseSensitive  (v :Boolean);
begin
If fCaseSensitive = v  Then Exit;
fCaseSensitive := v;
fPrepared      := False;
End;
 
 
constructor tMatchMaskList.Create (Const aMaskList :String);
begin
MaskList := aMaskList;
fFileNameMode := True;
 
fIncludeMasks := TStringList.Create;  With fIncludeMasks  Do begin
   Delimiter  := ';';
//    Sorted     := True;
//    Duplicates := dupIgnore;
End;
 
fExcludeMasks := tStringList.Create;  With fExcludeMasks  Do begin
   Delimiter  := ';';
//    Sorted     := True;
//    Duplicates := dupIgnore;
End;
End;
 
 
destructor tMatchMaskList.Destroy;
begin
fIncludeMasks.Free;
fExcludeMasks.Free;
End;
 
 
procedure tMatchMaskList.PrepareMasks;
 
procedure CleanList(l :tStrings);
var i :Integer;
begin
   For i := l.Count-1 downto 0 Do If l[i] = '' then l.Delete(i);
End;
 
var
s :String;
i :Integer;
begin
If fPrepared  Then Exit;
 
If CaseSensitive  Then
   s := MaskList
Else
   s := UpperCase(MaskList);
 
i := Pos('|',s);
If i =  0 Then begin
   fIncludeMasks.DelimitedText := s;
   fExcludeMasks.DelimitedText := '';
   End
Else begin
   fIncludeMasks.DelimitedText := Copy(s,1,i-1);
   fExcludeMasks.DelimitedText := Copy(s,i+1,MaxInt);
End;
 
CleanList(fIncludeMasks);
CleanList(fExcludeMasks);
 
// если список включаемых шаблонов пуст а
// список исключаемых шаблонов не пуст, то
// имеется ввиду что список включаемых шаблонов равен <все файлы>
If (fIncludeMasks.Count = 0) And (fExcludeMasks.Count <> 0)  Then
   fIncludeMasks.Add('*');
 
fPrepared := True;
End;
 
 
Function tMatchMaskList.IsMatch (aText :String) :Boolean;
var
i :Integer;
begin
Result := False;
If aText = '' then Exit;
If Not CaseSensitive  Then aText := UpperCase(aText);
If FileNameMode And (Pos('.',aText)=0)  then aText := aText+'.';
If Not fPrepared  Then PrepareMasks;
 
// поиск в списке "включаемых" масок до первого совпадения
For i := 0 To fIncludeMasks.Count-1 Do
   If IsMatchMask(PChar(aText),PChar(fIncludeMasks[i]))  Then begin
     Result := True;
     Break;
   End;
 
// если совпадение найдено, надо проверить по списку "исключаемых"
If Result  Then
   For i := 0 To fExcludeMasks.Count-1 Do
     If IsMatchMask(PChar(aText),PChar(fExcludeMasks[i]))  Then begin
       Result := False;
       Break;
     End;
End;
 
 
 
end.
Автор: Петрович Взято из http://forum.sources.ru

Модуль Delphi для поиска файлов на основе маски, более развитый, чем стандартный компонент Masks в Delphi. Модуль позволяет указать несколько масок и исключить определенные файлы из поиска.

Некоторые из ключевых функций:

  1. Множественные маски: можно указать несколько масок, разделенных точкой с запятой (;) или вертикальной чертой (|). Маски чувствительны к регистру по умолчанию, но можно изменить это поведение с помощью свойства CaseSensitive.
  2. Маски исключения: помимо включения файлов на основе маски, можно также исключать определенные файлы из поиска, указав маску исключения. Маска исключения отделяется от маски включения вертикальной чертой (|).
  3. FileNameMode: это свойство позволяет указать, следует ли модулю treat входящий текст как имя файла или нет. Если FileNameMode установлен в True, модуль автоматически добавит точку (.) к концу входящего текста, если она не уже есть.
  4. PrepareMasks метод: этот метод готовит маски для поиска, разделяя их на включительные и исключительные маски, и очищает любые пустые строки в списках.

Функции IsMatchMask и IsMatchMaskList проверяют, соответствует ли тексту входящий текст маске или списку масок соответственно.

В целом, это модуль предоставляет гибкий способ поиска файлов на основе нескольких критериев и более мощен, чем стандартный компонент Masks в Delphi.

Некоторые предложения для улучшения:

  1. Обработка ошибок: добавить обработку ошибок для случаев, когда входящий текст или маска недействительны.
  2. Оптимизация производительности: текущая реализация использует вложенные циклы для итерации над масками, что может быть медленным для больших количеств масок. Рассмотреть использование более эффективной структуры данных, такой как trie или хеш-таблица, для хранения масок и ускорения процесса поиска.
  3. Организация кода: код организован в несколько методов, но некоторые из этих методов quite длинны и сложны. Рассмотреть разбиение их на более маленькие, управляемые части для улучшения читаемости и поддержки.

В целом, это полезный модуль, который предоставляет много гибкости для поиска файлов на основе нескольких критериев. С дополнительными улучшениями он может стать еще мощнее и эффективнее.

Модуль поиска по маске, более совершенный нежели дельфийский masks.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Текст и Строки ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 11:29:37/0.0076649188995361/1