对具有扩展类型的二进制数据文件的多平台支持
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 }
我目前有以下代码支持从 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 }