Skip to content

Instantly share code, notes, and snippets.

@bbowyersmyth
Last active May 17, 2016 09:49
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bbowyersmyth/c308aa62e871d44024c0bab552567961 to your computer and use it in GitHub Desktop.
Save bbowyersmyth/c308aa62e871d44024c0bab552567961 to your computer and use it in GitHub Desktop.
public static bool ContainsTokenUnroll(string value, string token, char delimiter = ';')
{
if (string.IsNullOrEmpty(token)) return false;
if (string.IsNullOrEmpty(value)) return false;
var valueLength = value.Length;
var tokenLength = token.Length;
if (tokenLength > valueLength) return false;
unsafe
{
fixed (char* valuePtr = value, tokenPtr = token)
{
char currentChar;
var curValuePtr = valuePtr;
var endValuePtr = valuePtr + valueLength - tokenLength;
do
{
var curTokenPtr = tokenPtr;
var count = tokenLength;
// Match token against the current position in value
while (count >= 2)
{
if (*(int*)curValuePtr != *(int*)curTokenPtr)
{
goto advanceToNextDelimiter;
}
count -= 2;
curValuePtr += 2;
curTokenPtr += 2;
}
if (count == 1)
{
if (*curValuePtr != *curTokenPtr)
{
goto advanceToNextDelimiter;
}
curValuePtr++;
}
// Token has been matched, check if the _next_ char
// in value is a delimiter or the end of value
if (*curValuePtr == delimiter || *curValuePtr == '\0')
{
return true;
}
curValuePtr++;
advanceToNextDelimiter:
// Find the next delimiter in value or the end of the string
// Unroll the loop by 2
while (true)
{
currentChar = *curValuePtr;
curValuePtr++;
if (currentChar == delimiter || currentChar == '\0')
{
break;
}
currentChar = *curValuePtr;
curValuePtr++;
if (currentChar == delimiter || currentChar == '\0')
{
break;
}
}
} while (curValuePtr <= endValuePtr);
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment