Link to home
Start Free TrialLog in
Avatar of andrewjackson
andrewjackson

asked on

Make user-defined types persistent

Say I've a user-defined type and variable of that type

type  TSize = (szUndefined, szSmall, szMedium, szLarge, szXLarge)

var   MySize : TSize

When the app shutsdown I'd like to save the value of MySize to an IniFile (or anywhere else) so I've got to convert  MySize to some simple type that IniFile recognizes e.g. an integer:

MySize := szMedium;
IniFile.WriteInteger('Whatever', 'Size', Ord(MySize));

creates a file of this format
[Whatever]
Size=1

The 'Ord' function makes this code very neat but there doesn't seem to be an elegant way of reading the value again, the best I can think of is :

case IniFile.ReadInteger('Whatever', 'Size', Ord(szUndefined)) of
   Ord(szSmall) : MySize := szSmall;
   Ord(szMedium) : MySize := szMedium;
   Ord(szLarge) : MySize := szLarge;
   Ord(szXLarge) : MySize := szXLarge;
end;

If TSize is ever extended the 'write' code will not need to change but the 'read' code will just get bigger.  I could declare szMedium etc. as integer constants but I think making them user-defined types enforces stronger type-checking so I'd like to stick with it.

Any suggestions?
Avatar of kretzschmar
kretzschmar
Flag of Germany image

hi andrewjackson,

try by read

MySize := TSize(IniFile.ReadInteger('Whatever', 'Size', Ord(szUndefined)));

meikl

Avatar of andrewjackson
andrewjackson

ASKER

meikl,

So easy, why didn't I think of that!

There is still one potential problem though which I can't seem to workaround.  I want to handle the error condition where the integer value stored in the the ini file is out of bounds.  I'd have expected Delphi to raise an exception in this case but it doesn't.  I've written the following routine..

procedure TForm1.Button1Click(Sender: TObject);
var
   MySize : TSize;
   IniFile : TIniFile;
begin
{$OVERFLOWCHECKS ON}
{$RANGECHECKS ON}
   IniFile := TIniFile.Create('test.ini');
   try
     MySize := TSize(IniFile.ReadInteger('Whatever', 'Size', Ord(szUndefined)));
     ShowMessage(MySize is ' + IntToStr(Ord(MySize)))
   finally
     Inifile.Free;
   end;
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
end;


Range and overflow checking are both on but if the 'Size' field in the ini file is set to say 10 then no exception is generated.  If I inspect the value of MySize after the assignment the debugger displays

'MySize = (out of bound) 10'

I could add my own check :

if (Ord(MySize) < Ord(szUndefined)) or
   (Ord(MySize) > Ord(szXLarge)) then
  begin
    ERROR
  end

but again this check would need to be updated if TSize is ever extended.

Any suggestions?
hi andrewjackson,

try after reading

if not(MySize in TSize) then ...

meikl
No I've already tried that and it won't compile.

I've also tried High and Low but these aren't valid for user defined types.

Andrew
hi andrewjackson,

you've right,

but this should work

if not(MySize in [szUndefined..szXLarge]) then ..

of course you can new values insert only between this two.
Not the best solution, i will look to a better one

meikl
hi andrewjackson,

you've right,

but this should work

if not(MySize in [szUndefined..szXLarge]) then ..

of course you can new values insert only between this two.
Not the best solution, i will look to a better one

meikl
hi andrewjackson,

now i have it,

    if (ord(MySize) < ord(low(TSize))) or (ord(MySize) > ord(high(TSize))) then ..{out of bounds}

meikl
Thanks, that it now.

I want to give you the points but you've only posted a comment not proposed an answer so I'm not sure how to close this thread and give you the reward.

Any ideas?
ASKER CERTIFIED SOLUTION
Avatar of kretzschmar
kretzschmar
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial