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('What ever', '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('Whate ver', '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?
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('What
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('Whate
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?
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?
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
var
MySize : TSize;
IniFile : TIniFile;
begin
{$OVERFLOWCHECKS ON}
{$RANGECHECKS ON}
IniFile := TIniFile.Create('test.ini'
try
MySize := TSize(IniFile.ReadInteger(
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
try after reading
if not(MySize in TSize) then ...
meikl
ASKER
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
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
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
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
now i have it,
if (ord(MySize) < ord(low(TSize))) or (ord(MySize) > ord(high(TSize))) then ..{out of bounds}
meikl
ASKER
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?
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
try by read
MySize := TSize(IniFile.ReadInteger(
meikl