示例#1
0
        /// <summary>
        /// Returns an iterator which steps through the range, applying the specified
        /// step delegate on each iteration. The method determines whether to begin
        /// at the start or end of the range based on whether the step delegate appears to go
        /// "up" or "down". The step delegate is applied to the start point. If the result is
        /// more than the start point, the returned iterator begins at the start point; otherwise
        /// it begins at the end point.
        /// </summary>
        /// <param name="step">Delegate to apply to the "current value" on each iteration</param>
        public RangeIterator <T> Step(DotNet20.Func <T, T> step)
        {
            step.ThrowIfNull("step");
            bool ascending = (this.comparer.Compare(this.start, step(this.start)) < 0);

            return(ascending ? this.FromStart(step) : this.FromEnd(step));
        }
        /// <summary>
        /// Filters a data-producer based on a predicate on each value
        /// </summary>
        /// <param name="source">The data-producer to be filtered</param>
        /// <param name="predicate">The condition to be satisfied</param>
        /// <returns>A filtered data-producer; only matching values will raise the DataProduced event</returns>
        public static IDataProducer <TSource> Where <TSource>(this IDataProducer <TSource> source,
                                                              DotNet20.Func <TSource, bool> predicate)
        {
            predicate.ThrowIfNull("predicate");

            return(source.Where((x, index) => predicate(x)));
        }
示例#3
0
 /// <summary>
 /// Applies an accumulator function over the values yielded from
 /// a data-producer. The specified seed value
 /// is used as the initial accumulator value, and the specified function is used
 /// to select the result value
 /// </summary>
 /// <typeparam name="TSource">The type of data yielded by the data-source</typeparam>
 /// <typeparam name="TAccumulate">The type to be used for the accumulator</typeparam>
 /// <param name="func">Accumulator function to be applied to each term in the sequence</param>
 /// <param name="seed">The initial value for the accumulator</param>
 /// <param name="source">The data-source for the values</param>
 public static IFuture <TAccumulate> Aggregate <TSource, TAccumulate>
     (this IDataProducer <TSource> source,
     TAccumulate seed,
     DotNet20.Func <TAccumulate, TSource, TAccumulate> func)
 {
     return(source.Aggregate(seed, func, x => x));
 }
示例#4
0
        /// <summary>
        /// Applies an accumulator function over the values yielded from
        /// a data-producer. The first value in the seqnence
        /// is used as the initial accumulator value, and the specified function is used
        /// to select the result value. If the sequence is empty then
        /// the default value for TSource is returned.
        /// </summary>
        /// <typeparam name="TSource">The type of data yielded by the data-source</typeparam>
        /// <param name="func">Accumulator function to be applied to each term in the sequence</param>
        /// <param name="source">The data-source for the values</param>
        public static IFuture <TSource> Aggregate <TSource>
            (this IDataProducer <TSource> source,
            DotNet20.Func <TSource, TSource, TSource> func)
        {
            source.ThrowIfNull("source");
            func.ThrowIfNull("func");

            Future <TSource> ret   = new Future <TSource>();
            bool             first = true;

            TSource current = default(TSource);

            source.DataProduced += value =>
            {
                if (first)
                {
                    first   = false;
                    current = value;
                }
                else
                {
                    current = func(current, value);
                }
            };
            source.EndOfData += () => ret.Value = current;

            return(ret);
        }
 internal ReverseLineReader(DotNet20.Func <Stream> streamSource, Encoding encoding, int bufferSize)
 {
     this.streamSource = streamSource;
     this.encoding     = encoding;
     this.bufferSize   = bufferSize;
     if (encoding.IsSingleByte)
     {
         // For a single byte encoding, every byte is the start (and end) of a character
         characterStartDetector = (pos, data) => true;
     }
     else if (encoding is UnicodeEncoding)
     {
         // For UTF-16, even-numbered positions are the start of a character
         characterStartDetector = (pos, data) => (pos & 1) == 0;
     }
     else if (encoding is UTF8Encoding)
     {
         // For UTF-8, bytes with the top bit clear or the second bit set are the start of a character
         // See http://www.cl.cam.ac.uk/~mgk25/unicode.html
         characterStartDetector = (pos, data) => (data & 0x80) == 0 || (data & 0x40) != 0;
     }
     else
     {
         throw new ArgumentException("Only single byte, UTF-8 and Unicode encodings are permitted");
     }
 }
示例#6
0
        /// <summary>
        /// Returns a future to the minumum of a sequence of values that are
        /// obtained by taking a transform of the input sequence, using the default comparer
        /// </summary>
        /// <remarks>Null values are removed from the minimum</remarks>
        public static IFuture <TResult> Min <TSource, TResult>
            (this IDataProducer <TSource> source, DotNet20.Func <TSource, TResult> selector)
        {
            source.ThrowIfNull("source");
            selector.ThrowIfNull("selector");

            return(source.Select(selector).Min());
        }
        /// <summary>
        /// Returns a projection on the data-producer, using a transformation
        /// (involving the elements's index in the sequence) to
        /// map each element into a new form.
        /// </summary>
        /// <typeparam name="TSource">The source type</typeparam>
        /// <typeparam name="TResult">The projected type</typeparam>
        /// <param name="source">The source data-producer</param>
        /// <param name="projection">The transformation to apply to each element.</param>
        public static IDataProducer <TResult> Select <TSource, TResult>(this IDataProducer <TSource> source,
                                                                        DotNet20.Func <TSource, int, TResult> projection)
        {
            source.ThrowIfNull("source");
            projection.ThrowIfNull("projection");

            DataProducer <TResult> ret = new DataProducer <TResult>();
            int index = 0;

            source.DataProduced += value => ret.Produce(projection(value, index++));
            source.EndOfData    += () => ret.End();
            return(ret);
        }
示例#8
0
        /// <summary>
        /// Creates an iterator over the given range with the given step function,
        /// with the specified direction.
        /// </summary>
        public RangeIterator(Range <T> range, DotNet20.Func <T, T> step, bool ascending)
        {
            step.ThrowIfNull("step");

            if ((ascending && range.Comparer.Compare(range.Start, step(range.Start)) >= 0) ||
                (!ascending && range.Comparer.Compare(range.End, step(range.End)) <= 0))
            {
                throw new ArgumentException("step does nothing, or progresses the wrong way");
            }
            this.ascending = ascending;
            this.range     = range;
            this.step      = step;
        }
        /// <summary>
        /// Applies an accumulator function over the values yielded from
        /// a data-producer, performing a transformation on the final
        /// accululated value. The specified seed value
        /// is used as the initial accumulator value, and the specified function is used
        /// to select the result value
        /// </summary>
        /// <typeparam name="TSource">The type of data yielded by the data-source</typeparam>
        /// <typeparam name="TResult">The final result type (after the accumulator has been transformed)</typeparam>
        /// <typeparam name="TAccumulate">The type to be used for the accumulator</typeparam>
        /// <param name="func">Accumulator function to be applied to each term in the sequence</param>
        /// <param name="resultSelector">Transformation to apply to the final
        /// accumulated value to produce the result</param>
        /// <param name="seed">The initial value for the accumulator</param>
        /// <param name="source">The data-source for the values</param>
        public static IFuture <TResult> Aggregate <TSource, TAccumulate, TResult>
            (this IDataProducer <TSource> source,
            TAccumulate seed, DotNet20.Func <TAccumulate, TSource, TAccumulate> func, DotNet20.Func <TAccumulate, TResult> resultSelector)
        {
            source.ThrowIfNull("source");
            func.ThrowIfNull("func");
            resultSelector.ThrowIfNull("resultSelector");

            Future <TResult> result = new Future <TResult>();

            TAccumulate current = seed;

            source.DataProduced += value => current = func(current, value);
            source.EndOfData    += () => result.Value = resultSelector(current);

            return(result);
        }
