Search code examples
c++winapic-stringscrtlinguistics

Is there a function/WinAPI to tell if one string starts with another string in a case-insensitive linguistic way?


The best way to illustrate my question is with this example (that doesn't work if I use the strstr CRT function):

const wchar_t* s1 = L"Hauptstraße ist die längste";
const wchar_t* s2 = L"Hauptstrasse";

bool b_s1_starts_with_s2 = !!wcsstr(s1, s2);
_ASSERT(b_s1_starts_with_s2);   //Should be true

So far the only WinAPI that seems to recognize linguistic string equivalency is CompareStringEx when used with the LINGUISTIC_IGNORECASE flag, but it is somewhat tricky & inefficient to use for this purpose as I will have to call it on s2 repeatedly until I reach its end.

So I was wondering if there's a better approach to doing this (under Windows)?

EDIT: Here's what I mean:

bool b_s1_starts_with_s2 = false;

int ln1 = (int)wcslen(s1);
int ln2 = (int)wcslen(s2);

for(int p = 1; p <= ln1; p++)
{
    if(::CompareString(LOCALE_USER_DEFAULT, LINGUISTIC_IGNORECASE,
        s1, p,
        s2, ln2) == CSTR_EQUAL)
    {
        //Match
        b_s1_starts_with_s2 = true;
        break;
    }
}

Solution

  • You can use FindNLSString, check if the return value is zero.

    Evidently it matches ß with ss

    const wchar_t *s1 = L"Hauptstraße ist die längste";
    const wchar_t *s2 = L"Hauptstrasse";
    
    INT found = 0;
    int start = FindNLSString(0, LINGUISTIC_IGNORECASE, s1, -1, s2, -1, &found);
    wprintf(L"start = %d\n", start);
    
    s1 = L"δεθ Testing Greek";
    s2 = L"ΔΕΘ";
    start = FindNLSString(0, LINGUISTIC_IGNORECASE, s1, -1, s2, -1, &found);
    wprintf(L"start = %d\n", start);