Skip to content

Instantly share code, notes, and snippets.

@skalinets
Created March 16, 2012 11:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skalinets/8a1c93de263559216331 to your computer and use it in GitHub Desktop.
Save skalinets/8a1c93de263559216331 to your computer and use it in GitHub Desktop.
String.Split() implementation
[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