Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-08

Extended, Currency and TDateTime memory layout

10 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

I am interfacing with a server written in Delphi via network and it sends over data. The server sends some data types, and among the hardest ones to read are Currency and TDateTime.

The server is undocumented and does some strange transformations of the data using RTTI to pass properties.

I always though that Currency was a special kind of integer type, but it seams that RTTI will return tkFloat for it under Delphi. Where is the internal memory layout of Currency documented? Where is it declared in the compiler? I couldn't find it...

Similarly, it seams that most often TDateTime=double. Any docs on the memory layout of TDateTime?

Before sending the data over, the application seams to convert both types to Extended ... any docs on the memory layout of that? I am trying to convert the data that the server sends into a readable number, but it doesn't seam to work, so maybe the memory layout of this would help ...

A snap of what kind of stuff the server does:

var
  FloatProp: Extended;
  PropCnt, I: Integer;
  PropList: PPropList;
  ....
begin
...
    PropCnt := GetPropList(Result,PropList);
    for I := 0 to PropCnt - 1 do begin
      case PropList[I].PropType^^.Kind of
        ....
        tkFloat: begin
          Stream.Read(FloatProp, SizeOf(FloatProp));
          SetFloatProp(Result, PropList[i], FloatProp);
        end;

Plus, the Extended type is limited to x86 or does it also exist under x86_64? As in having the same memory layout...

If it doesn't exist, does anyone know a function to read/write an extended even without hardware support?

thanks,

Felipe Monteiro de Carvalho

Reply by email

Michael Van Canneyt
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 13 lines
Hello, I am interfacing with a server written in Delphi via network and it sends over data. The server sends some data types, and among the hardest ones to read are Currency and TDateTime. The server is undocumented and does some strange transformations of the data using RTTI to pass properties. I always though that Currency was a special kind of integer type, but it seams that RTTI will return tkFloat for it under Delphi. Where is the internal memory layout of Currency documented? Where is it declared in the compiler? I couldn't find it...

Strange, because tkCurrency exists ?

A currency is a Int64, which is the currency amount multiplied by 10000.

Similarly, it seams that most often TDateTime=double. Any docs on the memory layout of TDateTime?

TDateTime IS a double.

The integer part is the number of days since 1/1/1900 The fractional part is the fraction of the day passed since 0:0

I believe this is documented.
I also think this is not a Borland invention, but is introduced by Microsoft for variant datetime values.

Michael.

Reply by email

Marco van de Voort
to Michael Van Canneyt

In our previous episode, Michael Van Canneyt said:

Show quoted text 6 lines
> Similarly, it seams that most often TDateTime=double. Any docs on the > memory layout of TDateTime? TDateTime IS a double. The integer part is the number of days since 1/1/1900

No, since 12/30/1899. While the above definition was originally meant, it was adjusted later to account for (very) old Excels not handling leapyears well. So when they corrected leapyear handling, they adjusted the startdate to remain compatble with the older excels.

I also think this is not a Borland invention, but is introduced by Microsoft for variant datetime values.

Afaik it comes from Excel, and got into COM that way.

Reply by email

Felipe Monteiro de Carvalho
to Marco van de Voort

For single and double there is a nice converter which shows the binary layout:

http://babbage.cs.qc.edu/IEEE-754/Decimal.html

Unfortunately there seams to be much less resources about extended...

Michael Van Canneyt wrote
Strange, because tkCurrency exists ? A currency is a Int64, which is the currency amount multiplied by 10000.

Well, apparently Delphi 6 RTTI thinks that it is a float. Check this code:

471	          else if ElmTypeInfo.Kind in [tkFloat] then begin
472	            case TypeData.FloatType of
473	              ftSingle: Stream.Write(DynArray^, ArrayLength *
SizeOf(Single));
474	              ftDouble: Stream.Write(DynArray^, ArrayLength *
SizeOf(Double));
475	              ftComp: Stream.Write(DynArray^, ArrayLength * SizeOf(Comp));
476	              ftCurr: Stream.Write(DynArray^, ArrayLength *
SizeOf(Currency));
477	              ftExtended: Stream.Write(DynArray^, ArrayLength *
SizeOF(Extended));
478	            end;

But this code is in another part of the program.

For that particular part it simply converts any float type to extended, which was a pretty nasty thing to do.

Felipe Monteiro de Carvalho

Reply by email

Zaher Dirkey
to Felipe Monteiro de Carvalho

On Sat, Aug 7, 2010 at 9:56 PM, Felipe Monteiro de Carvalho <

Show quoted text 20 lines
wrote: > A currency is a Int64, which is the currency amount multiplied by 10000. Well, apparently Delphi 6 RTTI thinks that it is a float. Check this code: 471 else if ElmTypeInfo.Kind in [tkFloat] then begin 472 case TypeData.FloatType of 473 ftSingle: Stream.Write(DynArray^, ArrayLength * SizeOf(Single)); 474 ftDouble: Stream.Write(DynArray^, ArrayLength * SizeOf(Double)); 475 ftComp: Stream.Write(DynArray^, ArrayLength * SizeOf(Comp)); 476 ftCurr: Stream.Write(DynArray^, ArrayLength * SizeOf(Currency)); 477 ftExtended: Stream.Write(DynArray^, ArrayLength * SizeOF(Extended)); 478 end;

A Currency is a Int64 not float, if you assign currency to float variable (double/extended) and return back to currency variable, you will not get the same value.
Typecast the currency as Int64, assign it to int64 variable and vise versa you will not lose any thing.

Best regards

Zaher Dirkey

Reply by email

Felipe Monteiro de Carvalho
to Zaher Dirkey
Zaher Dirkey wrote
A Currency is a Int64 not float, if you assign currency to float variable (double/extended) and return back to currency variable, you will not get the same value.

Yes, but I didn't write the server .... I just need to interface with it's strange messages =) In general it works ok, but the Currency converted to Extended is giving me some headaches ...

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho

Hello,

I managed to read the extended by putting it in a program like this:

procedure TForm1.Button1Click(Sender: TObject);
var
  Hex: array[0..9] of Byte;
  Num: Extended;
begin
  Hex[0] := $00;
  Hex[1] := $00;
  Hex[2] := $00;
  Hex[3] := $00;
  Hex[4] := $00;
  Hex[5] := $00;
  Hex[6] := $00;
  Hex[7] := $80;
  Hex[8] := $FD;
  Hex[9] := $3F;
  Num := Extended(Hex);
  Caption := FloatToStr(Num);
end;

And that just confirms it, yep, the server converts the currency to extended ...

Felipe Monteiro de Carvalho

Reply by email

Felipe Monteiro de Carvalho
to Zaher Dirkey: On Sat, Aug 7, 2010 at 9:56 PM, Felipe Monteiro de Carvalho < A Currency is a Int64 not…
Zaher Dirkey wrote
A Currency is a Int64 not float, if you assign currency to float variable (double/extended) and return back to currency variable, you will not get the same value.

Interresting enough, the exact same value is returned. From my research on this subject a floating point is something like:

Sign bit || exponent bits || decimal places

Num = sign * (2^(exponent - offset) + decimal places)

And the server only sends numbers like: 0,25; 0,5; 1; 2; 4; etc

All those numbers can be fully represented using the exponent, so the double conversion maintains them exactly the same.

Felipe Monteiro de Carvalho

Reply by email

Marc Weustink
to Felipe Monteiro de Carvalho: For single and double there is a nice converter which shows the binary layout:…
Felipe Monteiro de Carvalho wrote 7 lines
On Fri, Aug 6, 2010 at 4:52 PM, Michael Van Canneyt wrote: > Strange, because tkCurrency exists ? > > A currency is a Int64, which is the currency amount multiplied by 10000. Well, apparently Delphi 6 RTTI thinks that it is a float. Check this code:

A currency being a float type makes some sense. IIRC the Comp type was used to represent currency, a fixed point number with 5 decimals. This Comp type was defined and calculated in the numeric coprocessor (like all other floatingpoint types)
Therefore older versions of Delphi see this as float (iirc)

Marc

Reply by email

Bart
to Marc Weustink
From D3 Help:

The Currency type is a fixed-point data type suitable for monetary calculations.
It is stored as a scaled 64-bit integer with the four least-significant digits implicitly representing four decimal places.

Bart

Reply by email