1
0
mirror of synced 2024-12-22 17:23:07 +01:00

Added: X2UtNamedFormat

Added: SE_CREATE_GLOBAL_NAME constant
This commit is contained in:
Mark van Renswoude 2008-03-17 06:10:11 +00:00
parent 5556e69a2d
commit 6d5d37bdf8
2 changed files with 185 additions and 1 deletions

183
X2UtNamedFormat.pas Normal file
View File

@ -0,0 +1,183 @@
{
:: X2UtNamedFormat implements Format-style functionality using named
:: instead of indexed parameters.
::
:: Last changed: $Date$
:: Revision: $Rev$
:: Author: $Author$
}
unit X2UtNamedFormat;
interface
{
AFormat uses the same format strings as SysUtils.Format, where each
format specifier may use a named instead of a numeric index.
AParams contains alternating the parameter name and it's value.
Note: NamedFormat works by mapping names to indices and passing the result
to SysUtils.Format. Unnamed specifiers will therefore be affected by
named specifiers! It is recommended to name all specifiers.
}
function NamedFormat(const AFormat: String; AParams: array of const): String;
implementation
uses
Classes,
SysUtils;
type
TProtectedMemoryStream = class(TMemoryStream);
const
SpecifierChar = '%';
ValidNameChars = ['A'..'Z', 'a'..'z', '0'..'9'];
procedure StreamWriteChar(const AStream: TStream; const AValue: Char);
begin
AStream.WriteBuffer(AValue, SizeOf(Char));
end;
procedure StreamWriteString(const AStream: TStream; const AValue: String);
begin
AStream.WriteBuffer(PChar(AValue)^, Length(AValue));
end;
function FindNameEnd(const APosition: PChar; const AEnd: PChar): PChar;
var
position: PChar;
begin
Result := nil;
position := APosition;
while position < AEnd do
begin
if position^ = ':' then
begin
Result := position;
break;
end;
if not (position^ in ValidNameChars) then
break;
Inc(position);
end;
end;
function NamedFormat(const AFormat: String; AParams: array of const): String;
var
currentPos: PChar;
formatEnd: PChar;
formatStream: TMemoryStream;
formatString: String;
name: String;
nameEnd: PChar;
nameStart: PChar;
param: TVarRec;
paramIndex: Integer;
paramNames: TStringList;
paramValues: array of TVarRec;
specifierIndex: Integer;
begin
if Length(AParams) mod 2 = 1 then
raise Exception.Create('AParams must contains a multiple of 2 number of items');
currentPos := PChar(AFormat);
SetLength(paramValues, 0);
formatEnd := currentPos;
Inc(formatEnd, Length(AFormat));
paramNames := TStringList.Create();
try
paramNames.CaseSensitive := False;
formatStream := TMemoryStream.Create();
try
{ Most likely scenario; the names are longer than the replacement
indexes. }
TProtectedMemoryStream(formatStream).Capacity := Length(AFormat);
while currentPos < formatEnd do
begin
{ Search for % }
if currentPos^ = SpecifierChar then
begin
StreamWriteChar(formatStream, currentPos^);
Inc(currentPos);
{ Check if this is not an escape character }
if (currentPos < formatEnd) and (currentPos^ <> SpecifierChar) then
begin
nameStart := currentPos;
nameEnd := FindNameEnd(currentPos, formatEnd);
if Assigned(nameEnd) then
begin
SetString(name, nameStart, nameEnd - nameStart);
specifierIndex := paramNames.IndexOf(name);
if specifierIndex = -1 then
specifierIndex := paramNames.Add(name);
StreamWriteString(formatStream, IntToStr(specifierIndex));
currentPos := nameEnd;
end;
end;
end;
StreamWriteChar(formatStream, currentPos^);
Inc(currentPos);
end;
SetString(formatString, PChar(formatStream.Memory), formatStream.Size);
finally
FreeAndNil(formatStream);
end;
SetLength(paramValues, paramNames.Count);
paramIndex := 0;
while paramIndex < High(AParams) do
begin
param := AParams[paramIndex];
case param.VType of
vtChar: name := param.VChar;
vtString: name := param.VString^;
vtPChar: name := param.VPChar;
vtAnsiString: name := PChar(param.VAnsiString);
else
raise Exception.CreateFmt('Parameter name at index %d is not a string value',
[paramIndex div 2]);
end;
Inc(paramIndex);
specifierIndex := paramNames.IndexOf(name);
if specifierIndex = -1 then
raise Exception.CreateFmt('Parameter "%s" could not be found in the format string',
[name]);
paramValues[specifierIndex] := AParams[paramIndex];
Inc(paramIndex);
end;
finally
FreeAndNil(paramNames);
end;
Result := Format(formatString, paramValues);
end;
end.

View File

@ -200,6 +200,7 @@ uses
const const
WindowClass = 'X2UtSingleInstance.Window'; WindowClass = 'X2UtSingleInstance.Window';
SE_CREATE_GLOBAL_NAME = 'SeCreateGlobalPrivilege';
var var