blob: fb9ece05c8f9122b56e290c99a7d5bbeff98548a [file] [log] [blame]
using System;
using System.Collections.Generic;
namespace Lucene.Net.Support
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
internal static class ListExtensions
{
public static IList<T> SubList<T>(this IList<T> list, int fromIndex, int toIndex)
{
// .NET Port: This is to mimic Java's List.subList method, which has a different usage
// than .NETs' List.GetRange. subList's parameters are indices, GetRange's parameters are a
// starting index and a count. So we would need to do some light index math to translate this into
// GetRange. This will be a safer extension method to use when translating java code
// as there will be no question as to how to change it into GetRange. Also, subList returns
// a list instance that, when modified, modifies the original list. So we're duplicating
// that behavior as well.
return new SubList<T>(list, fromIndex, toIndex);
}
}
#region SubList<T>
internal sealed class SubList<T> : IList<T>
{
private readonly IList<T> list;
private readonly int fromIndex;
private int toIndex;
/// <summary>
/// Creates a ranged view of the given <paramref name="list"/>.
/// </summary>
/// <param name="list">The original list to view.</param>
/// <param name="fromIndex">The inclusive starting index.</param>
/// <param name="toIndex">The exclusive ending index.</param>
public SubList(IList<T> list, int fromIndex, int toIndex)
{
if (fromIndex < 0)
throw new ArgumentOutOfRangeException(nameof(fromIndex));
if (toIndex > list.Count)
throw new ArgumentOutOfRangeException(nameof(toIndex));
if (toIndex < fromIndex)
throw new ArgumentOutOfRangeException(nameof(toIndex));
if (list == null)
throw new ArgumentNullException(nameof(list));
this.list = list;
this.fromIndex = fromIndex;
this.toIndex = toIndex;
}
public int IndexOf(T item)
{
for (int i = fromIndex, fakeIndex = 0; i < toIndex; i++, fakeIndex++)
{
var current = list[i];
if (current == null && item == null)
return fakeIndex;
if (current.Equals(item))
{
return fakeIndex;
}
}
return -1;
}
public void Insert(int index, T item)
{
throw new NotSupportedException();
}
public void RemoveAt(int index)
{
// TODO: is this the right behavior?
list.RemoveAt(fromIndex + index);
toIndex--;
}
public T this[int index]
{
get => list[fromIndex + index];
set => list[fromIndex + index] = value;
}
public void Add(T item)
{
throw new NotSupportedException();
}
public void Clear()
{
// TODO: is this the correct behavior?
for (int i = toIndex - 1; i >= fromIndex; i--)
{
list.RemoveAt(i);
}
toIndex = fromIndex; // can't move further
}
public bool Contains(T item)
{
return IndexOf(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
int count = array.Length - arrayIndex;
for (int i = fromIndex, arrayi = arrayIndex; i <= Math.Min(toIndex - 1, fromIndex + count - 1); i++, arrayi++)
{
array[arrayi] = list[i];
}
}
public int Count => Math.Max(toIndex - fromIndex, 0);
public bool IsReadOnly => list.IsReadOnly;
public bool Remove(T item)
{
var index = this.IndexOf(item); // get fake index
if (index < 0)
return false;
list.RemoveAt(fromIndex + index);
toIndex--;
return true;
}
public IEnumerator<T> GetEnumerator()
{
return YieldItems().GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private IEnumerable<T> YieldItems()
{
for (int i = fromIndex; i <= Math.Min(toIndex - 1, list.Count - 1); i++)
{
yield return list[i];
}
}
}
#endregion SubList<T>
}