Componentes.Terceros.jvcl/official/3.39/devtools/JvclVclClx/Utils.pas
2010-01-18 16:55:50 +00:00

414 lines
9.7 KiB
ObjectPascal

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: Utils.pas, released on 2004-05-19.
The Initial Developer of the Original Code is Andreas Hausladen
(Andreas dott Hausladen att gmx dott de)
Portions created by Andreas Hausladen are Copyright (C) 2004 Andreas Hausladen.
All Rights Reserved.
Contributor(s): -
You may retrieve the latest version of this file at the Project JEDI's JVCL
home page, located at http://jvcl.delphi-jedi.org
Known Issues:
-----------------------------------------------------------------------------}
// $Id: Utils.pas 12461 2009-08-14 17:21:33Z obones $
unit Utils;
interface
uses
SysUtils, Classes;
type
IStringBuilder = interface
procedure Append(const Text: string); overload;
procedure Append(const Args: array of string); overload;
function GetValue: string; overload;
procedure GetValue(var Value: string); overload;
function Length: Integer;
function Capacity: Integer;
end;
function StringBuilder(const StartValue: string; StartCapacity: Integer = 1024;
ADelta: Integer = 1024): IStringBuilder;
function AnsiStartsFilename(const SubStr, S: string): Boolean;
// AnsiStartsText/Str depends on the used OS
function ParsePath(const Path: string): string;
function RepeatStr(const S: string; Count: Integer): string;
function IsEmptyStr(const S: string): Boolean;
function RemoveCommentChars(const S: string): string;
function TrimCopy(const S: string; Index, Count: Integer): string;
procedure ReadFileToString(const Filename: string; var S: string);
procedure WriteFileFromString(const Filename, S: string);
function FollowRelativeFilename(const RootDir: string; RelFilename: string): string;
function CutFirstDirectory(var Dir: string): string;
procedure ConvertBinDfmToText(const Filename: string);
implementation
uses
StrUtils;
type
TStringBuilder = class(TInterfacedObject, IStringBuilder)
private
FBuffer: string;
FLength: Integer;
FDelta: Integer;
procedure Append(const Text: string); overload;
procedure Append(const Args: array of string); overload;
function GetValue: string; overload;
procedure GetValue(var Value: string); overload;
function Length: Integer;
function Capacity: Integer;
protected
procedure Grow(AddLen: Integer);
public
constructor Create(const StartValue: string; StartCapacity: Integer = 1024;
ADelta: Integer = 1024);
end;
{ TStringBuilder }
constructor TStringBuilder.Create(const StartValue: string; StartCapacity,
ADelta: Integer);
begin
inherited Create;
FDelta := ADelta;
if FDelta < 16 then
FDelta := 16;
FLength := System.Length(StartValue);
if StartCapacity < FLength then
FBuffer := StartValue
else
begin
SetLength(FBuffer, StartCapacity);
if FLength > 0 then
Move(StartValue[1], FBuffer[1], FLength * SizeOf(Char));
end;
end;
procedure TStringBuilder.Append(const Args: array of string);
var
AddLen: Integer;
i: Integer;
Len: Integer;
begin
AddLen := 0;
for i := 0 to High(Args) do
Inc(AddLen, System.Length(Args[i]));
if AddLen = 0 then
Exit; // nothing to do
if FLength + AddLen > System.Length(FBuffer) then
Grow(AddLen);
for i := 0 to High(Args) do
begin
Len := System.Length(Args[i]);
Move(Args[i][1], FBuffer[FLength + 1], Len * SizeOf(Char));
Inc(FLength, Len);
end;
end;
procedure TStringBuilder.Append(const Text: string);
type
PRec3 = ^TRec3;
TRec3 = packed record
res1: Word;
res2: Byte;
end;
PRec5 = ^TRec5;
TRec5 = packed record
res1: LongWord;
res2: Byte;
end;
PRec6 = ^TRec6;
TRec6 = packed record
res1: LongWord;
res2: Word;
end;
PRec7 = ^TRec7;
TRec7 = packed record
res1: LongWord;
res2: Word;
res3: Byte;
end;
var
AddLen: Integer;
P: PChar;
begin
AddLen := System.Length(Text);
if AddLen > 0 then
begin
if FLength + AddLen > System.Length(FBuffer) then
Grow(AddLen);
P := Pointer(FBuffer);
Inc(P, FLength);
case AddLen of
1: P^ := Text[1];
2: PWord(P)^ := PWord(Text)^;
3: PRec3(P)^ := PRec3(Text)^;
4: PLongWord(P)^ := PLongWord(Text)^;
5: PRec5(P)^ := PRec5(Text)^;
6: PRec6(P)^ := PRec6(Text)^;
7: PRec7(P)^ := PRec7(Text)^;
8: PInt64(P)^ := PInt64(Text)^;
else
Move(Text[1], P^, AddLen * SizeOf(Char));
end;
Inc(FLength, AddLen);
end;
end;
function TStringBuilder.Capacity: Integer;
begin
Result := System.Length(FBuffer);
end;
function TStringBuilder.Length: Integer;
begin
Result := FLength;
end;
function TStringBuilder.GetValue: string;
begin
GetValue(Result);
end;
procedure TStringBuilder.GetValue(var Value: string);
begin
if FLength > 0 then
SetString(Value, PChar(Pointer(FBuffer)), FLength)
else
Value := '';
end;
procedure TStringBuilder.Grow(AddLen: Integer);
var
NewLen: Integer;
begin
NewLen := FLength + AddLen + FDelta;
SetLength(FBuffer, NewLen);
end;
function StringBuilder(const StartValue: string; StartCapacity: Integer = 1024;
ADelta: Integer = 1024): IStringBuilder;
begin
Result := TStringBuilder.Create(StartValue, StartCapacity, ADelta);
end;
function AnsiStartsFilename(const SubStr, S: string): Boolean;
begin
{$IFDEF MSWINDOWS}
Result := AnsiStartsText(SubStr, S);
{$ENDIF MSWINDOWS}
{$IFDEF LINUX}
Result := AnsiStartsStr(SubStr, S);
{$ENDIF LINUX}
end;
{$IFDEF MSWINDOWS}
function ParsePath(const Path: string): string;
var
i: Integer;
begin
Result := Path;
for i := 1 to Length(Result) do
if Result[i] = '/' then
Result[i] := '\';
end;
{$ENDIF MSWINDOWS}
{$IFDEF LINUX}
function ParsePath(const Path: string): string;
var
i: Integer;
begin
Result := Path;
for i := 1 to Length(Result) do
if Result[i] = '\' then
Result[i] := '/';
end;
{$ENDIF LINUX}
function RepeatStr(const S: string; Count: Integer): string;
var
sb: IStringBuilder;
begin
sb := StringBuilder('', Length(S) * Count);
while Count > 0 do
begin
sb.Append(S);
Dec(Count);
end;
sb.GetValue(Result);
end;
function IsEmptyStr(const S: string): Boolean;
var
i: Integer;
begin
Result := True;
if S <> '' then
begin
for i := 1 to Length(S) do
if S[i] >= #32 then
begin
Result := False;
Exit;
end;
end;
end;
function RemoveCommentChars(const S: string): string;
begin
if S <> '' then
begin
if S[1] = '{' then
Result := Copy(S, 2, Length(S) - 2)
else // '(*'
Result := Copy(S, 3, Length(S) - 3);
end
else
Result := '';
end;
function TrimCopy(const S: string; Index, Count: Integer): string;
var
Len, StartIndex, EndIndex: Integer;
begin
Result := '';
Len := Length(S);
if Index <= 0 then
Index := 1;
if Count > Len then
Count := Len;
if (Count > 0) and (Len > 0) then
begin
StartIndex := Index;
while (StartIndex <= Len) and (S[StartIndex] <= #32) do
Inc(StartIndex);
Dec(Count, StartIndex - Index);
EndIndex := StartIndex + Count - 1;
if EndIndex > Len then
begin
Dec(Count, EndIndex - Len);
EndIndex := Len;
end;
while (EndIndex > 0) and (S[EndIndex] <= #32) do
begin
Dec(EndIndex);
Dec(Count);
end;
if EndIndex >= StartIndex then
SetString(Result, PChar(Pointer(S)) + StartIndex - 1, Count);
end;
end;
procedure ReadFileToString(const Filename: string; var S: string);
var
fs: TFileStream;
begin
fs := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
try
SetLength(S, fs.Size);
if Length(S) > 0 then
fs.Read(S[1], Length(S));
finally
fs.Free;
end;
end;
procedure WriteFileFromString(const Filename, S: string);
var
fs: TFileStream;
begin
fs := TFileStream.Create(Filename, fmCreate);
try
if Length(S) > 0 then
fs.Write(S[1], Length(S));
finally
fs.Free;
end;
end;
function CutFirstDirectory(var Dir: string): string;
var
ps: Integer;
begin
ps := Pos(PathDelim, Dir);
if ps > 0 then
begin
Result := Copy(Dir, 1, ps - 1);
Delete(Dir, 1, ps);
end
else
begin
Result := Dir;
Dir := '';
end;
end;
function FollowRelativeFilename(const RootDir: string; RelFilename: string): string;
var
Dir: string;
begin
Result := RootDir;
while RelFilename <> '' do
begin
Dir := CutFirstDirectory(RelFilename);
if Dir = '..' then
Result := ExtractFileDir(Result)
else if Dir = '.' then
Continue
else
Result := Result + PathDelim + Dir;
end;
end;
procedure ConvertBinDfmToText(const Filename: string);
var
InStream, OutStream: TStream;
begin
OutStream := TMemoryStream.Create;
try
InStream := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
try
ObjectResourceToText(InStream, OutStream);
finally
InStream.Free;
end;
TMemoryStream(OutStream).SaveToFile(Filename); // overwrite file
finally
OutStream.Free;
end;
end;
end.