2
0

Quick.Template.pas 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. { ***************************************************************************
  2. Copyright (c) 2016-2022 Kike Pérez
  3. Unit : Quick.Template
  4. Description : String Replace Templates
  5. Author : Kike Pérez
  6. Version : 2.0
  7. Created : 01/04/2020
  8. Modified : 31/03/2022
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Template;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. System.SysUtils,
  26. System.Generics.Collections,
  27. Quick.Commons;
  28. type
  29. {$IFNDEF FPC}
  30. TTokenFunc = reference to function(const aToken : string) : string;
  31. {$ELSE}
  32. TTokenFunc = function(const aToken : string) : string of object;
  33. {$ENDIF}
  34. TStringTemplate = class
  35. private
  36. fVariables : TDictionary<string,string>;
  37. fReplaceFunc : TTokenFunc;
  38. fQuoteBegin : string;
  39. fQuoteEnd : string;
  40. fBeginOffSet : Integer;
  41. fEndOffSet : Integer;
  42. protected
  43. constructor Create; overload;
  44. public
  45. constructor Create(const aQuoteBegin, aQuoteEnd : string; aVariables : TDictionary<string,string>); overload;
  46. constructor Create(const aQuoteBegin, aQuoteEnd : string; aReplaceFunc : TTokenFunc); overload;
  47. function Replace(const aTemplate : string) : string; virtual;
  48. end;
  49. EStringTemplateError = class(Exception);
  50. implementation
  51. { TStringTemplate }
  52. constructor TStringTemplate.Create;
  53. begin
  54. end;
  55. constructor TStringTemplate.Create(const aQuoteBegin, aQuoteEnd: string; aVariables: TDictionary<string, string>);
  56. begin
  57. inherited Create;
  58. if aQuoteBegin.IsEmpty or aQuoteEnd.IsEmpty then raise EStringTemplateError.Create('QuoteBegin and QuoteEnd cannot be null!');
  59. if aVariables = nil then raise EStringTemplateError.Create('Dictionary cannot be null!');
  60. fQuoteBegin := aQuoteBegin;
  61. fQuoteEnd := aQuoteEnd;
  62. fBeginOffSet := aQuoteBegin.Length;
  63. fEndOffSet := aQuoteEnd.Length;
  64. fVariables := aVariables;
  65. end;
  66. constructor TStringTemplate.Create(const aQuoteBegin, aQuoteEnd: string; aReplaceFunc: TTokenFunc);
  67. begin
  68. inherited Create;
  69. if aQuoteBegin.IsEmpty or aQuoteEnd.IsEmpty then raise EStringTemplateError.Create('QuoteBegin and QuoteEnd cannot be null!');
  70. if not Assigned(aReplaceFunc) then raise EStringTemplateError.Create('ReplaceFunc cannot be null!');
  71. fQuoteBegin := aQuoteBegin;
  72. fQuoteEnd := aQuoteEnd;
  73. fBeginOffSet := aQuoteBegin.Length;
  74. fEndOffSet := aQuoteEnd.Length;
  75. fReplaceFunc := aReplaceFunc;
  76. end;
  77. function TStringTemplate.Replace(const aTemplate : string) : string;
  78. var
  79. idx : Integer;
  80. st : Integer;
  81. et : Integer;
  82. token : string;
  83. tokrep : string;
  84. begin
  85. //resolve template
  86. Result := '';
  87. st := 0;
  88. idx := 1;
  89. repeat
  90. st := aTemplate.IndexOf(fQuoteBegin,st) + 1;
  91. if st > 0 then
  92. begin
  93. et := aTemplate.IndexOf(fQuoteEnd,st) + 1;
  94. if et = 0 then Break;
  95. Result := Result + Copy(aTemplate,idx,st-idx);
  96. token := Copy(aTemplate,st + fBeginOffSet,et-st-fBeginOffSet);
  97. //replace token
  98. tokrep := '';
  99. if fVariables <> nil then
  100. begin
  101. fVariables.TryGetValue(token,tokrep)
  102. end
  103. else
  104. begin
  105. tokrep := fReplaceFunc(token);
  106. end;
  107. if tokrep.IsEmpty then tokrep := fQuoteBegin + token + '?' + fQuoteEnd;
  108. Result := Result + tokrep;
  109. idx := et + fEndOffSet;
  110. end;
  111. until st = 0;
  112. Result := Result + Copy(aTemplate,idx,aTemplate.Length);
  113. end;
  114. end.