Override FieldLoader to not crash on invalid input; Implemented for settings loading.

This commit is contained in:
Paul Chote
2010-07-11 17:52:01 +12:00
parent af71f564e9
commit d680956b02
2 changed files with 69 additions and 15 deletions

View File

@@ -27,6 +27,16 @@ namespace OpenRA.FileFormats
{ {
public static class FieldLoader public static class FieldLoader
{ {
public static Func<string,Type,string,object> InvalidValueAction = (s,t,f) =>
{
throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s,f,t) );
};
public static Action<string,Type> UnknownFieldAction = (s,f) =>
{
throw new NotImplementedException( "FieldLoader: Missing field `{0}` on `{1}`".F( s, f.Name ) );
};
public static void Load(object self, IniSection ini) public static void Load(object self, IniSection ini)
{ {
foreach (var x in ini) foreach (var x in ini)
@@ -59,22 +69,39 @@ namespace OpenRA.FileFormats
public static void LoadField( object self, string key, string value ) public static void LoadField( object self, string key, string value )
{ {
var field = self.GetType().GetField( key.Trim() ); var field = self.GetType().GetField( key.Trim() );
if( field == null ) if( field == null )
throw new NotImplementedException( "Missing field `{0}` on `{1}`".F( key.Trim(), self.GetType().Name ) ); UnknownFieldAction(key.Trim(), self.GetType());
field.SetValue( self, GetValue( field.FieldType, value ) ); else
field.SetValue( self, GetValue( field.Name, field.FieldType, value ) );
} }
public static object GetValue( Type fieldType, string x ) public static object GetValue( string field, Type fieldType, string x )
{ {
if (x != null) x = x.Trim(); if (x != null) x = x.Trim();
if( fieldType == typeof( int ) ) if( fieldType == typeof( int ) )
return int.Parse( x ); {
int res;
if (int.TryParse(x,out res))
return res;
return InvalidValueAction(x,fieldType, field);
}
else if( fieldType == typeof( ushort ) ) else if( fieldType == typeof( ushort ) )
return ushort.Parse( x ); {
ushort res;
if (ushort.TryParse(x,out res))
return res;
return InvalidValueAction(x,fieldType, field);
}
else if (fieldType == typeof(float)) else if (fieldType == typeof(float))
return float.Parse(x.Replace("%","")) * (x.Contains( '%' ) ? 0.01f : 1f); {
float res;
if (float.TryParse(x.Replace("%",""), out res))
return res * (x.Contains( '%' ) ? 0.01f : 1f);
return InvalidValueAction(x,fieldType, field);
}
else if (fieldType == typeof(string)) else if (fieldType == typeof(string))
return x; return x;
@@ -82,14 +109,21 @@ namespace OpenRA.FileFormats
else if (fieldType == typeof(System.Drawing.Color)) else if (fieldType == typeof(System.Drawing.Color))
{ {
var parts = x.Split(','); var parts = x.Split(',');
if (parts.Length != 3)
return InvalidValueAction(x,fieldType, field);
return System.Drawing.Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2])); return System.Drawing.Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]));
} }
else if (fieldType.IsEnum) else if (fieldType.IsEnum)
{
if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower()))
return InvalidValueAction(x,fieldType, field);
return Enum.Parse(fieldType, x, true); return Enum.Parse(fieldType, x, true);
}
else if (fieldType == typeof(bool)) else if (fieldType == typeof(bool))
return ParseYesNo(x); return ParseYesNo(x, fieldType, field);
else if (fieldType.IsArray) else if (fieldType.IsArray)
{ {
@@ -100,7 +134,7 @@ namespace OpenRA.FileFormats
var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length); var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
for (int i = 0; i < parts.Length; i++) for (int i = 0; i < parts.Length; i++)
ret.SetValue(GetValue(fieldType.GetElementType(), parts[i].Trim()), i); ret.SetValue(GetValue(field, fieldType.GetElementType(), parts[i].Trim()), i);
return ret; return ret;
} }
else if (fieldType == typeof(int2)) else if (fieldType == typeof(int2))
@@ -108,18 +142,19 @@ namespace OpenRA.FileFormats
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return new int2(int.Parse(parts[0]), int.Parse(parts[1])); return new int2(int.Parse(parts[0]), int.Parse(parts[1]));
} }
else
throw new InvalidOperationException("FieldLoader: don't know how to load field of type " + fieldType.ToString()); UnknownFieldAction("[Type] {0}".F(x),fieldType);
return null;
} }
static bool ParseYesNo( string p ) static object ParseYesNo( string p, System.Type fieldType, string field )
{ {
p = p.ToLowerInvariant(); p = p.ToLowerInvariant();
if( p == "yes" ) return true; if( p == "yes" ) return true;
if( p == "true" ) return true; if( p == "true" ) return true;
if( p == "no" ) return false; if( p == "no" ) return false;
if( p == "false" ) return false; if( p == "false" ) return false;
throw new InvalidOperationException(); return InvalidValueAction(p,fieldType, field);
} }
} }

View File

@@ -69,6 +69,22 @@ namespace OpenRA.GameRules
defaults = new UserSettings(); defaults = new UserSettings();
SettingsFile = Game.SupportDir + "settings.yaml"; SettingsFile = Game.SupportDir + "settings.yaml";
// Override settings loading to not crash
var err1 = FieldLoader.UnknownFieldAction;
var err2 = FieldLoader.InvalidValueAction;
FieldLoader.InvalidValueAction = (s,t,f) =>
{
object ret = defaults.GetType().GetField(f).GetValue(defaults);
System.Console.WriteLine("FieldLoader: Cannot parse `{0}` into `{2}:{1}`; substituting default `{3}`".F(s,t.Name,f,ret) );
return ret;
};
FieldLoader.UnknownFieldAction = (s,f) =>
{
System.Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
};
if (File.Exists(SettingsFile)) if (File.Exists(SettingsFile))
{ {
System.Console.WriteLine("Loading settings file {0}",SettingsFile); System.Console.WriteLine("Loading settings file {0}",SettingsFile);
@@ -79,6 +95,9 @@ namespace OpenRA.GameRules
foreach (var f in this.GetType().GetFields()) foreach (var f in this.GetType().GetFields())
if (args.Contains(f.Name)) if (args.Contains(f.Name))
OpenRA.FileFormats.FieldLoader.LoadField( this, f.Name, args.GetValue(f.Name, "") ); OpenRA.FileFormats.FieldLoader.LoadField( this, f.Name, args.GetValue(f.Name, "") );
FieldLoader.UnknownFieldAction = err1;
FieldLoader.InvalidValueAction = err2;
} }
public void Save() public void Save()