MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / tcsrstr

Function tcsrstr

source/util.cpp:564–653  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

562
563
564LPTSTR tcsrstr(LPTSTR aStr, size_t aStr_length, LPCTSTR aPattern, StringCaseSenseType aStringCaseSense, int aOccurrence)
565// Returns NULL if not found, otherwise the address of the found string.
566// This could probably use a faster algorithm someday. For now it seems adequate because
567// scripts rarely use it and when they do, it's usually on short haystack strings (such as
568// to find the last period in a filename).
569{
570 if (aOccurrence < 1)
571 return NULL;
572 if (!*aPattern)
573 // The empty string is found in every string, and since we're searching from the right, return
574 // the position of the zero terminator to indicate the situation:
575 return aStr + aStr_length;
576
577 size_t aPattern_length = _tcslen(aPattern);
578 TCHAR aPattern_last_char = aPattern[aPattern_length - 1];
579 TCHAR aPattern_last_char_lower = (aStringCaseSense == SCS_INSENSITIVE_LOCALE)
580 ? (TCHAR)ltolower(aPattern_last_char)
581 : ctolower(aPattern_last_char);
582
583 int occurrence = 0;
584 LPCTSTR match_starting_pos = aStr + aStr_length - 1;
585
586 // Keep finding matches from the right until the Nth occurrence (specified by the caller) is found.
587 for (;;)
588 {
589 if (match_starting_pos < aStr)
590 return NULL; // No further matches are possible.
591 // Find (from the right) the first occurrence of aPattern's last char:
592 LPCTSTR last_char_match;
593 for (last_char_match = match_starting_pos; last_char_match >= aStr; --last_char_match)
594 {
595 if (aStringCaseSense == SCS_INSENSITIVE) // The most common mode is listed first for performance.
596 {
597 if (ctolower(*last_char_match) == aPattern_last_char_lower)
598 break;
599 }
600 else if (aStringCaseSense == SCS_INSENSITIVE_LOCALE)
601 {
602 if (ltolower(*last_char_match) == aPattern_last_char_lower)
603 break;
604 }
605 else // Case sensitive.
606 {
607 if (*last_char_match == aPattern_last_char)
608 break;
609 }
610 }
611
612 if (last_char_match < aStr) // No further matches are possible.
613 return NULL;
614
615 // Now that aPattern's last character has been found in aStr, ensure the rest of aPattern
616 // exists in aStr to the left of last_char_match:
617 LPCTSTR full_match, cp;
618 bool found;
619 for (found = false, cp = aPattern + aPattern_length - 2, full_match = last_char_match - 1;; --cp, --full_match)
620 {
621 if (cp < aPattern) // The complete pattern has been found at the position in full_match + 1.

Callers 1

BIF_DECLFunction · 0.85

Calls 1

ctolowerFunction · 0.85

Tested by

no test coverage detected