home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / Chip_2003-01_cd1.bin / zkuste / delphi / unity / d56 / FNDUTL.ZIP / Unicode / cUnicode.pas next >
Encoding:
Pascal/Delphi Source File  |  2002-10-29  |  23.0 KB  |  816 lines

  1. {$INCLUDE ..\cDefines.inc}
  2. unit cUnicode;
  3.  
  4. {                                                                              }
  5. {                        Unicode string functions v3.03                        }
  6. {                                                                              }
  7. {         This unit is copyright ⌐ 2002 by David Butler (david@e.co.za)        }
  8. {                                                                              }
  9. {                  This unit is part of Delphi Fundamentals.                   }
  10. {                   Its original file name is cUnicode.pas                     }
  11. {       The latest version is available from the Fundamentals home page        }
  12. {                     http://fundementals.sourceforge.net/                     }
  13. {                                                                              }
  14. {                I invite you to use this unit, free of charge.                }
  15. {        I invite you to distibute this unit, but it must be for free.         }
  16. {             I also invite you to contribute to its development,              }
  17. {             but do not distribute a modified copy of this file.              }
  18. {                                                                              }
  19. {          A forum is available on SourceForge for general discussion          }
  20. {             http://sourceforge.net/forum/forum.php?forum_id=2117             }
  21. {                                                                              }
  22. {                                                                              }
  23. { Description:                                                                 }
  24. {   Unicode functions for using WideStrings.                                   }
  25. {                                                                              }
  26. { Revision history:                                                            }
  27. {   19/04/2002  0.01  Initial version                                          }
  28. {   26/04/2002  0.02  Added WidePos, WideReplace, Append                       }
  29. {   28/10/2002  3.03  Refactored for Fundamentals 3.                           }
  30. {                                                                              }
  31.  
  32. interface
  33.  
  34. uses
  35.   // Delphi
  36.   SysUtils,
  37.  
  38.   // Fundamentals
  39.   cUtils,
  40.   cUnicodeChar;
  41.  
  42. const
  43.   UnitName      = 'cUnicode';
  44.   UnitVersion   = '3.03';
  45.   UnitDesc      = 'Unicode unit';
  46.   UnitCopyright = '(c) 2002 by David Butler';
  47.  
  48.  
  49.  
  50. {                                                                              }
  51. { Unicode errors                                                               }
  52. {                                                                              }
  53. type
  54.   EUnicode = class(Exception);
  55.  
  56.  
  57.  
  58. {                                                                              }
  59. { Null terminated WideString functions                                         }
  60. {                                                                              }
  61. function  WideMatchChars(const CharMatchFunc: WideCharMatchFunction;
  62.           const P: PWideChar; const Length: Integer = -1): Integer;
  63. function  WideMatchAllChars(const CharMatchFunc: WideCharMatchFunction;
  64.           const P: PWideChar; const Length: Integer = -1): Integer;
  65. function  WideMatchAnsiCharNoCase(const M: Char; const C: WideChar): Boolean;
  66. function  WideMatchAnsiStr(const M: String; const P: PWideChar;
  67.           const CaseSensitive: Boolean = True): Boolean;
  68. function  WideMatch(const M: WideString; const P: PWideChar): Boolean;
  69.  
  70. function  WidePosChar(const F: WideChar; const P: PWideChar): Integer; overload;
  71. function  WidePosAnsiChar(const F: Char; const P: PWideChar): Integer;
  72. function  WidePosAnsiCharSet(const F: CharSet; const P: PWideChar): Integer;
  73. function  WidePosAnsiStr(const F: String; const P: PWideChar;
  74.           const CaseSensitive: Boolean = True): Integer;
  75.  
  76. function  WideSkipChar(const CharMatchFunc: WideCharMatchFunction;
  77.           var P: PWideChar): Boolean;
  78. function  WideSkipChars(const CharMatchFunc: WideCharMatchFunction;
  79.           var P: PWideChar): Integer;
  80. function  WideSkipAnsiChar(const Ch: Char; var P: PWideChar): Boolean;
  81. function  WideSkipAnsiStr(const M: String; var P: PWideChar;
  82.           const CaseSensitive: Boolean = True): Boolean;
  83.  
  84. function  WideExtractBeforeChar(const Ch: WideChar; var P: PWideChar;
  85.           var S: WideString): Boolean;
  86. function  WideExtractBeforeAnsiChar(const Ch: Char; var P: PWideChar;
  87.           var S: WideString): Boolean;
  88. function  WideExtractAnsiCharDelimited(const LeftDelimiter, RightDelimiter: Char;
  89.           var P: PWideChar; var S: WideString): Boolean;
  90. function  WideExtractAnsiCharQuoted(const Delimiter: Char;
  91.           var P: PWideChar; var S: WideString): Boolean;
  92.  
  93.  
  94.  
  95. {                                                                              }
  96. { WideString functions                                                         }
  97. {                                                                              }
  98. function  WideDup(const Ch: WideChar; const Count: Integer): WideString;
  99.  
  100. procedure WideTrimInPlace(var S: WideString;
  101.           const MatchFunc: WideCharMatchfunction = nil);
  102. procedure WideTrimLeftInPlace(var S: WideString;
  103.           const MatchFunc: WideCharMatchfunction = nil);
  104. procedure WideTrimRightInPlace(var S: WideString;
  105.           const MatchFunc: WideCharMatchfunction = nil);
  106.  
  107. function  WideTrim(const S: WideString;
  108.           const MatchFunc: WideCharMatchfunction = nil): WideString;
  109. function  WideTrimLeft(const S: WideString;
  110.           const MatchFunc: WideCharMatchfunction = nil): WideString;
  111. function  WideTrimRight(const S: WideString;
  112.           const MatchFunc: WideCharMatchfunction = nil): WideString;
  113.  
  114. function  WideCountChar(const CharMatchFunc: WideCharMatchFunction;
  115.           const S: WideString): Integer; overload;
  116. function  WideCountChar(const Ch: WideChar; const S: WideString): Integer; overload;
  117.  
  118. function  WidePosChar(const F: WideChar; const S: WideString;
  119.           const StartIndex: Integer = 1): Integer; overload;
  120. function  WidePos(const F: WideString; const S: WideString;
  121.           const StartIndex: Integer = 1): Integer; overload;
  122.  
  123. procedure WideReplaceChar(const Find: WideChar; const Replace: WideString;
  124.           var S: WideString);
  125.  
  126.  
  127.  
  128. {                                                                              }
  129. { Dynamic Array functions                                                      }
  130. {                                                                              }
  131. type
  132.   WideStringArray = Array of WideString;
  133.  
  134. function  Append(var V : WideStringArray;
  135.           const R: WideString): Integer; overload;
  136. function  AppendWideStringArray(var V : WideStringArray;
  137.           const R: WideStringArray): Integer;
  138.  
  139.  
  140.  
  141. {                                                                              }
  142. { Self-testing code                                                            }
  143. {                                                                              }
  144. procedure SelfTest;
  145.  
  146.  
  147.  
  148. implementation
  149.  
  150.  
  151.  
  152. {                                                                              }
  153. { Match                                                                        }
  154. {                                                                              }
  155. function WideMatchChars(const CharMatchFunc: WideCharMatchFunction; const P: PWideChar; const Length: Integer): Integer;
  156. var Q : PWideChar;
  157.     L : Integer;
  158.     C : WideChar;
  159. begin
  160.   Result := 0;
  161.   Q := P;
  162.   L := Length;
  163.   if not Assigned(Q) or (L = 0) then
  164.     exit;
  165.   C := Q^;
  166.   if (L < 0) and (C = WideNULL) then
  167.     exit;
  168.   Repeat
  169.     if not CharMatchFunc(C) then
  170.       exit;
  171.     Inc(Result);
  172.     Inc(Q);
  173.     if L > 0 then
  174.       Dec(L);
  175.     C := Q^;
  176.   Until (L = 0) or ((L < 0) and (C = WideNULL));
  177. end;
  178.  
  179. function WideMatchAllChars(const CharMatchFunc: WideCharMatchFunction; const P: PWideChar; const Length: Integer): Integer;
  180. var Q : PWideChar;
  181.     L : Integer;
  182.     C : WideChar;
  183. begin
  184.   Result := 0;
  185.   Q := P;
  186.   L := Length;
  187.   if not Assigned(Q) or (L = 0) then
  188.     exit;
  189.   C := Q^;
  190.   if (L < 0) and (C = WideNULL) then
  191.     exit;
  192.   Repeat
  193.     if CharMatchFunc(C) then
  194.       Inc(Result);
  195.     Inc(Q);
  196.     if L > 0 then
  197.       Dec(L);
  198.     C := Q^;
  199.   Until (L = 0) or ((L < 0) and (C = WideNULL));
  200. end;
  201.  
  202. function WideMatchAnsiCharNoCase(const M: Char; const C: WideChar): Boolean;
  203. const ASCIICaseOffset = Ord('a') - Ord('A');
  204. var D, N : Char;
  205. begin
  206.   if Ord(C) > $7F then
  207.     begin
  208.       Result := False;
  209.       exit;
  210.     end;
  211.   D := Char(Ord(C));
  212.   if D in ['A'..'Z'] then
  213.     D := Char(Ord(D) + ASCIICaseOffset);
  214.   N := M;
  215.   if N in ['A'..'Z'] then
  216.     N := Char(Ord(N) + ASCIICaseOffset);
  217.   Result := D = N;
  218. end;
  219.  
  220. function WideMatchAnsiStr(const M: String; const P: PWideChar; const CaseSensitive: Boolean): Boolean;
  221. var I, L : Integer;
  222.     Q : PWideChar;
  223.     R : PChar;
  224. begin
  225.   L := Length(M);
  226.   if L = 0 then
  227.     begin
  228.       Result := False;
  229.       exit;
  230.     end;
  231.   R := Pointer(M);
  232.   Q := P;
  233.   if CaseSensitive then
  234.     begin
  235.       For I := 1 to L do
  236.         if Ord(R^) <> Ord(Q^) then
  237.           begin
  238.             Result := False;
  239.             exit;
  240.           end else
  241.           begin
  242.             Inc(R);
  243.             Inc(Q);
  244.           end;
  245.     end else
  246.     begin
  247.       For I := 1 to L do
  248.         if not WideMatchAnsiCharNoCase(R^, Q^) then
  249.           begin
  250.             Result := False;
  251.             exit;
  252.           end else
  253.           begin
  254.             Inc(R);
  255.             Inc(Q);
  256.           end;
  257.     end;
  258.   Result := True;
  259. end;
  260.  
  261. function WideMatch(const M: WideString; const P: PWideChar): Boolean;
  262. var I, L : Integer;
  263.     Q, R : PWideChar;
  264. begin
  265.   L := Length(M);
  266.   if L = 0 then
  267.     begin
  268.       Result := False;
  269.       exit;
  270.     end;
  271.   R := Pointer(M);
  272.   Q := P;
  273.   For I := 1 to L do
  274.     if R^ <> Q^ then
  275.       begin
  276.         Result := False;
  277.         exit;
  278.       end else
  279.       begin
  280.         Inc(R);
  281.         Inc(Q);
  282.       end;
  283.   Result := True;
  284. end;
  285.  
  286.  
  287.  
  288. {                                                                              }
  289. { Pos                                                                          }
  290. {                                                                              }
  291. function WidePosAnsiChar(const F: Char; const P: PWideChar): Integer;
  292. var Q : PWideChar;
  293.     I : Integer;
  294. begin
  295.   Result := -1;
  296.   Q := P;
  297.   if not Assigned(Q) then
  298.     exit;
  299.   I := 0;
  300.   While Q^ <> #0 do
  301.     if Ord(Q^) = Ord(F) then
  302.       begin
  303.         Result := I;
  304.         exit;
  305.       end else
  306.       begin
  307.         Inc(Q);
  308.         Inc(I);
  309.       end;
  310. end;
  311.  
  312. function WidePosAnsiCharSet(const F: CharSet; const P: PWideChar): Integer;
  313. var Q : PWideChar;
  314.     I : Integer;
  315. begin
  316.   Result := -1;
  317.   Q := P;
  318.   if not Assigned(Q) then
  319.     exit;
  320.   I := 0;
  321.   While Q^ <> #0 do
  322.     if (Ord(Q^) < $80) and (Char(Ord(Q^)) in F) then
  323.       begin
  324.         Result := I;
  325.         exit;
  326.       end else
  327.       begin
  328.         Inc(Q);
  329.         Inc(I);
  330.       end;
  331. end;
  332.  
  333. function WidePosChar(const F: WideChar; const P: PWideChar): Integer;
  334. var Q : PWideChar;
  335.     I : Integer;
  336. begin
  337.   Result := -1;
  338.   Q := P;
  339.   if not Assigned(Q) then
  340.     exit;
  341.   I := 0;
  342.   While Q^ <> #0 do
  343.     if Q^ = F then
  344.       begin
  345.         Result := I;
  346.         exit;
  347.       end else
  348.       begin
  349.         Inc(Q);
  350.         Inc(I);
  351.       end;
  352. end;
  353.  
  354. function WidePosAnsiStr(const F: String; const P: PWideChar; const CaseSensitive: Boolean): Integer;
  355. var Q : PWideChar;
  356.     I : Integer;
  357. begin
  358.   Result := -1;
  359.   Q := P;
  360.   if not Assigned(Q) then
  361.     exit;
  362.   I := 0;
  363.   While Q^ <> #0 do
  364.     if WideMatchAnsiStr(F, Q, CaseSensitive) then
  365.       begin
  366.         Result := I;
  367.         exit;
  368.       end else
  369.       begin
  370.         Inc(Q);
  371.         Inc(I);
  372.       end;
  373. end;
  374.  
  375.  
  376.  
  377. {                                                                              }
  378. { Skip                                                                         }
  379. {                                                                              }
  380. function WideSkipChar(const CharMatchFunc: WideCharMatchFunction; var P: PWideChar): Boolean;
  381. var C : WideChar;
  382. begin
  383.   Assert(Assigned(CharMatchFunc), 'Assigned(CharMatchFunc)');
  384.   C := P^;
  385.   if C = #0 then
  386.     begin
  387.       Result := False;
  388.       exit;
  389.     end;
  390.   Result := CharMatchFunc(C);
  391.   if Result then
  392.     Inc(P);
  393. end;
  394.  
  395. function WideSkipChars(const CharMatchFunc: WideCharMatchFunction; var P: PWideChar): Integer;
  396. var C : WideChar;
  397. begin
  398.   Assert(Assigned(CharMatchFunc), 'Assigned(CharMatchFunc)');
  399.   Result := 0;
  400.   if not Assigned(P) then
  401.     exit;
  402.   C := P^;
  403.   While C <> #0 do
  404.     if not CharMatchFunc(C) then
  405.       exit else
  406.       Inc(P);
  407. end;
  408.  
  409. function WideSkipAnsiChar(const Ch: Char; var P: PWideChar): Boolean;
  410. begin
  411.   Result := Ord(P^) = Ord(Ch);
  412.   if Result then
  413.     Inc(P);
  414. end;
  415.  
  416. function WideSkipAnsiStr(const M: String; var P: PWideChar; const CaseSensitive: Boolean): Boolean;
  417. begin
  418.   Result := WideMatchAnsiStr(M, P, CaseSensitive);
  419.   if Result then
  420.     Inc(P, Length(M));
  421. end;
  422.  
  423.  
  424.  
  425. {                                                                              }
  426. { Extract                                                                      }
  427. {                                                                              }
  428. function WideExtractBeforeChar(const Ch: WideChar; var P: PWideChar; var S: WideString): Boolean;
  429. var I : Integer;
  430. begin
  431.   I := WidePosChar(Ch, P);
  432.   Result := I >= 0;
  433.   if I <= 0 then
  434.     begin
  435.       S := '';
  436.       exit;
  437.     end;
  438.   Inc(P, I);
  439.   SetLength(S, I);
  440.   Move(P^, Pointer(S)^, I * Sizeof(WideChar));
  441. end;
  442.  
  443. function WideExtractBeforeAnsiChar(const Ch: Char; var P: PWideChar; var S: WideString): Boolean;
  444. var I : Integer;
  445. begin
  446.   I := WidePosAnsiChar(Ch, P);
  447.   Result := I >= 0;
  448.   if I <= 0 then
  449.     begin
  450.       S := '';
  451.       exit;
  452.     end;
  453.   Inc(P, I);
  454.   SetLength(S, I);
  455.   Move(P^, Pointer(S)^, I * Sizeof(WideChar));
  456. end;
  457.  
  458. function WideExtractAnsiCharDelimited(const LeftDelimiter, RightDelimiter: Char;
  459.          var P: PWideChar; var S: WideString): Boolean;
  460. var Q : PWideChar;
  461. begin
  462.   Q := P;
  463.   Result := Assigned(Q) and (Ord(Q^) < $80) and (Ord(Q^) = Ord(LeftDelimiter));
  464.   if not Result then
  465.     begin
  466.       S := '';
  467.       exit;
  468.     end;
  469.   Inc(Q);
  470.   Result := WideExtractBeforeAnsiChar(RightDelimiter, Q, S);
  471.   if not Result then
  472.     exit;
  473.   Inc(Q);
  474.   P := Q;
  475. end;
  476.  
  477. function WideExtractAnsiCharQuoted(const Delimiter: Char; var P: PWideChar; var S: WideString): Boolean;
  478. begin
  479.   Result := WideExtractAnsiCharDelimited(Delimiter, Delimiter, P, S);
  480. end;
  481.  
  482.  
  483.  
  484. {                                                                              }
  485. { Dup                                                                          }
  486. {                                                                              }
  487. function WideDup(const Ch: WideChar; const Count: Integer): WideString;
  488. var I : Integer;
  489.     P : PWideChar;
  490. begin
  491.   if Count <= 0 then
  492.     begin
  493.       Result := '';
  494.       exit;
  495.     end;
  496.   SetLength(Result, Count);
  497.   P := Pointer(Result);
  498.   For I := 1 to Count do
  499.     begin
  500.       P^ := Ch;
  501.       Inc(P);
  502.     end;
  503. end;
  504.  
  505.  
  506.  
  507. {                                                                              }
  508. { Trim                                                                         }
  509. {                                                                              }
  510. procedure WideTrimLeftInPlace(var S: WideString; const MatchFunc: WideCharMatchFunction);
  511. var I, L : Integer;
  512.     P : PWideChar;
  513.     F: WideCharMatchFunction;
  514. begin
  515.   L := Length(S);
  516.   if L = 0 then
  517.     exit;
  518.   F := MatchFunc;
  519.   if not Assigned(F) then
  520.     F := IsControlOrWhiteSpace;
  521.   I := 0;
  522.   P := Pointer(S);
  523.   While F (P^) do
  524.     begin
  525.       Inc(I);
  526.       Inc(P);
  527.       Dec(L);
  528.       if L = 0 then
  529.         begin
  530.           S := '';
  531.           exit;
  532.         end;
  533.     end;
  534.   if I = 0 then
  535.     exit;
  536.   S := Copy(S, I + 1, L);
  537. end;
  538.  
  539. procedure WideTrimRightInPlace(var S: WideString; const MatchFunc: WideCharMatchFunction);
  540. var I, L : Integer;
  541.     P : PWideChar;
  542.     F: WideCharMatchFunction;
  543. begin
  544.   L := Length(S);
  545.   if L = 0 then
  546.     exit;
  547.   F := MatchFunc;
  548.   if not Assigned(F) then
  549.     F := IsControlOrWhiteSpace;
  550.   I := 0;
  551.   P := Pointer(S);
  552.   Inc(P, L - 1);
  553.   While F (P^) do
  554.     begin
  555.       Inc(I);
  556.       Dec(P);
  557.       Dec(L);
  558.       if L = 0 then
  559.         begin
  560.           S := '';
  561.           exit;
  562.         end;
  563.     end;
  564.   if I = 0 then
  565.     exit;
  566.   SetLength(S, L);
  567. end;
  568.  
  569. procedure WideTrimInPlace(var S: WideString; const MatchFunc: WideCharMatchFunction);
  570. var I, J, L : Integer;
  571.     P : PWideChar;
  572.     F: WideCharMatchFunction;
  573. begin
  574.   L := Length(S);
  575.   if L = 0 then
  576.     exit;
  577.   F := MatchFunc;
  578.   if not Assigned(F) then
  579.     F := IsControlOrWhiteSpace;
  580.   I := 0;
  581.   P := Pointer(S);
  582.   Inc(P, L - 1);
  583.   While F (P^) or IsControl (P^) do
  584.     begin
  585.       Inc(I);
  586.       Dec(P);
  587.       Dec(L);
  588.       if L = 0 then
  589.         begin
  590.           S := '';
  591.           exit;
  592.         end;
  593.     end;
  594.   J := 0;
  595.   P := Pointer(S);
  596.   While F (P^) or IsControl (P^) do
  597.     begin
  598.       Inc(J);
  599.       Inc(P);
  600.       Dec(L);
  601.       if L = 0 then
  602.         begin
  603.           S := '';
  604.           exit;
  605.         end;
  606.     end;
  607.   if (I = 0) and (J = 0) then
  608.     exit;
  609.   S := Copy(S, J + 1, L);
  610. end;
  611.  
  612. function WideTrimLeft(const S: WideString; const MatchFunc: WideCharMatchFunction): WideString;
  613. begin
  614.   Result := S;
  615.   WideTrimLeftInPlace(Result, MatchFunc);
  616. end;
  617.  
  618. function WideTrimRight(const S: WideString; const MatchFunc: WideCharMatchFunction): WideString;
  619. begin
  620.   Result := S;
  621.   WideTrimRightInPlace(Result, MatchFunc);
  622. end;
  623.  
  624. function WideTrim(const S: WideString; const MatchFunc: WideCharMatchFunction): WideString;
  625. begin
  626.   Result := S;
  627.   WideTrimInPlace(Result, MatchFunc);
  628. end;
  629.  
  630.  
  631.  
  632. {                                                                              }
  633. { Count                                                                        }
  634. {                                                                              }
  635. function WideCountChar(const CharMatchFunc: WideCharMatchFunction; const S: WideString): Integer;
  636. begin
  637.   Result := WideMatchAllChars(CharMatchFunc, Pointer(S), Length(S));
  638. end;
  639.  
  640. function WideCountChar(const Ch: WideChar; const S: WideString): Integer;
  641. var Q : PWideChar;
  642.     I : Integer;
  643. begin
  644.   Result := 0;
  645.   Q := PWideChar(S);
  646.   if not Assigned(Q) then
  647.     exit;
  648.   For I := 1 to Length(S) do
  649.     begin
  650.       if Q^ = Ch then
  651.         Inc(Result);
  652.       Inc(Q);
  653.     end;
  654. end;
  655.  
  656.  
  657.  
  658. {                                                                              }
  659. { Pos                                                                          }
  660. {                                                                              }
  661. function WidePosChar(const F: WideChar; const S: WideString; const StartIndex: Integer): Integer;
  662. var P : PWideChar;
  663.     I, L : Integer;
  664. begin
  665.   L := Length(S);
  666.   if (StartIndex > L) or (StartIndex < 1) then
  667.     begin
  668.       Result := 0;
  669.       exit;
  670.     end;
  671.   P := Pointer(S);
  672.   Inc(P, StartIndex - 1);
  673.   For I := StartIndex to L do
  674.     if P^ = F then
  675.       begin
  676.         Result := I;
  677.         exit;
  678.       end else
  679.       Inc(P);
  680.   Result := 0;
  681. end;
  682.  
  683. function WidePos(const F: WideString; const S: WideString; const StartIndex: Integer): Integer;
  684. var P : PWideChar;
  685.     I, L : Integer;
  686. begin
  687.   L := Length(S);
  688.   if (StartIndex > L) or (StartIndex < 1) then
  689.     begin
  690.       Result := 0;
  691.       exit;
  692.     end;
  693.   P := Pointer(S);
  694.   Inc(P, StartIndex - 1);
  695.   For I := StartIndex to L do
  696.     if WideMatch(F, P) then
  697.       begin
  698.         Result := I;
  699.         exit;
  700.       end else
  701.       Inc(P);
  702.   Result := 0;
  703. end;
  704.  
  705.  
  706.  
  707. {                                                                              }
  708. { Replace                                                                      }
  709. {                                                                              }
  710. procedure WideReplaceChar(const Find: WideChar; const Replace: WideString; var S: WideString);
  711. var C, L, M, I, R : Integer;
  712.     P, Q : PWideChar;
  713.     T : WideString;
  714. begin
  715.   C := WideCountChar(Find, S);
  716.   if C = 0 then
  717.     exit;
  718.   R := Length(Replace);
  719.   M := Length(S);
  720.   L := M + (R - 1) * C;
  721.   if L = 0 then
  722.     begin
  723.       S := '';
  724.       exit;
  725.     end;
  726.   SetLength(T, L);
  727.   P := Pointer(S);
  728.   Q := Pointer(T);
  729.   For I := 1 to M do
  730.     if P^ = Find then
  731.       begin
  732.         if R > 0 then
  733.           begin
  734.             Move(Pointer(Replace)^, Q^, Sizeof(WideChar) * R);
  735.             Inc(Q, R);
  736.           end;
  737.         Inc(P);
  738.       end else
  739.       begin
  740.         Q^ := P^;
  741.         Inc(P);
  742.         Inc(Q);
  743.       end;
  744.   S := T;
  745. end;
  746.  
  747.  
  748.  
  749. {                                                                              }
  750. { Dynamic Array functions                                                      }
  751. {                                                                              }
  752. function Append(var V : WideStringArray; const R: WideString): Integer;
  753. begin
  754.   Result := Length(V);
  755.   SetLength(V, Result + 1);
  756.   V[Result] := R;
  757. end;
  758.  
  759. function AppendWideStringArray(var V : WideStringArray; const R: WideStringArray): Integer;
  760. var I, LR : Integer;
  761. begin
  762.   Result := Length(V);
  763.   LR := Length(R);
  764.   if LR > 0 then
  765.     begin
  766.       SetLength(V, Result + LR);
  767.       For I := 0 to LR - 1 do
  768.         V[Result + I] := R[I];
  769.     end;
  770. end;
  771.  
  772.  
  773.  
  774. {                                                                              }
  775. { Self-testing code                                                            }
  776. {                                                                              }
  777. procedure SelfTest;
  778. var S: WideString;
  779. begin
  780.   Assert(WideMatchAnsiCharNoCase('A', 'a'), 'WideMatchAnsiCharNoCase');
  781.   Assert(WideMatchAnsiCharNoCase('z', 'Z'), 'WideMatchAnsiCharNoCase');
  782.   Assert(WideMatchAnsiCharNoCase('1', '1'), 'WideMatchAnsiCharNoCase');
  783.   Assert(not WideMatchAnsiCharNoCase('A', 'B'), 'WideMatchAnsiCharNoCase');
  784.   Assert(not WideMatchAnsiCharNoCase('0', 'A'), 'WideMatchAnsiCharNoCase');
  785.  
  786.   Assert(WideMatchAnsiStr('Unicode', 'uNicode', False), 'WideMatchAnsiStr');
  787.   Assert(not WideMatchAnsiStr('Unicode', 'uNicode', True), 'WideMatchAnsiStr');
  788.   Assert(WideMatchAnsiStr('Unicode', 'Unicode', True), 'WideMatchAnsiStr');
  789.  
  790.   Assert(WideTrimLeft(' X ') = 'X ', 'WideTrimLeft');
  791.   Assert(WideTrimRight(' X ') = ' X', 'WideTrimRight');
  792.   Assert(WideTrim(' X ') = 'X', 'WideTrim');
  793.  
  794.   Assert(WideDup('X', 0) = '', 'WideDup');
  795.   Assert(WideDup('X', 1) = 'X', 'WideDup');
  796.   Assert(WideDup('A', 4) = 'AAAA', 'WideDup');
  797.  
  798.   S := 'AXAYAA';
  799.   WideReplaceChar('A', '', S);
  800.   Assert(S = 'XY', 'WideReplaceChar');
  801.   S := 'AXAYAA';
  802.   WideReplaceChar('A', 'B', S);
  803.   Assert(S = 'BXBYBB', 'WideReplaceChar');
  804.   S := 'AXAYAA';
  805.   WideReplaceChar('A', 'CC', S);
  806.   Assert(S = 'CCXCCYCCCC', 'WideReplaceChar');
  807.   S := 'AXAXAA';
  808.   WideReplaceChar('X', 'IJK', S);
  809.   Assert(S = 'AIJKAIJKAA', 'WideReplaceChar');
  810. end;
  811.  
  812.  
  813.  
  814. end.
  815.  
  816.