You are not logged in.
Using Delphi XE2, 32-bit target:
For the minimum Int64 value of -9223372036854775808, StrInt64() returns an invalid result (however StrInt32 works fine for the minimum 32 bit value):
program StrToInt64Bug;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SynCommons,
System.SysUtils;
procedure DoInt32ToStr(Value: Integer);
var
tmp: array[0..23] of AnsiChar;
output: array[0..23] of AnsiChar;
P: PAnsiChar;
T: PAnsiChar;
Len: Integer;
begin
FillChar(tmp, SizeOf(tmp), 0);
T := @tmp[23];
P := StrInt32(T, Value);
Len := T-P;
FillChar(output, SizeOf(output), 0);
move(P[0],output[0],Len);
Writeln;
Writeln('SynCommons.StrInt32(', Value, ') = ', output);
end;
procedure DoInt64ToStr(Value: Int64);
var
tmp: array[0..23] of AnsiChar;
output: array[0..23] of AnsiChar;
P: PAnsiChar;
T: PAnsiChar;
Len: Integer;
begin
FillChar(tmp, SizeOf(tmp), 0);
T := @tmp[23];
P := StrInt64(T, Value);
Len := T-P;
FillChar(output, SizeOf(output), 0);
move(P[0],output[0],Len);
Writeln;
Writeln('SynCommons.StrInt64(', Value, ') = ', output);
end;
var
Value32: Integer;
Value64: Int64;
begin
try
// 32 bit
Value32 := Low(Integer);
Writeln('Low(Integer) = ', Value32);
DoInt32ToStr(Value32);
Writeln;
Value32 := Low(Int32)+1;
Writeln('Low(Int32)+1 = ', Value32);
DoInt32ToStr(Value32);
Writeln;
// 64 bit
Value64 := Low(Int64);
Writeln('Low(Int64) = ', Value64);
DoInt64ToStr(Value64);
Writeln;
Value64 := Low(Int64)+1;
Writeln('Low(Int64)+1 = ', Value64);
DoInt64ToStr(Value64);
Writeln;
Writeln;
Writeln('Press ENTER to continue...');
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Last edited by avista (2014-05-07 05:23:01)
Offline
AFAIK Int64ToUtf8(-9223372036854775808) just does not compile under Delphi 7.
Sounds more like a compiler bug...
The following tests do pass:
Check(Int64ToUtf8(-maxInt)='-2147483647');
Check(Int64ToUtf8(-1)='-1');
Check(Int64ToUtf8(-9223372036854775807)='-9223372036854775807');
Offline
Int64ToUtf8(-9223372036854775808) works under XE2, however I'm using this conversion with text based record serialization, which fails and returns garbage:
procedure DoTestRec;
type
TTestRec = packed record
aInt64: Int64;
end;
const
__TestRec = 'aInt64 Int64';
var
Rec: TTestRec;
Json: RawUTF8;
begin
TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TTestRec), __TestRec);
Rec.aInt64 := -9223372036854775808;
Json := RecordSaveJSON(Rec, TypeInfo(TTestRec));
Writeln(Json);
end;
{"aInt64":-E'#0'Ü›F'#0'D›E'#0'T˜'#0#0'F'#0'h›ü'#$1A'}
1 more than the minimum value returns the correct JSON:
{"aInt64":-9223372036854775807}
I traced the call to the following routine, which is why I created the small test application in my previous email:
procedure TTextWriter.Add(Value: Int64);
var tmp: array[0..23] of AnsiChar;
P: PAnsiChar;
Len: integer;
begin
if B+24>=BEnd then
Flush;
{$ifdef CPU64}
P := StrInt32(@tmp[23],Value); // StrInt32 use PtrInt, i.e. Int64
{$else}
P := StrInt64(@tmp[23],Value);
{$endif}
Len := @tmp[23]-P;
move(P[0],B[1],Len);
inc(B,Len);
end;
Thanks
Last edited by avista (2014-05-07 15:25:09)
Offline
I think we found the problem, and fixed the issue.
See http://synopse.info/fossil/info/9da5910e5c
Thanks for the report!
Offline
Thanks, I've confirmed that this fixes the problem.
Offline