parseutils.pas 5.8 KB

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