{ This file is part of the Free Pascal run time library. Copyright (c) 2004 by Marco van de Voort member of the Free Pascal development team. An implementation for unit convutils, which converts between units and simple combinations of them. Based on a guessed interface derived from some programs on the web. (Like Marco Cantu's EuroConv example), so things can be a bit Delphi incompatible. Also part on Delphibasics.co.uk. Quantities are mostly taken from my HP48g/gx or the unix units program This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} unit convutils; interface {$mode objfpc} {$H+} {$ifndef FPUNONE} Type TConvType = type Integer; TConvFamily = type Integer; TConvFamilyArray = array of TConvFamily; TConvTypeArray = array of TConvType; TConversionProc = function(const AValue: Double): Double; TConvUtilFloat = double; Function RegisterConversionFamily(Const S : String):TConvFamily; Function RegisterConversionType(Fam:TConvFamily;Const S:String;Value:TConvUtilFloat):TConvType; function Convert ( const Measurement : Double; const FromType, ToType : TConvType ) :TConvUtilFloat; function Convert ( const Measurement : Double; const FromType1, FromType2, ToType1, ToType2 : TConvType ) :TConvUtilFloat; function ConvFamilyToDescription(const AFamily: TConvFamily): string; function ConvTypeToDescription(const AType: TConvType): string; procedure GetConvFamilies(out AFamilies: TConvFamilyArray); procedure GetConvTypes(const AFamily: TConvFamily; out ATypes: TConvTypeArray); Type TConvTypeInfo = Class(Tobject) private FDescription : String; FConvFamily : TConvFamily; FConvType : TConvType; public Constructor Create(Const AConvFamily : TConvFamily;const ADescription:String); function ToCommon(const AValue: Double) : Double; virtual; abstract; function FromCommon(const AValue: Double) : Double; virtual; abstract; property ConvFamily : TConvFamily read FConvFamily; property ConvType : TConvType read FConvType; property Description: String read FDescription; end; TConvTypeFactor = class(TConvTypeInfo) private FFactor: Double; protected property Factor: Double read FFactor; public constructor Create(const AConvFamily: TConvFamily; const ADescription: string; const AFactor: Double); function ToCommon(const AValue: Double): Double; override; function FromCommon(const AValue: Double): Double; override; end; TConvTypeProcs = class(TConvTypeInfo) private FToProc: TConversionProc; FFromProc: TConversionProc; public constructor Create(const AConvFamily: TConvFamily; const ADescription: string; const AToProc, AFromProc: TConversionProc); function ToCommon(const AValue: Double): Double; override; function FromCommon(const AValue: Double): Double; override; end; Implementation Type ResourceData = record Description : String; Value : TConvUtilFloat; Fam : TConvFamily; end; var TheUnits : array of ResourceData =nil; TheFamilies : array of string =nil; function ConvFamilyToDescription(const AFamily: TConvFamily): string; begin result:=''; if AFamilyTheFamilies[i]) do inc(i); if i=l Then begin SetLength(TheFamilies,l+1); TheFamilies[l]:=s; end; Result:=i; end; end; Function CheckFamily(i:TConvFamily):Boolean; begin Result:=i=l1 then exit(false); r:=theunits[thetype]; result:=true; end; function Convert ( const Measurement : Double; const FromType, ToType : TConvType ) :TConvUtilFloat; var fromrec,torec : resourcedata; begin if not SearchConvert(fromtype,fromrec) then exit(-1.0); // raise exception? if not SearchConvert(totype,torec) then exit(-1.0); // raise except? if fromrec.fam<>torec.fam then exit(-1.0); result:=Measurement*fromrec.value/torec.value; end; function Convert ( const Measurement : Double; const FromType1, FromType2, ToType1, ToType2 : TConvType ) :TConvUtilFloat; var fromrec1,fromrec2,torec1 , torec2 : resourcedata; begin if not SearchConvert(fromtype1,fromrec1) then exit(-1.0); // raise exception? if not SearchConvert(totype1,torec1) then exit(-1.0); // raise except? if not SearchConvert(fromtype2,fromrec2) then exit(-1.0); // raise exception? if not SearchConvert(totype2,torec2) then exit(-1.0); // raise except? if (fromrec1.fam<>torec1.fam) or (fromrec1.fam<>torec1.fam) then exit(-1.0); result:=Measurement*(fromrec1.value/fromrec2.value)/(torec1.value/torec2.value); end; Constructor TConvTypeInfo.Create(Const AConvFamily : TConvFamily;const ADescription:String); begin FDescription:=ADescription; FConvFamily :=AConvFamily; end; constructor TConvTypeFactor.Create(const AConvFamily: TConvFamily; const ADescription: string;const AFactor: Double); begin inherited create(AConvFamily,ADescription); FFactor:=AFactor; end; function TConvTypeFactor.ToCommon(const AValue: Double): Double; begin result:=AValue * FFactor; end; function TConvTypeFactor.FromCommon(const AValue: Double): Double; begin result:=AValue / FFactor; end; constructor TConvTypeProcs.Create(const AConvFamily: TConvFamily; const ADescription: string; const AToProc, AFromProc: TConversionProc); begin inherited create(AConvFamily,ADescription); ftoproc:=AToProc; ffromproc:=AFromProc; end; function TConvTypeProcs.ToCommon(const AValue: Double): Double; begin result:=FTOProc(Avalue); end; function TConvTypeProcs.FromCommon(const AValue: Double): Double; begin result:=FFromProc(Avalue); end; finalization setlength(theunits,0); setlength(thefamilies,0); {$else} implementation {$endif} end.