October 28, 2020, 05:48:50 AM

Author Topic: [bmx] Program settings with reflection by JoshK [ 1+ years ago ]  (Read 1081 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : Program settings with reflection
Author : JoshK
Posted : 1+ years ago

Description : This code will handle settings loading and saving automatically, with a nice interface for accessing the values in your program.

You can add fields to the TSettings type, or create an extended type with your fields.

The following types are supported:
float
double
int
string
int array
float array
double array

I didn't bother with string arrays, but it will probably work.

Here is what the saved settings file looks like:
Code: [Select]
greeting="Hello"
color=255,128,64


Code :
Code: BlitzMax
  1. SuperStrict
  2.  
  3. Import brl.reflection
  4. Import brl.stream
  5.  
  6. Type TSettings
  7.        
  8.         Field greeting:String="Hello"
  9.         Field color:Int[]=[255,128,64]
  10.        
  11.         Method Save:Int(url:Object)
  12.                 Local typeid:TTypeId
  13.                 Local f:TField
  14.                 Local stream:TStream
  15.                 Local o:Object
  16.                 Local otypeid:TTypeId
  17.                 Local etypeid:TTypeId
  18.                 Local n:Int
  19.                 Local element:Object
  20.                 Local value:String
  21.                
  22.                 stream=WriteStream(url)
  23.                 If Not stream Return False
  24.                
  25.                 typeid=TTypeId.ForObject(Self)
  26.                
  27.                 For f=EachIn typeid.enumfields()
  28.                        
  29.                         Select f._typeid
  30.                        
  31.                         Case IntTypeId
  32.                                 stream.WriteLine f.name()+"="+f.GetInt(Self)
  33.                        
  34.                         Case FloatTypeId,DoubleTypeId
  35.                                 stream.WriteLine f.name()+"="+f.GetFloat(Self)
  36.                        
  37.                         Case StringTypeId
  38.                                 stream.WriteLine f.name()+"=~q"+f.getstring(Self)+"~q"
  39.                        
  40.                         Default
  41.                                 If f._typeid.Extendstype(ArrayTypeId)
  42.                                         o=f.Get(Self)
  43.                                         otypeid=TTypeId.ForObject(o)
  44.                                         value=""
  45.                                         For n=0 To otypeid.ArrayLength(o)-1
  46.                                                 element=otypeid.GetArrayElement(o,n)
  47.                                                 If n>0 value:+","
  48.                                                 value:+String(element) 
  49.                                         Next
  50.                                         stream.WriteLine f.name()+"="+value
  51.                                 EndIf
  52.                         EndSelect
  53.                        
  54.                 Next
  55.                 stream.close()
  56.                
  57.                 Return True
  58.         EndMethod
  59.        
  60.         Method Load:Int(url:Object)
  61.                 Local map:TMap=New TMap
  62.                 Local p:Int
  63.                 Local key:String
  64.                 Local value:String
  65.                 Local typeid:TTypeId
  66.                 Local stream:TStream
  67.                 Local s:String
  68.                 Local f:TField
  69.                 Local fieldid:TTypeId
  70.                 Local o:Object
  71.                 Local otypeid:TTypeId
  72.                 Local sarr:String[]
  73.                 Local n:Int
  74.                
  75.                 stream=ReadStream(url)
  76.                 If Not stream Return False
  77.                
  78.                 'Load pairs into map
  79.                 While Not stream.Eof()
  80.                         s=stream.ReadLine()
  81.                         p=s.Find("=")
  82.                         If p>-1
  83.                                 key=s[..p]
  84.                                 value=s[p+1..]
  85.                                 map.insert key,value
  86.                         EndIf
  87.                 Wend
  88.                 stream.close()
  89.                
  90.                 typeid=TTypeId.ForObject(Self)
  91.                 For f=EachIn typeid.enumfields()
  92.                         key=f.name()
  93.                         If map.contains(key)
  94.                                 value=String(map.valueforkey(key))
  95.                                
  96.                                 Select f._typeId
  97.                                
  98.                                 Case StringTypeId
  99.                                         value=value[1..]
  100.                                         value=value[..value.length-1]
  101.                                         f.setstring(Self,value)
  102.                                
  103.                                 Case FloatTypeId
  104.                                         f.setstring(Self,Float(value))
  105.                                
  106.                                 Case DoubleTypeId
  107.                                         f.setstring(Self,Double(value))
  108.                                
  109.                                 Case IntTypeId
  110.                                         f.setstring(Self,Int(value))
  111.                                
  112.                                 Default
  113.                                         If f._typeid.Extendstype(ArrayTypeId)
  114.                                                 o=f.Get(Self)
  115.                                                 otypeid=TTypeId.ForObject(o)
  116.                                                 sarr=value.split(",")
  117.                                                 sarr=sarr[..otypeid.ArrayLength(o)]
  118.                                                 For n=0 To otypeid.ArrayLength(o)-1
  119.                                                         otypeid.SetArrayElement(o,n,sarr[n])
  120.                                                 Next
  121.                                         EndIf
  122.                                
  123.                                 EndSelect
  124.                         EndIf
  125.                 Next
  126.                
  127.                 Return True
  128.         EndMethod
  129.        
  130. EndType
  131.  
  132. Local settings:TSettings=New TSettings
  133. settings.Save("settings.cfg")
  134. settings.color=[0,0,0]
  135. settings.Load("settings.cfg")
  136. Print settings.greeting
  137. Print settings.color[0]+", "+settings.color[1]+", "+settings.color[2]
  138. End


Comments :


JoshK(Posted 1+ years ago)

 And this version will handle string arrays with quotes:
Code: [Select]
SuperStrict

Import brl.reflection
Import brl.stream

Type TSettings

Method Save:Int(url:Object)
Local typeid:TTypeId
Local f:TField
Local stream:TStream
Local o:Object
Local otypeid:TTypeId
Local etypeid:TTypeId
Local n:Int
Local element:Object
Local value:String

stream=WriteStream(url)
If Not stream Return False

typeid=TTypeId.ForObject(Self)

For f=EachIn typeid.enumfields()

Select f._typeid

Case IntTypeId
stream.WriteLine f.name()+"="+f.GetInt(Self)

Case FloatTypeId,DoubleTypeId
stream.WriteLine f.name()+"="+f.GetFloat(Self)

Case StringTypeId
stream.WriteLine f.name()+"=~q"+f.getstring(Self)+"~q"

Default
If f._typeid.Extendstype(ArrayTypeId)
o=f.Get(Self)
otypeid=TTypeId.ForObject(o)
value=""
For n=0 To otypeid.ArrayLength(o)-1
element=otypeid.GetArrayElement(o,n)
etypeid=otypeid.ElementType()
If n>0 value:+","
Select etypeid
Case StringTypeId
value:+"~q"+String(element)+"~q"
Default
value:+String(element)
EndSelect
Next
stream.WriteLine f.name()+"="+value
EndIf
EndSelect

Next
stream.close()

Return True
EndMethod

Method Load:Int(url:Object)
Local map:TMap=New TMap
Local p:Int
Local key:String
Local value:String
Local typeid:TTypeId
Local stream:TStream
Local s:String
Local f:TField
Local fieldid:TTypeId
Local o:Object
Local otypeid:TTypeId
Local etypeid:TTypeId
Local sarr:String[]
Local n:Int

stream=ReadStream(url)
If Not stream Return False

'Load pairs into map
While Not stream.Eof()
s=stream.ReadLine()
p=s.Find("=")
If p>-1
key=s[..p]
value=s[p+1..]
map.insert key,value
EndIf
Wend
stream.close()

typeid=TTypeId.ForObject(Self)
For f=EachIn typeid.enumfields()
key=f.name()
If map.contains(key)
value=String(map.valueforkey(key))

Select f._typeId

Case StringTypeId
value=value[1..]
value=value[..value.length-1]
f.setstring(Self,value)

Case FloatTypeId
f.setstring(Self,Float(value))

Case DoubleTypeId
f.setstring(Self,Double(value))

Case IntTypeId
f.setstring(Self,Int(value))

Default
If f._typeid.Extendstype(ArrayTypeId)
o=f.Get(Self)
otypeid=TTypeId.ForObject(o)
sarr=value.split(",")
sarr=sarr[..otypeid.ArrayLength(o)]
etypeid=otypeid.ElementType()
For n=0 To otypeid.ArrayLength(o)-1
If etypeid=StringTypeId
sarr[n]=sarr[n][1..]
sarr[n]=sarr[n][..sarr[n].length-1]
EndIf
otypeid.SetArrayElement(o,n,sarr[n])
Next
EndIf

EndSelect
EndIf
Next

Return True
EndMethod

EndType



JoshK(Posted 1+ years ago)

 This version has a Copy() method that will work on extended types, without adding a new method:
Code: [Select]
SuperStrict

Import brl.reflection
Import brl.stream

Type TSettings

Method Save:Int(url:Object)
Local typeid:TTypeId
Local f:TField
Local stream:TStream
Local o:Object
Local otypeid:TTypeId
Local etypeid:TTypeId
Local n:Int
Local element:Object
Local value:String

stream=WriteStream(url)
If Not stream Return False

typeid=TTypeId.ForObject(Self)

For f=EachIn typeid.enumfields()

Select f._typeid

Case IntTypeId
stream.WriteLine f.name()+"="+f.GetInt(Self)

Case FloatTypeId,DoubleTypeId
stream.WriteLine f.name()+"="+f.GetFloat(Self)

Case StringTypeId
stream.WriteLine f.name()+"=~q"+f.getstring(Self)+"~q"

Default
If f._typeid.Extendstype(ArrayTypeId)
o=f.Get(Self)
otypeid=TTypeId.ForObject(o)
value=""
For n=0 To otypeid.ArrayLength(o)-1
element=otypeid.GetArrayElement(o,n)
etypeid=otypeid.ElementType()
If n>0 value:+","
Select etypeid
Case StringTypeId
value:+"~q"+String(element)+"~q"
Default
value:+String(element)
EndSelect
Next
stream.WriteLine f.name()+"="+value
EndIf
EndSelect

Next
stream.close()

Return True
EndMethod

Method Copy:TSettings()
Local settings:TSettings
Local bank:TBank=CreateBank()
Local stream:TStream=CreateBankStream(bank)
Local typeid:TTypeId=TTypeId.ForObject(Self)

Save(stream)
stream=CreateBankStream(bank)

settings=TSettings(typeid.NewObject())
settings.Load(stream)

Return settings
EndMethod

Method Load:Int(url:Object)
Local map:TMap=New TMap
Local p:Int
Local key:String
Local value:String
Local typeid:TTypeId
Local stream:TStream
Local s:String
Local f:TField
Local fieldid:TTypeId
Local o:Object
Local otypeid:TTypeId
Local etypeid:TTypeId
Local sarr:String[]
Local n:Int

stream=ReadStream(url)
If Not stream Return False

'Load pairs into map
While Not stream.Eof()
s=stream.ReadLine()
p=s.Find("=")
If p>-1
key=s[..p]
value=s[p+1..]
map.insert key,value
EndIf
Wend
stream.close()

typeid=TTypeId.ForObject(Self)
For f=EachIn typeid.enumfields()
key=f.name()
If map.contains(key)
value=String(map.valueforkey(key))

Select f._typeId

Case StringTypeId
value=value[1..]
value=value[..value.length-1]
f.setstring(Self,value)

Case FloatTypeId
f.setstring(Self,Float(value))

Case DoubleTypeId
f.setstring(Self,Double(value))

Case IntTypeId
f.setstring(Self,Int(value))

Default
If f._typeid.Extendstype(ArrayTypeId)
o=f.Get(Self)
otypeid=TTypeId.ForObject(o)
sarr=value.split(",")
sarr=sarr[..otypeid.ArrayLength(o)]
etypeid=otypeid.ElementType()
For n=0 To otypeid.ArrayLength(o)-1
If etypeid=StringTypeId
sarr[n]=sarr[n][1..]
sarr[n]=sarr[n][..sarr[n].length-1]
EndIf
otypeid.SetArrayElement(o,n,sarr[n])
Next
EndIf

EndSelect
EndIf
Next

Return True
EndMethod

EndType


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal