123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- unit mPegFilter;
- interface
- uses
- Classes, SysUtils, PerlRegEx;
- type
- // analyse Peg Num
- // YK1+000 --> K1+000
- TPegFilter = class
- private
- FBeginPeg: string;
- FBeginPegNum: Double;
- FEndPeg: string;
- FEndPegNum: Double;
- function PegFormat(const AStr: string): string;
- function FilterPeg(const AStr: string; var APeg: string; var ANum: Double; var ABegin, AEnd: Integer): Boolean;
- public
- function Filter(const AStr: string): Boolean;
- property BeginPeg: string read FBeginPeg;
- property BeginPegNum: Double read FBeginPegNum;
- property EndPeg: string read FEndPeg;
- property EndPegNum: Double read FEndPegNum;
- end;
- // filter begin/end Peg, keep orginal Peg
- // GLK1+000 --> GLK1+000
- TPegInfo = class
- FPeg: string;
- FOffset: Integer;
- FLength: Integer;
- end;
- TPegStrFilter = class
- private
- FToRegStr: string;
- FPegRegStr: string;
- FPegStr: string;
- FPegList: TList;
- FBeginPegList: TList;
- FEndPegList: TList;
- procedure ClearHistory;
- procedure FilterPeg;
- procedure FilterBeginAndEnd;
- procedure AnalysePeg;
- function MergePeg(Pegs: TList): string;
- procedure SetPegStr(const Value: string);
- function GetBeginPeg: string;
- function GetEndPeg: string;
- function GetSubPegCount: Integer;
- function GetSubPeg(AIndex: Integer): string;
- public
- constructor Create;
- destructor Destory;
- property PegRegStr: string read FPegRegStr;
- property ToRegStr: string read FToRegStr;
- property PegStr: string read FPegStr write SetPegStr;
- property BeginPeg: string read GetBeginPeg;
- property EndPeg: string read GetEndPeg;
- property SubPegCount: Integer read GetSubPegCount;
- property SubPeg[AIndex: Integer]: string read GetSubPeg;
- end;
- function PegFilter: TPegFilter;
- implementation
- uses Math, ZhAPI;
- var
- FPegFilter: TPegFilter;
- function PegFilter: TPegFilter;
- begin
- if FPegFilter = nil then
- FPegFilter := TPegFilter.Create;
- Result := FPegFilter;
- end;
- { TPegFilter }
- function TPegFilter.Filter(const AStr: string): Boolean;
- var
- sPeg: string;
- iPos, iBegin, iEnd: Integer;
- begin
- sPeg := PegFormat(AStr);
- Result := FilterPeg(sPeg, FBeginPeg, FBeginPegNum, iBegin, iEnd);
- if Result and (sPeg[iEnd+1] = '~') then
- begin
- sPeg := StringReplace(sPeg, FBeginPeg, '', []);
- FilterPeg(sPeg, FEndPeg, FEndPegNum, iBegin, iEnd);
- if FEndPegNum = 0 then
- begin
- FEndPeg := FBeginPeg;
- FEndPegNum := FBeginPegNum;
- end
- else
- Result := FEndPegNum >= FBeginPegNum;
- end
- else
- begin
- FEndPeg := '';
- FEndPegNum := 0;
- end;
- end;
- function TPegFilter.FilterPeg(const AStr: string; var APeg: string;
- var ANum: Double; var ABegin, AEnd: Integer): Boolean;
- function FilterInt(ABegin: Integer; var AEnd: Integer; var AIntStr: string; var AValue: Integer): Boolean;
- var
- iPos, iLength: Integer;
- sInt: string;
- begin
- AIntStr := '';
- AEnd := ABegin;
- iPos := ABegin;
- iLength := Length(AStr);
- while (iPos <= iLength) do
- begin
- if AStr[iPos] in ['0'..'9'] then
- begin
- AIntStr := AIntStr + AStr[iPos];
- AEnd := iPos;
- end
- else Break;
- Inc(iPos);
- end;
- Result := AIntStr <> '';
- AValue := StrToIntDef(AIntStr, 0);
- end;
- // 过滤一个小于1000的Float
- function FilterFloat(ABegin: Integer; var AEnd: Integer; var AFloatStr: string; var AValue: Double): Boolean;
- var
- iPos, iLength, iIntPartLength: Integer;
- bHasPoint, bAllZero: Boolean;
- begin
- AFloatStr := '';
- AEnd := ABegin;
- iPos := ABegin;
- iLength := Length(AStr);
- bHasPoint := False;
- bAllZero := True;
- iIntPartLength := 0;
- while (iPos <= iLength) do
- begin
- if AStr[iPos] in ['0'..'9'] then
- begin
- AFloatStr := AFloatStr + AStr[iPos];
- AEnd := iPos;
- if not bHasPoint then
- Inc(iIntPartLength);
- bAllZero := bAllZero and (AStr[iPos] = '0');
- end
- else if (AStr[iPos] = '.') and (not bHasPoint) then
- begin
- AFloatStr := AFloatStr + AStr[iPos];
- AEnd := iPos;
- bHasPoint := True;
- end
- else Break;
- Inc(iPos);
- end;
- if iIntPartLength > 3 then
- begin
- AEnd := ABegin + 3 - 1;
- AFloatStr := Copy(AFloatStr, 1, 3);
- end;
- AValue := StrToFloatDef(AFloatStr, 0);
- Result := (AValue <> 0) or (bAllZero and (AEnd > ABegin));
- end;
- var
- iPos, iLength: Integer;
- iBeginNum, iEndNum, iPosPuls, iBeginNum2, iEndNum2: Integer;
- sNum, sNum2: string;
- iNum: Integer;
- fNum: Double;
- begin
- Result := False;
- APeg := '';
- ANum := 0;
- ABegin := -1;
- AEnd := -1;
- iPos := 1;
- iLength := Length(AStr);
- while (iPos <= iLength) and (not Result) do
- begin
- if AStr[iPos] = 'k' then
- begin
- iBeginNum := iPos + 1;
- if FilterInt(iBeginNum, iEndNum, sNum, iNum) then
- begin
- iPosPuls := iEndNum + 1;
- if AStr[iPosPuls] = '+' then
- begin
- iBeginNum2 := iPosPuls + 1;
- if FilterFloat(iBeginNum2, iEndNum2, sNum2, fNum) then
- begin
- Result := True;
- APeg := Copy(AStr, iPos, iEndNum2-iPos+1);
- ANum := iNum * 1000 + fNum;
- ABegin := iPos;
- AEnd := iEndNum2;
- end;
- end;
- end
- end;
- inc(iPos);
- end;
- end;
- function TPegFilter.PegFormat(const AStr: string): string;
- begin
- Result := AStr;
- Result := StringReplace(Result, 'K', 'k', [rfReplaceAll]);
- Result := StringReplace(Result, '+', '+', [rfReplaceAll]);
- Result := StringReplace(Result, '~', '~', [rfReplaceAll]);
- Result := StringReplace(Result, ' ', '', [rfReplaceAll]);
- end;
- { TPegStrFilter }
- procedure TPegStrFilter.AnalysePeg;
- begin
- ClearHistory;
- FilterPeg;
- FilterBeginAndEnd;
- end;
- procedure TPegStrFilter.ClearHistory;
- begin
- ClearObjects(FPegList);
- FPegList.Clear;
- FBeginPegList.Clear;
- FEndPegList.Clear;
- end;
- constructor TPegStrFilter.Create;
- begin
- FPegRegStr := '[a-zA-z]{0,2}[kK]\d+[++][0-9.]+';
- FToRegStr := '[--~~]';
- FPegList := TList.Create;
- FBeginPegList := TList.Create;
- FEndPegList := TList.Create;
- end;
- destructor TPegStrFilter.Destory;
- begin
- FEndPegList.Free;
- FBeginPegList.Free;
- ClearObjects(FPegList);
- FPegList.Free;
- end;
- procedure TPegStrFilter.FilterBeginAndEnd;
- var
- vToReg: TPerlRegEx;
- vPeg1, vPeg2: TPegInfo;
- i, iPos: Integer;
- begin
- vToReg := TPerlRegEx.Create;
- vToReg.RegEx := FToRegStr;
- if FPegList.Count > 0 then
- begin
- for i := 1 to FPegList.Count - 1 do
- begin
- iPos := i;
- vPeg1 := TPegInfo(FPegList.Items[i - 1]);
- vPeg2 := TPegInfo(FPegList.Items[i]);
- vToReg.Subject := Copy(FPegStr, vPeg1.FOffSet + vPeg1.FLength, vPeg2.FOffSet - (vPeg1.FOffSet + vPeg1.FLength));
- if vToReg.Match then
- Break;
- end;
- for i := 0 to FPegList.Count - 1 do
- begin
- if i < iPos then
- FBeginPegList.Add(FPegList.Items[i])
- else
- FEndPegList.Add(FPegList.Items[i]);
- end;
- end;
- vToReg.Free;
- end;
- procedure TPegStrFilter.FilterPeg;
- var
- vPegReg: TPerlRegEx;
- vPegInfo: TPegInfo;
- begin
- vPegReg := TPerlRegEx.Create;
- vPegReg.Subject := PegStr;
- vPegReg.RegEx := PegRegStr;
- while vPegReg.MatchAgain do
- begin
- vPegInfo := TPegInfo.Create;
- vPegInfo.FPeg := vPegReg.MatchedText;
- vPegInfo.FOffset := vPegReg.MatchedOffset;
- vPegInfo.FLength := vPegReg.MatchedLength;
- FPegList.Add(vPegInfo);
- end;
- vPegReg.Free;
- end;
- function TPegStrFilter.GetBeginPeg: string;
- begin
- Result := MergePeg(FBeginPegList);
- end;
- function TPegStrFilter.GetEndPeg: string;
- begin
- if FEndPegList.Count > 0 then
- Result := MergePeg(FEndPegList)
- else
- Result := MergePeg(FBeginPegList);
- end;
- function TPegStrFilter.GetSubPeg(AIndex: Integer): string;
- begin
- if (AIndex < 0) or (AIndex >= SubPegCount) then
- Result := ''
- else
- Result := TPegInfo(FPegList.Items[AIndex]).FPeg;
- end;
- function TPegStrFilter.GetSubPegCount: Integer;
- begin
- Result := FPegList.Count;
- end;
- function TPegStrFilter.MergePeg(Pegs: TList): string;
- var
- i: Integer;
- begin
- Result := '';
- for i := 0 to Pegs.Count - 1 do
- begin
- if i = 0 then
- Result := TPegInfo(Pegs.Items[i]).FPeg
- else
- Result := Result + '/' + TPegInfo(Pegs.Items[i]).FPeg;
- end;
- end;
- procedure TPegStrFilter.SetPegStr(const Value: string);
- begin
- FPegStr := Value;
- AnalysePeg;
- end;
- initialization
- FPegFilter := nil;
- finalization
- FPegFilter.Free;
- end.
|