Added: X2UtNamedFormat
Added: SE_CREATE_GLOBAL_NAME constant
This commit is contained in:
parent
5556e69a2d
commit
6d5d37bdf8
183
X2UtNamedFormat.pas
Normal file
183
X2UtNamedFormat.pas
Normal 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.
|
@ -200,6 +200,7 @@ uses
|
|||||||
|
|
||||||
const
|
const
|
||||||
WindowClass = 'X2UtSingleInstance.Window';
|
WindowClass = 'X2UtSingleInstance.Window';
|
||||||
|
SE_CREATE_GLOBAL_NAME = 'SeCreateGlobalPrivilege';
|
||||||
|
|
||||||
|
|
||||||
var
|
var
|
||||||
|
Loading…
Reference in New Issue
Block a user