mPegFilter.pas 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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. end;
  207. { TPegStrFilter }
  208. procedure TPegStrFilter.AnalysePeg;
  209. begin
  210. ClearHistory;
  211. FilterPeg;
  212. FilterBeginAndEnd;
  213. end;
  214. procedure TPegStrFilter.ClearHistory;
  215. begin
  216. ClearObjects(FPegList);
  217. FPegList.Clear;
  218. FBeginPegList.Clear;
  219. FEndPegList.Clear;
  220. end;
  221. constructor TPegStrFilter.Create;
  222. begin
  223. FPegRegStr := '[a-zA-z]{0,2}[kK]\d+[++][0-9.]+';
  224. FToRegStr := '[--~~]';
  225. FPegList := TList.Create;
  226. FBeginPegList := TList.Create;
  227. FEndPegList := TList.Create;
  228. end;
  229. destructor TPegStrFilter.Destory;
  230. begin
  231. FEndPegList.Free;
  232. FBeginPegList.Free;
  233. ClearObjects(FPegList);
  234. FPegList.Free;
  235. end;
  236. procedure TPegStrFilter.FilterBeginAndEnd;
  237. var
  238. vToReg: TPerlRegEx;
  239. vPeg1, vPeg2: TPegInfo;
  240. i, iPos: Integer;
  241. begin
  242. vToReg := TPerlRegEx.Create;
  243. vToReg.RegEx := FToRegStr;
  244. if FPegList.Count > 0 then
  245. begin
  246. for i := 1 to FPegList.Count - 1 do
  247. begin
  248. iPos := i;
  249. vPeg1 := TPegInfo(FPegList.Items[i - 1]);
  250. vPeg2 := TPegInfo(FPegList.Items[i]);
  251. vToReg.Subject := Copy(FPegStr, vPeg1.FOffSet + vPeg1.FLength, vPeg2.FOffSet - (vPeg1.FOffSet + vPeg1.FLength));
  252. if vToReg.Match then
  253. Break;
  254. end;
  255. for i := 0 to FPegList.Count - 1 do
  256. begin
  257. if i < iPos then
  258. FBeginPegList.Add(FPegList.Items[i])
  259. else
  260. FEndPegList.Add(FPegList.Items[i]);
  261. end;
  262. end;
  263. vToReg.Free;
  264. end;
  265. procedure TPegStrFilter.FilterPeg;
  266. var
  267. vPegReg: TPerlRegEx;
  268. vPegInfo: TPegInfo;
  269. begin
  270. vPegReg := TPerlRegEx.Create;
  271. vPegReg.Subject := PegStr;
  272. vPegReg.RegEx := PegRegStr;
  273. while vPegReg.MatchAgain do
  274. begin
  275. vPegInfo := TPegInfo.Create;
  276. vPegInfo.FPeg := vPegReg.MatchedText;
  277. vPegInfo.FOffset := vPegReg.MatchedOffset;
  278. vPegInfo.FLength := vPegReg.MatchedLength;
  279. FPegList.Add(vPegInfo);
  280. end;
  281. vPegReg.Free;
  282. end;
  283. function TPegStrFilter.GetBeginPeg: string;
  284. begin
  285. Result := MergePeg(FBeginPegList);
  286. end;
  287. function TPegStrFilter.GetEndPeg: string;
  288. begin
  289. if FEndPegList.Count > 0 then
  290. Result := MergePeg(FEndPegList)
  291. else
  292. Result := MergePeg(FBeginPegList);
  293. end;
  294. function TPegStrFilter.GetSubPeg(AIndex: Integer): string;
  295. begin
  296. if (AIndex < 0) or (AIndex >= SubPegCount) then
  297. Result := ''
  298. else
  299. Result := TPegInfo(FPegList.Items[AIndex]).FPeg;
  300. end;
  301. function TPegStrFilter.GetSubPegCount: Integer;
  302. begin
  303. Result := FPegList.Count;
  304. end;
  305. function TPegStrFilter.MergePeg(Pegs: TList): string;
  306. var
  307. i: Integer;
  308. begin
  309. Result := '';
  310. for i := 0 to Pegs.Count - 1 do
  311. begin
  312. if i = 0 then
  313. Result := TPegInfo(Pegs.Items[i]).FPeg
  314. else
  315. Result := Result + '/' + TPegInfo(Pegs.Items[i]).FPeg;
  316. end;
  317. end;
  318. procedure TPegStrFilter.SetPegStr(const Value: string);
  319. begin
  320. FPegStr := Value;
  321. AnalysePeg;
  322. end;
  323. initialization
  324. FPegFilter := nil;
  325. finalization
  326. FPegFilter.Free;
  327. end.