}
return CompareString(
- string1.AsSpan().Slice(offset1, length1),
- string2.AsSpan().Slice(offset2, length2),
+ string1.AsSpan(offset1, length1),
+ string2.AsSpan(offset2, length2),
options);
}
{
Debug.Assert(indexA + lengthA <= strA.Length);
Debug.Assert(indexB + lengthB <= strB.Length);
- return CompareOrdinalIgnoreCase(strA.AsSpan().Slice(indexA, lengthA), strB.AsSpan().Slice(indexB, lengthB));
+ return CompareOrdinalIgnoreCase(strA.AsSpan(indexA, lengthA), strB.AsSpan(indexB, lengthB));
}
internal static unsafe int CompareOrdinalIgnoreCase(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
//
////////////////////////////////////////////////////////////////////////////
- // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
+ // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
private static DS[][] dateParsingStates = {
// DS.BEGIN // DS.BEGIN
new DS[] { DS.BEGIN, DS.ERROR, DS.TX_N, DS.N, DS.D_Nd, DS.T_Nt, DS.ERROR, DS.D_M, DS.D_M, DS.D_S, DS.T_S, DS.BEGIN, DS.D_Y, DS.D_Y, DS.ERROR, DS.BEGIN, DS.BEGIN, DS.ERROR},
return false;
}
- // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as
+ // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as
// we are sure we are not parsing time.
dtok.dtt = DTT.YearDateSep;
break;
return false;
}
- // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as
+ // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as
// we are sure we are not parsing time.
dtok.dtt = DTT.MonthDatesep;
break;
// The has was un-paired
return false;
}
- // Valid Hash usage: eat the hash and continue.
+ // Valid Hash usage: eat the hash and continue.
str.GetNext();
return true;
}
{
if (dtok.dtt == DTT.YearEnd || dtok.dtt == DTT.YearSpace || dtok.dtt == DTT.YearDateSep)
{
- // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized
+ // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized
// as part of time (and not a date) DS.T_Nt, DS.T_NNt then change the state to be a date so we try to parse it as a date instead
if (dps == DS.T_Nt)
{
{
switch (dtok.dtt)
{
- // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
+ // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
// changing the token to end with space instead of Date Separator will avoid failing the parsing.
case DTT.YearDateSep: dtok.dtt = atEnd ? DTT.YearEnd : DTT.YearSpace; break;
{
if ((result.flags & ParseFlags.CaptureOffset) != 0)
{
- // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
+ // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
// no adjustment is required in most cases
return DateTimeOffsetTimeZonePostProcessing(ref str, ref result, styles);
}
// Apply validation and adjustments specific to DateTimeOffset
private static Boolean DateTimeOffsetTimeZonePostProcessing(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles)
{
- // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
+ // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
// the input string.
if ((result.flags & ParseFlags.TimeZoneUsed) == 0)
{
Int64 utcTicks = result.parsedDate.Ticks - offsetTicks;
// For DateTimeOffset, both the parsed time and the corresponding UTC value must be within the boundaries
- // of a DateTime instance.
+ // of a DateTime instance.
if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks)
{
result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_UTCOutOfRange));
}
}
- // assume the offset is Local
+ // assume the offset is Local
return DateTime.Now;
}
}
// The "r" and "u" formats incorrectly quoted 'GMT' and 'Z', respectively. We cannot
- // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can
+ // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can
// fix it for DateTimeOffset.ParseExact as DateTimeOffset has not been publically released
// with this issue.
if ((result.flags & ParseFlags.CaptureOffset) != 0)
{
return false;
}
- if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength)) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
{
return false;
}
- if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength)) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
{
try
{
- int advance = Int32.Parse(str.AsSpan().Slice(HijriAdvanceRegKeyEntry.Length), provider:CultureInfo.InvariantCulture);
+ int advance = Int32.Parse(str.AsSpan(HijriAdvanceRegKeyEntry.Length), provider:CultureInfo.InvariantCulture);
if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri))
{
hijriAdvance = advance;
// Path is current drive rooted i.e. starts with \:
// "\Foo" and "C:\Bar" => "C:\Foo"
// "\Foo" and "\\?\C:\Bar" => "\\?\C:\Foo"
- combinedPath = Join(GetPathRoot(basePath.AsSpan()), path.AsSpan().Slice(1)); // Cut the separator to ensure we don't end up with two separators when joining with the root.
+ combinedPath = Join(GetPathRoot(basePath.AsSpan()), path.AsSpan(1)); // Cut the separator to ensure we don't end up with two separators when joining with the root.
}
else if (length >= 2 && PathInternal.IsValidDriveChar(path[0]) && path[1] == PathInternal.VolumeSeparatorChar)
{
// Matching root
// "C:Foo" and "C:\Bar" => "C:\Bar\Foo"
// "C:Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
- combinedPath = Join(basePath, path.AsSpan().Slice(2));
+ combinedPath = Join(basePath, path.AsSpan(2));
}
else
{
combinedPath = !PathInternal.IsDevice(basePath)
? path.Insert(2, @"\")
: length == 2
- ? JoinInternal(basePath.AsSpan().Slice(0, 4), path, @"\")
- : JoinInternal(basePath.AsSpan().Slice(0, 4), path.AsSpan().Slice(0, 2), @"\", path.AsSpan().Slice(2));
+ ? JoinInternal(basePath.AsSpan(0, 4), path, @"\")
+ : JoinInternal(basePath.AsSpan(0, 4), path.AsSpan(0, 2), @"\", path.AsSpan(2));
}
}
else
buffer.Append(PathInternal.UncExtendedPathPrefix);
// Copy Server\Share\... over to the buffer
- buffer.Append(content.AsSpan().Slice(PathInternal.UncPrefixLength));
+ buffer.Append(content.AsSpan(PathInternal.UncPrefixLength));
// Return the prefix difference
return PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength;
if (foundIndex < inputLength - 1)
{
// It was a partial find, put the non-existent part of the path back
- outputBuilder.Append(inputBuilder.AsSpan().Slice(foundIndex, inputBuilder.Length - foundIndex));
+ outputBuilder.Append(inputBuilder.AsSpan(foundIndex, inputBuilder.Length - foundIndex));
}
}
}
builderToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\';
// Strip out any added characters at the front of the string
- ReadOnlySpan<char> output = builderToUse.AsSpan().Slice(rootDifference);
+ ReadOnlySpan<char> output = builderToUse.AsSpan(rootDifference);
string returnValue = output.EqualsOrdinal(originalPath.AsSpan())
? originalPath : new string(output);
return result;
}
- // a remove that just takes a startindex.
+ // a remove that just takes a startindex.
public string Remove(int startIndex)
{
if (startIndex < 0)
int count = replacementIdx - thisIdx;
if (count != 0)
{
- this.AsSpan().Slice(thisIdx, count).CopyTo(dstSpan.Slice(dstIdx));
+ this.AsSpan(thisIdx, count).CopyTo(dstSpan.Slice(dstIdx));
dstIdx += count;
}
thisIdx = replacementIdx + oldValueLength;
// Copy over the final non-matching portion at the end of the string.
Debug.Assert(this.Length - thisIdx == dstSpan.Length - dstIdx);
- this.AsSpan().Slice(thisIdx).CopyTo(dstSpan.Slice(dstIdx));
+ this.AsSpan(thisIdx).CopyTo(dstSpan.Slice(dstIdx));
return dst;
}
return new string[] { this };
}
- string[] result = omitEmptyEntries
+ string[] result = omitEmptyEntries
? SplitOmitEmptyEntries(sepList, default, 1, count)
: SplitKeepEmptyEntries(sepList, default, 1, count);
{
return SplitInternal(separator, count, options);
}
-
+
Span<int> sepListInitialSpan = stackalloc int[StackallocIntBufferSizeLimit];
var sepListBuilder = new ValueListBuilder<int>(sepListInitialSpan);
MakeSeparatorList(separators, ref sepListBuilder, ref lengthListBuilder);
ReadOnlySpan<int> sepList = sepListBuilder.AsSpan();
ReadOnlySpan<int> lengthList = lengthListBuilder.AsSpan();
-
+
// Handle the special case of no replaces.
if (sepList.Length == 0)
{
return new string[] { this };
}
- string[] result = omitEmptyEntries
+ string[] result = omitEmptyEntries
? SplitOmitEmptyEntries(sepList, lengthList, 0, count)
: SplitKeepEmptyEntries(sepList, lengthList, 0, count);
return new string[] { this };
}
- string[] result = options == StringSplitOptions.RemoveEmptyEntries
+ string[] result = options == StringSplitOptions.RemoveEmptyEntries
? SplitOmitEmptyEntries(sepList, default, separator.Length, count)
: SplitKeepEmptyEntries(sepList, default, separator.Length, count);
}
- // This function will not keep the Empty string
+ // This function will not keep the Empty string
private string[] SplitOmitEmptyEntries(ReadOnlySpan<int> sepList, ReadOnlySpan<int> lengthList, int defaultLength, int count)
{
Debug.Assert(count >= 2);
int numReplaces = sepList.Length;
- // Allocate array to hold items. This array may not be
- // filled completely in this function, we will create a
+ // Allocate array to hold items. This array may not be
+ // filled completely in this function, we will create a
// new array and copy string references to that new array.
int maxItems = (numReplaces < count) ? (numReplaces + 1) : count;
string[] splitStrings = new string[maxItems];
/// </summary>
/// <param name="separators">separator strngs</param>
/// <param name="sepListBuilder"><see cref="ValueListBuilder{T}"/> for separator indexes</param>
- /// <param name="lengthListBuilder"><see cref="ValueListBuilder{T}"/> for separator length values</param>
+ /// <param name="lengthListBuilder"><see cref="ValueListBuilder{T}"/> for separator length values</param>
private void MakeSeparatorList(string[] separators, ref ValueListBuilder<int> sepListBuilder, ref ValueListBuilder<int> lengthListBuilder)
{
Debug.Assert(separators != null && separators.Length > 0, "separators != null && separators.Length > 0");
namespace System.Text
{
// This class represents a mutable string. It is convenient for situations in
- // which it is desirable to modify a string, perhaps by removing, replacing, or
+ // which it is desirable to modify a string, perhaps by removing, replacing, or
// inserting characters, without creating a new String subsequent to
- // each modification.
- //
+ // each modification.
+ //
// The methods contained within this class do not return a new StringBuilder
// object unless specified otherwise. This class may be used in conjunction with the String
// class to carry out modifications upon strings.
public sealed partial class StringBuilder : ISerializable
{
// A StringBuilder is internally represented as a linked list of blocks each of which holds
- // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
- // so that is what we do.
+ // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
+ // so that is what we do.
/// <summary>
/// The character buffer for this chunk.
// We want to keep chunk arrays out of large object heap (< 85K bytes ~ 40K chars) to be sure.
// Making the maximum chunk size big means less allocation code called, but also more waste
// in unused characters and slower inserts / replaces (since you do need to slide characters over
- // within a buffer).
+ // within a buffer).
internal const int MaxChunkSize = 8000;
/// <summary>
int chunkOffset = chunk.m_ChunkOffset;
int chunkLength = chunk.m_ChunkLength;
- // Check that we will not overrun our boundaries.
+ // Check that we will not overrun our boundaries.
if ((uint)(chunkLength + chunkOffset) <= (uint)result.Length && (uint)chunkLength <= (uint)sourceArray.Length)
{
fixed (char* sourcePtr = &sourceArray[0])
}
// We put this fixed in its own helper to avoid the cost of zero-initing `valueChars` in the
- // case we don't actually use it.
+ // case we don't actually use it.
private void AppendHelper(string value)
{
unsafe
return this;
}
- // Ensure we don't insert more chars than we can hold, and we don't
+ // Ensure we don't insert more chars than we can hold, and we don't
// have any integer overflow in our new length.
long insertingChars = (long)value.Length * count;
if (insertingChars > MaxCapacity - this.Length)
{
return AppendJoinCore(&separator, 1, values);
}
-
+
private unsafe StringBuilder AppendJoinCore<T>(char* separator, int separatorLength, IEnumerable<T> values)
{
Debug.Assert(separator != null);
if (startPos != pos)
{
// There was no brace escaping, extract the item format as a single string
- itemFormatSpan = format.AsSpan().Slice(startPos, pos - startPos);
+ itemFormatSpan = format.AsSpan(startPos, pos - startPos);
}
}
else
int indexInChunk = startIndex - chunk.m_ChunkOffset;
while (count > 0)
{
- // Look for a match in the chunk,indexInChunk pointer
+ // Look for a match in the chunk,indexInChunk pointer
if (StartsWith(chunk, indexInChunk, count, oldValue))
{
// Push it on the replacements array (with growth), we will do all replacements in a
if (indexInChunk >= chunk.m_ChunkLength || count == 0) // Have we moved out of the current chunk?
{
- // Replacing mutates the blocks, so we need to convert to a logical index and back afterwards.
+ // Replacing mutates the blocks, so we need to convert to a logical index and back afterwards.
int index = indexInChunk + chunk.m_ChunkOffset;
int indexBeforeAdjustment = index;
// See if we accumulated any replacements, if so apply them.
ReplaceAllInChunk(replacements, replacementsCount, chunk, oldValue.Length, newValue);
- // The replacement has affected the logical index. Adjust it.
+ // The replacement has affected the logical index. Adjust it.
index += ((newValue.Length - oldValue.Length) * replacementsCount);
replacementsCount = 0;
throw new ArgumentOutOfRangeException(nameof(valueCount), SR.ArgumentOutOfRange_LengthGreaterThanCapacity);
}
- // This case is so common we want to optimize for it heavily.
+ // This case is so common we want to optimize for it heavily.
int newIndex = valueCount + m_ChunkLength;
if (newIndex <= m_ChunkChars.Length)
{
m_ChunkLength = m_ChunkChars.Length;
}
- // Expand the builder to add another chunk.
+ // Expand the builder to add another chunk.
int restLength = valueCount - firstLength;
ExpandByABlock(restLength);
Debug.Assert(m_ChunkLength == 0, "A new block was not created.");
{
fixed (char* valuePtr = value)
{
- // calculate the total amount of extra space or space needed for all the replacements.
+ // calculate the total amount of extra space or space needed for all the replacements.
int delta = (value.Length - removeCount) * replacementsCount;
StringBuilder targetChunk = sourceChunk; // the target as we copy chars down
int targetIndexInChunk = replacements[0];
- // Make the room needed for all the new characters if needed.
+ // Make the room needed for all the new characters if needed.
if (delta > 0)
MakeRoom(targetChunk.m_ChunkOffset + targetIndexInChunk, delta, out targetChunk, out targetIndexInChunk, true);
- // We made certain that characters after the insertion point are not moved,
+ // We made certain that characters after the insertion point are not moved,
int i = 0;
for (;;)
{
Debug.Assert(gapStart < sourceChunk.m_ChunkChars.Length, "gap starts at end of buffer. Should not happen");
Debug.Assert(gapStart <= gapEnd, "negative gap size");
Debug.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big");
- if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
+ if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
{
// Copy the gap data between the current replacement and the next replacement
fixed (char* sourcePtr = &sourceChunk.m_ChunkChars[gapStart])
}
}
- // Remove extra space if necessary.
+ // Remove extra space if necessary.
if (delta < 0)
Remove(targetChunk.m_ChunkOffset + targetIndexInChunk, -delta, out targetChunk, out targetIndexInChunk);
}
int lengthToCopy = Math.Min(lengthInChunk, count);
ThreadSafeCopy(value, chunk.m_ChunkChars, indexInChunk, lengthToCopy);
- // Advance the index.
+ // Advance the index.
indexInChunk += lengthToCopy;
if (indexInChunk >= chunk.m_ChunkLength)
{
int endIndex = startIndex + count;
- // Find the chunks for the start and end of the block to delete.
+ // Find the chunks for the start and end of the block to delete.
chunk = this;
StringBuilder endChunk = null;
int endIndexInChunk = 0;
// SafeCritical: We ensure that `endIndexInChunk + copyCount` is within range of `m_ChunkChars`, and
// also ensure that `copyTargetIndexInChunk + copyCount` is within the chunk.
- // Remove any characters in the end chunk, by sliding the characters down.
+ // Remove any characters in the end chunk, by sliding the characters down.
if (copyTargetIndexInChunk != endIndexInChunk) // Sometimes no move is necessary
{
ThreadSafeCopy(endChunk.m_ChunkChars, endIndexInChunk, endChunk.m_ChunkChars, copyTargetIndexInChunk, copyCount);
}
/// <summary>
- /// Enumerate files
+ /// Enumerate files
/// </summary>
private static IEnumerable<string> EnumerateFilesRecursively(string path)
{
int secondDotIndex = dateRule.IndexOf('.', firstDotIndex + 1);
if (secondDotIndex > 0)
{
- if (int.TryParse(dateRule.AsSpan().Slice(1, firstDotIndex - 1), out month) &&
- int.TryParse(dateRule.AsSpan().Slice(firstDotIndex + 1, secondDotIndex - firstDotIndex - 1), out week) &&
- int.TryParse(dateRule.AsSpan().Slice(secondDotIndex + 1), out int day))
+ if (int.TryParse(dateRule.AsSpan(1, firstDotIndex - 1), out month) &&
+ int.TryParse(dateRule.AsSpan(firstDotIndex + 1, secondDotIndex - firstDotIndex - 1), out week) &&
+ int.TryParse(dateRule.AsSpan(secondDotIndex + 1), out int day))
{
dayOfWeek = (DayOfWeek)day;
return true;