示例#10
0
        /// <summary>
        /// Sorts the elements in the entire System.Collections.Generic.List{T} using
        /// a projection.
        /// </summary>
        /// <param name="source">Data source</param>
        /// <param name="selector">The projection to use to obtain values for comparison</param>
        /// <param name="comparer">The comparer to use to compare projected values (on null to use the default comparer)</param>
        /// <param name="descending">Should the list be sorted ascending or descending?</param>
        public static void Sort <T, TValue>(this List <T> source, DotNet20.Func <T, TValue> selector, IComparer <TValue> comparer, bool descending)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (comparer == null)
            {
                comparer = Comparer <TValue> .Default;
            }
            IComparer <T> itemComparer = new ProjectionComparer <T, TValue>(selector, comparer);

            if (descending)
            {
                itemComparer = itemComparer.Reverse();
            }
            source.Sort(itemComparer);
        }
        /// <summary>
        /// Filters a data-producer based on a predicate on each value; the index
        /// in the sequence is used in the predicate
        /// </summary>
        /// <param name="source">The data-producer to be filtered</param>
        /// <param name="predicate">The condition to be satisfied</param>
        /// <returns>A filtered data-producer; only matching values will raise the DataProduced event</returns>
        public static IDataProducer <TSource> Where <TSource>(this IDataProducer <TSource> source,
                                                              DotNet20.Func <TSource, int, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            DataProducer <TSource> ret = new DataProducer <TSource>();

            int index = 0;

            source.DataProduced += value =>
            {
                if (predicate(value, index++))
                {
                    ret.Produce(value);
                }
            };
            source.EndOfData += () => ret.End();
            return(ret);
        }
 /// <summary>
 /// Orders the values from a data-source by a transform on each term, ascending
 /// </summary>
 /// <param name="source">The original data-producer</param>
 /// <param name="selector">Returns the value (for each term) by which to order the sequence</param>
 /// <returns>A data-producer that yeilds the sequence ordered
 /// by the selected value</returns>
 /// <remarks>This will force all data to be buffered</remarks>
 public static IOrderedDataProducer <TSource> OrderBy <TSource, TKey>(this IDataProducer <TSource> source, DotNet20.Func <TSource, TKey> selector)
 {
     return(OrderBy(source, selector, Comparer <TKey> .Default, false));
 }
 /// <summary>
 /// Further orders the values from an ordered data-source by a transform on each term, descending
 /// (the sort operation is only applied once for the combined ordering)
 /// </summary>
 /// <param name="source">The original data-producer and ordering</param>
 /// <param name="selector">Returns the value (for each term) by which to order the sequence</param>
 /// <returns>A data-producer that yeilds the sequence ordered
 /// by the selected value</returns>
 /// <remarks>This will force all data to be buffered</remarks>
 public static IOrderedDataProducer <TSource> ThenByDescending <TSource, TKey>(this IOrderedDataProducer <TSource> source, DotNet20.Func <TSource, TKey> selector)
 {
     return(ThenBy(source, selector, Comparer <TKey> .Default, true));
 }
 /// <summary>
 /// Further orders the values from an ordered data-source by a transform on each term, ascending
 /// (the sort operation is only applied once for the combined ordering)
 /// </summary>
 /// <param name="source">The original data-producer and ordering</param>
 /// <param name="selector">Returns the value (for each term) by which to order the sequence</param>
 /// <param name="comparer">Comparer to compare the selected values</param>
 /// <returns>A data-producer that yeilds the sequence ordered
 /// by the selected value</returns>
 /// <remarks>This will force all data to be buffered</remarks>
 public static IOrderedDataProducer <TSource> ThenBy <TSource, TKey>(this IOrderedDataProducer <TSource> source, DotNet20.Func <TSource, TKey> selector, IComparer <TKey> comparer)
 {
     return(ThenBy(source, selector, comparer, false));
 }
        /// <summary>
        /// Returns a data-producer that will ignore the
        /// elements from the start of a sequence while a condition
        /// (involving the elements's index in the sequence)
        /// is satsified; when the condition fails for an element,
        /// that element and all subsequent elements are yielded.
        /// </summary>
        /// <param name="source">The source data-producer</param>
        /// <param name="predicate">The condition to skip elements</param>
        public static IDataProducer <TSource> SkipWhile <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, int, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            DataProducer <TSource> ret = new DataProducer <TSource>();
            Action completion          = () => ret.End();

            bool skipping = true;
            int  index    = 0;

            source.DataProduced += value =>
            {
                if (skipping)
                {
                    skipping = predicate(value, index++);
                }
                // Note - not an else clause!
                if (!skipping)
                {
                    ret.Produce(value);
                }
            };
            source.EndOfData += completion;
            return(ret);
        }
        /// <summary>
        /// Returns a data-producer that will ignore the
        /// elements from the start of a sequence while a condition
        /// is satsified; when the condition fails for an element,
        /// that element and all subsequent elements are yielded.
        /// </summary>
        /// <param name="source">The source data-producer</param>
        /// <param name="predicate">The condition to skip elements</param>
        public static IDataProducer <TSource> SkipWhile <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, bool> predicate)
        {
            predicate.ThrowIfNull("predicate");

            return(source.SkipWhile((t, index) => predicate(t)));
        }
        private static IOrderedDataProducer <TSource> ThenBy <TSource, TKey>(IOrderedDataProducer <TSource> source, DotNet20.Func <TSource, TKey> selector, IComparer <TKey> comparer, bool descending)
        {
            comparer.ThrowIfNull("comparer");
            IComparer <TSource> itemComparer = new ProjectionComparer <TSource, TKey>(selector, comparer);

            if (descending)
            {
                itemComparer = itemComparer.Reverse();
            }
            itemComparer = new LinkedComparer <TSource>(source.Comparer, itemComparer);
            return(new OrderedDataProducer <TSource>(source, itemComparer));
        }
示例#18
0
 /// <summary>
 /// Returns an iterator which begins at the end of this range,
 /// applying the given step delegate on each iteration until the
 /// start is reached or passed. The start and end points are included
 /// or excluded according to this range.
 /// </summary>
 /// <param name="step">Delegate to apply to the "current value" on each iteration</param>
 public RangeIterator <T> FromEnd(DotNet20.Func <T, T> step)
 {
     return(new RangeIterator <T>(this, step, false));
 }
示例#19
0
        /// <summary>
        /// Returns a future that indicates whether any suitable values are
        /// yielded by the data-producer. The future will return false
        /// for an empty sequence or one with no matching values, or true for a sequence with matching values.
        /// </summary>
        /// <param name="source">The data-producer to be monitored.</param>
        /// <param name="predicate">The condition that must be satisfied.</param>
        public static IFuture <bool> Any <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            Future <bool> ret = new Future <bool>();

            Action <TSource> production = null;
            Action           completion = () => ret.Value = false;

            production = value =>
            {
                if (predicate(value))
                {
                    ret.Value            = true;
                    source.DataProduced -= production;
                    source.EndOfData    -= completion;
                }
            };

            source.DataProduced += production;
            source.EndOfData    += completion;

            return(ret);
        }
 /// <summary>
 /// Creates a LineReader from a stream source. The delegate is only
 /// called when the enumerator is fetched.
 /// </summary>
 /// <param name="streamSource">Data source</param>
 /// <param name="encoding">Encoding to use to decode the stream into text</param>
 public ReverseLineReader(DotNet20.Func <Stream> streamSource, Encoding encoding)
     : this(streamSource, encoding, DefaultBufferSize)
 {
 }
 /// <summary>
 /// Creates a LineReader from a stream source. The delegate is only
 /// called when the enumerator is fetched. UTF-8 is used to decode
 /// the stream into text.
 /// </summary>
 /// <param name="streamSource">Data source</param>
 public ReverseLineReader(DotNet20.Func <Stream> streamSource)
     : this(streamSource, Encoding.UTF8)
 {
 }
示例#22
0
 /// <summary>
 /// Creates an instance of ProjectionEqualityComparer using the specified projection.
 /// The ignored parameter is solely present to aid type inference.
 /// </summary>
 /// <typeparam name="TSource">Type parameter for the elements to be compared</typeparam>
 /// <typeparam name="TKey">Type parameter for the keys to be compared, after being projected from the elements</typeparam>
 /// <param name="ignored">Value is ignored - type may be used by type inference</param>
 /// <param name="projection">Projection to use when determining the key of an element</param>
 /// <returns>A comparer which will compare elements by projecting each element to its key, and comparing keys</returns>
 public static ProjectionEqualityComparer <TSource, TKey> Create <TSource, TKey>
     (TSource ignored, DotNet20.Func <TSource, TKey> projection)
 {
     return(new ProjectionEqualityComparer <TSource, TKey>(projection));
 }
 /// <summary>
 /// Orders the values from a data-source by a transform on each term, descending
 /// </summary>
 /// <param name="source">The original data-producer</param>
 /// <param name="selector">Returns the value (for each term) by which to order the sequence</param>
 /// <param name="comparer">Comparer to compare the selected values</param>
 /// <returns>A data-producer that yeilds the sequence ordered
 /// by the selected value</returns>
 /// <remarks>This will force all data to be buffered</remarks>
 public static IOrderedDataProducer <TSource> OrderByDescending <TSource, TKey>(this IDataProducer <TSource> source, DotNet20.Func <TSource, TKey> selector, IComparer <TKey> comparer)
 {
     return(OrderBy(source, selector, comparer, true));
 }
