/// <summary>
        /// Descendants iterator
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        private static IEnumerable <TokenSequence> DescendantsIterator(TokenSequence source)
        {
            if (ModelSubsequencer.IsPrimitive(source))
            {
                yield break;
            }

            if (ModelSubsequencer.IsObject(source))
            {
                foreach (KeyValuePair <DataName, TokenSequence> property in ModelSubsequencer.Properties(source, null))
                {
                    yield return(property.Value);

                    foreach (TokenSequence descendant in ModelSubsequencer.Descendants(property.Value))
                    {
                        yield return(descendant);
                    }
                }
                yield break;
            }

            if (ModelSubsequencer.IsArray(source))
            {
                foreach (TokenSequence item in ModelSubsequencer.ArrayItems(source, null))
                {
                    yield return(item);

                    foreach (TokenSequence descendant in ModelSubsequencer.Descendants(item))
                    {
                        yield return(descendant);
                    }
                }
                yield break;
            }
        }
 /// <summary>
 /// Gets all properties of the root object
 /// </summary>
 /// <param name="source"></param>
 /// <param name="predicate"></param>
 /// <returns>all properties for the object</returns>
 public static TokenSequence Property(this TokenSequence source, DataName propertyName)
 {
     using (var enumerator = ModelSubsequencer.Properties(source, name => (name == propertyName)).GetEnumerator())
     {
         // effectively FirstOrDefault()
         return(enumerator.MoveNext() ? enumerator.Current.Value : null);
     }
 }
 private static IEnumerable <TokenSequence> SplitValuesIterator(TokenSequence source)
 {
     using (var stream = Stream <ModelToken> .Create(source))
     {
         while (!stream.IsCompleted)
         {
             yield return(ModelSubsequencer.SpliceNextValue(stream));
         }
     }
 }
        /// <summary>
        /// DescendantsAndSelf iterator
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        private static IEnumerable <TokenSequence> DescendantsAndSelfIterator(TokenSequence source)
        {
            // and self
            yield return(source);

            foreach (TokenSequence descendant in ModelSubsequencer.DescendantsIterator(source))
            {
                yield return(descendant);
            }
        }
        /// <summary>
        /// Covers the sitation where a stream of sequences may be back to back
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        internal static IEnumerable <TokenSequence> SplitValues(this TokenSequence source)
        {
            if (source == null)
            {
                return(new TokenSequence[0]);
            }

            if (!(source is IList <ModelToken>))
            {
                // ensure buffered
                source = new SequenceBuffer <ModelToken>(source);
            }

            return(ModelSubsequencer.SplitValuesIterator(source));
        }
        /// <summary>
        /// Gets all descendant values below the current root, as well as the current root
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IEnumerable <TokenSequence> DescendantsAndSelf(this TokenSequence source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (!(source is IList <ModelToken>))
            {
                // ensure buffered
                source = new SequenceBuffer <ModelToken>(source);
            }

            return(ModelSubsequencer.DescendantsAndSelfIterator(source));
        }
        /// <summary>
        /// Gets the items of the root array with indexes satisfying the <paramref name="predicate"/>
        /// </summary>
        /// <param name="source"></param>
        /// <param name="predicate"></param>
        /// <returns>items of the root array which statisfy the predicate</returns>
        public static IEnumerable <TokenSequence> ArrayItems(this TokenSequence source, Func <int, bool> predicate)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (!(source is IList <ModelToken>))
            {
                // ensure buffered
                source = new SequenceBuffer <ModelToken>(source);
            }

            return(ModelSubsequencer.ArrayItemsIterator(source, predicate));
        }
        /// <summary>
        /// Gets the properties of the root object which satisfies the <paramref name="predicate"/>
        /// </summary>
        /// <param name="source"></param>
        /// <param name="predicate"></param>
        /// <returns>matching properties for the root object</returns>
        public static IEnumerable <KeyValuePair <DataName, TokenSequence> > Properties(this TokenSequence source, Func <DataName, bool> predicate)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (!(source is IList <ModelToken>))
            {
                // ensure buffered
                source = new SequenceBuffer <ModelToken>(source);
            }

            return(ModelSubsequencer.PropertiesIterator(source, predicate));
        }
        /// <summary>
        /// ArrayItems iterator
        /// </summary>
        /// <param name="source"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        private static IEnumerable <TokenSequence> ArrayItemsIterator(TokenSequence source, Func <int, bool> predicate)
        {
            IStream <ModelToken> stream = Stream <ModelToken> .Create(source);

            if (stream.IsCompleted)
            {
                yield break;
            }

            if (stream.Pop().TokenType != ModelTokenType.ArrayBegin)
            {
                yield return(source);

                yield break;
            }

            int index = 0;

            while (!stream.IsCompleted)
            {
                ModelToken token = stream.Peek();
                if (token.TokenType == ModelTokenType.ArrayEnd)
                {
                    break;
                }

                if (predicate == null || predicate(index))
                {
                    yield return(ModelSubsequencer.SpliceNextValue(stream));
                }
                else
                {
                    ModelSubsequencer.SkipNextValue(stream);
                }
                index++;
            }
        }
 /// <summary>
 /// Gets all the items of the array
 /// </summary>
 /// <param name="source"></param>
 /// <returns>all items of the array</returns>
 public static IEnumerable <TokenSequence> ArrayItems(this TokenSequence source)
 {
     return(ModelSubsequencer.ArrayItems(source, null));
 }
        /// <summary>
        /// Gets the properties of the root object which satisfies the <paramref name="predicate"/>
        /// </summary>
        /// <param name="source"></param>
        /// <param name="predicate"></param>
        /// <returns>matching properties for the root object</returns>
        private static IEnumerable <KeyValuePair <DataName, TokenSequence> > PropertiesIterator(TokenSequence source, Func <DataName, bool> predicate)
        {
            IStream <ModelToken> stream = Stream <ModelToken> .Create(source);

            if (stream.IsCompleted ||
                stream.Pop().TokenType != ModelTokenType.ObjectBegin)
            {
                yield break;
            }

            int depth = 0;

            while (!stream.IsCompleted)
            {
                ModelToken token = stream.Peek();
                switch (token.TokenType)
                {
                case ModelTokenType.ArrayBegin:
                case ModelTokenType.ObjectBegin:
                {
                    depth++;
                    stream.Pop();
                    continue;
                }

                case ModelTokenType.ArrayEnd:
                {
                    depth--;
                    stream.Pop();
                    continue;
                }

                case ModelTokenType.ObjectEnd:
                {
                    if (depth != 0)
                    {
                        depth--;
                        stream.Pop();
                        continue;
                    }

                    // don't look beyond end of object
                    yield break;
                }

                case ModelTokenType.Property:
                {
                    stream.Pop();

                    if (depth != 0 ||
                        (predicate != null && !predicate(token.Name)))
                    {
                        continue;
                    }

                    // return property value sequence
                    yield return(new KeyValuePair <DataName, TokenSequence>(token.Name, ModelSubsequencer.SpliceNextValue(stream)));

                    continue;
                }

                default:
                {
                    stream.Pop();
                    continue;
                }
                }
            }
        }
 /// <summary>
 /// Gets all properties of the root object
 /// </summary>
 /// <param name="source"></param>
 /// <param name="predicate"></param>
 /// <returns>all properties for the object</returns>
 public static IEnumerable <KeyValuePair <DataName, TokenSequence> > Properties(this TokenSequence source)
 {
     return(ModelSubsequencer.Properties(source, null));
 }