123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- string.c
- Abstract:
- This module implements common string manipulation functions used by the
- kernel.
- Author:
- Evan Green 24-Jul-2012
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "rtlp.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // ------------------------------------------------------------------ Functions
- //
- RTL_API
- ULONG
- RtlStringCopy (
- PSTR Destination,
- PSTR Source,
- ULONG BufferSize
- )
- /*++
- Routine Description:
- This routine copies a string from one buffer to another, including the NULL
- terminator.
- Arguments:
- Destination - Supplies a pointer to the buffer where the string will be
- copied to.
- Source - Supplies a pointer to the string to copy.
- BufferSize - Supplies the size of the destination buffer.
- Return Value:
- Returns the number of bytes copied, including the NULL terminator. If the
- source string is longer than the destination buffer, the string will be
- truncated but still NULL terminated.
- --*/
- {
- ULONG ByteIndex;
- ASSERT(BufferSize != 0);
- for (ByteIndex = 0; ByteIndex < BufferSize; ByteIndex += 1) {
- Destination[ByteIndex] = Source[ByteIndex];
- if (Source[ByteIndex] == STRING_TERMINATOR) {
- break;
- }
- }
- if (ByteIndex == BufferSize) {
- ByteIndex -= 1;
- }
- //
- // Terminate the string in case the source was too long.
- //
- Destination[ByteIndex] = STRING_TERMINATOR;
- return ByteIndex + 1;
- }
- RTL_API
- VOID
- RtlStringReverse (
- PSTR String,
- PSTR StringEnd
- )
- /*++
- Routine Description:
- This routine reverses the contents of a string. For example, the string
- "abcd" would get reversed to "dcba".
- Arguments:
- String - Supplies a pointer to the beginning of the string to reverse.
- StringEnd - Supplies a pointer to one beyond the end of the string. That is,
- this pointer points to the first byte *not* in the string.
- Return Value:
- None.
- --*/
- {
- ULONG Length;
- ULONG Position;
- UCHAR SwapSpace;
- Length = StringEnd - String;
- //
- // Work from the left towards the middle, swapping characters with their
- // positions on the other extreme. The truncation of Length / 2 is okay
- // because odd length strings do not need their middle byte swapped.
- //
- for (Position = 0; Position < (Length / 2); Position += 1) {
- SwapSpace = String[Position];
- String[Position] = String[Length - Position - 1];
- String[Length - Position - 1] = SwapSpace;
- }
- return;
- }
- RTL_API
- ULONG
- RtlStringLength (
- PSTR String
- )
- /*++
- Routine Description:
- This routine determines the length of the given string, not including its
- NULL terminator.
- Arguments:
- String - Supplies a pointer to the beginning of the string.
- Return Value:
- Returns the length of the string, not including the NULL terminator.
- --*/
- {
- ULONG Length;
- Length = 0;
- while (*String != STRING_TERMINATOR) {
- Length += 1;
- String += 1;
- }
- return Length;
- }
- RTL_API
- BOOL
- RtlAreStringsEqual (
- PSTR String1,
- PSTR String2,
- ULONG MaxLength
- )
- /*++
- Routine Description:
- This routine determines if the contents of two strings are equal, up to a
- maximum number of characters.
- Arguments:
- String1 - Supplies a pointer to the first string to compare.
- String2 - Supplies a pointer to the second string to compare.
- MaxLength - Supplies the minimum of either string's buffer size.
- Return Value:
- TRUE if the strings are equal up to the maximum length.
- FALSE if the strings differ in some way.
- --*/
- {
- if (String1 == String2) {
- return TRUE;
- }
- while ((*String1 != STRING_TERMINATOR) &&
- (*String2 != STRING_TERMINATOR) &&
- (MaxLength != 0)) {
- if (*String1 != *String2) {
- return FALSE;
- }
- String1 += 1;
- String2 += 1;
- MaxLength -= 1;
- }
- if ((MaxLength != 0) && (*String1 != *String2)) {
- return FALSE;
- }
- return TRUE;
- }
- RTL_API
- BOOL
- RtlAreStringsEqualIgnoringCase (
- PSTR String1,
- PSTR String2,
- ULONG MaxLength
- )
- /*++
- Routine Description:
- This routine determines if the contents of two strings are equal, up to a
- maximum number of characters. This routine is case insensitive.
- Arguments:
- String1 - Supplies a pointer to the first string to compare.
- String2 - Supplies a pointer to the second string to compare.
- MaxLength - Supplies the minimum of either string's buffer size.
- Return Value:
- TRUE if the strings are equal up to the maximum length.
- FALSE if the strings differ in some way.
- --*/
- {
- CHAR Character1;
- CHAR Character2;
- if (String1 == String2) {
- return TRUE;
- }
- while ((*String1 != STRING_TERMINATOR) &&
- (*String2 != STRING_TERMINATOR) &&
- (MaxLength != 0)) {
- Character1 = *String1;
- Character2 = *String2;
- if ((Character1 >= 'a') && (Character1 <= 'z')) {
- Character1 = Character1 - 'a' + 'A';
- }
- if ((Character2 >= 'a') && (Character2 <= 'z')) {
- Character2 = Character2 - 'a' + 'A';
- }
- if (Character1 != Character2) {
- return FALSE;
- }
- String1 += 1;
- String2 += 1;
- MaxLength -= 1;
- }
- if ((MaxLength != 0) && (*String1 != *String2)) {
- return FALSE;
- }
- return TRUE;
- }
- RTL_API
- PSTR
- RtlStringFindCharacter (
- PSTR String,
- CHAR Character,
- ULONG StringLength
- )
- /*++
- Routine Description:
- This routine searches a string for the first instance of the given
- character, scanning from the left.
- Arguments:
- String - Supplies a pointer to the string to search.
- Character - Supplies a pointer to the character to search for within the
- string.
- StringLength - Supplies the length of the string, in bytes, including the
- NULL terminator.
- Return Value:
- Returns a pointer to the first instance of the character on success.
- NULL if the character could not be found in the string.
- --*/
- {
- //
- // Search the string for the character as long as the end of the string
- // is not reached according to a NULL terminator or the string length.
- //
- while ((StringLength != 0) && (*String != STRING_TERMINATOR)) {
- if (*String == Character) {
- return String;
- }
- String += 1;
- StringLength -= 1;
- }
- return NULL;
- }
- RTL_API
- PSTR
- RtlStringFindCharacterRight (
- PSTR String,
- CHAR Character,
- ULONG StringLength
- )
- /*++
- Routine Description:
- This routine searches a string for the first instance of the given
- character, scanning from the right backwards. The function will search
- starting at the NULL terminator or string length, whichever comes first.
- Arguments:
- String - Supplies a pointer to the string to search.
- Character - Supplies a pointer to the character to search for within the
- string.
- StringLength - Supplies the length of the string, in bytes, including the
- NULL terminator.
- Return Value:
- Returns a pointer to the first instance of the character on success.
- NULL if the character could not be found in the string.
- --*/
- {
- PSTR Current;
- if ((String == NULL) || (StringLength == 0)) {
- return NULL;
- }
- //
- // Find the end of the string.
- //
- Current = String;
- while ((*Current != STRING_TERMINATOR) &&
- ((UINTN)Current - (UINTN)String < StringLength)) {
- Current += 1;
- }
- //
- // Now walk backwards looking for the character.
- //
- while (Current != String) {
- if (*Current == Character) {
- return Current;
- }
- Current -= 1;
- }
- if (*Current == Character) {
- return String;
- }
- return NULL;
- }
- RTL_API
- PSTR
- RtlStringSearch (
- PSTR InputString,
- UINTN InputStringLength,
- PSTR QueryString,
- UINTN QueryStringLength
- )
- /*++
- Routine Description:
- This routine searches a string for the first instance of the given string
- within it.
- Arguments:
- InputString - Supplies a pointer to the string to search.
- InputStringLength - Supplies the length of the string, in bytes, including
- the NULL terminator.
- QueryString - Supplies a pointer to the null terminated string to search
- for.
- QueryStringLength - Supplies the length of the query string in bytes
- including the null terminator.
- Return Value:
- Returns a pointer to the first instance of the string on success.
- NULL if the character could not be found in the string.
- --*/
- {
- size_t BadCharacterShift[MAX_UCHAR + 1];
- int Character;
- size_t LastIndex;
- size_t ScanIndex;
- if ((QueryString == NULL) || (InputString == NULL)) {
- return NULL;
- }
- if (QueryStringLength <= 1) {
- return (char *)InputString;
- }
- if (InputStringLength < QueryStringLength) {
- return NULL;
- }
- InputStringLength -= 1;
- QueryStringLength -= 1;
- //
- // Initialize the bad shift table assuming that no character exists in the
- // query string, and thus the search can be advanced by the entire query
- // string.
- //
- for (ScanIndex = 0; ScanIndex <= MAX_UCHAR; ScanIndex += 1) {
- BadCharacterShift[ScanIndex] = QueryStringLength;
- }
- //
- // Now find the last occurrence of each character and save it in the shift
- // table.
- //
- LastIndex = QueryStringLength - 1;
- for (ScanIndex = 0; ScanIndex < LastIndex; ScanIndex += 1) {
- Character = (UCHAR)(QueryString[ScanIndex]);
- BadCharacterShift[Character] = LastIndex - ScanIndex;
- }
- //
- // Search the query string.
- //
- while (InputStringLength >= QueryStringLength) {
- //
- // Scan from the end.
- //
- ScanIndex = LastIndex;
- while (InputString[ScanIndex] == QueryString[ScanIndex]) {
- if (ScanIndex == 0) {
- return (PSTR)InputString;
- }
- ScanIndex -= 1;
- }
- //
- // Move on to a new position. Skip based on the last character of the
- // input no matter where the mismatch is.
- //
- Character = (UCHAR)(InputString[LastIndex]);
- InputStringLength -= BadCharacterShift[Character];
- InputString += BadCharacterShift[Character];
- }
- return NULL;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
|