Quick.Template.pas 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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 : 30/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. {$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. idx := 1;
  88. repeat
  89. st := aTemplate.IndexOf(fQuoteBegin,st) + 1;
  90. if st > 0 then
  91. begin
  92. et := aTemplate.IndexOf(fQuoteEnd,st) + 1;
  93. if et = 0 then Break;
  94. Result := Result + Copy(aTemplate,idx,st-idx);
  95. token := Copy(aTemplate,st + fBeginOffSet,et-st-fBeginOffSet);
  96. //replace token
  97. tokrep := '';
  98. if fVariables <> nil then
  99. begin
  100. fVariables.TryGetValue(token,tokrep)
  101. end
  102. else
  103. begin
  104. tokrep := fReplaceFunc(token);
  105. end;
  106. if tokrep.IsEmpty then tokrep := fQuoteBegin + token + '?' + fQuoteEnd;
  107. Result := Result + tokrep;
  108. idx := et + fEndOffSet;
  109. end;
  110. until st = 0;
  111. Result := Result + Copy(aTemplate,idx,aTemplate.Length);
  112. end;
  113. end.