mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 01:26:58 +00:00
update to pcre 7.9
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13706 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
820
libs/pcre/pcregexp.pas
Normal file
820
libs/pcre/pcregexp.pas
Normal file
@@ -0,0 +1,820 @@
|
||||
{
|
||||
pcRegExp - Perl compatible regular expressions for Virtual Pascal
|
||||
(c) 2001 Peter S. Voronov aka Chem O'Dun <petervrn@yahoo.com>
|
||||
|
||||
Based on PCRE library interface unit for Virtual Pascal.
|
||||
(c) 2001 Alexander Tokarev <dwalin@dwalin.ru>
|
||||
|
||||
The current PCRE version is: 3.7
|
||||
|
||||
This software must be distributed as Freeware.
|
||||
|
||||
The PCRE library is written by: Philip Hazel <ph10@cam.ac.uk>
|
||||
Copyright (c) 1997-2004 University of Cambridge
|
||||
|
||||
AngelsHolocaust 4-11-04 updated to use version v5.0
|
||||
(INFO: this is regex-directed, NFA)
|
||||
AH: 9-11-04 - pcre_free: removed var, pcre already gives the ptr, now
|
||||
everything works as it should (no more crashes)
|
||||
-> removed CheckRegExp because pcre handles errors perfectly
|
||||
10-11-04 - added pcError (errorhandling), pcInit
|
||||
13-11-04 - removed the ErrorPos = 0 check -> always print erroroffset
|
||||
17-10-05 - support for \1-\9 backreferences in TpcRegExp.GetReplStr
|
||||
17-02-06 - added RunTimeOptions: caller can set options while searching
|
||||
19-02-06 - added SearchOfs(): let PCRE use the complete string and offset
|
||||
into the string itself
|
||||
20-12-06 - support for version 7.0
|
||||
27.08.08 - support for v7.7
|
||||
}
|
||||
|
||||
{$H+} {$DEFINE PCRE_3_7} {$DEFINE PCRE_5_0} {$DEFINE PCRE_7_0} {$DEFINE PCRE_7_7}
|
||||
|
||||
Unit pcregexp;
|
||||
|
||||
Interface
|
||||
|
||||
uses objects;
|
||||
|
||||
Type
|
||||
PpcRegExp = ^TpcRegExp;
|
||||
// TpcRegExp = object
|
||||
TpcRegExp = object(TObject)
|
||||
MatchesCount: integer;
|
||||
RegExpC, RegExpExt : Pointer;
|
||||
Matches:Pointer;
|
||||
RegExp: shortstring;
|
||||
SourceLen: integer;
|
||||
PartialMatch : boolean;
|
||||
Error : boolean;
|
||||
ErrorMsg : Pchar;
|
||||
ErrorPos : integer;
|
||||
RunTimeOptions: Integer; // options which can be set by the caller
|
||||
constructor Init(const ARegExp : shortstring; AOptions : integer; ALocale : Pointer);
|
||||
function Search(AStr: Pchar; ALen : longint) : boolean; virtual;
|
||||
function SearchNext( AStr: Pchar; ALen : longint) : boolean; virtual;
|
||||
function SearchOfs ( AStr: Pchar; ALen, AOfs : longint) : boolean; virtual;
|
||||
function MatchSub(ANom: integer; var Pos, Len : longint) : boolean; virtual;
|
||||
function MatchFull(var Pos, Len : longint) : boolean; virtual;
|
||||
function GetSubStr(ANom: integer; AStr: Pchar) : string; virtual;
|
||||
function GetFullStr(AStr: Pchar) : string; virtual;
|
||||
function GetReplStr(AStr: Pchar; const ARepl: string) : string; virtual;
|
||||
function GetPreSubStr(AStr: Pchar) : string; virtual;
|
||||
function GetPostSubStr(AStr: Pchar) : string; virtual;
|
||||
function ErrorStr : string; virtual;
|
||||
destructor Done; virtual;
|
||||
end;
|
||||
|
||||
function pcGrepMatch(WildCard, aStr: string; AOptions:integer; ALocale : Pointer): Boolean;
|
||||
function pcGrepSub(WildCard, aStr, aRepl: string; AOptions:integer; ALocale : Pointer): string;
|
||||
|
||||
function pcFastGrepMatch(WildCard, aStr: string): Boolean;
|
||||
function pcFastGrepSub(WildCard, aStr, aRepl: string): string;
|
||||
|
||||
{$IFDEF PCRE_5_0}
|
||||
function pcGetVersion : pchar;
|
||||
{$ENDIF}
|
||||
|
||||
function pcError (var pRegExp : Pointer) : Boolean;
|
||||
function pcInit (const Pattern: Shortstring; CaseSens: Boolean) : Pointer;
|
||||
|
||||
Const { Options }
|
||||
PCRE_CASELESS = $0001;
|
||||
PCRE_MULTILINE = $0002;
|
||||
PCRE_DOTALL = $0004;
|
||||
PCRE_EXTENDED = $0008;
|
||||
PCRE_ANCHORED = $0010;
|
||||
PCRE_DOLLAR_ENDONLY = $0020;
|
||||
PCRE_EXTRA = $0040;
|
||||
PCRE_NOTBOL = $0080;
|
||||
PCRE_NOTEOL = $0100;
|
||||
PCRE_UNGREEDY = $0200;
|
||||
PCRE_NOTEMPTY = $0400;
|
||||
{$IFDEF PCRE_5_0}
|
||||
PCRE_UTF8 = $0800;
|
||||
PCRE_NO_AUTO_CAPTURE = $1000;
|
||||
PCRE_NO_UTF8_CHECK = $2000;
|
||||
PCRE_AUTO_CALLOUT = $4000;
|
||||
PCRE_PARTIAL = $8000;
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_7_0}
|
||||
PCRE_DFA_SHORTEST = $00010000;
|
||||
PCRE_DFA_RESTART = $00020000;
|
||||
PCRE_FIRSTLINE = $00040000;
|
||||
PCRE_DUPNAMES = $00080000;
|
||||
PCRE_NEWLINE_CR = $00100000;
|
||||
PCRE_NEWLINE_LF = $00200000;
|
||||
PCRE_NEWLINE_CRLF = $00300000;
|
||||
PCRE_NEWLINE_ANY = $00400000;
|
||||
PCRE_NEWLINE_ANYCRLF = $00500000;
|
||||
|
||||
PCRE_NEWLINE_BITS = PCRE_NEWLINE_CR or PCRE_NEWLINE_LF or PCRE_NEWLINE_ANY;
|
||||
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_7_7}
|
||||
PCRE_BSR_ANYCRLF = $00800000;
|
||||
PCRE_BSR_UNICODE = $01000000;
|
||||
PCRE_JAVASCRIPT_COMPAT= $02000000;
|
||||
{$ENDIF}
|
||||
|
||||
PCRE_COMPILE_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_AUTO_CALLOUT + PCRE_CASELESS +
|
||||
PCRE_DOLLAR_ENDONLY + PCRE_DOTALL + PCRE_EXTENDED +
|
||||
PCRE_EXTRA + PCRE_MULTILINE + PCRE_NO_AUTO_CAPTURE +
|
||||
PCRE_UNGREEDY + PCRE_UTF8 + PCRE_NO_UTF8_CHECK
|
||||
{$IFDEF PCRE_7_0}
|
||||
+ PCRE_DUPNAMES + PCRE_FIRSTLINE + PCRE_NEWLINE_BITS
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_7_7}
|
||||
+ PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE + PCRE_JAVASCRIPT_COMPAT
|
||||
{$ENDIF}
|
||||
;
|
||||
|
||||
PCRE_EXEC_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_NOTBOL + PCRE_NOTEOL +
|
||||
PCRE_NOTEMPTY + PCRE_NO_UTF8_CHECK + PCRE_PARTIAL
|
||||
{$IFDEF PCRE_7_0}
|
||||
+ PCRE_NEWLINE_BITS
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_7_7}
|
||||
+ PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE
|
||||
{$ENDIF}
|
||||
;
|
||||
|
||||
{$IFDEF PCRE_7_0}
|
||||
PCRE_DFA_EXEC_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_NOTBOL + PCRE_NOTEOL +
|
||||
PCRE_NOTEMPTY + PCRE_NO_UTF8_CHECK + PCRE_PARTIAL +
|
||||
PCRE_DFA_SHORTEST + PCRE_DFA_RESTART +
|
||||
PCRE_NEWLINE_BITS
|
||||
{$IFDEF PCRE_7_7}
|
||||
+ PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE
|
||||
{$ENDIF}
|
||||
;
|
||||
{$ENDIF}
|
||||
|
||||
{ Exec-time and get/set-time error codes }
|
||||
PCRE_ERROR_NOMATCH = -1;
|
||||
PCRE_ERROR_NULL = -2;
|
||||
PCRE_ERROR_BADOPTION = -3;
|
||||
PCRE_ERROR_BADMAGIC = -4;
|
||||
PCRE_ERROR_UNKNOWN_MODE = -5;
|
||||
PCRE_ERROR_NOMEMORY = -6;
|
||||
PCRE_ERROR_NOSUBSTRING = -7;
|
||||
{$IFDEF PCRE_5_0}
|
||||
PCRE_ERROR_MATCHLIMIT = -8;
|
||||
PCRE_ERROR_CALLOUT = -9; { Never used by PCRE itself }
|
||||
PCRE_ERROR_BADUTF8 = -10;
|
||||
PCRE_ERROR_BADUTF8_OFFSET = -11;
|
||||
PCRE_ERROR_PARTIAL = -12;
|
||||
PCRE_ERROR_BADPARTIAL = -13;
|
||||
PCRE_ERROR_INTERNAL = -14;
|
||||
PCRE_ERROR_BADCOUNT = -15;
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_7_0}
|
||||
PCRE_ERROR_DFA_UITEM = -16;
|
||||
PCRE_ERROR_DFA_UCOND = -17;
|
||||
PCRE_ERROR_DFA_UMLIMIT = -18;
|
||||
PCRE_ERROR_DFA_WSSIZE = -19;
|
||||
PCRE_ERROR_DFA_RECURSE = -20;
|
||||
PCRE_ERROR_RECURSIONLIMIT = -21;
|
||||
PCRE_ERROR_NULLWSLIMIT = -22;
|
||||
PCRE_ERROR_BADNEWLINE = -23;
|
||||
{$ENDIF}
|
||||
|
||||
{ Request types for pcre_fullinfo() }
|
||||
|
||||
PCRE_INFO_OPTIONS = 0;
|
||||
PCRE_INFO_SIZE = 1;
|
||||
PCRE_INFO_CAPTURECOUNT = 2;
|
||||
PCRE_INFO_BACKREFMAX = 3;
|
||||
PCRE_INFO_FIRSTBYTE = 4;
|
||||
PCRE_INFO_FIRSTCHAR = 4; { For backwards compatibility }
|
||||
PCRE_INFO_FIRSTTABLE = 5;
|
||||
{$IFDEF PCRE_5_0}
|
||||
PCRE_INFO_LASTLITERAL = 6;
|
||||
PCRE_INFO_NAMEENTRYSIZE = 7;
|
||||
PCRE_INFO_NAMECOUNT = 8;
|
||||
PCRE_INFO_NAMETABLE = 9;
|
||||
PCRE_INFO_STUDYSIZE = 10;
|
||||
PCRE_INFO_DEFAULT_TABLES = 11;
|
||||
{$ENDIF PCRE_5_0}
|
||||
{$IFDEF PCRE_7_7}
|
||||
PCRE_INFO_OKPARTIAL = 12;
|
||||
PCRE_INFO_JCHANGED = 13;
|
||||
PCRE_INFO_HASCRORLF = 14;
|
||||
{$ENDIF}
|
||||
|
||||
{ Request types for pcre_config() }
|
||||
{$IFDEF PCRE_5_0}
|
||||
PCRE_CONFIG_UTF8 = 0;
|
||||
PCRE_CONFIG_NEWLINE = 1;
|
||||
PCRE_CONFIG_LINK_SIZE = 2;
|
||||
PCRE_CONFIG_POSIX_MALLOC_THRESHOLD = 3;
|
||||
PCRE_CONFIG_MATCH_LIMIT = 4;
|
||||
PCRE_CONFIG_STACKRECURSE = 5;
|
||||
PCRE_CONFIG_UNICODE_PROPERTIES = 6;
|
||||
{$ENDIF PCRE_5_0}
|
||||
{$IFDEF PCRE_7_0}
|
||||
PCRE_CONFIG_MATCH_LIMIT_RECURSION = 7;
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_7_7}
|
||||
PCRE_CONFIG_BSR = 8;
|
||||
{$ENDIF}
|
||||
|
||||
{ Bit flags for the pcre_extra structure }
|
||||
{$IFDEF PCRE_5_0}
|
||||
PCRE_EXTRA_STUDY_DATA = $0001;
|
||||
PCRE_EXTRA_MATCH_LIMIT = $0002;
|
||||
PCRE_EXTRA_CALLOUT_DATA = $0004;
|
||||
PCRE_EXTRA_TABLES = $0008;
|
||||
{$ENDIF PCRE_5_0}
|
||||
{$IFDEF PCRE_7_0}
|
||||
PCRE_EXTRA_MATCH_LIMIT_RECURSION = $0010;
|
||||
{$ENDIF}
|
||||
|
||||
Const
|
||||
// DefaultOptions : integer = 0;
|
||||
DefaultLocaleTable : pointer = nil;
|
||||
|
||||
{$IFDEF PCRE_5_0}
|
||||
{ The structure for passing additional data to pcre_exec(). This is defined in
|
||||
such as way as to be extensible. Always add new fields at the end, in order to
|
||||
remain compatible. }
|
||||
|
||||
type ppcre_extra = ^tpcre_extra;
|
||||
tpcre_extra = record
|
||||
flags : longint; { Bits for which fields are set }
|
||||
study_data : pointer; { Opaque data from pcre_study() }
|
||||
match_limit : longint; { Maximum number of calls to match() }
|
||||
callout_data : pointer; { Data passed back in callouts }
|
||||
tables : pointer; { Pointer to character tables }
|
||||
match_limit_recursion: longint; { Max recursive calls to match() }
|
||||
end;
|
||||
|
||||
type ppcre_callout_block = ^pcre_callout_block;
|
||||
pcre_callout_block = record
|
||||
version,
|
||||
(* ------------------------ Version 0 ------------------------------- *)
|
||||
callout_number : integer;
|
||||
offset_vector : pointer;
|
||||
subject : pchar;
|
||||
subject_length, start_match, current_position, capture_top,
|
||||
capture_last : integer;
|
||||
callout_data : pointer;
|
||||
(* ------------------- Added for Version 1 -------------------------- *)
|
||||
pattern_position, next_item_length : integer;
|
||||
end;
|
||||
{$ENDIF PCRE_5_0}
|
||||
|
||||
{$OrgName+}
|
||||
{$IFDEF VIRTUALPASCAL} {&Cdecl+} {$ENDIF VIRTUALPASCAL}
|
||||
|
||||
{ local replacement of external pcre memory management functions }
|
||||
function pcre_malloc( size : integer ) : pointer;
|
||||
procedure pcre_free( {var} p : pointer );
|
||||
{$IFDEF PCRE_5_0}
|
||||
const pcre_stack_malloc: function ( size : integer ): pointer = pcre_malloc;
|
||||
pcre_stack_free: procedure ( {var} p : pointer ) = pcre_free;
|
||||
function pcre_callout(var p : ppcre_callout_block) : integer;
|
||||
{$ENDIF PCRE_5_0}
|
||||
{$IFDEF VIRTUALPASCAL} {&Cdecl-} {$ENDIF VIRTUALPASCAL}
|
||||
|
||||
Implementation
|
||||
|
||||
Uses strings, collect, messages, dnapp, commands, advance0, stringsx
|
||||
{$IFDEF VIRTUALPASCAL} ,vpsyslow {$ENDIF VIRTUALPASCAL};
|
||||
|
||||
Const
|
||||
MAGIC_NUMBER = $50435245; { 'PCRE' }
|
||||
MAX_MATCHES = 90; { changed in 3.5 version; should be divisible by 3, was 64}
|
||||
|
||||
Type
|
||||
PMatchArray = ^TMatchArray;
|
||||
TMatchArray = array[0..( MAX_MATCHES * 3 )] of integer;
|
||||
|
||||
PRegExpCollection = ^TRegExpCollection;
|
||||
TRegExpCollection = object(TSortedCollection)
|
||||
MaxRegExp : integer;
|
||||
SearchRegExp : shortstring;
|
||||
CompareModeInsert : boolean;
|
||||
constructor Init(AMaxRegExp:integer);
|
||||
procedure FreeItem(P: Pointer); virtual;
|
||||
function Compare(P1, P2: Pointer): Integer; virtual;
|
||||
function Find(ARegExp:shortstring;var P: PpcRegExp):boolean; virtual;
|
||||
function CheckNew(ARegExp:shortstring):PpcRegExp;virtual;
|
||||
end;
|
||||
|
||||
Var
|
||||
PRegExpCache : PRegExpCollection;
|
||||
|
||||
|
||||
{$IFDEF VIRTUALPASCAL} {&Cdecl+} {$ENDIF VIRTUALPASCAL}
|
||||
|
||||
{ imported original pcre functions }
|
||||
|
||||
function pcre_compile( const pattern : PChar; options : integer;
|
||||
var errorptr : PChar; var erroroffset : integer;
|
||||
const tables : PChar ) : pointer {pcre}; external;
|
||||
{$IFDEF PCRE_7_0}
|
||||
function pcre_compile2( const pattern : PChar; options : integer;
|
||||
var errorcodeptr : Integer;
|
||||
var errorptr : PChar; var erroroffset : integer;
|
||||
const tables : PChar ) : pointer {pcre}; external;
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_5_0}
|
||||
function pcre_config( what : integer; where : pointer) : integer; external;
|
||||
function pcre_copy_named_substring( const code : pointer {pcre};
|
||||
const subject : pchar;
|
||||
var ovector : integer;
|
||||
stringcount : integer;
|
||||
const stringname : pchar;
|
||||
var buffer : pchar;
|
||||
size : integer) : integer; external;
|
||||
function pcre_copy_substring( const subject : pchar; var ovector : integer;
|
||||
stringcount, stringnumber : integer;
|
||||
var buffer : pchar; size : integer )
|
||||
: integer; external;
|
||||
function pcre_exec( const argument_re : pointer {pcre};
|
||||
const extra_data : pointer {pcre_extra};
|
||||
{$ELSE}
|
||||
function pcre_exec( const external_re : pointer;
|
||||
const external_extra : pointer;
|
||||
{$ENDIF}
|
||||
const subject : PChar;
|
||||
length, start_offset, options : integer;
|
||||
offsets : pointer;
|
||||
offsetcount : integer ) : integer; external;
|
||||
{$IFDEF PCRE_7_0}
|
||||
function pcre_dfa_exec( const argument_re : pointer {pcre};
|
||||
const extra_data : pointer {pcre_extra};
|
||||
const subject : pchar;
|
||||
length, start_offset, options : integer;
|
||||
offsets : pointer;
|
||||
offsetcount : integer;
|
||||
workspace : pointer;
|
||||
wscount : integer ) : integer; external;
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_5_0}
|
||||
procedure pcre_free_substring( const p : pchar ); external;
|
||||
procedure pcre_free_substring_list( var p : pchar ); external;
|
||||
function pcre_fullinfo( const argument_re : pointer {pcre};
|
||||
const extra_data : pointer {pcre_extra};
|
||||
what : integer;
|
||||
where : pointer ) : integer; external;
|
||||
function pcre_get_named_substring( const code : pointer {pcre};
|
||||
const subject : pchar;
|
||||
var ovector : integer;
|
||||
stringcount : integer;
|
||||
const stringname : pchar;
|
||||
var stringptr : pchar ) : integer; external;
|
||||
function pcre_get_stringnumber( const code : pointer {pcre};
|
||||
const stringname : pchar ) : integer; external;
|
||||
function pcre_get_stringtable_entries( const code : pointer {pcre};
|
||||
const stringname : pchar;
|
||||
var firstptr,
|
||||
lastptr : pchar ) : integer; external;
|
||||
function pcre_get_substring( const subject : pchar; var ovector : integer;
|
||||
stringcount, stringnumber : integer;
|
||||
var stringptr : pchar ) : integer; external;
|
||||
function pcre_get_substring_list( const subject : pchar; var ovector : integer;
|
||||
stringcount : integer;
|
||||
listptr : pointer {const char ***listptr}) : integer; external;
|
||||
function pcre_info( const argument_re : pointer {pcre};
|
||||
var optptr : integer;
|
||||
var first_byte : integer ) : integer; external;
|
||||
function pcre_maketables : pchar; external;
|
||||
{$ENDIF}
|
||||
{$IFDEF PCRE_7_0}
|
||||
function pcre_refcount( const argument_re : pointer {pcre};
|
||||
adjust : integer ) : pchar; external;
|
||||
{$ENDIF}
|
||||
function pcre_study( const external_re : pointer {pcre};
|
||||
options : integer;
|
||||
var errorptr : PChar ) : pointer {pcre_extra}; external;
|
||||
{$IFDEF PCRE_5_0}
|
||||
function pcre_version : pchar; external;
|
||||
{$ENDIF}
|
||||
|
||||
function pcre_malloc( size : integer ) : pointer;
|
||||
begin
|
||||
GetMem( result, size );
|
||||
end;
|
||||
|
||||
procedure pcre_free( {var} p : pointer );
|
||||
begin
|
||||
if (p <> nil) then
|
||||
FreeMem( p, 0 );
|
||||
{@p := nil;}
|
||||
end;
|
||||
|
||||
{$IFDEF PCRE_5_0}
|
||||
(* Called from PCRE as a result of the (?C) item. We print out where we are in
|
||||
the match. Yield zero unless more callouts than the fail count, or the callout
|
||||
data is not zero. *)
|
||||
|
||||
function pcre_callout;
|
||||
begin
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VIRTUALPASCAL} {&Cdecl-} {$ENDIF VIRTUALPASCAL}
|
||||
|
||||
// Always include the newest version of the library
|
||||
{$IFDEF PCRE_7_7}
|
||||
{$L pcre77.lib}
|
||||
{$ELSE}
|
||||
{$IFDEF PCRE_7_0}
|
||||
{$L pcre70.lib}
|
||||
{$ELSE}
|
||||
{$IFDEF PCRE_5_0}
|
||||
{$L pcre50.lib}
|
||||
{$ELSE}
|
||||
{$IFDEF PCRE_3_7}
|
||||
{$L pcre37.lib}
|
||||
{$ENDIF PCRE_3_7}
|
||||
{$ENDIF PCRE_5_0}
|
||||
{$ENDIF PCRE_7_0}
|
||||
{$ENDIF PCRE_7_7}
|
||||
|
||||
{TpcRegExp}
|
||||
|
||||
constructor TpcRegExp.Init(const ARegExp:shortstring; AOptions:integer; ALocale : Pointer);
|
||||
var
|
||||
pRegExp : PChar;
|
||||
begin
|
||||
RegExp:=ARegExp;
|
||||
RegExpC:=nil;
|
||||
RegExpExt:=nil;
|
||||
Matches:=nil;
|
||||
MatchesCount:=0;
|
||||
Error:=true;
|
||||
ErrorMsg:=nil;
|
||||
ErrorPos:=0;
|
||||
RunTimeOptions := 0;
|
||||
if length(RegExp) < 255 then
|
||||
begin
|
||||
RegExp[length(RegExp)+1]:=#0;
|
||||
pRegExp:=@RegExp[1];
|
||||
end
|
||||
else
|
||||
begin
|
||||
GetMem(pRegExp,length(RegExp)+1);
|
||||
pRegExp:=strpcopy(pRegExp,RegExp);
|
||||
end;
|
||||
RegExpC := pcre_compile( pRegExp,
|
||||
AOptions and PCRE_COMPILE_ALLOWED_OPTIONS,
|
||||
ErrorMsg, ErrorPos, ALocale);
|
||||
if length(RegExp) = 255 then
|
||||
StrDispose(pRegExp);
|
||||
if RegExpC = nil then
|
||||
exit;
|
||||
ErrorMsg:=nil;
|
||||
RegExpExt := pcre_study( RegExpC, 0, ErrorMsg );
|
||||
if (RegExpExt = nil) and (ErrorMsg <> nil) then
|
||||
begin
|
||||
pcre_free(RegExpC);
|
||||
exit;
|
||||
end;
|
||||
GetMem(Matches,SizeOf(TMatchArray));
|
||||
Error:=false;
|
||||
end;
|
||||
|
||||
destructor TpcRegExp.Done;
|
||||
begin
|
||||
if RegExpC <> nil then
|
||||
pcre_free(RegExpC);
|
||||
if RegExpExt <> nil then
|
||||
pcre_free(RegExpExt);
|
||||
if Matches <> nil then
|
||||
FreeMem(Matches,SizeOf(TMatchArray));
|
||||
end;
|
||||
|
||||
function TpcRegExp.SearchNext( AStr: Pchar; ALen : longint ) : boolean;
|
||||
var Options: Integer;
|
||||
begin // must handle PCRE_ERROR_PARTIAL here
|
||||
Options := (RunTimeOptions or startup.MiscMultiData.cfgRegEx.DefaultOptions) and
|
||||
PCRE_EXEC_ALLOWED_OPTIONS;
|
||||
if MatchesCount > 0 then
|
||||
MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, PMatchArray(Matches)^[1],
|
||||
Options, Matches, MAX_MATCHES ) else
|
||||
MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, 0,
|
||||
Options, Matches, MAX_MATCHES );
|
||||
{ if MatchesCount = 0 then
|
||||
MatchesCount := MatchesCount div 3;}
|
||||
PartialMatch := MatchesCount = PCRE_ERROR_PARTIAL;
|
||||
SearchNext := MatchesCount > 0;
|
||||
end;
|
||||
|
||||
function TpcRegExp.Search( AStr: Pchar; ALen : longint):boolean;
|
||||
begin
|
||||
MatchesCount:=0;
|
||||
Search:=SearchNext(AStr,ALen);
|
||||
SourceLen:=ALen;
|
||||
end;
|
||||
|
||||
function TpcRegExp.SearchOfs( AStr: Pchar; ALen, AOfs: longint ) : boolean;
|
||||
var Options: Integer;
|
||||
begin
|
||||
MatchesCount:=0;
|
||||
Options := (RunTimeOptions or startup.MiscMultiData.cfgRegEx.DefaultOptions) and
|
||||
PCRE_EXEC_ALLOWED_OPTIONS;
|
||||
MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, AOfs,
|
||||
Options, Matches, MAX_MATCHES );
|
||||
PartialMatch := MatchesCount = PCRE_ERROR_PARTIAL;
|
||||
SearchOfs := MatchesCount > 0;
|
||||
SourceLen := ALen-AOfs;
|
||||
end;
|
||||
|
||||
function TpcRegExp.MatchSub(ANom:integer; var Pos,Len:longint):boolean;
|
||||
begin
|
||||
if (MatchesCount > 0) and (ANom <= (MatchesCount-1)) then
|
||||
begin
|
||||
ANom:=ANom*2;
|
||||
Pos:=PMatchArray(Matches)^[ANom];
|
||||
Len:=PMatchArray(Matches)^[ANom+1]-Pos;
|
||||
MatchSub:=true;
|
||||
end
|
||||
else
|
||||
MatchSub:=false;
|
||||
end;
|
||||
|
||||
function TpcRegExp.MatchFull(var Pos,Len:longint):boolean;
|
||||
begin
|
||||
MatchFull:=MatchSub(0,Pos,Len);
|
||||
end;
|
||||
|
||||
function TpcRegExp.GetSubStr(ANom: integer; AStr: Pchar):string;
|
||||
var
|
||||
s: ansistring;
|
||||
pos,len: longint;
|
||||
begin
|
||||
s:='';
|
||||
if MatchSub(ANom, pos, len) then
|
||||
begin
|
||||
setlength(s, len);
|
||||
Move(AStr[pos], s[1], len);
|
||||
end;
|
||||
GetSubStr:=s;
|
||||
end;
|
||||
|
||||
function TpcRegExp.GetPreSubStr(AStr: Pchar):string;
|
||||
var
|
||||
s: ansistring;
|
||||
l: longint;
|
||||
begin
|
||||
s:='';
|
||||
if (MatchesCount > 0) then
|
||||
begin
|
||||
l:=PMatchArray(Matches)^[0]-1;
|
||||
if l > 0 then
|
||||
begin
|
||||
setlength(s,l);
|
||||
Move(AStr[1],s[1],l);
|
||||
end;
|
||||
end;
|
||||
GetPreSubStr:=s;
|
||||
end;
|
||||
|
||||
function TpcRegExp.GetPostSubStr(AStr: Pchar):string;
|
||||
var
|
||||
s: ansistring;
|
||||
l: longint;
|
||||
ANom: integer;
|
||||
begin
|
||||
s:='';
|
||||
if (MatchesCount > 0) then
|
||||
begin
|
||||
ANom:=(MatchesCount-1){*2} shl 1;
|
||||
l:=SourceLen-PMatchArray(Matches)^[ANom+1]+1;
|
||||
if l > 0 then
|
||||
begin
|
||||
setlength(s,l);
|
||||
Move(AStr[PMatchArray(Matches)^[ANom+1]],s[1],l);
|
||||
end;
|
||||
end;
|
||||
GetPostSubStr:=s;
|
||||
end;
|
||||
|
||||
|
||||
function TpcRegExp.GetFullStr(AStr: Pchar):string;
|
||||
var
|
||||
s: ansistring;
|
||||
l: longint;
|
||||
begin
|
||||
GetFullStr:=GetSubStr(0,AStr);
|
||||
end;
|
||||
|
||||
function TpcRegExp.GetReplStr(AStr: Pchar; const ARepl: string):string;
|
||||
var
|
||||
s: ansistring;
|
||||
l,i,lasti: longint;
|
||||
begin
|
||||
l:=length(ARepl);
|
||||
i:=1;
|
||||
lasti:=1;
|
||||
s:='';
|
||||
while i <= l do
|
||||
begin
|
||||
case ARepl[i] of
|
||||
'\' :
|
||||
begin
|
||||
if i < l then
|
||||
begin
|
||||
s:=s+copy(ARepl,lasti,i-lasti){+ARepl[i+1]};
|
||||
{AH 17-10-05 support for POSIX \1-\9 backreferences}
|
||||
case ARepl[i+1] of
|
||||
'0' : s:=s+GetFullStr(AStr);
|
||||
'1'..'9' : s:=s+GetSubStr(ord(ARepl[i+1])-ord('0'),AStr);
|
||||
else s:=s+ARepl[i+1]; // copy the escaped character
|
||||
end;
|
||||
end;
|
||||
inc(i);
|
||||
lasti:=i+1;
|
||||
end;
|
||||
'$' :
|
||||
begin
|
||||
if i < l then
|
||||
begin
|
||||
s:=s+copy(ARepl,lasti,i-lasti);
|
||||
case ARepl[i+1] of
|
||||
'&' : s:=s+GetFullStr(AStr);
|
||||
'1'..'9' : s:=s+GetSubStr(ord(ARepl[i+1])-ord('0'),AStr);
|
||||
'`' : s:=s+GetPreSubStr(AStr);
|
||||
#39 : s:=s+GetPostSubStr(AStr);
|
||||
end;
|
||||
end;
|
||||
inc(i);
|
||||
lasti:=i+1;
|
||||
end;
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
if lasti <= {AH 25-10-2004 added =, else l==1 won't work} l then
|
||||
s:=s+copy(ARepl,lasti,l-lasti+1);
|
||||
GetReplStr:=s;
|
||||
end;
|
||||
|
||||
function TpcRegExp.ErrorStr:string;
|
||||
begin
|
||||
ErrorStr:=StrPas(ErrorMsg);
|
||||
end;
|
||||
|
||||
{TRegExpCollection}
|
||||
|
||||
constructor TRegExpCollection.Init(AMaxRegExp: integer);
|
||||
begin
|
||||
Inherited Init(1,1);
|
||||
MaxRegExp:=AMaxRegExp;
|
||||
CompareModeInsert:=true;
|
||||
end;
|
||||
|
||||
procedure TRegExpCollection.FreeItem(P: Pointer);
|
||||
begin
|
||||
if P <> nil then
|
||||
begin
|
||||
Dispose(PpcRegExp(P),Done);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TRegExpCollection.Compare(P1, P2: Pointer): Integer;
|
||||
//var
|
||||
// l,l1,l2,i : byte;
|
||||
//// wPos: pchar;
|
||||
begin
|
||||
if CompareModeInsert then
|
||||
begin
|
||||
// l1:=length(PpcRegExp(P1)^.RegExp);
|
||||
// l2:=length(PpcRegExp(P2)^.RegExp);
|
||||
// if l1 > l2 then l:=l2 else
|
||||
// l:=l1;
|
||||
// for i:=1 to l do
|
||||
// if PpcRegExp(P1).RegExp[i] <> PpcRegExp(P2).RegExp[i] then break;
|
||||
// if i <=l then
|
||||
// Compare:=ord(PpcRegExp(P1).RegExp[i])-ord(PpcRegExp(P2).RegExp[i]) else
|
||||
// Compare:=l1-l2;
|
||||
Compare := stringsx.PasStrCmp(PpcRegExp(P1).RegExp, PpcRegExp(P2).RegExp, False);
|
||||
end
|
||||
else
|
||||
begin
|
||||
// l1:=length(PpcRegExp(P1)^.RegExp);
|
||||
// l2:=length(SearchRegExp);
|
||||
// if l1 > l2 then l:=l2 else
|
||||
// l:=l1;
|
||||
// for i:=1 to l do
|
||||
// if PpcRegExp(P1).RegExp[i] <> SearchRegExp[i] then
|
||||
// begin
|
||||
// Compare:=ord(PpcRegExp(P1).RegExp[i])-ord(SearchRegExp[i]);
|
||||
// break;
|
||||
// end;
|
||||
// if i > l then Compare:=l1-l2;
|
||||
Compare := stringsx.PasStrCmp(PpcRegExp(P1).RegExp, SearchRegExp, False);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TRegExpCollection.Find(ARegExp:shortstring;var P: PpcRegExp):boolean;
|
||||
var I : integer;
|
||||
begin
|
||||
CompareModeInsert:=false;
|
||||
SearchRegExp:=ARegExp;
|
||||
if Search(nil,I) then
|
||||
begin
|
||||
P:=PpcRegExp(At(I));
|
||||
Find:=true;
|
||||
end
|
||||
else
|
||||
begin
|
||||
P:=nil;
|
||||
Find:=false;
|
||||
end;
|
||||
CompareModeInsert:=true;
|
||||
end;
|
||||
|
||||
function TRegExpCollection.CheckNew(ARegExp:shortstring):PpcRegExp;
|
||||
var
|
||||
P : PpcRegExp;
|
||||
begin
|
||||
if not Find(ARegExp,P) then
|
||||
begin
|
||||
if Count = MaxRegExp then
|
||||
AtFree(0);
|
||||
P:=New(ppcRegExp,Init(ARegExp,PCRE_CASELESS,nil));
|
||||
Insert(P);
|
||||
end;
|
||||
CheckNew:=P;
|
||||
end;
|
||||
|
||||
function pcGrepMatch(WildCard, aStr: string; AOptions:integer; ALocale : Pointer): Boolean;
|
||||
var
|
||||
PpcRE:PpcRegExp;
|
||||
begin
|
||||
PpcRE:=New(ppcRegExp,Init(WildCard,AOptions,Alocale));
|
||||
pcGrepMatch:=PpcRE^.Search(pchar(AStr),Length(AStr));
|
||||
Dispose(PpcRE,Done);
|
||||
end;
|
||||
|
||||
function pcGrepSub(WildCard, aStr, aRepl: string; AOptions:integer; ALocale : Pointer): string;
|
||||
var
|
||||
PpcRE:PpcRegExp;
|
||||
begin
|
||||
PpcRE:=New(ppcRegExp,Init(WildCard,AOptions,Alocale));
|
||||
if PpcRE^.Search(pchar(AStr),Length(AStr)) then
|
||||
pcGrepSub:=PpcRE^.GetReplStr(pchar(AStr),ARepl)
|
||||
else
|
||||
pcGrepSub:='';
|
||||
Dispose(PpcRE,Done);
|
||||
end;
|
||||
|
||||
function pcFastGrepMatch(WildCard, aStr: string): Boolean;
|
||||
var
|
||||
PpcRE:PpcRegExp;
|
||||
begin
|
||||
PpcRE:=PRegExpCache^.CheckNew(WildCard);
|
||||
pcFastGrepMatch:=PpcRE^.Search(pchar(AStr),Length(AStr));
|
||||
end;
|
||||
|
||||
function pcFastGrepSub(WildCard, aStr, aRepl: string): string;
|
||||
var
|
||||
PpcRE:PpcRegExp;
|
||||
begin
|
||||
PpcRE:=PRegExpCache^.CheckNew(WildCard);
|
||||
if PpcRE^.Search(pchar(AStr),Length(AStr)) then
|
||||
pcFastGrepSub:=PpcRE^.GetReplStr(pchar(AStr),ARepl)
|
||||
else
|
||||
pcFastGrepSub:='';
|
||||
end;
|
||||
|
||||
{$IFDEF PCRE_5_0}
|
||||
function pcGetVersion : pchar; assembler; {$FRAME-}{$USES none}
|
||||
asm
|
||||
call pcre_version
|
||||
end;
|
||||
{$ENDIF PCRE_5_0}
|
||||
|
||||
function pcError;
|
||||
var P: ppcRegExp absolute pRegExp;
|
||||
begin
|
||||
Result := (P = nil) or P^.Error;
|
||||
If Result and (P <> nil) then
|
||||
begin
|
||||
{ if P^.ErrorPos = 0 then
|
||||
MessageBox(GetString(erRegExpCompile)+'"'+P^.ErrorStr+'"', nil,mfConfirmation+mfOkButton)
|
||||
else}
|
||||
MessageBox(GetString(erRegExpCompile)+'"'+P^.ErrorStr+'"'+GetString(erRegExpCompPos),
|
||||
@P^.ErrorPos,mfConfirmation+mfOkButton);
|
||||
Dispose(P, Done);
|
||||
P:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function pcInit;
|
||||
var Options : Integer;
|
||||
begin
|
||||
If CaseSens then Options := 0 else Options := PCRE_CASELESS;
|
||||
Result := New( PpcRegExp, Init( Pattern,
|
||||
{DefaultOptions}
|
||||
startup.MiscMultiData.cfgRegEx.DefaultOptions or Options,
|
||||
DefaultLocaleTable) );
|
||||
end;
|
||||
|
||||
Initialization
|
||||
PRegExpCache:=New(PRegExpCollection,Init(64));
|
||||
Finalization
|
||||
Dispose(PRegExpCache,Done);
|
||||
End.
|
Reference in New Issue
Block a user