unit number_encodings; {$MODE OBJFPC} interface uses type_fixes, classes; function ReadType2Operand(aStream : TStream; b0: TByte) : Variant; function ReadOperand(aStream : TStream; b0 : TByte) : Variant; implementation uses sysutils; function ReadType2Operand(aStream : TStream; b0: TByte) : Variant; var fValue16 : TUINT16; fValue32 : TUINT32; begin if b0 = 28 then begin aStream.ReadBuffer(fValue16, Sizeof(fValue16)); ToHostByteOrderFromBigEndianM(fValue16); Result := fValue16; end else if b0 = 255 then begin aStream.ReadBuffer(fValue32, Sizeof(fValue32)); ToHostByteOrderFromBigEndianM(fValue32); Result := fValue32 / 65536.0; end else Result := ReadOperand(aStream, b0); end; function ReadFloatingPointBody(aStream : TStream) : Variant; var B_done : TBoolean; fText : shortstring; procedure ProcessNibble(aNibble : TByte); begin if aNibble < 10 then fText := fText + chr(ord('0') + aNibble) else if aNibble = $a then fText := fText + '.' else if aNibble = $b then fText := fText + 'E' else if aNibble = $c then fText := fText + 'E-' else if aNibble = $d then fText := fText // reserved else if aNibble = $e then fText := fText + '-' else if aNibble = $f then B_done := True; end; var fInput : TByte; begin fText := ''; B_done := False; while not B_done do begin fInput := aStream.ReadByte(); ProcessNibble(fInput shr 4); if not B_done then ProcessNibble(fInput and 7); end; Result := StrToFloat(fText); end; function ReadOperand(aStream : TStream; b0 : TByte) : Variant; var v : TUINT32; begin assert(b0 >= 29); // FIXME what about 31? if b0 = 29 then begin aStream.ReadBuffer(v, Sizeof(v)); ToHostByteOrderFromBigEndianM(v); Result := v end else if b0 = 30 then begin Result := ReadFloatingPointBody(aStream); end else if b0 < 247 then begin assert(b0 >= 32); Result := Integer(b0) - 139 end else if b0 < 251 then Result := (Integer(b0) - 247) * 256 + aStream.ReadByte() + 108 else if b0 < 255 then Result := -(Integer(b0) - 251) * 256 - aStream.ReadByte() - 108 else assert(False); end; end.