mPegFilter.pas 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. unit mPegFilter;
  2. interface
  3. uses
  4. Classes, SysUtils, PerlRegEx;
  5. type
  6. // analyse Peg Num
  7. // YK1+000 --> K1+000
  8. TPegFilter = class
  9. private
  10. FBeginPeg: string;
  11. FBeginPegNum: Double;
  12. FEndPeg: string;
  13. FEndPegNum: Double;
  14. function PegFormat(const AStr: string): string;
  15. function FilterPeg(const AStr: string; var APeg: string; var ANum: Double; var ABegin, AEnd: Integer): Boolean;
  16. public
  17. function Filter(const AStr: string): Boolean;
  18. property BeginPeg: string read FBeginPeg;
  19. property BeginPegNum: Double read FBeginPegNum;
  20. property EndPeg: string read FEndPeg;
  21. property EndPegNum: Double read FEndPegNum;
  22. end;
  23. // filter begin/end Peg, keep orginal Peg
  24. // GLK1+000 --> GLK1+000
  25. TPegInfo = class
  26. FPeg: string;
  27. FOffset: Integer;
  28. FLength: Integer;
  29. end;
  30. TPegStrFilter = class
  31. private
  32. FToRegStr: string;
  33. FPegRegStr: string;
  34. FPegStr: string;
  35. FPegList: TList;
  36. FBeginPegList: TList;
  37. FEndPegList: TList;
  38. procedure ClearHistory;
  39. procedure FilterPeg;
  40. procedure FilterBeginAndEnd;
  41. procedure AnalysePeg;
  42. function MergePeg(Pegs: TList): string;
  43. procedure SetPegStr(const Value: string);
  44. function GetBeginPeg: string;
  45. function GetEndPeg: string;
  46. function GetSubPegCount: Integer;
  47. function GetSubPeg(AIndex: Integer): string;
  48. public
  49. constructor Create;
  50. destructor Destory;
  51. property PegRegStr: string read FPegRegStr;
  52. property ToRegStr: string read FToRegStr;
  53. property PegStr: string read FPegStr write SetPegStr;
  54. property BeginPeg: string read GetBeginPeg;
  55. property EndPeg: string read GetEndPeg;
  56. property SubPegCount: Integer read GetSubPegCount;
  57. property SubPeg[AIndex: Integer]: string read GetSubPeg;
  58. end;
  59. function PegFilter: TPegFilter;
  60. implementation
  61. uses Math, ZhAPI;
  62. var
  63. FPegFilter: TPegFilter;
  64. function PegFilter: TPegFilter;
  65. begin
  66. if FPegFilter = nil then
  67. FPegFilter := TPegFilter.Create;
  68. Result := FPegFilter;
  69. end;
  70. { TPegFilter }
  71. function TPegFilter.Filter(const AStr: string): Boolean;
  72. var
  73. sPeg: string;
  74. iPos, iBegin, iEnd: Integer;
  75. begin
  76. sPeg := PegFormat(AStr);
  77. Result := FilterPeg(sPeg, FBeginPeg, FBeginPegNum, iBegin, iEnd);
  78. if Result and (sPeg[iEnd+1] = '~') then
  79. begin
  80. sPeg := StringReplace(sPeg, FBeginPeg, '', []);
  81. FilterPeg(sPeg, FEndPeg, FEndPegNum, iBegin, iEnd);
  82. if FEndPegNum = 0 then
  83. begin
  84. FEndPeg := FBeginPeg;
  85. FEndPegNum := FBeginPegNum;
  86. end
  87. else
  88. Result := FEndPegNum >= FBeginPegNum;
  89. end
  90. else
  91. begin
  92. FEndPeg := '';
  93. FEndPegNum := 0;
  94. end;
  95. end;
  96. function TPegFilter.FilterPeg(const AStr: string; var APeg: string;
  97. var ANum: Double; var ABegin, AEnd: Integer): Boolean;
  98. function FilterInt(ABegin: Integer; var AEnd: Integer; var AIntStr: string; var AValue: Integer): Boolean;
  99. var
  100. iPos, iLength: Integer;
  101. sInt: string;
  102. begin
  103. AIntStr := '';
  104. AEnd := ABegin;
  105. iPos := ABegin;
  106. iLength := Length(AStr);
  107. while (iPos <= iLength) do
  108. begin
  109. if AStr[iPos] in ['0'..'9'] then
  110. begin
  111. AIntStr := AIntStr + AStr[iPos];
  112. AEnd := iPos;
  113. end
  114. else Break;
  115. Inc(iPos);
  116. end;
  117. Result := AIntStr <> '';
  118. AValue := StrToIntDef(AIntStr, 0);
  119. end;
  120. // 过滤一个小于1000的Float
  121. function FilterFloat(ABegin: Integer; var AEnd: Integer; var AFloatStr: string; var AValue: Double): Boolean;
  122. var
  123. iPos, iLength, iIntPartLength: Integer;
  124. bHasPoint, bAllZero: Boolean;
  125. begin
  126. AFloatStr := '';
  127. AEnd := ABegin;
  128. iPos := ABegin;
  129. iLength := Length(AStr);
  130. bHasPoint := False;
  131. bAllZero := True;
  132. iIntPartLength := 0;
  133. while (iPos <= iLength) do
  134. begin
  135. if AStr[iPos] in ['0'..'9'] then
  136. begin
  137. AFloatStr := AFloatStr + AStr[iPos];
  138. AEnd := iPos;
  139. if not bHasPoint then
  140. Inc(iIntPartLength);
  141. bAllZero := bAllZero and (AStr[iPos] = '0');
  142. end
  143. else if (AStr[iPos] = '.') and (not bHasPoint) then
  144. begin
  145. AFloatStr := AFloatStr + AStr[iPos];
  146. AEnd := iPos;
  147. bHasPoint := True;
  148. end
  149. else Break;
  150. Inc(iPos);
  151. end;
  152. if iIntPartLength > 3 then
  153. begin
  154. AEnd := ABegin + 3 - 1;
  155. AFloatStr := Copy(AFloatStr, 1, 3);
  156. end;
  157. AValue := StrToFloatDef(AFloatStr, 0);
  158. Result := (AValue <> 0) or (bAllZero and (AEnd > ABegin));
  159. end;
  160. var
  161. iPos, iLength: Integer;
  162. iBeginNum, iEndNum, iPosPuls, iBeginNum2, iEndNum2: Integer;
  163. sNum, sNum2: string;
  164. iNum: Integer;
  165. fNum: Double;
  166. begin
  167. Result := False;
  168. APeg := '';
  169. ANum := 0;
  170. ABegin := -1;
  171. AEnd := -1;
  172. iPos := 1;
  173. iLength := Length(AStr);
  174. while (iPos <= iLength) and (not Result) do
  175. begin
  176. if AStr[iPos] = 'k' then
  177. begin
  178. iBeginNum := iPos + 1;
  179. if FilterInt(iBeginNum, iEndNum, sNum, iNum) then
  180. begin
  181. iPosPuls := iEndNum + 1;
  182. if AStr[iPosPuls] = '+' then
  183. begin
  184. iBeginNum2 := iPosPuls + 1;
  185. if FilterFloat(iBeginNum2, iEndNum2, sNum2, fNum) then
  186. begin
  187. Result := True;
  188. APeg := Copy(AStr, iPos, iEndNum2-iPos+1);
  189. ANum := iNum * 1000 + fNum;
  190. ABegin := iPos;
  191. AEnd := iEndNum2;
  192. end;
  193. end;
  194. end
  195. end;
  196. inc(iPos);
  197. end;
  198. end;
  199. function TPegFilter.PegFormat(const AStr: string): string;
  200. begin
  201. Result := AStr;
  202. Result := StringReplace(Result, 'K', 'k', [rfReplaceAll]);
  203. Result := StringReplace(Result, '+', '+', [rfReplaceAll]);
  204. Result := StringReplace(Result, '-', '-', [rfReplaceAll]);
  205. Result := StringReplace(Result, '~', '~', [rfReplaceAll]);
  206. Result := StringReplace(Result, ' ', '', [rfReplaceAll]);
  207. end;
  208. { TPegStrFilter }
  209. procedure TPegStrFilter.AnalysePeg;
  210. begin
  211. ClearHistory;
  212. FilterPeg;
  213. FilterBeginAndEnd;
  214. end;
  215. procedure TPegStrFilter.ClearHistory;
  216. begin
  217. ClearObjects(FPegList);
  218. FPegList.Clear;
  219. FBeginPegList.Clear;
  220. FEndPegList.Clear;
  221. end;
  222. constructor TPegStrFilter.Create;
  223. begin
  224. FPegRegStr := '[a-zA-z]{0,2}[kK]\d+[++][0-9.]+';
  225. FToRegStr := '[--~~]';
  226. FPegList := TList.Create;
  227. FBeginPegList := TList.Create;
  228. FEndPegList := TList.Create;
  229. end;
  230. destructor TPegStrFilter.Destory;
  231. begin
  232. FEndPegList.Free;
  233. FBeginPegList.Free;
  234. ClearObjects(FPegList);
  235. FPegList.Free;
  236. end;
  237. procedure TPegStrFilter.FilterBeginAndEnd;
  238. var
  239. vToReg: TPerlRegEx;
  240. vPeg1, vPeg2: TPegInfo;
  241. i, iPos: Integer;
  242. begin
  243. vToReg := TPerlRegEx.Create;
  244. vToReg.RegEx := FToRegStr;
  245. if FPegList.Count > 0 then
  246. begin
  247. for i := 1 to FPegList.Count - 1 do
  248. begin
  249. iPos := i;
  250. vPeg1 := TPegInfo(FPegList.Items[i - 1]);
  251. vPeg2 := TPegInfo(FPegList.Items[i]);
  252. vToReg.Subject := Copy(FPegStr, vPeg1.FOffSet + vPeg1.FLength, vPeg2.FOffSet - (vPeg1.FOffSet + vPeg1.FLength));
  253. if vToReg.Match then
  254. Break;
  255. end;
  256. for i := 0 to FPegList.Count - 1 do
  257. begin
  258. if i < iPos then
  259. FBeginPegList.Add(FPegList.Items[i])
  260. else
  261. FEndPegList.Add(FPegList.Items[i]);
  262. end;
  263. end;
  264. vToReg.Free;
  265. end;
  266. procedure TPegStrFilter.FilterPeg;
  267. var
  268. vPegReg: TPerlRegEx;
  269. vPegInfo: TPegInfo;
  270. begin
  271. vPegReg := TPerlRegEx.Create;
  272. vPegReg.Subject := PegStr;
  273. vPegReg.RegEx := PegRegStr;
  274. while vPegReg.MatchAgain do
  275. begin
  276. vPegInfo := TPegInfo.Create;
  277. vPegInfo.FPeg := vPegReg.MatchedText;
  278. vPegInfo.FOffset := vPegReg.MatchedOffset;
  279. vPegInfo.FLength := vPegReg.MatchedLength;
  280. FPegList.Add(vPegInfo);
  281. end;
  282. vPegReg.Free;
  283. end;
  284. function TPegStrFilter.GetBeginPeg: string;
  285. begin
  286. Result := MergePeg(FBeginPegList);
  287. end;
  288. function TPegStrFilter.GetEndPeg: string;
  289. begin
  290. if FEndPegList.Count > 0 then
  291. Result := MergePeg(FEndPegList)
  292. else
  293. Result := MergePeg(FBeginPegList);
  294. end;
  295. function TPegStrFilter.GetSubPeg(AIndex: Integer): string;
  296. begin
  297. if (AIndex < 0) or (AIndex >= SubPegCount) then
  298. Result := ''
  299. else
  300. Result := TPegInfo(FPegList.Items[AIndex]).FPeg;
  301. end;
  302. function TPegStrFilter.GetSubPegCount: Integer;
  303. begin
  304. Result := FPegList.Count;
  305. end;
  306. function TPegStrFilter.MergePeg(Pegs: TList): string;
  307. var
  308. i: Integer;
  309. begin
  310. Result := '';
  311. for i := 0 to Pegs.Count - 1 do
  312. begin
  313. if i = 0 then
  314. Result := TPegInfo(Pegs.Items[i]).FPeg
  315. else
  316. Result := Result + '/' + TPegInfo(Pegs.Items[i]).FPeg;
  317. end;
  318. end;
  319. procedure TPegStrFilter.SetPegStr(const Value: string);
  320. begin
  321. FPegStr := Value;
  322. AnalysePeg;
  323. end;
  324. initialization
  325. FPegFilter := nil;
  326. finalization
  327. FPegFilter.Free;
  328. end.