Override FieldLoader to not crash on invalid input; Implemented for settings loading.
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user