tw34442.pp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. { %norun }
  2. {$mode delphi}
  3. uses
  4. sysutils;
  5. {$define use_inline }
  6. function IndyMin(const AValueOne, AValueTwo: Int32): Int32;
  7. {$IFDEF USE_INLINE}inline;{$ENDIF} overload;
  8. begin
  9. if AValueOne > AValueTwo then begin
  10. Result := AValueTwo;
  11. end else begin
  12. Result := AValueOne;
  13. end;
  14. end;
  15. function IndyMin(const AValueOne, AValueTwo: Int64): Int64;
  16. {$IFDEF USE_INLINE}inline;{$ENDIF} overload;
  17. begin
  18. if AValueOne > AValueTwo then begin
  19. Result := AValueTwo;
  20. end else begin
  21. Result := AValueOne;
  22. end;
  23. end;
  24. function IndyMin(const AValueOne, AValueTwo: UInt16): UInt16;
  25. {$IFDEF USE_INLINE}inline;{$ENDIF} overload;
  26. begin
  27. if AValueOne > AValueTwo then begin
  28. Result := AValueTwo;
  29. end else begin
  30. Result := AValueOne;
  31. end;
  32. end;
  33. function IndyMax(const AValueOne, AValueTwo: Int64): Int64;
  34. {$IFDEF USE_INLINE}inline;{$ENDIF} overload;
  35. begin
  36. if AValueOne < AValueTwo then begin
  37. Result := AValueTwo;
  38. end else begin
  39. Result := AValueOne;
  40. end;
  41. end;
  42. function IndyMax(const AValueOne, AValueTwo: Int32): Int32;
  43. {$IFDEF USE_INLINE}inline;{$ENDIF} overload;
  44. begin
  45. if AValueOne < AValueTwo then begin
  46. Result := AValueTwo;
  47. end else begin
  48. Result := AValueOne;
  49. end;
  50. end;
  51. function IndyMax(const AValueOne, AValueTwo: UInt16): UInt16;
  52. {$IFDEF USE_INLINE}inline;{$ENDIF} overload;
  53. begin
  54. if AValueOne < AValueTwo then begin
  55. Result := AValueTwo;
  56. end else begin
  57. Result := AValueOne;
  58. end;
  59. end;
  60. function IndyLength(const ABuffer: String; const ALength: Integer = -1; const AIndex: Integer = 1): Integer;
  61. {$IFDEF USE_INLINE}inline;{$ENDIF}
  62. var
  63. LAvailable: Integer;
  64. begin
  65. Assert(AIndex >= 1);
  66. LAvailable := IndyMax(Length(ABuffer)-AIndex+1, 0);
  67. if ALength < 0 then begin
  68. Result := LAvailable;
  69. end else begin
  70. Result := IndyMin(LAvailable, ALength);
  71. end;
  72. end;
  73. function CharEquals(const AString: string; const ACharPos: Integer; const AValue: Char): Boolean;
  74. {$IFDEF USE_INLINE}inline;{$ENDIF}
  75. begin
  76. if ACharPos < 1 then begin
  77. raise Exception.Create('Invalid ACharPos');{ do not localize }
  78. end;
  79. Result := ACharPos <= Length(AString);
  80. if Result then begin
  81. Result := AString[ACharPos] = AValue;
  82. end;
  83. end;
  84. {$HINTS OFF}
  85. function IsNumeric(const AString: string): Boolean; overload;
  86. var
  87. LCode: Integer;
  88. LVoid: Int64;
  89. begin
  90. Val(AString, LVoid, LCode);
  91. Result := LCode = 0;
  92. end;
  93. {$HINTS ON}
  94. function IsNumeric(const AString: string; const ALength: Integer; const AIndex: Integer = 1): Boolean; overload;
  95. var
  96. I: Integer;
  97. LLen: Integer;
  98. begin
  99. Result := False;
  100. LLen := IndyLength(AString, ALength, AIndex);
  101. if LLen > 0 then begin
  102. for I := 0 to LLen-1 do begin
  103. if not IsNumeric(AString[AIndex+i]) then begin
  104. Exit;
  105. end;
  106. end;
  107. Result := True;
  108. end;
  109. end;
  110. function IsNumeric(const AChar: Char): Boolean; overload;
  111. {$IFDEF USE_INLINE}inline;{$ENDIF}
  112. begin
  113. // TODO: under XE3.5+, use TCharHelper.IsDigit() instead
  114. // TODO: under D2009+, use TCharacter.IsDigit() instead
  115. // Do not use IsCharAlpha or IsCharAlphaNumeric - they are Win32 routines
  116. Result := (AChar >= '0') and (AChar <= '9'); {Do not Localize}
  117. end;
  118. function StripNo(const AData : String): String; inline;
  119. var
  120. i : Integer;
  121. LPos : Integer;
  122. begin
  123. LPos := 1;
  124. for i := 1 to Length(AData) do begin
  125. LPos := i;
  126. if (not IsNumeric(AData[i])) and (not CharEquals(AData, i, ',')) then begin
  127. Break;
  128. end;
  129. end;
  130. Result := Copy(AData, LPos, Length(AData));
  131. end;
  132. function TextStartsWith(const S, SubS: string): Boolean;
  133. var
  134. LLen: Integer;
  135. {$IFDEF WINDOWS}
  136. {$IFDEF COMPARE_STRING_MISMATCH}
  137. LS, LSubS: {$IFDEF WINCE}TIdUnicodeString{$ELSE}TIdPlatformString{$ENDIF};
  138. P1, P2: {$IFDEF WINCE}PIdWideChar{$ELSE}PIdPlatformChar{$ENDIF};
  139. {$ENDIF}
  140. {$ENDIF}
  141. begin
  142. LLen := Length(SubS);
  143. Result := LLen <= Length(S);
  144. if Result then
  145. begin
  146. {$IFDEF DOTNET}
  147. Result := System.String.Compare(S, 0, SubS, 0, LLen, True) = 0;
  148. {$ELSE}
  149. {$IFDEF WINDOWS}
  150. {$IFDEF COMPARE_STRING_MISMATCH}
  151. // explicit convert to Ansi/Unicode
  152. LS := {$IFDEF WINCE}TIdUnicodeString{$ELSE}TIdPlatformString{$ENDIF}(S);
  153. LSubS := {$IFDEF WINCE}TIdUnicodeString{$ELSE}TIdPlatformString{$ENDIF}(SubS);
  154. LLen := Length(LSubS);
  155. Result := LLen <= Length(LS);
  156. if Result then begin
  157. P1 := {$IFDEF WINCE}PIdWideChar{$ELSE}PIdPlatformChar{$ENDIF}(LS);
  158. P2 := {$IFDEF WINCE}PIdWideChar{$ELSE}PIdPlatformChar{$ENDIF}(LSubS);
  159. Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, P1, LLen, P2, LLen) = 2;
  160. end;
  161. {$ELSE}
  162. Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S), LLen, PChar(SubS), LLen) = 2;
  163. {$ENDIF}
  164. {$ELSE}
  165. Result := AnsiCompareText(Copy(S, 1, LLen), SubS) = 0;
  166. {$ENDIF}
  167. {$ENDIF}
  168. end;
  169. end;
  170. procedure IdDelete(var s: string; AOffset, ACount: Integer);
  171. {$IFDEF USE_INLINE}inline;{$ENDIF}
  172. begin
  173. Delete(s, AOffset, ACount);
  174. end;
  175. function TextEndsWith(const S, SubS: string): Boolean;
  176. var
  177. LLen: Integer;
  178. {$IFDEF WINDOWS}
  179. {$IFDEF COMPARE_STRING_MISMATCH}
  180. LS, LSubS: {$IFDEF WINCE}TIdUnicodeString{$ELSE}TIdPlatformString{$ENDIF};
  181. P1, P2: {$IFDEF WINCE}PIdWideChar{$ELSE}PIdPlatformChar{$ENDIF};
  182. {$ELSE}
  183. P: PChar;
  184. {$ENDIF}
  185. {$ENDIF}
  186. begin
  187. LLen := Length(SubS);
  188. Result := LLen <= Length(S);
  189. if Result then
  190. begin
  191. {$IFDEF DOTNET}
  192. Result := System.String.Compare(S, Length(S)-LLen, SubS, 0, LLen, True) = 0;
  193. {$ELSE}
  194. {$IFDEF WINDOWS}
  195. {$IFDEF COMPARE_STRING_MISMATCH}
  196. // explicit convert to Ansi/Unicode
  197. LS := {$IFDEF WINCE}TIdUnicodeString{$ELSE}TIdPlatformString{$ENDIF}(S);
  198. LSubS := {$IFDEF WINCE}TIdUnicodeString{$ELSE}TIdPlatformString{$ENDIF}(SubS);
  199. LLen := Length(LSubS);
  200. Result := LLen <= Length(S);
  201. if Result then begin
  202. P1 := {$IFDEF WINCE}PIdWideChar{$ELSE}PIdPlatformChar{$ENDIF}(LS);
  203. P2 := {$IFDEF WINCE}PIdWideChar{$ELSE}PIdPlatformChar{$ENDIF}(LSubS);
  204. Inc(P1, Length(LS)-LLen);
  205. Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, P1, LLen, P2, LLen) = 2;
  206. end;
  207. {$ELSE}
  208. P := PChar(S);
  209. Inc(P, Length(S)-LLen);
  210. Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, P, LLen, PChar(SubS), LLen) = 2;
  211. {$ENDIF}
  212. {$ELSE}
  213. Result := AnsiCompareText(Copy(S, Length(S)-LLen+1, LLen), SubS) = 0;
  214. {$ENDIF}
  215. {$ENDIF}
  216. end;
  217. end;
  218. const
  219. IdFetchDelimDefault = ' '; {Do not Localize}
  220. IdFetchDeleteDefault = True;
  221. IdFetchCaseSensitiveDefault = True;
  222. function FetchCaseInsensitive(var AInput: string; const ADelim: string;
  223. const ADelete: Boolean): string;
  224. {$IFDEF USE_INLINE}inline;{$ENDIF}
  225. var
  226. LPos: Integer;
  227. begin
  228. if ADelim = #0 then begin
  229. // AnsiPos does not work with #0
  230. LPos := Pos(ADelim, AInput);
  231. end else begin
  232. //? may be AnsiUpperCase?
  233. LPos := Pos(UpperCase(ADelim), UpperCase(AInput));
  234. end;
  235. if LPos = 0 then begin
  236. Result := AInput;
  237. if ADelete then begin
  238. AInput := ''; {Do not Localize}
  239. end;
  240. end else begin
  241. Result := Copy(AInput, 1, LPos - 1);
  242. if ADelete then begin
  243. //faster than Delete(AInput, 1, LPos + Length(ADelim) - 1); because the
  244. //remaining part is larger than the deleted
  245. AInput := Copy(AInput, LPos + Length(ADelim), MaxInt);
  246. end;
  247. end;
  248. end;
  249. function Fetch(var AInput: string; const ADelim: string = IdFetchDelimDefault;
  250. const ADelete: Boolean = IdFetchDeleteDefault;
  251. const ACaseSensitive: Boolean = IdFetchCaseSensitiveDefault): string;
  252. {$IFDEF USE_INLINE}inline;{$ENDIF}
  253. var
  254. LPos: Integer;
  255. begin
  256. if ACaseSensitive then begin
  257. if ADelim = #0 then begin
  258. // AnsiPos does not work with #0
  259. LPos := Pos(ADelim, AInput);
  260. end else begin
  261. LPos := Pos(ADelim, AInput);
  262. end;
  263. if LPos = 0 then begin
  264. Result := AInput;
  265. if ADelete then begin
  266. AInput := ''; {Do not Localize}
  267. end;
  268. end
  269. else begin
  270. Result := Copy(AInput, 1, LPos - 1);
  271. if ADelete then begin
  272. //slower Delete(AInput, 1, LPos + Length(ADelim) - 1); because the
  273. //remaining part is larger than the deleted
  274. AInput := Copy(AInput, LPos + Length(ADelim), MaxInt);
  275. end;
  276. end;
  277. end else begin
  278. Result := FetchCaseInsensitive(AInput, ADelim, ADelete);
  279. end;
  280. end;
  281. function ExtractRecFormat(const ARecFM : String): String;
  282. {$IFDEF USE_INLINE} inline; {$ENDIF}
  283. begin
  284. Result := ARecFM;
  285. if TextStartsWith(Result, '<') then begin
  286. IdDelete(Result, 1, 1);
  287. end;
  288. if TextEndsWith(Result, '>') then begin
  289. Result := Fetch(Result, '>');
  290. end;
  291. end;
  292. procedure test;
  293. var
  294. LTmp: string;
  295. s: string;
  296. begin
  297. LTmp:='ac';
  298. s:=ExtractRecFormat(StripNo(LTmp));
  299. end;
  300. begin
  301. end.