-
-
Save skalinets/8a1c93de263559216331 to your computer and use it in GitHub Desktop.
String.Split() implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ComVisible(false)] | |
public String[] Split(String[] separator, Int32 count, StringSplitOptions options) { | |
if (count < 0) { | |
throw new ArgumentOutOfRangeException("count", | |
Environment.GetResourceString("ArgumentOutOfRange_NegativeCount")); | |
} | |
if (options < StringSplitOptions.None || options > StringSplitOptions.RemoveEmptyEntries) { | |
throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options)); | |
} | |
Contract.EndContractBlock(); | |
bool omitEmptyEntries = (options == StringSplitOptions.RemoveEmptyEntries); | |
if (separator == null || separator.Length ==0) { | |
return SplitInternal((char[]) null, count, options); | |
} | |
if ((count == 0) || (omitEmptyEntries && this.Length ==0)) { | |
return new String[0]; | |
} | |
int[] sepList = new int[Length]; | |
int[] lengthList = new int[Length]; | |
int numReplaces = MakeSeparatorList(separator, ref sepList, ref lengthList); | |
//Handle the special case of no replaces and special count. | |
if (0 == numReplaces || count == 1) { | |
String[] stringArray = new String[1]; | |
stringArray[0] = this; | |
return stringArray; | |
} | |
if (omitEmptyEntries) { | |
return InternalSplitOmitEmptyEntries(sepList, lengthList, numReplaces, count); | |
} | |
else { | |
return InternalSplitKeepEmptyEntries(sepList, lengthList, numReplaces, count); | |
} | |
} | |
// Note a few special case in this function: | |
// If there is no separator in the string, a string array which only contains | |
// the original string will be returned regardless of the count. | |
// | |
private String[] InternalSplitKeepEmptyEntries(Int32 [] sepList, Int32 [] lengthList, Int32 numReplaces, int count) { | |
Contract.Requires(numReplaces >= 0); | |
Contract.Requires(count >= 2, "Count>=2"); | |
int currIndex = 0; | |
int arrIndex = 0; | |
count--; | |
int numActualReplaces = (numReplaces < count) ? numReplaces : count; | |
//Allocate space for the new array. | |
//+1 for the string from the end of the last replace to the end of the String. | |
String[] splitStrings = new String[numActualReplaces+1]; | |
for (int i = 0; i < numActualReplaces && currIndex < Length; i++) { | |
splitStrings[arrIndex++] = Substring(currIndex, sepList[i]-currIndex ); | |
currIndex=sepList[i] + ((lengthList == null) ? 1 : lengthList[i]); | |
} | |
//Handle the last string at the end of the array if there is one. | |
if (currIndex < Length && numActualReplaces >= 0) { | |
splitStrings[arrIndex] = Substring(currIndex); | |
} | |
else if (arrIndex==numActualReplaces) { | |
//We had a separator character at the end of a string. Rather than just allowing | |
//a null character, we'll replace the last element in the array with an empty string. | |
splitStrings[arrIndex] = String.Empty; | |
} | |
return splitStrings; | |
} | |
// This function will not keep the Empty String | |
private String[] InternalSplitOmitEmptyEntries(Int32[] sepList, Int32[] lengthList, Int32 numReplaces, int count) { | |
Contract.Requires(numReplaces >= 0); | |
Contract.Requires(count >= 2, "Count>=2"); | |
// 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]; | |
int currIndex = 0; | |
int arrIndex = 0; | |
for(int i=0; i< numReplaces && currIndex < Length; i++) { | |
if( sepList[i]-currIndex > 0) { | |
splitStrings[arrIndex++] = Substring(currIndex, sepList[i]-currIndex ); | |
} | |
currIndex=sepList[i] + ((lengthList == null) ? 1 : lengthList[i]); | |
if( arrIndex == count -1 ) { | |
// If all the remaining entries at the end are empty, skip them | |
while( i < numReplaces - 1 && currIndex == sepList[++i]) { | |
currIndex += ((lengthList == null) ? 1 : lengthList[i]); | |
} | |
break; | |
} | |
} | |
// we must have at least one slot left to fill in the last string. | |
Contract.Assert( arrIndex < maxItems, "arrIndex < maxItems"); | |
//Handle the last string at the end of the array if there is one. | |
if (currIndex< Length) { | |
splitStrings[arrIndex++] = Substring(currIndex); | |
} | |
String[] stringArray = splitStrings; | |
if( arrIndex!= maxItems) { | |
stringArray = new String[arrIndex]; | |
for( int j = 0; j < arrIndex; j++) { | |
stringArray[j] = splitStrings[j]; | |
} | |
} | |
return stringArray; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment