对具有扩展类型的二进制数据文件的多平台支持

Multi-platform support for binary data files with Extended type

我目前有以下代码支持从 Win32 保存在二进制文件中的 10 字节扩展值,并在其他平台上加载这些值。但是,对于 Android(它是 ARM 而不是 INTEL),我需要一些代码来在 10 字节内存中与 10 字节 IEEE 格式和编译器中的 "Extended" 类型进行相互转换(实际上是一个 8 字节的双精度数)。

TYPE
  TExtended     = TExtended80Rec;

{$IFDEF INTEL64 }
PROCEDURE ExtendedToIEEE(VAR D : Extended ; VAR E : TExtended); ASSEMBLER;
  ASM
                FLD     QWORD PTR [RCX]
                FSTP    TBYTE PTR [RDX]
                FWAIT
  END;

PROCEDURE IEEEToExtended(CONST E : TExtended ; VAR D : Extended); ASSEMBLER;
  ASM
                FLD     TBYTE PTR [RCX]
                FSTP    QWORD PTR [RDX]
                FWAIT
  END;
{$ELSE }
PROCEDURE ExtendedToIEEE(D : Extended ; VAR E : TExtended);
  BEGIN
    {$IF SizeOf(Extended)=SizeOf(TExtended) }
      MOVE(D,E,SizeOf(Extended))
    {$ELSE }
      !! MISSING !!
    {$ENDIF }
  END;

PROCEDURE IEEEToExtended(CONST E : TExtended ; VAR D : Extended);
  BEGIN
    {$IF SizeOf(Extended)=SizeOf(TExtended) }
      MOVE(E,D,SizeOf(Extended))
    {$ELSE }
      !! MISSING !!
    {$ENDIF }
  END;
{$ENDIF }

如果可能,我还希望能够从 MacOS/Linux 转换 to/from 16 字节 "Extended" 类型(除非 16 字节大小是 "just" 对齐,即 10 字节填充到 16).

在上面评论中大卫的帮助下,我想出了这个,并提供在这里以供将来参考:

TYPE
  TExtended     = TExtended80Rec;
  PExtended     = ^TExtended;

{$IF SizeOf(Extended)=SizeOf(TExtended) }
PROCEDURE ExtendedToIntel(VAR D : Extended ; VAR E : TExtended); INLINE;
  BEGIN
    D:=Extended(E)
  END;

PROCEDURE IntelToExtended(VAR E : TExtended ; VAR D : Extended); INLINE;
  BEGIN
    E:=TExtended(D)
  END;
{$ELSEIF DEFINED(WIN64) }
PROCEDURE ExtendedToIntel(VAR D : Extended {Double} ; VAR E : TExtended); ASSEMBLER;
  ASM
                FLD     QWORD PTR [RCX]
                FSTP    TBYTE PTR [RDX]
                FWAIT
  END;

PROCEDURE IntelToExtended(VAR E : TExtended ; VAR D : Extended {Double} ); ASSEMBLER;
  ASM
                FLD     TBYTE PTR [RCX]
                FSTP    QWORD PTR [RDX]
                FWAIT
  END;
{$ELSE }
PROCEDURE ExtendedToIntel(D : Extended ; VAR E : TExtended);
  BEGIN
    PExtended(@E)^:=TExtended(D)
  END;

PROCEDURE IntelToExtended(CONST E : TExtended ; VAR D : Extended);
  BEGIN
    D:=Double(PExtended(@E)^)
  END;
{$ENDIF }

TYPE
  TStreamHelper = CLASS HELPER FOR TStream
                    FUNCTION ReadExtended : Extended;
                    PROCEDURE WriteExtended(E : Extended);
                  END;

{$IF SizeOf(Extended)=SizeOf(TExtended) }
FUNCTION TStreamHelper.ReadExtended : Extended;
  BEGIN
    Read(Result,SizeOf(Extended))
  END;

PROCEDURE TStreamHelper.WriteExtended(E : Extended);
  BEGIN
    Write(E,SizeOf(Extended))
  END;
{$ELSE }
FUNCTION TStreamHelper.ReadExtended : Extended;
  VAR
    EX  : TExtended;

  BEGIN
    Read(EX,SizeOf(TExtended));
    IntelToExtended(EX,Result)
  END;

PROCEDURE TStreamHelper.WriteExtended(E : Extended);
  VAR
    EX  : TExtended;

  BEGIN
    ExtendedToIntel(E,EX);
    Write(EX,SizeOf(EX))
  END;
{$ENDIF }