parseutils.pas 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. unit parseutils;
  2. {$ifdef fpc}{$mode delphi}{$h+}{$endif}
  3. interface
  4. uses
  5. Classes, SysUtils;
  6. type
  7. TCharSet = set of Char;
  8. const
  9. EoLnChars = [#10,#13];
  10. SpaceChars = [#32,#9];
  11. InvsChars = [#0..#32];
  12. WhiteSpaceChars = SpaceChars;
  13. SpaceEolnChars = EoLnChars+SpaceChars;
  14. NumericChars = ['0'..'9'];
  15. AlphabetChars = ['a'..'z','A'..'Z'];
  16. AlphaNumChars = AlphabetChars+NumericChars;
  17. function ScanWhile(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
  18. function ScanTo(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
  19. function SkipToEoln(const s: AnsiString; var index: Integer): AnsiString;
  20. function ScanToSubstr(const s: AnsiString; var index: Integer; const substr: string): AnsiString;
  21. // returns #10, #13, #10#13 or #13#10, if s[index] is end-of-line sequence
  22. // otherwise returns empty string
  23. function EolnStr(const s: AnsiString; index: Integer): String;
  24. function IsSubStr(const sbs, s: AnsiString; index: Integer): Boolean;
  25. // todo: not used?
  26. function SkipCommentBlock(const s: AnsiString; var index: Integer; const closecmt: AnsiString): AnsiString;
  27. function SkipLine(const s: AnsiString; var index: Integer): AnsiString;
  28. procedure OffsetToLinePos(const t: AnsiString; Offset: Integer; var P: TPoint);
  29. procedure ParseCSSValues(const s: String; css: TStrings);
  30. procedure GetCssAbsBoundsRect(Css: TStrings; var r: TRect);
  31. function CssValInt(const s: String; Def: integer): Integer;
  32. implementation
  33. function CssValInt(const s: String; Def: integer): Integer;
  34. var
  35. i : integer;
  36. n : String;
  37. err : Integer;
  38. begin
  39. i:=1;
  40. n:=ScanWhile(s, i, ['+','-']+NumericChars);
  41. Val(n, Result, err);
  42. if err<>0 then Result:=Def;
  43. end;
  44. procedure GetCssAbsBoundsRect(Css: TStrings; var r: TRect);
  45. begin
  46. r.Left:=CssValInt(Css.Values['LEFT'], 0);
  47. r.Top:=CssValInt(Css.Values['top'], 0);
  48. r.Right:=r.Left+CssValInt(Css.Values['width'], 0);
  49. r.Bottom:=r.Top+CssValInt(Css.Values['height'], 0);
  50. end;
  51. procedure ParseCSSValues(const s: String; css: TStrings);
  52. var
  53. i : integer;
  54. n : String;
  55. v : String;
  56. begin
  57. i:=1;
  58. if (s='') or not Assigned(css) then Exit;
  59. while (i<=length(s)) do begin
  60. ScanTo(s, i, AlphaNumChars);
  61. n:=ScanWhile(s, i, AlphaNumChars+['_']);
  62. ScanTo(s, i, [':']);
  63. inc(i);
  64. ScanWhile(s, i, SpaceEolnChars);
  65. v:=ScanTo(s, i, [';']);
  66. css.Values[n]:=v;
  67. end;
  68. end;
  69. function ScanWhile(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
  70. var
  71. i : Integer;
  72. begin
  73. Result := '';
  74. if (index <= 0) or (index > length(s)) then Exit;
  75. for i := index to length(s) do
  76. if not (s[i] in ch) then begin
  77. if i = index then Result := ''
  78. else Result := Copy(s, index, i - index);
  79. index := i;
  80. Exit;
  81. end;
  82. Result := Copy(s, index, length(s) - index + 1);
  83. index := length(s) + 1;
  84. end;
  85. function ScanTo(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
  86. var
  87. i : Integer;
  88. begin
  89. Result := '';
  90. if (index <= 0) or (index > length(s)) then Exit;
  91. for i := index to length(s) do
  92. if (s[i] in ch) then begin
  93. if i = index then Result := ''
  94. else Result := Copy(s, index, i - index);
  95. index := i;
  96. Exit;
  97. end;
  98. Result := Copy(s, index, length(s) - index + 1);
  99. index := length(s) + 1;
  100. end;
  101. function EolnStr(const s: AnsiString; index: Integer): String;
  102. begin
  103. if (index<=0) or (index>length(s)) or (not (s[index] in EoLnChars)) then
  104. Result:=''
  105. else begin
  106. if (index<length(s)) and (s[index+1] in EolnChars) and (s[index]<>s[index+1]) then
  107. Result:=Copy(s, index, 2)
  108. else
  109. Result:=s[index];
  110. end;
  111. end;
  112. function SkipToEoln(const s: AnsiString; var index: Integer): AnsiString;
  113. begin
  114. Result := ScanTo(s, index, EoLnChars);
  115. end;
  116. function IsSubStr(const sbs, s: AnsiString; index: Integer): Boolean;
  117. var
  118. i : Integer;
  119. j : Integer;
  120. begin
  121. Result := false;
  122. if (sbs = '') or (length(sbs) > length(s) - index) then Exit;
  123. j := index;
  124. for i := 1 to length(sbs) do begin
  125. if sbs[i] <> s[j] then Exit;
  126. inc(j);
  127. end;
  128. Result := true;
  129. end;
  130. function SkipCommentBlock(const s: AnsiString; var index: Integer; const closecmt: AnsiString): AnsiString;
  131. begin
  132. Result := '';
  133. if closecmt = '' then begin
  134. index := length(s) + 1;
  135. Exit;
  136. end;
  137. while index <= length(s) do begin
  138. Result := Result + ScanTo(s, index, [closecmt[1]]+EoLnChars);
  139. //if (index<=length(s)) and (s in EoLnChars(
  140. if IsSubStr(closecmt, s, index) then begin
  141. inc(index, length(closecmt));
  142. Exit;
  143. end else begin
  144. Result := Result + s[index];
  145. inc(index);
  146. end;
  147. end;
  148. end;
  149. function SkipLine(const s: AnsiString; var index: Integer): AnsiString;
  150. begin
  151. Result:=ScanTo(s, index, EoLnChars);
  152. if (index<length(s)) and (s[index+1] in EoLnChars) and (s[index]<>s[index+1]) then
  153. inc(index);
  154. inc(index);
  155. end;
  156. procedure OffsetToLinePos(const t: AnsiString; Offset: Integer; var P: TPoint);
  157. var
  158. i, le : Integer;
  159. begin
  160. i := 1;
  161. le := 0;
  162. P.X := 0;
  163. P.Y := 0;
  164. while i < Offset do begin
  165. Inc(P.Y);
  166. le := i;
  167. SkipLine(t, i);
  168. end;
  169. P.X := Offset - le + 1;
  170. end;
  171. function isSubStrMatch(const s: AnsiString; index: integer; const substr: string): Boolean;
  172. var
  173. i : integer;
  174. j : integer;
  175. begin
  176. j:=index;
  177. Result:=false;
  178. for i:=1 to length(substr) do begin
  179. if s[j]<>substr[i] then Exit;
  180. inc(j);
  181. end;
  182. Result:=true;
  183. end;
  184. function ScanToSubstr(const s: AnsiString; var index: Integer; const substr: string): AnsiString;
  185. var
  186. i: integer;
  187. begin
  188. if substr='' then begin
  189. Result:='';
  190. Exit;
  191. end;
  192. i:=index;
  193. while (index<=length(s)) do begin
  194. ScanTo(s, index, [substr[1]]);
  195. if isSubStrMatch(s, index, substr) then begin
  196. inc(index, length(substr));
  197. Break;
  198. end else
  199. inc(index);
  200. end;
  201. Result:=Copy(s, i, index-i);
  202. end;
  203. end.