/donations/source/common/JclStringsDonations.pas

https://github.com/the-Arioch/jcl · Pascal · 160 lines · 113 code · 31 blank · 16 comment · 16 complexity · 78470adf211c30c383079c1943a54220 MD5 · raw file

  1. unit JclStringsDonations;
  2. interface
  3. uses
  4. Classes, JclStrings, JclSysUtils;
  5. const
  6. AnsiQuoteChars = AnsiString('"''');
  7. { TODO : Author: Mario R. Carro <ochnap2@yahoo.com.ar> }
  8. procedure StrToStrings(S, Sep: AnsiString; const List: TStrings;
  9. const AllowEmptyString: Boolean = True; const QuoteChars: String = '';
  10. const CaseSensitive: Boolean = True); overload;
  11. { TODO : Author: Mario R. Carro <ochnap2@yahoo.com.ar> }
  12. procedure StrIToStrings(S, Sep: AnsiString; const List: TStrings;
  13. const AllowEmptyString: Boolean = True; const QuoteChars: String = '');
  14. { TODO : Author: Peter Panino <peter-panino@aon.at> }
  15. function MyStrToken(var S: AnsiString; Separator: AnsiString): AnsiString;
  16. { TODO : Author: Peter Panino <peter-panino@aon.at> }
  17. procedure StrTokenToStrings(S, Separator: AnsiString; const List: TStrings); overload;
  18. implementation
  19. //--------------------------------------------------------------------------------------------------
  20. procedure StrToStrings(S, Sep: AnsiString; const List: TStrings;
  21. const AllowEmptyString: Boolean = True; const QuoteChars: String = '';
  22. const CaseSensitive: Boolean = True);
  23. var
  24. FindNextStr: function (const Substr, S: AnsiString; const Index: Integer): Integer;
  25. A, B, L, LS, LQ, Q: Integer;
  26. function FindNextQuote(From: Integer): Integer;
  27. var
  28. I, QI: Integer;
  29. begin
  30. Result := 0;
  31. if Q < 0 then
  32. begin
  33. // Find the nearest opening quote.
  34. for I := 1 to LQ do
  35. begin
  36. QI := FindNextStr(QuoteChars[I], S, From + 1);
  37. if (QI > 0) and ((Result = 0) or (QI < Result)) then
  38. Result := QI;
  39. end;
  40. end
  41. else
  42. begin
  43. // Find the next quote of an item (closing o nested).
  44. QI := FindNextStr(S[Q], S, From + 1);
  45. if QI > 0 then
  46. Result := QI;
  47. end;
  48. end;
  49. begin
  50. Assert(List <> nil);
  51. List.Clear;
  52. if S = '' then
  53. Exit;
  54. if CaseSensitive then
  55. FindNextStr := StrSearch
  56. else
  57. FindNextStr := StrFind;
  58. L := Length(Sep);
  59. LS := Length(S);
  60. LQ := Length(QuoteChars);
  61. // Q = -1 means no quote found so far,
  62. // but need to check for them.
  63. // Q = 0 means don't bother about quotes,
  64. // or, in the repeat, no more quotes.
  65. Q := iff(LQ > 0, -1, 0);
  66. B := -L;
  67. repeat
  68. A := B + L + 1;
  69. B := FindNextStr(Sep, S, A) - 1;
  70. if B < 0 then B := LS;
  71. // Need to check for (more) quotes?
  72. if (Q <> 0) and (Q < B) then
  73. begin
  74. if Q < 0 then
  75. Q := FindNextQuote(A);
  76. if (Q > 0) and (Q < B) then
  77. begin
  78. Q := FindNextQuote(Q);
  79. // Jump over nested quotes.
  80. while (Q < LS) and (S[Q + 1] = S[Q]) do
  81. Q := FindNextQuote(Q);
  82. B := FindNextStr(Sep, S, Q + 1) - 1;
  83. if B < 0 then B := LS;
  84. Q := -1;
  85. end;
  86. end;
  87. List.Add(Copy(S, A, B - A + 1));
  88. until B = LS;
  89. end;
  90. //--------------------------------------------------------------------------------------------------
  91. procedure StrIToStrings(S, Sep: AnsiString; const List: TStrings;
  92. const AllowEmptyString: Boolean = True; const QuoteChars: String = '');
  93. begin
  94. StrToStrings(S, Sep, List, AllowEmptyString, QuoteChars, False);
  95. end;
  96. //--------------------------------------------------------------------------------------------------
  97. function MyStrToken(var S: AnsiString; Separator: AnsiString): AnsiString;
  98. var
  99. I: Integer;
  100. begin
  101. I := Pos(Separator, S);
  102. if I <> 0 then
  103. begin
  104. Result := Copy(S, 1, I - 1);
  105. Delete(S, 1, I + Length(Separator) - 1);
  106. end
  107. else
  108. begin
  109. Result := S;
  110. S := '';
  111. end;
  112. end;
  113. //--------------------------------------------------------------------------------------------------
  114. procedure StrTokenToStrings(S, Separator: AnsiString; const List: TStrings);
  115. var
  116. Token: AnsiString;
  117. begin
  118. Assert(List <> nil);
  119. if List = nil then
  120. Exit;
  121. List.Clear;
  122. while S <> '' do
  123. begin
  124. Token := MyStrToken(S, Separator);
  125. if Token <> '' then {if S starts with Separator}
  126. List.Add(Token);
  127. end;
  128. end;
  129. end.