Example #1
0
            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;
            }
Example #2
0
        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;
                }
            }
        }