}
/// <summary>
- /// Forms a slice out of the given memory, beginning at 'startIndex'
- /// </summary>
- /// <param name="startIndex">The index at which to begin this slice.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Memory<T> Slice(Index startIndex)
- {
- int actualIndex = startIndex.GetOffset(_length);
- return Slice(actualIndex);
- }
-
- /// <summary>
- /// Forms a slice out of the given memory using the range start and end indexes.
- /// </summary>
- /// <param name="range">The range used to slice the memory using its start and end indexes.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Memory<T> Slice(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(_length);
- // It is expected for _index + start to be negative if the memory is already pre-pinned.
- return new Memory<T>(_object, _index + start, length);
- }
-
- /// <summary>
- /// Forms a slice out of the given memory using the range start and end indexes.
- /// </summary>
- /// <param name="range">The range used to slice the memory using its start and end indexes.</param>
- public Memory<T> this[Range range] => Slice(range);
-
- /// <summary>
/// Returns a span from the memory.
/// </summary>
public unsafe Span<T> Span
}
/// <summary>
- /// Forms a slice out of the given memory, beginning at 'startIndex'
- /// </summary>
- /// <param name="startIndex">The index at which to begin this slice.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlyMemory<T> Slice(Index startIndex)
- {
- int actualIndex = startIndex.GetOffset(_length);
- return Slice(actualIndex);
- }
-
- /// <summary>
- /// Forms a slice out of the given memory using the range start and end indexes.
- /// </summary>
- /// <param name="range">The range used to slice the memory using its start and end indexes.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlyMemory<T> Slice(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(_length);
- // It is expected for _index + start to be negative if the memory is already pre-pinned.
- return new ReadOnlyMemory<T>(_object, _index + start, length);
- }
-
- /// <summary>
- /// Forms a slice out of the given memory using the range start and end indexes.
- /// </summary>
- /// <param name="range">The range used to slice the memory using its start and end indexes.</param>
- public ReadOnlyMemory<T> this[Range range] => Slice(range);
-
- /// <summary>
/// Returns a span from the memory.
/// </summary>
public unsafe ReadOnlySpan<T> Span
#endif
}
- public ref readonly T this[Index index]
- {
- get
- {
- // Evaluate the actual index first because it helps performance
- int actualIndex = index.GetOffset(_length);
- return ref this [actualIndex];
- }
- }
-
- public ReadOnlySpan<T> this[Range range] => Slice(range);
-
/// <summary>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
/// It can be used for pinning and is required to support the use of span within a fixed statement.
}
/// <summary>
- /// Forms a slice out of the given read-only span, beginning at 'startIndex'
- /// </summary>
- /// <param name="startIndex">The index at which to begin this slice.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlySpan<T> Slice(Index startIndex)
- {
- int actualIndex;
- if (startIndex.IsFromEnd)
- actualIndex = _length - startIndex.Value;
- else
- actualIndex = startIndex.Value;
-
- return Slice(actualIndex);
- }
-
- /// <summary>
- /// Forms a slice out of the given read-only span, beginning at range start index to the range end
- /// </summary>
- /// <param name="range">The range which has the start and end indexes used to slice the span.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlySpan<T> Slice(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(_length);
- return new ReadOnlySpan<T>(ref Unsafe.Add(ref _pointer.Value, start), length);
- }
-
- /// <summary>
/// Copies the contents of this read-only span into a new array. This heap
/// allocates, so should generally be avoided, however it is sometimes
/// necessary to bridge the gap with APIs written in terms of arrays.
#endif
}
- public ref T this[Index index]
- {
- get
- {
- // Evaluate the actual index first because it helps performance
- int actualIndex = index.GetOffset(_length);
- return ref this [actualIndex];
- }
- }
-
- public Span<T> this[Range range] => Slice(range);
-
/// <summary>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
/// It can be used for pinning and is required to support the use of span within a fixed statement.
}
/// <summary>
- /// Forms a slice out of the given span, beginning at 'startIndex'
- /// </summary>
- /// <param name="startIndex">The index at which to begin this slice.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Span<T> Slice(Index startIndex)
- {
- int actualIndex = startIndex.GetOffset(_length);
- return Slice(actualIndex);
- }
-
- /// <summary>
- /// Forms a slice out of the given span, beginning at range start index to the range end
- /// </summary>
- /// <param name="range">The range which has the start and end indexes used to slice the span.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Span<T> Slice(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(_length);
- return new Span<T>(ref Unsafe.Add(ref _pointer.Value, start), length);
- }
-
- /// <summary>
/// Copies the contents of this span into a new array. This heap
/// allocates, so should generally be avoided, however it is sometimes
/// necessary to bridge the gap with APIs written in terms of arrays.
return InternalSubString(startIndex, length);
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public string Substring(Index startIndex)
- {
- int actualIndex = startIndex.GetOffset(Length);
- return Substring(actualIndex);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public string Substring(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(Length);
- return Substring(start, length);
- }
-
private unsafe string InternalSubString(int startIndex, int length)
{
Debug.Assert(startIndex >= 0 && startIndex <= this.Length, "StartIndex is out of range!");
return (value == null || 0u >= (uint)value.Length) ? true : false;
}
- [System.Runtime.CompilerServices.IndexerName("Chars")]
- public char this[Index index]
- {
- get
- {
- int actualIndex = index.GetOffset(Length);
- return this[actualIndex];
- }
- }
-
- [System.Runtime.CompilerServices.IndexerName("Chars")]
- public string this[Range range] => Substring(range);
-
public static bool IsNullOrWhiteSpace(string? value)
{
if (value == null) return true;
return InternalSubstring(startIndex, length);
}
+ // Slice intended to be used by the compiler only to provide indexer with range parameter functionality.
+ // Developers should be using Substring method instead.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Utf8String Substring(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(Length);
- return Substring(start, length);
- }
+ [ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)]
+ public Utf8String Slice(int startIndex, int length) => Substring(startIndex, length);
+
[StackTraceHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
}
}
- /// <summary>
- /// Gets the <see cref="Char8"/> at the specified position.
- /// </summary>
- public Char8 this[Index index]
- {
- get
- {
- // Just like String, we don't allow indexing into the null terminator itself.
-
- int actualIndex = index.GetOffset(Length);
- return this[actualIndex];
- }
- }
-
- /// <summary>
- /// Gets a substring of this <see cref="Utf8String"/> based on the provided <paramref name="range"/>.
- /// </summary>
- public Utf8String this[Range range] => Substring(range);
-
/*
* METHODS
*/
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-
-// This test was extracted from the Indexer tests in the corefx System.Memory.Tests.
-// The JIT was trying to expand the form of indexer that takes a range, but was not
-// correctly expanding it, as it was expecting only the scalar index form.
-
-public class GitHub_20958
-{
-
- public static int IndexerWithRangeTest()
- {
- int returnVal = 100;
-
- ReadOnlySpan<char> span = "Hello".AsSpan();
- ReadOnlySpan<char> sliced = span[new Range(new Index(1, fromEnd: false), new Index(1, fromEnd: true))];
- if (span.Slice(1, 3) != sliced)
- {
- returnVal = -1;
- }
- try
- {
- ReadOnlySpan<char> s = "Hello".AsSpan()[new Range(new Index(1, fromEnd: true), new Index(1, fromEnd: false))];
- returnVal = -1;
- }
- catch (ArgumentOutOfRangeException)
- {
- }
- catch (Exception e)
- {
- returnVal = -1;
- }
- Span<char> span1 = new Span<char>(new char[] { 'H', 'e', 'l', 'l', 'o' });
- Span<char> sliced1 = span1[new Range(new Index(2, fromEnd: false), new Index(1, fromEnd: true))];
- if (span1.Slice(2, 2) != sliced1)
- {
- returnVal = -1;
- }
- try
- {
- Span<char> s = new Span<char>(new char[] { 'H', 'i' })[new Range(new Index(0, fromEnd: true), new Index(1, fromEnd: false))];
- returnVal = -1;
- }
- catch (ArgumentOutOfRangeException)
- {
- }
- catch (Exception e)
- {
- returnVal = -1;
- }
- return returnVal;
- }
-
- public static int Main()
- {
- return IndexerWithRangeTest();
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <AssemblyName>$(MSBuildProjectName)</AssemblyName>
- <OutputType>Exe</OutputType>
- <DebugType></DebugType>
- <Optimize>True</Optimize>
- </PropertyGroup>
- <ItemGroup>
- <Compile Include="$(MSBuildProjectName).cs" />
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
- <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
-</Project>
\ No newline at end of file