public ArraySegment(ModelPath path, ObjectFilter filter, int?index = null) : base(path) { if (!index.HasValue && filter == null) { throw new ArgumentException("index must have a value when not using a filter"); } Index = index; Filter = filter; }
internal ModelPath(ModelPathContext context, string modelPath) { Context = context; var segments = new List <PathSegment>(); var i = 0; int start; while (i < modelPath.Length) { var c = modelPath[i]; switch (c) { case '[': if (RootObjectName == null) { RootObjectName = modelPath.Substring(0, i); } Increment(ref i); c = modelPath[i]; int? index; string propertyName; switch (c) { case '(': Increment(ref i); EatWhiteSpace(ref i); c = modelPath[i]; ObjectFilter filter = null; while (c != ')') { switch (c) { case '\'': Increment(ref i); propertyName = GetPropertyName(ref i); if (string.IsNullOrEmpty(propertyName)) { throw new ArgumentException("bad path"); } Increment(ref i); break; default: var s = i; while (char.IsLetterOrDigit(c) || c == '_') { Increment(ref i); c = modelPath[i]; } if (s == i) { throw new ArgumentException("bad path"); } propertyName = modelPath.Substring(s, i - s); break; } EatWhiteSpace(ref i); if (modelPath[i] != '=') { throw new ArgumentException("bad path"); } Increment(ref i); if (modelPath[i] != '=') { throw new ArgumentException("bad path"); } Increment(ref i); EatWhiteSpace(ref i); string value; c = modelPath[i]; switch (c) { case '\'': Increment(ref i); value = GetPropertyName(ref i); Increment(ref i); break; default: start = i; var integerValue = 0; while (char.IsDigit(c)) { integerValue = integerValue * 10 + (c - '0'); Increment(ref i); c = modelPath[i]; } if (start == i) { throw new ArgumentException("only integers allowed in unescaped filter values"); } value = integerValue.ToString(); break; } var propertyFilter = new PropertyFilter(propertyName, value); EatWhiteSpace(ref i); c = modelPath[i]; if (c == '&') { Increment(ref i); if (modelPath[i] != '&') { throw new ArgumentException("bad path"); } Increment(ref i); EatWhiteSpace(ref i); if (modelPath[i] == ')') { throw new ArgumentException("bad path"); } } filter = filter?.And(propertyFilter) ?? propertyFilter; c = modelPath[i]; } if (filter == null) { throw new ArgumentException("bad path"); } Increment(ref i); if (modelPath[i] != ']') { throw new ArgumentException("bad path"); } index = null; if (i + 2 < modelPath.Length && modelPath[i + 1] == '[' && char.IsDigit(modelPath[i + 2])) { i += 2; c = modelPath[i]; index = 0; while (char.IsDigit(c)) { index = index * 10 + (c - '0'); Increment(ref i); c = modelPath[i]; } if (c != ']') { throw new ArgumentException("only digits in non-filter brackets"); } } segments.Add(new ArraySegment(this, filter, index)); break; case ']': throw new ArgumentException("no empty brackets"); case '\'': Increment(ref i); propertyName = GetPropertyName(ref i); if (string.IsNullOrEmpty(propertyName)) { throw new ArgumentException("bad path"); } segments.Add(new PropertySegment(this, propertyName)); Increment(ref i); if (modelPath[i] != ']') { throw new ArgumentException("bad path"); } break; default: index = 0; while (char.IsDigit(c)) { index = index * 10 + (c - '0'); Increment(ref i); c = modelPath[i]; } if (c != ']') { throw new ArgumentException("only digits in non-filter brackets"); } segments.Add(new ArraySegment(this, index.GetValueOrDefault())); break; } break; case '.': if (RootObjectName == null) { RootObjectName = modelPath.Substring(0, i); } Increment(ref i); start = i; while (i < modelPath.Length && char.IsLetterOrDigit((c = modelPath[i])) || c == '_') { ++i; } if (i == start) { throw new ArgumentException("bad path"); } segments.Add(new PropertySegment(this, modelPath.Substring(start, i - start))); --i; break; } ++i; } if (RootObjectName == null) { throw new ArgumentException("bad path"); } Segments = new ReadOnlyCollection <PathSegment>(segments); // Local functions void Increment(ref int value) { ++value; if (value >= modelPath.Length) { throw new ArgumentException("bad path"); } } string GetPropertyName(ref int value) { var sb = new StringBuilder(); var c = modelPath[value]; while (c != '\'') { if (c == '\\') { ++value; if (value >= modelPath.Length) { throw new ArgumentException("bad path"); } c = modelPath[value]; if (c != '\\' && c != '\'') { throw new ArgumentException("bad escape character"); } sb.Append(c); break; } sb.Append(c); ++value; if (value >= modelPath.Length) { throw new ArgumentException("bad path"); } c = modelPath[value]; } return(sb.ToString()); } void EatWhiteSpace(ref int index, bool throwAtEnd = true) { while (index < modelPath.Length ? char.IsWhiteSpace(modelPath[index]) : (throwAtEnd ? throw new ArgumentException("bad path") : false)) { ++index; } } }