[new] range和size都支持固定大小或者区间段 xxx=value 或 xxx=[a,b] 的写法
parent
665b9a4cea
commit
699b5a167a
|
|
@ -0,0 +1,145 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Luban.Job.Cfg.Validators
|
||||||
|
{
|
||||||
|
internal class Range
|
||||||
|
{
|
||||||
|
private readonly string _str;
|
||||||
|
|
||||||
|
private long? _min;
|
||||||
|
private long? _max;
|
||||||
|
|
||||||
|
private double? _mind;
|
||||||
|
private double? _maxd;
|
||||||
|
|
||||||
|
private bool _includeMinBound;
|
||||||
|
|
||||||
|
private bool _includeMaxBound;
|
||||||
|
|
||||||
|
public Range(string strRange)
|
||||||
|
{
|
||||||
|
_str = strRange.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string RawStr => _str;
|
||||||
|
|
||||||
|
private bool TryParse(string s, ref long? x)
|
||||||
|
{
|
||||||
|
s = s.Trim();
|
||||||
|
if (string.IsNullOrEmpty(s))
|
||||||
|
{
|
||||||
|
x = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (long.TryParse(s, out var v))
|
||||||
|
{
|
||||||
|
x = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryParse(string s, ref double? x)
|
||||||
|
{
|
||||||
|
s = s.Trim();
|
||||||
|
if (string.IsNullOrEmpty(s))
|
||||||
|
{
|
||||||
|
x = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (double.TryParse(s, out var v))
|
||||||
|
{
|
||||||
|
x = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Compile()
|
||||||
|
{
|
||||||
|
void ThrowError()
|
||||||
|
{
|
||||||
|
throw new Exception($"range定义不合法");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (long.TryParse(_str, out long value))
|
||||||
|
{
|
||||||
|
// size=xxxx
|
||||||
|
_min = _max = value;
|
||||||
|
_mind = _maxd = value;
|
||||||
|
_includeMinBound = _includeMaxBound = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_str.Length <= 2)
|
||||||
|
{
|
||||||
|
ThrowError();
|
||||||
|
}
|
||||||
|
switch (_str[0])
|
||||||
|
{
|
||||||
|
case '[': _includeMinBound = true; break;
|
||||||
|
case '(': _includeMinBound = false; break;
|
||||||
|
default: ThrowError(); break;
|
||||||
|
}
|
||||||
|
switch (_str[^1])
|
||||||
|
{
|
||||||
|
case ']': _includeMaxBound = true; break;
|
||||||
|
case ')': _includeMaxBound = false; break;
|
||||||
|
default: ThrowError(); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pars = _str[1..^1].Split(',');
|
||||||
|
if (pars.Length != 2)
|
||||||
|
{
|
||||||
|
ThrowError();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p1 = TryParse(pars[0], ref _min);
|
||||||
|
bool p2 = TryParse(pars[0], ref _mind);
|
||||||
|
bool p3 = TryParse(pars[1], ref _max);
|
||||||
|
bool p4 = TryParse(pars[1], ref _maxd);
|
||||||
|
|
||||||
|
if ((!p1 && !p2) || (!p3 && !p4))
|
||||||
|
{
|
||||||
|
ThrowError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool CheckInLongRange(long x)
|
||||||
|
{
|
||||||
|
if (_min is long m && (_includeMinBound ? m > x : m >= x))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_max is long n && (_includeMaxBound ? n < x : n <= x))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckInDoubleRange(double x)
|
||||||
|
{
|
||||||
|
if (_mind is double m && (_includeMinBound ? m > x : m >= x))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_maxd is double n && (_includeMaxBound ? n < x : n <= x))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,128 +11,17 @@ namespace Luban.Job.Cfg.Validators
|
||||||
{
|
{
|
||||||
public TType Type { get; }
|
public TType Type { get; }
|
||||||
|
|
||||||
private readonly string _str;
|
private Range _range;
|
||||||
|
|
||||||
private long? _min;
|
|
||||||
private long? _max;
|
|
||||||
|
|
||||||
private double? _mind;
|
|
||||||
private double? _maxd;
|
|
||||||
|
|
||||||
private bool _includeMinBound;
|
|
||||||
|
|
||||||
private bool _includeMaxBound;
|
|
||||||
|
|
||||||
public RangeValidator(TType type, string strRange)
|
public RangeValidator(TType type, string strRange)
|
||||||
{
|
{
|
||||||
Type = type;
|
Type = type;
|
||||||
_str = strRange.Trim();
|
_range = new Range(strRange);
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryParse(string s, ref long? x)
|
|
||||||
{
|
|
||||||
s = s.Trim();
|
|
||||||
if (string.IsNullOrEmpty(s))
|
|
||||||
{
|
|
||||||
x = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (long.TryParse(s, out var v))
|
|
||||||
{
|
|
||||||
x = v;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryParse(string s, ref double? x)
|
|
||||||
{
|
|
||||||
s = s.Trim();
|
|
||||||
if (string.IsNullOrEmpty(s))
|
|
||||||
{
|
|
||||||
x = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (double.TryParse(s, out var v))
|
|
||||||
{
|
|
||||||
x = v;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Compile(DefFieldBase def)
|
public void Compile(DefFieldBase def)
|
||||||
{
|
{
|
||||||
void ThrowError()
|
_range.Compile();
|
||||||
{
|
|
||||||
throw new Exception($"结构:{ def.HostType.FullName } 字段: { def.Name} range 定义:{_str} 不合法");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_str.Length <= 2)
|
|
||||||
{
|
|
||||||
ThrowError();
|
|
||||||
}
|
|
||||||
switch (_str[0])
|
|
||||||
{
|
|
||||||
case '[': _includeMinBound = true; break;
|
|
||||||
case '(': _includeMinBound = false; break;
|
|
||||||
default: ThrowError(); break;
|
|
||||||
}
|
|
||||||
switch (_str[^1])
|
|
||||||
{
|
|
||||||
case ']': _includeMaxBound = true; break;
|
|
||||||
case ')': _includeMaxBound = false; break;
|
|
||||||
default: ThrowError(); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pars = _str[1..^1].Split(',');
|
|
||||||
if (pars.Length != 2)
|
|
||||||
{
|
|
||||||
ThrowError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool p1 = TryParse(pars[0], ref _min);
|
|
||||||
bool p2 = TryParse(pars[0], ref _mind);
|
|
||||||
bool p3 = TryParse(pars[1], ref _max);
|
|
||||||
bool p4 = TryParse(pars[1], ref _maxd);
|
|
||||||
|
|
||||||
if ((!p1 && !p2) || (!p3 && !p4))
|
|
||||||
{
|
|
||||||
ThrowError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private bool CheckInLongRange(long x)
|
|
||||||
{
|
|
||||||
if (_min is long m && (_includeMinBound ? m > x : m >= x))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_max is long n && (_includeMaxBound ? n < x : n <= x))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckInDoubleRange(double x)
|
|
||||||
{
|
|
||||||
if (_mind is double m && (_includeMinBound ? m > x : m >= x))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_maxd is double n && (_includeMaxBound ? n < x : n <= x))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Source => ValidatorContext.CurrentVisitor.CurrentValidateRecord.Source;
|
public string Source => ValidatorContext.CurrentVisitor.CurrentValidateRecord.Source;
|
||||||
|
|
@ -142,7 +31,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
var assembly = ctx.Assembly;
|
var assembly = ctx.Assembly;
|
||||||
void LogError()
|
void LogError()
|
||||||
{
|
{
|
||||||
assembly.Agent.Error("记录 {0}:{1} (来自文件:{2}) 不在范围:{3}内", ValidatorContext.CurrentRecordPath, data, Source, _str);
|
assembly.Agent.Error("记录 {0}:{1} (来自文件:{2}) 不在范围:{3}内", ValidatorContext.CurrentRecordPath, data, Source, _range.RawStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.IsNullable && data == null)
|
if (type.IsNullable && data == null)
|
||||||
|
|
@ -154,7 +43,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
{
|
{
|
||||||
case DByte b:
|
case DByte b:
|
||||||
{
|
{
|
||||||
if (!CheckInLongRange(b.Value))
|
if (!_range.CheckInLongRange(b.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
@ -163,7 +52,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DFshort s:
|
case DFshort s:
|
||||||
{
|
{
|
||||||
if (!CheckInLongRange(s.Value))
|
if (!_range.CheckInLongRange(s.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
@ -172,7 +61,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DShort s:
|
case DShort s:
|
||||||
{
|
{
|
||||||
if (!CheckInLongRange(s.Value))
|
if (!_range.CheckInLongRange(s.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
@ -181,7 +70,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DInt i:
|
case DInt i:
|
||||||
{
|
{
|
||||||
if (!CheckInLongRange(i.Value))
|
if (!_range.CheckInLongRange(i.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
@ -190,7 +79,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DFint i:
|
case DFint i:
|
||||||
{
|
{
|
||||||
if (!CheckInLongRange(i.Value))
|
if (!_range.CheckInLongRange(i.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
@ -199,7 +88,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DLong l:
|
case DLong l:
|
||||||
{
|
{
|
||||||
if (!CheckInLongRange(l.Value))
|
if (!_range.CheckInLongRange(l.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
@ -208,7 +97,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DFlong fl:
|
case DFlong fl:
|
||||||
{
|
{
|
||||||
if (!CheckInLongRange(fl.Value))
|
if (!_range.CheckInLongRange(fl.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
@ -217,7 +106,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DFloat ff:
|
case DFloat ff:
|
||||||
{
|
{
|
||||||
if (!CheckInDoubleRange(ff.Value))
|
if (!_range.CheckInDoubleRange(ff.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
@ -226,7 +115,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DDouble dd:
|
case DDouble dd:
|
||||||
{
|
{
|
||||||
if (!CheckInDoubleRange(dd.Value))
|
if (!_range.CheckInDoubleRange(dd.Value))
|
||||||
{
|
{
|
||||||
LogError();
|
LogError();
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,16 @@ namespace Luban.Job.Cfg.Validators
|
||||||
[Validator("size")]
|
[Validator("size")]
|
||||||
internal class SizeValidator : IValidator
|
internal class SizeValidator : IValidator
|
||||||
{
|
{
|
||||||
private readonly int _size;
|
private Range _range;
|
||||||
|
|
||||||
public SizeValidator(TType type, string rule)
|
public SizeValidator(TType type, string rule)
|
||||||
{
|
{
|
||||||
this._size = int.Parse(rule);
|
_range = new Range(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Compile(DefFieldBase def)
|
public void Compile(DefFieldBase def)
|
||||||
{
|
{
|
||||||
|
_range.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string Source => ValidatorContext.CurrentVisitor.CurrentValidateRecord.Source;
|
private static string Source => ValidatorContext.CurrentVisitor.CurrentValidateRecord.Source;
|
||||||
|
|
@ -31,7 +31,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
var assembly = ctx.Assembly;
|
var assembly = ctx.Assembly;
|
||||||
void LogError(int size)
|
void LogError(int size)
|
||||||
{
|
{
|
||||||
assembly.Agent.Error("记录 {0}:{1} (来自文件:{2}) size:{3},但要求为 {4} ", ValidatorContext.CurrentRecordPath, data, Source, size, _size);
|
assembly.Agent.Error("记录 {0}:{1} (来自文件:{2}) size:{3},但要求为 {4} ", ValidatorContext.CurrentRecordPath, data, Source, size, _range.RawStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.IsNullable && data == null)
|
if (type.IsNullable && data == null)
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
{
|
{
|
||||||
case DArray b:
|
case DArray b:
|
||||||
{
|
{
|
||||||
if (b.Datas.Count != _size)
|
if (!_range.CheckInLongRange(b.Datas.Count))
|
||||||
{
|
{
|
||||||
LogError(b.Datas.Count);
|
LogError(b.Datas.Count);
|
||||||
return;
|
return;
|
||||||
|
|
@ -52,7 +52,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DList b:
|
case DList b:
|
||||||
{
|
{
|
||||||
if (b.Datas.Count != _size)
|
if (!_range.CheckInLongRange(b.Datas.Count))
|
||||||
{
|
{
|
||||||
LogError(b.Datas.Count);
|
LogError(b.Datas.Count);
|
||||||
return;
|
return;
|
||||||
|
|
@ -61,7 +61,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DSet b:
|
case DSet b:
|
||||||
{
|
{
|
||||||
if (b.Datas.Count != _size)
|
if (!_range.CheckInLongRange(b.Datas.Count))
|
||||||
{
|
{
|
||||||
LogError(b.Datas.Count);
|
LogError(b.Datas.Count);
|
||||||
return;
|
return;
|
||||||
|
|
@ -70,7 +70,7 @@ namespace Luban.Job.Cfg.Validators
|
||||||
}
|
}
|
||||||
case DMap b:
|
case DMap b:
|
||||||
{
|
{
|
||||||
if (b.Datas.Count != _size)
|
if (!_range.CheckInLongRange(b.Datas.Count))
|
||||||
{
|
{
|
||||||
LogError(b.Datas.Count);
|
LogError(b.Datas.Count);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace Luban.Job.Common.Utils
|
||||||
{
|
{
|
||||||
++braceDepth;
|
++braceDepth;
|
||||||
}
|
}
|
||||||
else if (c == ')' || c == ')' || c == '}')
|
else if (c == ')' || c == ']' || c == '}')
|
||||||
{
|
{
|
||||||
--braceDepth;
|
--braceDepth;
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +119,7 @@ namespace Luban.Job.Common.Utils
|
||||||
{
|
{
|
||||||
++braceDepth;
|
++braceDepth;
|
||||||
}
|
}
|
||||||
else if (c == ')' || c == ')' || c == '}')
|
else if (c == ')' || c == ']' || c == '}')
|
||||||
{
|
{
|
||||||
--braceDepth;
|
--braceDepth;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue