lazarus-ccr/components/orpheus/o32rxvld.pas
2007-01-16 02:17:08 +00:00

295 lines
10 KiB
ObjectPascal

{*********************************************************}
{* O32RXVLD.PAS 4.06 *}
{*********************************************************}
{* ***** BEGIN LICENSE BLOCK ***** *}
{* Version: MPL 1.1 *}
{* *}
{* The contents of this file are subject to the Mozilla Public License *}
{* Version 1.1 (the "License"); you may not use this file except in *}
{* compliance with the License. You may obtain a copy of the License at *}
{* http://www.mozilla.org/MPL/ *}
{* *}
{* Software distributed under the License is distributed on an "AS IS" basis, *}
{* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *}
{* for the specific language governing rights and limitations under the *}
{* License. *}
{* *}
{* The Original Code is TurboPower Orpheus *}
{* *}
{* The Initial Developer of the Original Code is TurboPower Software *}
{* *}
{* Portions created by TurboPower Software Inc. are Copyright (C)1995-2002 *}
{* TurboPower Software Inc. All Rights Reserved. *}
{* *}
{* Contributor(s): *}
{* *}
{* ***** END LICENSE BLOCK ***** *}
{$I OVC.INC}
{$B-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{.W-} {Windows Stack Frame}
{$X+} {Extended Syntax}
unit o32rxvld;
{Unit for the Orpheus RegEx Validator}
interface
uses Classes, O32Vldtr, O32RxNgn, SysUtils;
const
RXMaskCount = 13;
RXMaskLength = 80;
{Sample Regular Expressions for the Regex validator Property editor...}
RXMaskLookup : array [1..RXMaskCount] of string =
('.+ 1 or more of any characters allowed. Minimum of 1 character required. Note: This is the default behavior. No expression is needed.',
'.* Any number of any character allowed. Note: Although This expression allows an empty string, The RegexEngine will fail an empty string.',
'(1[012]|[1-9]):[0-5][0-9] (am|pm) Time of day: Standard AM/PM time display (9:17 am) or (12:30 pm)',
'(1[012]|[1-9]):[0-5][0-9]:[0-5][0-9] (am|pm) Time of day: Standard AM/PM time diplay with seconds. (9:17:22 am)',
'(([01]?[0-9])|(2[0-3])):[0-5][0-9] Time of day: 24 hour clock (15:22).',
'(([01]?[0-9])|(2[0-3])):[0-5][0-9]:[0-5][0-9] Time of day: 24 hour clock with seconds (15:22:07).',
'(\(?[1-9][0-9][0-9]\)? )?[1-9][0-9][0-9]\-[0-9][0-9][0-9][0-9] Telephone Number: Optional area-code with optional parenthesis',
'(0?[1-9]|1[012])(\\|/|\-)([012]?[1-9]|[123]0|31)(\\|/|\-)([123][0-9])?[0-9][0-9] Date: (mm\dd\yy) or (mm\dd\yyyy) formats. Also accepts / and - separators. Note: Only covers years from 1000-3999',
'(y(es)?)|(no?) Boolean: Y, y, N, n, Yes, yes, No or no',
'(t(rue)?)|(f(alse)?) Boolean: T, t, F, f, True, False, true or false',
'([0-9]|[A-F])+ Hexadecimal: Allows any number of characters in the range 0-9 and A-F',
'[0-7]+ Octal: Allows any number of characters in the range 0-7.',
'[01]+ Binary:Allows any number of binary characters (0 and 1).');
{Error Codes}
EC_NO_ERROR = 0;
EC_INVALID_EXPR = 1;
EC_INVALID_INPUT = 2;
EC_NO_MATCH = 3;
type
{class - TO32RegExValidator}
TO32RegExValidator = class(TO32BaseValidator)
protected {private}
FLogging : Boolean; {Log validator parsing?}
FLogFile : String; {Logging file name}
FRegexEngine : TO32RegExEngine; {Regex engine used by the validator}
FExprErrorPos : Integer; {Error position in the Regex string}
FExprErrorCode : TO32RegexError; {Regex string error code}
FIgnoreCase : Boolean; {Case sensitive matching}
procedure SetIgnoreCase(const Value: Boolean);
procedure SetLogging(const Value: Boolean);
procedure SetLogFile(const Value: String);
procedure SetMask(const Value: String); override;
function GetValid: Boolean; override;
function GetSampleMasks: TStringList; override;
procedure SetInput(const Value: string); override;
function CheckExpression(var ErrorPos: Integer): Boolean;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function IsValid: Boolean; override;
function GetExprError: String;
property Valid;
property ExprErrorPos: Integer read FExprErrorPos write FExprErrorPos;
published
property Input;
{ Surfaced the Mask property as "Expression" for the Regex validator
Left Mask exposed as public for automated use such as the ValidatorPool}
property Expression: string read FMask write SetMask stored true;
property Logging: Boolean read FLogging write SetLogging
default False;
property LogFile: String read FLogFile write SetLogFile;
property IgnoreCase: Boolean read FIgnoreCase write SetIgnoreCase stored true
default True;
{Events}
property BeforeValidation;
property AfterValidation;
property OnValidationError;
end;
implementation
uses
O32VlReg;
{=== TO32RegExValidator ==============================================}
constructor TO32RegExValidator.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLogging := false;
FLogFile := 'parse.log';
FIgnoreCase := true;
FRegexEngine := TO32RegExEngine.Create('');
FRegexEngine.Logging := FLogging;
FRegexEngine.LogFile := FLogFile;
FRegexEngine.IgnoreCase := FIgnoreCase;
end;
{=====}
destructor TO32RegExValidator.Destroy;
begin
FRegexEngine.Free;
inherited Destroy;
end;
{=====}
function TO32RegExValidator.GetSampleMasks: TStringList;
var
I : Integer;
begin
{ Set the length of the mask portion of the string }
FSampleMaskLength := RXMaskLength;
FSampleMasks.Clear;
{ Load the string list }
for I := 1 to RXMaskCount do
FSampleMasks.Add(RXMaskLookup[I]);
result := FSampleMasks;
end;
{=====}
procedure TO32RegExValidator.SetMask(const Value: String);
var
OldExpression: String;
begin
OldExpression := FMask;
FMask := Value;
if not CheckExpression(FExprErrorPos) then
FMask := OldExpression;
end;
{=====}
procedure TO32RegExValidator.SetInput(const Value: string);
begin
if FInput <> Value then
FInput := Value;
end;
{=====}
function TO32RegExValidator.CheckExpression(var ErrorPos: Integer): Boolean;
begin
if (FMask <> '') then begin
FRegexEngine.RegexString := FMask;
if not FRegexEngine.Parse(FExprErrorPos, FExprErrorCode) then begin
result := false;
FErrorCode := EC_INVALID_EXPR;
DoOnError(self, GetExprError);
end else
result := true;
end else begin
{Allow the user to initialize the Validator with an empty string}
result := true;
ErrorPos := 0;
FExprErrorPos := 0;
FErrorCode := EC_NO_ERROR;
FExprErrorCode := recNone;
end;
end;
{=====}
function TO32RegExValidator.GetValid: Boolean;
begin
result := IsValid;
end;
{=====}
function TO32RegExValidator.IsValid: Boolean;
var
RegExStr: String;
begin
DoBeforeValidation;
{assume the worst}
FValid := false;
{Create a copy of the Expression and then enclose it in anchor operators so
that the RegexEngine only matches the whole string...}
RegExStr := FMask;
{Check for Anchor operator ^}
if (Pos('^', RegExStr) <> 1) then
Insert('^', RegExStr, 1);
{Check for Anchor operator $}
if (Pos('$', RegExStr) <> Length(RegExStr)) then
RegexStr := RegExStr + '$';
{Pass the RegexStr into the RegexEngine}
FRegexEngine.RegexString := RegExStr;
if (RegExStr = '') then begin
FErrorCode := EC_INVALID_EXPR;
FValid := false;
end else if (FInput = '') then begin
FErrorCode := EC_INVALID_INPUT;
FValid := false;
end else begin
if (FRegexEngine.MatchString(FInput) = 1) then begin
FValid := true;
FErrorCode := 0;
end else begin
FValid := false;
FErrorCode := EC_NO_MATCH;
end;
end;
result := FValid;
DoAfterValidation
end;
{=====}
procedure TO32RegExValidator.SetLogging(const Value: Boolean);
begin
if (FLogging <> Value) then begin
FLogging := Value;
FRegexEngine.Logging := FLogging;
end;
end;
{=====}
procedure TO32RegExValidator.SetIgnoreCase(const Value: Boolean);
begin
if (FIgnoreCase <> Value) then begin
FIgnoreCase := Value;
FRegexEngine.IgnoreCase := FIgnoreCase;
end;
end;
{=====}
procedure TO32RegExValidator.SetLogFile(const Value: String);
begin
if (FLogFile <> Value) then begin
FLogFile := Value;
FRegexEngine.LogFile := FLogFile;
end;
end;
{=====}
function TO32RegExValidator.GetExprError: String;
begin
case FExprErrorCode of
recNone : result := '';
recSuddenEnd : result := 'Incomplete Expression';
recMetaChar : result := 'Read a metacharacter where there should have'
+ ' been a normal character';
recNoCloseParen : result := 'Missing closing parenthesis';
recExtraChars : result := 'Unrecognizable text at the end of the'
+ ' expression';
end;
end;
{=====}
initialization
RegisterValidator(TO32RegexValidator);
finalization
UnRegisterValidator(TO32RegexValidator);
end.