示例#24
0
        /// <summary>
        /// Returns the number of elements in the specified sequence satisfy a condition,
        /// as a future value.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
        /// <param name="source">A sequence that contains elements to be tested and counted.</param>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <returns>A number that represents how many elements in the sequence satisfy
        /// the condition in the predicate function, as a future value.
        /// The actual count can only be retrieved after the source has indicated the end
        /// of its data.
        /// </returns>
        public static IFuture <long> LongCount <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            Future <long> ret   = new Future <long>();
            int           count = 0;

            source.DataProduced += t =>
            {
                if (predicate(t))
                {
                    count++;
                }
            };
            source.EndOfData += () => ret.Value = count;

            return(ret);
        }
        private static IOrderedDataProducer <TSource> OrderBy <TSource, TKey>(IDataProducer <TSource> source, DotNet20.Func <TSource, TKey> selector, IComparer <TKey> comparer, bool descending)
        {
            source.ThrowIfNull("source");
            comparer.ThrowIfNull("comparer");

            IComparer <TSource> itemComparer = new ProjectionComparer <TSource, TKey>(selector, comparer);

            if (descending)
            {
                itemComparer = itemComparer.Reverse();
            }

            // first, discard any existing "order by"s by going back to the producer
            IOrderedDataProducer <TSource> orderedProducer;
            bool first = true;

            while ((orderedProducer = source as IOrderedDataProducer <TSource>) != null)
            {
                if (first)
                {
                    // keep the top-most comparer to enforce a balanced sort
                    itemComparer = new LinkedComparer <TSource>(itemComparer, orderedProducer.Comparer);
                    first        = false;
                }
                source = orderedProducer.BaseProducer;
            }
            return(new OrderedDataProducer <TSource>(source, itemComparer));
        }
        /// <summary>
        /// Returns a data-producer that will yield
        /// elements a sequence as long as a condition
        /// (involving the element's index in the sequence)
        /// is satsified; when the condition fails for an element,
        /// that element and all subsequent elements are ignored.
        /// </summary>
        /// <param name="source">The source data-producer</param>
        /// <param name="predicate">The condition to yield elements</param>
        public static IDataProducer <TSource> TakeWhile <TSource>(this IDataProducer <TSource> source, DotNet20.Func <TSource, int, bool> predicate)
        {
            source.ThrowIfNull("source");
            predicate.ThrowIfNull("predicate");

            DataProducer <TSource> ret  = new DataProducer <TSource>();
            Action           completion = () => ret.End();
            Action <TSource> production = null;

            int index = 0;

            production = value =>
            {
                if (!predicate(value, index++))
                {
                    ret.End();
                    source.DataProduced -= production;
                    source.EndOfData    -= completion;
                }
                else
                {
                    ret.Produce(value);
                }
            };

            source.DataProduced += production;
            source.EndOfData    += completion;
            return(ret);
        }
 /// <summary>
 /// Returns a projection on the data-producer, using a transformation to
 /// map each element into a new form.
 /// </summary>
 /// <typeparam name="TSource">The source type</typeparam>
 /// <typeparam name="TResult">The projected type</typeparam>
 /// <param name="source">The source data-producer</param>
 /// <param name="projection">The transformation to apply to each element.</param>
 public static IDataProducer <TResult> Select <TSource, TResult>(this IDataProducer <TSource> source, DotNet20.Func <TSource, TResult> projection)
 {
     projection.ThrowIfNull("projection");
     return(source.Select((t, index) => projection(t)));
 }
示例#28
0
 /// <summary>
 /// Creates an ascending iterator over the given range with the given step function
 /// </summary>
 public RangeIterator(Range <T> range, DotNet20.Func <T, T> step)
     : this(range, step, true)
 {
 }
示例#29
0
 /// <summary>
 /// Sorts the elements in the entire System.Collections.Generic.List{T} using
 /// a projection.
 /// </summary>
 /// <param name="source">Data source</param>
 /// <param name="selector">The projection to use to obtain values for comparison</param>
 public static void Sort <T, TValue>(this List <T> source, DotNet20.Func <T, TValue> selector)
 {
     Sort <T, TValue>(source, selector, null, false);
 }
示例#30
0
 /// <summary>
 /// Returns an iterator which begins at the start of this range,
 /// applying the given step delegate on each iteration until the
 /// end is reached or passed. The start and end points are included
 /// or excluded according to this range.
 /// </summary>
 /// <param name="step">Delegate to apply to the "current value" on each iteration</param>
 public RangeIterator <T> FromStart(DotNet20.Func <T, T> step)
 {
     return(new RangeIterator <T>(this, step));
 }