fptemplate.pp 21 KB

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