📄 jclwideformat.pas
字号:
if (Low(CharClassTable) <= C) and (C <= High(CharClassTable)) then
State := StateTable[State, CharClassTable[C]]
else
State := StateTable[State, ccOther];
case State of
stError:
raise FormatSyntaxError(Src); // syntax error at index [Src]
stBeginAcc:
begin
// Begin accumulating characters to copy to Result
P := @Format[Src];
CharCount := 1;
end;
stAcc:
Inc(CharCount);
stPercent:
begin
if CharCount > 0 then
begin
// Copy accumulated characters into result
EnsureResultLen(Dest + CharCount - 1, ResultLen);
MoveWideChar(P^, Result[Dest], CharCount);
Inc(Dest, CharCount);
CharCount := 0;
end;
// Prepare a new format string
Width := 0;
Prec := NoPrecision;
FormatStart := Src;
LeftAlign := False;
end;
stDigit:
begin
// We read into Width, but we might actually be reading the ArgIndex
// value. If that turns out to be the case, it gets addressed in the
// stColon state below and Width is reset to its default value, 0.
Width := Width * 10 + Cardinal(Ord(C) - Ord('0'));
end;
stPrecDigit:
begin
if Prec = NoPrecision then
Prec := 0;
Prec := Prec * 10 + Cardinal(Ord(C) - Ord('0'));
end;
stStar, stPrecStar:
begin
if ArgIndex > Cardinal(High(Args)) then
raise FormatNoArgumentError(ArgIndex);
Arg := @Args[ArgIndex];
if State = stStar then
PrecWidth := @Width
else
PrecWidth := @Prec;
// PrecWidth^ := Args[ArgIndex++]
case Arg^.VType of
vtInteger:
PrecWidth^ := Arg^.VInteger;
{$IFDEF FORMAT_EXTENSIONS}
vtVariant:
PrecWidth^ := Arg^.VVariant^;
vtInt64:
PrecWidth^ := Arg^.VInt64^;
{$ENDIF FORMAT_EXTENSIONS}
else
raise FormatBadArgumentTypeError(Arg.VType, ArgIndex, AllowedStarTypes);
end;
Inc(ArgIndex);
end;
stColon:
begin
ArgIndex := Width;
Width := 0;
end;
stDash:
LeftAlign := True;
stDot: ;
stFloat, stInt, stPointer, stString:
begin
if ArgIndex > Cardinal(High(Args)) then
raise FormatNoArgumentErrorEx(Format, FormatStart, Src, ArgIndex);
Arg := @Args[ArgIndex];
case State of
stFloat:
begin
// The floating-point formats are all similar. The conversion
// eventually happens in FloatToText.
case Arg.VType of
vtExtended:
begin
ValueType := fvExtended;
FloatVal := Arg.VExtended;
end;
vtCurrency:
begin
ValueType := fvCurrency;
FloatVal := Arg.VCurrency;
end;
{$IFDEF FORMAT_EXTENSIONS}
vtVariant:
begin
// We can't give FloatToText a pointer to a Variant, so we
// extract the Variant's value and point to a temporary value
// instead.
if VarType(Arg.VVariant^) and varCurrency <> 0 then
begin
TempCurr := Arg.VVariant^;
FloatVal := @TempCurr;
ValueType := fvCurrency;
end
else
begin
TempExt := Arg.VVariant^;
FloatVal := @TempExt;
ValueType := fvExtended;
end;
end;
{$ENDIF FORMAT_EXTENSIONS}
else
raise FormatBadArgumentTypeErrorEx(Format, FormatStart, Src, Arg.VType, ArgIndex, AllowedFloatTypes);
end; // case Arg.VType
case C of
'e', 'E':
FloatFormat := ffExponent;
'f', 'F':
FloatFormat := ffFixed;
'g', 'G':
FloatFormat := ffGeneral;
'm', 'M':
FloatFormat := ffCurrency;
else {'n', 'N':}
FloatFormat := ffNumber;
end;
P := @Buffer;
// Prec is interpeted differently depending on the format.
if FloatFormat in [ffGeneral, ffExponent] then
begin
if (Prec = NoPrecision) or (Prec > MaxFloatPrecision) then
Prec := DefaultGeneralPrecision;
AnsiCount := FloatToText(P, FloatVal^, ValueType, FloatFormat, Prec, GeneralDigits);
end
else {[ffFixed, ffNumber, ffCurrency]}
begin
if (Prec = NoPrecision) or (Prec > MaxFloatPrecision) then
begin
if FloatFormat = ffCurrency then
Prec := SysUtils.CurrencyDecimals
else
Prec := DefaultFixedDigits;
end;
AnsiCount := FloatToText(P, FloatVal^, ValueType, FloatFormat, FixedPrecision, Prec);
end;
CharCount := AnsiCount;
Wide := False;
end;
stInt:
begin
if (C = 'x') or (C = 'X') then
Base := 16
else
Base := 10;
case Arg^.VType of
vtInteger {$IFDEF FORMAT_EXTENSIONS}, vtVariant {$ENDIF}:
begin
{$IFDEF FORMAT_EXTENSIONS}
if Arg^.VType <> vtInteger then
Temp32 := Arg^.VVariant^
else
{$ENDIF FORMAT_EXTENSIONS}
Temp32 := Cardinal(Arg^.VInteger);
// The value may be signed and negative, but the converter only
// interprets unsigned values.
Neg := ((C = 'd') or (C = 'D')) and (Integer(Temp32) < 0);
if Neg then
SafeNegate32(Integer(Temp32));
P := @Buffer[High(Buffer)];
CharCount := ConvertInt32(Temp32, Base, PWideChar(P));
end;
vtInt64:
begin
Temp64 := Arg^.VInt64^;
// The value may be signed and negative, but the converter only
// interprets unsigned values.
Neg := ((C = 'd') or (C = 'D')) and (Temp64 < 0);
if Neg then
SafeNegate64(Temp64);
P := @Buffer[High(Buffer)];
CharCount := ConvertInt64(Temp64, Base, PWideChar(P));
end;
else
raise FormatBadArgumentTypeErrorEx(Format, FormatStart, Src, Arg.VType, ArgIndex, AllowedIntegerTypes);
end;
// If Prec was specified, then we need to see whether any
// zero-padding is necessary
if Prec > MaxIntPrecision then
Prec := NoPrecision;
if Prec <> NoPrecision then
while Prec > CharCount do
begin
Dec(PWideChar(P));
PWideChar(P)^ := '0';
Inc(CharCount);
end;
if Neg then
begin
Dec(PWideChar(P));
PWideChar(P)^ := '-';
Inc(CharCount);
end;
Assert(PWideChar(P) >= @Buffer);
Wide := True;
end;
stPointer:
begin
// The workings are similar to the integer-converting code above,
// but the pointer specifier accepts a few more types that make it
// worth writing separate code.
if Arg.VType in AllowedPointerTypes then
begin
P := @Buffer[High(Buffer)];
CharCount := ConvertInt32(Cardinal(Arg.VInteger), 16, PWideChar(P));
end
else
raise FormatBadArgumentTypeErrorEx(Format, FormatStart, Src, Arg.VType, ArgIndex, AllowedPointerTypes);
// Prec is ignored. Alternatively, it is assumed to be 8
while (2 * SizeOf(Pointer)) > CharCount do
begin
Dec(PWideChar(P));
PWideChar(P)^ := '0';
Inc(CharCount);
end;
Assert(PWideChar(P) >= @Buffer);
Wide := True;
end; // stPointer case
else {stString:}
begin
Wide := Arg^.VType in [vtWideChar, vtPWideChar, vtBoolean, vtVariant, vtWideString];
case Arg^.VType of
vtChar, vtWideChar:
begin
Assert(@Arg^.VChar = @Arg^.VWideChar);
P := @Arg^.VChar;
CharCount := 1;
end;
vtString:
begin
CharCount := Length(Arg^.VString^);
P := @Arg^.VString^[1];
end;
vtPChar, vtPWideChar:
begin
P := Arg^.VPChar;
if Wide then
CharCount := StrLenW(P)
else
CharCount := StrLen(P);
end;
vtVariant{$IFDEF FORMAT_EXTENSIONS}, vtBoolean{$ENDIF}:
begin
{$IFDEF FORMAT_EXTENSIONS}
if Arg^.VType = vtBoolean then
TempWS := BooleanToStr(Arg^.VBoolean)
else
{$ENDIF FORMAT_EXTENSIONS}
TempWS := Arg^.VVariant^;
CharCount := Length(TempWS);
P := Pointer(TempWS);
end;
{$IFDEF FORMAT_EXTENSIONS}
vtClass:
begin
P := GetPClassName(Arg^.VClass);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -