fptemplate.pp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. {
  2. $Id: header,v 1.1 2000/07/13 06:33:45 michael Exp $
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$H+}
  13. {$define NOCONTNRS}
  14. {$IFNDEF FPC_DOTTEDUNITS}
  15. unit fpTemplate;
  16. {$ENDIF FPC_DOTTEDUNITS}
  17. interface
  18. {$IFDEF FPC_DOTTEDUNITS}
  19. uses
  20. System.SysUtils,
  21. System.Classes;
  22. {$ELSE FPC_DOTTEDUNITS}
  23. uses
  24. SysUtils,
  25. Classes;
  26. {$ENDIF FPC_DOTTEDUNITS}
  27. Const
  28. DefaultParseDepth = 100;
  29. MaxDelimLength = 5;
  30. Type
  31. TParseDelimiter = String[MaxDelimLength];
  32. Var
  33. DefaultStartDelimiter : TParseDelimiter = '{'; //Template tag start |If you want Delphi-like, set it to '<#'
  34. DefaultEndDelimiter : TParseDelimiter = '}'; //Template tag end | '>'
  35. DefaultParamStartDelimiter : TParseDelimiter = '[-'; //Tag parameter start | ' '
  36. DefaultParamEndDelimiter : TParseDelimiter = '-]'; //Tag parameter end | '"'
  37. DefaultParamValueSeparator : TParseDelimiter = '='; //Tag parameter name/value separator | '="'
  38. // |for tags like <#TagName paramname1="paramvalue1" paramname2="paramvalue2">
  39. Type
  40. TGetParamEvent = Procedure(Sender : TObject; Const ParamName : String; Out AValue : String) Of Object; //for simple template tag support only (ex: {Name})
  41. TReplaceTagEvent = Procedure(Sender : TObject; Const TagString : String; TagParams:TStringList; Out ReplaceText : String) Of Object;//for tags with parameters support
  42. { TTemplateParser }
  43. TTemplateParser = Class(TObject)
  44. Private
  45. FParseLevel : Integer;
  46. FMaxParseDepth : Integer;
  47. FEndDelimiter: TParseDelimiter;
  48. FStartDelimiter: TParseDelimiter;
  49. FParamStartDelimiter: TParseDelimiter;
  50. FParamEndDelimiter: TParseDelimiter;
  51. FParamValueSeparator: TParseDelimiter;
  52. FAllowTagParams: Boolean; //default is false -> simple template tags allowed only [FValues, FOnGetParam (optional) used];
  53. //if true -> template tags with parameters allowed, [FOnReplaceTag] is used for all tag replacements
  54. FRecursive: Boolean; //when only simple tags are used in a template (AllowTagParams=false), the replacement can
  55. FValues : TStringList; //contain further tags for recursive processing (only used when no tag params are allowed)
  56. FOnGetParam: TGetParamEvent; //Event handler to use for templates containing simple tags only (ex: {Name})
  57. FOnReplaceTag: TReplaceTagEvent; //Event handler to use for templates containing tags with parameters (ex: <#TagName paramname1="paramvalue1" paramname2="paramvalue2">)
  58. function GetDelimiter(Index: integer): TParseDelimiter;
  59. function GetNameByIndex(index : Integer): String;
  60. function GetValue(const Key : String): String;
  61. function GetValueByIndex(index : Integer): String;
  62. function GetValueCount: Integer;
  63. procedure SetDelimiter(Index: integer; const AValue: TParseDelimiter);
  64. procedure SetValue(const Key : String; const AValue: String);
  65. Function IntParseString(const Src : String) : String;
  66. Public
  67. Constructor Create;
  68. Destructor Destroy; override;
  69. Procedure Clear;
  70. Function ReplaceTag(const Key: String; TagParams:TStringList; out ReplaceWith: String): Boolean;//used only when AllowTagParams = true
  71. Function GetParam(Const Key : String; Out AValue : String) : Boolean; //used only when AllowTagParams = false
  72. Procedure GetTagParams(var TagName:String; var TagParams : TStringList) ;
  73. Function ParseString(const Src : String) : String;
  74. Function ParseStream(Src : TStream; Dest : TStream) : Integer; // Wrapper, Returns number of bytes written.
  75. Procedure ParseStrings(Src : TStrings; Dest : TStrings) ; // Wrapper
  76. Procedure ParseFiles(Const Src,Dest : String);
  77. Property OnGetParam : TGetParamEvent Read FOnGetParam Write FOnGetParam; // Called if not found in values //used only when AllowTagParams = false
  78. Property OnReplaceTag : TReplaceTagEvent Read FOnReplaceTag Write FOnReplaceTag; // Called if a tag found //used only when AllowTagParams = true
  79. Property StartDelimiter : TParseDelimiter Index 1 Read GetDelimiter Write SetDelimiter;// Start char/string, default '}'
  80. Property EndDelimiter : TParseDelimiter Index 2 Read GetDelimiter Write SetDelimiter; // end char/string, default '{'
  81. Property ParamStartDelimiter : TParseDelimiter Index 3 Read GetDelimiter Write SetDelimiter;
  82. Property ParamEndDelimiter : TParseDelimiter Index 4 Read GetDelimiter Write SetDelimiter;
  83. Property ParamValueSeparator : TParseDelimiter Index 5 Read GetDelimiter Write SetDelimiter;
  84. Property Values[Key : String] : String Read GetValue Write SetValue; // Contains static values. //used only when AllowTagParams = false
  85. Property ValuesByIndex[index : Integer] : String Read GetValueByIndex; // Contains static values. //used only when AllowTagParams = false
  86. Property NamesByIndex[index : Integer] : String Read GetNameByIndex; // Contains static values. //used only when AllowTagParams = false
  87. Property ValueCount: Integer Read GetValueCount; //used only when AllowTagParams = false
  88. Property Recursive : Boolean Read FRecursive Write FRecursive; //used only when AllowTagParams = false
  89. Property AllowTagParams : Boolean Read FAllowTagParams Write FAllowTagParams;
  90. end;
  91. { TFPCustomTemplate }
  92. TFPCustomTemplate = Class(TPersistent)
  93. private
  94. FEndDelimiter: TParseDelimiter;
  95. FStartDelimiter: TParseDelimiter;
  96. FParamStartDelimiter: TParseDelimiter;
  97. FParamEndDelimiter: TParseDelimiter;
  98. FParamValueSeparator: TParseDelimiter;
  99. FFileName: String;
  100. FTemplate: String;
  101. FOnGetParam: TGetParamEvent; //used only when AllowTagParams = false
  102. FOnReplaceTag: TReplaceTagEvent; //used only when AllowTagParams = true
  103. FAllowTagParams: Boolean;
  104. Protected
  105. Procedure GetParam(Sender : TObject; Const ParamName : String; Out AValue : String);virtual; //used only when AllowTagParams = false
  106. Procedure ReplaceTag(Sender : TObject; Const TagName: String; TagParams:TStringList; Out AValue: String);virtual; //used only when AllowTagParams = true
  107. Function CreateParser : TTemplateParser; virtual;
  108. Public
  109. Function HasContent : Boolean;
  110. Function GetContent : String;
  111. Procedure Assign(Source : TPersistent); override;
  112. Property StartDelimiter : TParseDelimiter Read FStartDelimiter Write FStartDelimiter;
  113. Property EndDelimiter : TParseDelimiter Read FEndDelimiter Write FEndDelimiter;
  114. Property ParamStartDelimiter : TParseDelimiter Read FParamStartDelimiter Write FParamStartDelimiter;
  115. Property ParamEndDelimiter : TParseDelimiter Read FParamEndDelimiter Write FParamEndDelimiter;
  116. Property ParamValueSeparator : TParseDelimiter Read FParamValueSeparator Write FParamValueSeparator;
  117. Property FileName : String Read FFileName Write FFileName;
  118. Property Template : String Read FTemplate Write FTemplate;
  119. Property OnGetParam : TGetParamEvent Read FOnGetParam Write FOnGetParam;
  120. Property OnReplaceTag : TReplaceTagEvent Read FOnReplaceTag Write FOnReplaceTag;
  121. Property AllowTagParams : Boolean Read FAllowTagParams Write FAllowTagParams;
  122. end;
  123. TFPTemplate = Class(TFPCustomTemplate)
  124. Published
  125. Property FileName;
  126. Property Template;
  127. Property AllowTagParams;
  128. Property OnReplaceTag;
  129. Property StartDelimiter;
  130. Property EndDelimiter;
  131. Property ParamStartDelimiter;
  132. Property ParamEndDelimiter;
  133. Property ParamValueSeparator;
  134. Property OnGetParam;
  135. end;
  136. ETemplateParser = Class(Exception);
  137. Var
  138. MaxParseDepth : Integer = DefaultParseDepth;
  139. implementation
  140. Resourcestring
  141. SErrParseDepthExceeded = 'Maximum parse level (%d) exceeded.';
  142. SErrNoEmptyDelimiters = 'Delimiters cannot be empty';
  143. { TTemplateParser }
  144. Type
  145. { TStringItem }
  146. TStringItem = Class(TObject)
  147. Private
  148. FValue : String;
  149. Public
  150. Constructor Create(const AValue : String);
  151. Property Value : String Read FValue Write FValue;
  152. end;
  153. { TStringItem }
  154. constructor TStringItem.Create(const AValue: String);
  155. begin
  156. FValue:=AValue;
  157. end;
  158. { TTemplateParser }
  159. function TTemplateParser.GetValue(const Key : String): String;
  160. Var
  161. I : Integer;
  162. begin
  163. Result:='';
  164. If Assigned(FValues) then
  165. begin
  166. I:=FValues.IndexOf(Key);
  167. If (I<>-1) then
  168. Result:=TStringItem(FValues.Objects[i]).Value;
  169. end;
  170. end;
  171. function TTemplateParser.GetValueByIndex(index : Integer): String;
  172. begin
  173. Result:='';
  174. If Assigned(FValues) then
  175. Result:=TStringItem(FValues.Objects[index]).Value;
  176. end;
  177. function TTemplateParser.GetValueCount: Integer;
  178. begin
  179. if assigned(FValues) then
  180. result := FValues.Count
  181. else
  182. result := 0;
  183. end;
  184. function TTemplateParser.GetDelimiter(Index: integer): TParseDelimiter;
  185. begin
  186. case Index of
  187. 1: Result:=FStartDelimiter;
  188. 2: Result:=FEndDelimiter;
  189. 3: Result:=FParamStartDelimiter;
  190. 4: Result:=FParamEndDelimiter;
  191. else
  192. Result:=FParamValueSeparator;
  193. end;
  194. end;
  195. function TTemplateParser.GetNameByIndex(index : Integer): String;
  196. begin
  197. Result:='';
  198. If Assigned(FValues) then
  199. Result:=FValues.ValueFromIndex[index];
  200. end;
  201. procedure TTemplateParser.SetDelimiter(Index: integer;
  202. const AValue: TParseDelimiter);
  203. begin
  204. If Length(AValue)=0 then
  205. Raise ETemplateParser.Create(SErrNoEmptyDelimiters);
  206. case Index of
  207. 1: FStartDelimiter:=AValue;
  208. 2: FEndDelimiter:=AValue;
  209. 3: FParamStartDelimiter:=AValue;
  210. 4: FParamEndDelimiter:=AValue;
  211. else
  212. FParamValueSeparator:=AValue;
  213. end;
  214. end;
  215. procedure TTemplateParser.SetValue(const Key : String; const AValue: String);
  216. Var
  217. I : Integer;
  218. begin
  219. If (AValue='') then
  220. begin
  221. If Assigned(FValues) then
  222. begin
  223. I:=FValues.IndexOf(Key);
  224. If (I<>-1) then
  225. begin
  226. FValues.Objects[i].Free;
  227. FValues.Delete(I);
  228. end;
  229. end;
  230. end
  231. else
  232. begin
  233. if Not Assigned(FValues) then
  234. begin
  235. FVAlues:=TStringList.Create;
  236. FValues.Sorted:=True;
  237. end;
  238. I:=FValues.IndexOf(Key);
  239. If (I=-1) then
  240. FValues.AddObject(Key,TStringItem.Create(AValue))
  241. else
  242. TStringItem(FValues.Objects[I]).Value:=AValue;
  243. end;
  244. end;
  245. constructor TTemplateParser.Create;
  246. begin
  247. FParseLevel:=0;
  248. FMaxParseDepth:=MaxParseDepth;
  249. FStartDelimiter:=DefaultStartDelimiter;
  250. FEndDelimiter:=DefaultEndDelimiter;
  251. FParamStartDelimiter:=DefaultParamStartDelimiter;
  252. FParamEndDelimiter:=DefaultParamEndDelimiter;
  253. FParamValueSeparator:=DefaultParamValueSeparator;
  254. FAllowTagParams := false;
  255. end;
  256. destructor TTemplateParser.Destroy;
  257. begin
  258. Clear;
  259. inherited Destroy;
  260. end;
  261. procedure TTemplateParser.Clear;
  262. Var
  263. I : Integer;
  264. begin
  265. If Assigned(FValues) then
  266. For I:=0 to FValues.Count-1 do
  267. FValues.Objects[i].Free;
  268. FreeAndNil(FValues);
  269. end;
  270. function TTemplateParser.GetParam(const Key: String; out AValue: String): Boolean;
  271. Var
  272. I : Integer;
  273. begin
  274. If Assigned(FValues) then
  275. I:=FValues.IndexOf(Key)
  276. else
  277. I:=-1;
  278. Result:=(I<>-1);
  279. If Result then
  280. AValue:=TStringItem(FValues.Objects[i]).Value
  281. else
  282. begin
  283. Result:=Assigned(FOnGetParam);
  284. If Result then
  285. FOnGetParam(Self,Key,AValue);
  286. end;
  287. If Result and Recursive then
  288. AValue:=IntParseString(AValue);
  289. end;
  290. function TTemplateParser.ReplaceTag(const Key: String; TagParams:TStringList; out ReplaceWith: String): Boolean;
  291. begin
  292. Result:=Assigned(FOnReplaceTag);
  293. If Result then
  294. FOnReplaceTag(Self,Key,TagParams,ReplaceWith);
  295. end;
  296. Function FindDelimiter(SP : PChar; D : TParseDelimiter; MaxLen : Integer) : PChar; Inline;
  297. Var
  298. P,P2 : PChar;
  299. I,DLen : Integer;
  300. begin
  301. Result:=Nil;
  302. DLen:=Length(D);
  303. Dec(MaxLen,(DLen-1));
  304. If MaxLen<=0 then
  305. exit;
  306. P:=SP;
  307. While (Result=Nil) and (P-SP<=MaxLen) do
  308. begin
  309. While (P-SP<=MaxLen) and (P^<>D[1]) do
  310. Inc(P);
  311. If ((P-SP)<=MaxLen) then
  312. begin
  313. Result:=P;
  314. P2:=P+1;
  315. // Check Other characters
  316. I:=2;
  317. While (I<=DLen) and (Result<>Nil) do
  318. If (P2^=D[i]) then
  319. begin
  320. inc(i);
  321. Inc(p2);
  322. end
  323. else
  324. begin
  325. P:=Result;
  326. Result:=Nil;
  327. end;
  328. // Either result<>Nil -> match or result=nil -> no match
  329. inc(P);
  330. end;
  331. end;
  332. end;
  333. Procedure AddToString(Var S : String; P : PChar; NChars : Integer);inline;
  334. Var
  335. SLen : Integer;
  336. begin
  337. if (NChars=0) then Exit;
  338. SLen:=Length(S);
  339. SetLength(S,SLen+NChars);
  340. Move(P^,S[Slen+1],NChars*SizeOf(Char));
  341. end;
  342. procedure TTemplateParser.GetTagParams(var TagName:String; var TagParams : TStringList) ;
  343. var
  344. I,SLen:Integer;
  345. TS,TM,TE,SP,P : PChar;
  346. PName, PValue, TP : String;
  347. IsFirst:Boolean;
  348. begin
  349. SLen:=Length(TagName);
  350. if SLen=0 then exit;
  351. IsFirst := true;
  352. SP:=PChar(TagName);
  353. TP := TagName;
  354. P:=SP;
  355. while (P-SP<SLen) do
  356. begin
  357. TS:=FindDelimiter(P,FParamStartDelimiter,SLen-(P-SP));
  358. if (TS<>Nil) then
  359. begin//Found param start delimiter
  360. if IsFirst then
  361. begin//Get the real Tag name
  362. IsFirst := false;
  363. I := 1;
  364. while not (P[I] in [#0..' ']) do Inc(I);
  365. if i>(TS-SP) then
  366. i := TS-SP;
  367. SetLength(TP, I);
  368. Move(P^, TP[1], I*SizeOf(Char));
  369. end;
  370. inc(TS, Length(FParamStartDelimiter));
  371. I:=TS-P;//index of param name
  372. TM:=FindDelimiter(TS,FParamValueSeparator,SLen-I+1);
  373. if (TM<>Nil) then
  374. begin//Found param value separator
  375. I:=TM-TS;//lenght of param name
  376. SetLength(PName, I);
  377. Move(TS^, PName[1], I*SizeOf(Char));//param name
  378. inc(TS, Length(FParamValueSeparator) + I);
  379. I := TS - P;//index of param value
  380. end;
  381. TE:=FindDelimiter(TS,FParamEndDelimiter, SLen-I+1);
  382. if (TE<>Nil) then
  383. begin//Found param end
  384. I:=TE-TS;//Param length
  385. Setlength(PValue,I);
  386. Move(TS^,PValue[1],I*SizeOf(Char));//Param value
  387. if TM=nil then
  388. TagParams.Add(Trim(PValue))
  389. else
  390. TagParams.Add(Trim(PName) + '=' + PValue);//Param names cannot contain '='
  391. P:=TE+Length(FParamEndDelimiter);
  392. TS:=P;
  393. end else break;
  394. end else break;
  395. end;
  396. TagName := Trim(TP);
  397. end;
  398. function TTemplateParser.ParseString(const Src: String): String;
  399. begin
  400. FParseLevel:=0;
  401. Result:=IntParseString(Src);
  402. end;
  403. function TTemplateParser.IntParseString(const Src: String): String;
  404. Var
  405. PN,PV,ReplaceWith : String;
  406. i,SLen : Integer;
  407. TS,TE,SP,P : PChar;
  408. TagParams:TStringList;
  409. begin
  410. if FAllowTagParams then
  411. begin//template tags with parameters are allowed
  412. SLen:=Length(Src);
  413. Result:='';
  414. If SLen=0 then
  415. exit;
  416. SP:=PChar(Src);
  417. P:=SP;
  418. While (P-SP<SLen) do
  419. begin
  420. TS:=FindDelimiter(P,FStartDelimiter,SLen-(P-SP));
  421. If (TS=Nil) then
  422. begin//Tag Start Delimiter not found
  423. TS:=P;
  424. P:=SP;
  425. Inc(P,SLen);
  426. end
  427. else
  428. begin
  429. I:=TS-P;
  430. inc(TS,Length(FStartDelimiter));//points to first char of Tag name now
  431. TE:=FindDelimiter(TS,FEndDelimiter,SLen-I+1);
  432. If (TE=Nil) then
  433. begin//Tag End Delimiter not found
  434. TS:=P;
  435. P:=SP;
  436. Inc(P,SLen);
  437. end
  438. else//Found start and end delimiters for the Tag
  439. begin
  440. // Add text prior to template tag to result
  441. AddToString(Result,P,I);
  442. // Retrieve the full template tag (only tag name if no params specified)
  443. I:=TE-TS;//full Tag length
  444. Setlength(PN,I);
  445. Move(TS^,PN[1],I*SizeOf(Char));//full Tag string (only tag name if no params specified)
  446. TagParams := TStringList.Create;
  447. try
  448. TagParams.Sorted := True;
  449. GetTagParams(PN, Tagparams);
  450. If ReplaceTag(PN,TagParams,ReplaceWith) then
  451. Result:=Result+ReplaceWith;
  452. finally
  453. TagParams.Free;
  454. end;
  455. P:=TE;
  456. Inc(P,Length(FEndDelimiter));
  457. TS:=P;
  458. end;
  459. end
  460. end;
  461. I:=P-TS;
  462. If (I>0) then
  463. AddToString(Result,TS,I);
  464. end else begin//template tags with parameters are not allowed
  465. Inc(FParseLevel);
  466. If FParseLevel>FMaxParseDepth then
  467. Raise ETemplateParser.CreateFmt(SErrParseDepthExceeded,[FMaxParseDepth]);
  468. SLen:=Length(Src); // Minimum
  469. Result:='';
  470. If SLen=0 then
  471. exit;
  472. // STLen:=Length(FStartDelimiter);
  473. SP:=PChar(Src);
  474. P:=SP;
  475. While (P-SP<SLen) do
  476. begin
  477. TS:=FindDelimiter(P,FStartDelimiter,SLen-(P-SP));
  478. If (TS=Nil) then
  479. begin
  480. TS:=P;
  481. P:=SP;
  482. Inc(P,SLen);
  483. end
  484. else
  485. begin
  486. I:=TS-P;
  487. inc(TS,Length(FStartDelimiter));
  488. TE:=FindDelimiter(TS,FEndDelimiter,SLen-I+1);
  489. If (TE=Nil) then
  490. begin
  491. TS:=P;
  492. P:=SP;
  493. Inc(P,SLen);
  494. end
  495. else
  496. begin
  497. // Add text prior to template to result
  498. AddToString(Result,P,I);
  499. // retrieve template name
  500. I:=TE-TS;
  501. Setlength(PN,I);
  502. Move(TS^,PN[1],I*SizeOf(Char));
  503. If GetParam(PN,PV) then
  504. begin
  505. Result:=Result+PV;
  506. end;
  507. P:=TE+Length(FEndDelimiter);
  508. TS:=P;
  509. end;
  510. end
  511. end;
  512. I:=P-TS;
  513. If (I>0) then
  514. AddToString(Result,TS,I);
  515. end;
  516. end;
  517. function TTemplateParser.ParseStream(Src: TStream; Dest: TStream): Integer;
  518. Var
  519. SS : TStringStream;
  520. S,R : String;
  521. begin
  522. SS:=TStringStream.Create('');
  523. Try
  524. SS.CopyFrom(Src,0);
  525. S:=SS.DataString;
  526. Finally
  527. SS.Free;
  528. end;
  529. R:=ParseString(S);
  530. Result:=Length(R)*SizeOf(Char);
  531. If (Result>0) then
  532. Dest.Write(R[1],Result);
  533. end;
  534. procedure TTemplateParser.ParseStrings(Src: TStrings; Dest: TStrings);
  535. Var
  536. I : Integer;
  537. begin
  538. For I:=0 to Src.Count-1 do
  539. Dest.Add(ParseString(Src[i]));
  540. end;
  541. procedure TTemplateParser.ParseFiles(const Src, Dest: String);
  542. Var
  543. Fin,Fout : TFileStream;
  544. begin
  545. Fin:=TFileStream.Create(Src,fmOpenRead or fmShareDenyWrite);
  546. try
  547. Fout:=TFileStream.Create(Dest,fmCreate);
  548. try
  549. ParseStream(Fin,Fout);
  550. finally
  551. Fout.Free;
  552. end;
  553. finally
  554. Fin.Free;
  555. end;
  556. end;
  557. { TFPCustomTemplate }
  558. procedure TFPCustomTemplate.GetParam(Sender: TObject; const ParamName: String; out AValue: String);
  559. begin
  560. If Assigned(FOnGetParam) then
  561. FOnGetParam(Self,ParamName,AValue);
  562. end;
  563. procedure TFPCustomTemplate.ReplaceTag(Sender: TObject; const TagName: String; TagParams:TStringList; Out AValue: String);
  564. begin
  565. If Assigned(FOnReplaceTag) then
  566. begin
  567. FOnReplaceTag(Self,TagName,TagParams,AValue);
  568. end;
  569. end;
  570. function TFPCustomTemplate.CreateParser: TTemplateParser;
  571. begin
  572. Result:=TTemplateParser.Create;
  573. Result.FParseLevel := 0;
  574. If (FStartDelimiter<>'') then
  575. Result.StartDelimiter:=FStartDelimiter;
  576. If (FEndDelimiter<>'') then
  577. Result.EndDelimiter:=FEndDelimiter;
  578. If (FParamStartDelimiter<>'') then
  579. Result.ParamStartDelimiter:=FParamStartDelimiter;
  580. If (FParamEndDelimiter<>'') then
  581. Result.ParamEndDelimiter:=FParamEndDelimiter;
  582. If (FParamValueSeparator<>'') then
  583. Result.ParamValueSeparator:=FParamValueSeparator;
  584. Result.OnGetParam:=@GetParam;
  585. Result.OnReplaceTag:=@ReplaceTag;
  586. Result.AllowTagParams:=FAllowTagParams;
  587. end;
  588. function TFPCustomTemplate.HasContent: Boolean;
  589. begin
  590. Result:=(FTemplate<>'') or (FFileName<>'');
  591. end;
  592. function TFPCustomTemplate.GetContent: String;
  593. Var
  594. P : TTemplateParser;
  595. S : TStringStream;
  596. F : TFileStream;
  597. begin
  598. F:=Nil;
  599. S:=Nil;
  600. If HasContent then
  601. begin
  602. if (FFileName<>'') then
  603. begin
  604. F:=TFileStream.Create(FFileName,fmOpenRead);
  605. {$IF SIZEOF(Char)=2}
  606. S:=TStringStream.Create('',TEncoding.Unicode);
  607. {$ELSE}
  608. S:=TStringStream.Create('',TEncoding.UTF8);
  609. {$ENDIF}
  610. end;
  611. Try
  612. P:=CreateParser;
  613. Try
  614. If (F<>Nil) then
  615. begin
  616. P.ParseStream(F,S);
  617. Result:=S.DataString;
  618. end
  619. else
  620. Result:=P.IntParseString(FTemplate);
  621. Finally
  622. P.Free;
  623. end;
  624. Finally
  625. F.Free;
  626. S.Free;
  627. end;
  628. end;
  629. end;
  630. procedure TFPCustomTemplate.Assign(Source: TPersistent);
  631. Var
  632. T : TFPCustomTemplate;
  633. begin
  634. If Source is TFPCustomTemplate then
  635. begin
  636. T:=Source as TFPCustomTemplate;
  637. FEndDelimiter:=T.EndDelimiter;
  638. FStartDelimiter:=T.StartDelimiter;
  639. FParamEndDelimiter:=T.ParamEndDelimiter;
  640. FParamStartDelimiter:=T.ParamStartDelimiter;
  641. FParamValueSeparator:=T.ParamValueSeparator;
  642. FFileName:=T.FileName;
  643. FTemplate:=T.Template;
  644. FOnGetParam:=T.OnGetParam;
  645. FOnReplaceTag:=T.OnReplaceTag;
  646. FAllowTagParams := T.AllowTagParams;
  647. end
  648. else
  649. inherited Assign(Source);
  650. end;
  651. end.