Quick.Template.pas 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. { ***************************************************************************
  2. Copyright (c) 2016-2020 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 : 28/06/2020
  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. TTokenFunc = function(const aToken : string) : string of object;
  30. TStringTemplate = class
  31. private
  32. fVariables : TDictionary<string,string>;
  33. fReplaceFunc : TTokenFunc;
  34. fQuoteBegin : string;
  35. fQuoteEnd : string;
  36. fBeginOffSet : Integer;
  37. fEndOffSet : Integer;
  38. protected
  39. constructor Create; overload;
  40. public
  41. constructor Create(const aQuoteBegin, aQuoteEnd : string; aVariables : TDictionary<string,string>); overload;
  42. constructor Create(const aQuoteBegin, aQuoteEnd : string; aReplaceFunc : TTokenFunc); overload;
  43. function Replace(const aTemplate : string) : string; virtual;
  44. end;
  45. EStringTemplateError = class(Exception);
  46. implementation
  47. { TStringTemplate }
  48. constructor TStringTemplate.Create;
  49. begin
  50. end;
  51. constructor TStringTemplate.Create(const aQuoteBegin, aQuoteEnd: string; aVariables: TDictionary<string, string>);
  52. begin
  53. inherited Create;
  54. if aQuoteBegin.IsEmpty or aQuoteEnd.IsEmpty then raise EStringTemplateError.Create('QuoteBegin and QuoteEnd cannot be null!');
  55. if aVariables = nil then raise EStringTemplateError.Create('Dictionary cannot be null!');
  56. fQuoteBegin := aQuoteBegin;
  57. fQuoteEnd := aQuoteEnd;
  58. fBeginOffSet := aQuoteBegin.Length;
  59. fEndOffSet := aQuoteEnd.Length;
  60. fVariables := aVariables;
  61. end;
  62. constructor TStringTemplate.Create(const aQuoteBegin, aQuoteEnd: string; aReplaceFunc: TTokenFunc);
  63. begin
  64. inherited Create;
  65. if aQuoteBegin.IsEmpty or aQuoteEnd.IsEmpty then raise EStringTemplateError.Create('QuoteBegin and QuoteEnd cannot be null!');
  66. if not Assigned(aReplaceFunc) then raise EStringTemplateError.Create('ReplaceFunc cannot be null!');
  67. fQuoteBegin := aQuoteBegin;
  68. fQuoteEnd := aQuoteEnd;
  69. fBeginOffSet := aQuoteBegin.Length;
  70. fEndOffSet := aQuoteEnd.Length;
  71. fReplaceFunc := aReplaceFunc;
  72. end;
  73. function TStringTemplate.Replace(const aTemplate : string) : string;
  74. var
  75. idx : Integer;
  76. st : Integer;
  77. et : Integer;
  78. token : string;
  79. tokrep : string;
  80. begin
  81. //resolve template
  82. Result := '';
  83. idx := 1;
  84. repeat
  85. st := aTemplate.IndexOf(fQuoteBegin,st) + 1;
  86. if st > 0 then
  87. begin
  88. et := aTemplate.IndexOf(fQuoteEnd,st) + 1;
  89. if et = 0 then Break;
  90. Result := Result + Copy(aTemplate,idx,st-idx);
  91. token := Copy(aTemplate,st + fBeginOffSet,et-st-fBeginOffSet);
  92. //replace token
  93. tokrep := '';
  94. if fVariables <> nil then
  95. begin
  96. fVariables.TryGetValue(token,tokrep)
  97. end
  98. else
  99. begin
  100. tokrep := fReplaceFunc(token);
  101. end;
  102. if tokrep.IsEmpty then tokrep := fQuoteBegin + token + '?' + fQuoteEnd;
  103. Result := Result + tokrep;
  104. idx := et + fEndOffSet;
  105. end;
  106. until st = 0;
  107. Result := Result + Copy(aTemplate,idx,aTemplate.Length);
  108. end;
  109. end.