123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- /** (c) Nullsoft, Inc. C O N F I D E N T I A L
- ** Filename:
- ** Project:
- ** Description:
- ** Author: Ben Allison [email protected]
- ** Created:
- **/
- #include <windows.h>
- #include <Shlwapi.h>
- #include "strutil.h"
- char *SkipX(char *str, int count)
- {
- while (count--)
- {
- str = CharNextA(str);
- }
- return str;
- }
- wchar_t *SkipXW(wchar_t *str, int count)
- {
- while (count--)
- {
- str = CharNextW(str);
- }
- return str;
- }
- void CopyChar(char *dest, const char *src)
- {
- char *end = CharNextA(src);
- ptrdiff_t count = end-src;
- while (count--)
- {
- *dest++=*src++;
- }
- }
- ptrdiff_t CopyCharW(wchar_t *dest, const wchar_t *src)
- {
- wchar_t *end = CharNextW(src);
- ptrdiff_t count = end-src;
- for (ptrdiff_t i=0;i<count;i++)
- {
- *dest++=*src++;
- }
- return count;
- }
- void MakeRelativePathName(const wchar_t *filename, wchar_t *outFile, const wchar_t *path)
- {
- wchar_t outPath[MAX_PATH] = {0};
- int common = PathCommonPrefixW(path, filename, outPath);
- if (common && common == lstrlenW(path))
- {
- PathAddBackslashW(outPath);
- const wchar_t *p = filename + lstrlenW(outPath);
- lstrcpynW(outFile, p, FILENAME_SIZE);
- }
- else if (!PathIsUNCW(filename) && PathIsSameRootW(filename, path))
- {
- lstrcpynW(outFile, filename+2, FILENAME_SIZE);
- }
- }
- static int CharacterCompareW(const wchar_t *ch1, const wchar_t *ch2)
- {
- wchar_t str1[3]={0,0,0}, str2[3]={0,0,0};
- CopyCharW(str1, ch1);
- CharUpperW(str1);
- CopyCharW(str2, ch2);
- CharUpperW(str2);
- return memcmp(str1, str2, 3*sizeof(wchar_t));
- }
- static void IncHelperW(LPCWSTR *src, ptrdiff_t *size)
- {
- wchar_t *end = CharNextW(*src);
- ptrdiff_t count = end-*src;
- *size-=count;
- *src=end;
- }
- int IsCharDigit(char digit)
- {
- WORD type=0;
- GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, &digit, 1, &type);
- return type&C1_DIGIT;
- }
- int IsCharDigitW(wchar_t digit)
- {
- WORD type=0;
- GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &digit, 1, &type);
- return type&C1_DIGIT;
- }
- int FileCompareLogical(const wchar_t *str1, const wchar_t *str2)
- {
- if (str1 && str2)
- {
- while (str1 && *str1)
- {
- if (!*str2)
- return 1;
- else if (IsCharDigitW(*str1))
- {
- int iStr, iComp;
-
- if (!IsCharDigitW(*str2))
- return -1;
- /* Compare the numbers */
- StrToIntExW(str1, 0, &iStr);
- StrToIntExW(str2, 0, &iComp);
- if (iStr < iComp)
- return -1;
- else if (iStr > iComp)
- return 1;
- /* Skip */
- while (IsCharDigitW(*str1))
- str1=CharNextW(str1);
- while (IsCharDigitW(*str2))
- str2=CharNextW(str2);
- }
- else if (IsCharDigitW(*str2))
- return 1;
- else
- {
- int diff = CharacterCompareW(str1, str2);
- if (diff > 0)
- return 1;
- else if (diff < 0)
- return -1;
- str1=CharNextW(str1);
- str2=CharNextW(str2);
- }
- }
- if (*str2)
- return -1;
- }
- return 0;
- }
- static int StringLengthNoDigits(LPCWSTR str, LPCWSTR *end)
- {
- ptrdiff_t length=0;
- while (str && *str && !IsCharDigitW(*str))
- {
- IncHelperW(&str, &length);
- }
- if (end) *end = str;
- return (int)(-length); // IncHelper decrements so we need to negate
- }
- int CompareStringLogical(LPCWSTR str1, LPCWSTR str2)
- {
- if (str1 && str2)
- {
- while (str1 && *str1)
- {
- if (!*str2)
- return 1;
- else if (IsCharDigitW(*str1))
- {
- int iStr, iComp;
-
- if (!IsCharDigitW(*str2))
- return -1;
-
- /* Compare the numbers */
- StrToIntExW(str1, 0, &iStr);
- StrToIntExW(str2, 0, &iComp);
- if (iStr < iComp)
- return -1;
- else if (iStr > iComp)
- return 1;
- /* Skip */
- while (IsCharDigitW(*str1))
- str1=CharNextW(str1);
- while (IsCharDigitW(*str2))
- str2=CharNextW(str2);
- }
- else if (IsCharDigitW(*str2))
- return 1;
- else
- {
- LPCWSTR next1, next2;
- int len1 = StringLengthNoDigits(str1, &next1);
- int len2 = StringLengthNoDigits(str2, &next2);
- int comp = CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE|NORM_IGNOREWIDTH, str1, len1, str2, len2);
- if (comp == CSTR_LESS_THAN)
- return -1;
- else if (comp == CSTR_GREATER_THAN)
- return 1;
- str1 = next1;
- str2 = next2;
- }
- }
- if (*str2)
- return -1;
- }
- return 0;
- }
- int FileCompareLogicalN(LPCWSTR str1, ptrdiff_t str1size, LPCWSTR str2, ptrdiff_t str2size)
- {
- if (str1 && str2)
- {
- while (str1 && *str1 && str1size)
- {
- if (!*str2 || !str2size)
- return 1;
- else if (IsCharDigitW(*str1))
- {
- int iStr, iComp;
-
- if (!IsCharDigitW(*str2))
- return -1;
- /* Compare the numbers */
- StrToIntExW(str1, 0, &iStr);
- StrToIntExW(str2, 0, &iComp);
- if (iStr < iComp)
- return -1;
- else if (iStr > iComp)
- return 1;
- /* Skip */
- while (IsCharDigitW(*str1))
- IncHelperW(&str1, &str1size);
- while (IsCharDigitW(*str2))
- IncHelperW(&str2, &str2size);
- }
- else if (IsCharDigitW(*str2))
- return 1;
- else
- {
- int diff = CharacterCompareW(str1, str2);
- if (diff > 0)
- return 1;
- else if (diff < 0)
- return -1;
- IncHelperW(&str1, &str1size);
- IncHelperW(&str2, &str2size);
- }
- }
- if (!str1size && !str2size)
- return 0;
- if (*str2 || str2size < str1size)
- return -1;
- if (*str1 || str1size < str2size)
- return 1;
- }
- return 0;
- }
- char *GetLastCharacter(char *string)
- {
- if (!string || !*string)
- return string;
- return CharPrevA(string, string+lstrlenA(string));
- }
- wchar_t *GetLastCharacterW(wchar_t *string)
- {
- if (!string || !*string)
- return string;
- return CharPrevW(string, string+lstrlenW(string));
- }
- const char *GetLastCharacterc(const char *string)
- {
- if (!string || !*string)
- return string;
- for (;;)
- {
- const char *next = CharNextA(string);
- if (!*next)
- return string;
- string = next;
- }
- }
- const wchar_t *GetLastCharactercW(const wchar_t *string)
- {
- if (!string || !*string)
- return string;
- return CharPrevW(string, string+lstrlenW(string));
- }
- wchar_t *scanstr_backW(wchar_t *str, wchar_t *toscan, wchar_t *defval)
- {
- wchar_t *s = GetLastCharacterW(str);
- if (!s || !str[0]) return defval;
- if (!toscan || !toscan[0]) return defval;
- for (;;)
- {
- wchar_t *t = toscan;
- while (t && *t)
- {
- if (*t == *s) return s;
- t = CharNextW(t);
- }
- t = CharPrevW(str, s);
- if (t == s)
- return defval;
- s = t;
- }
- }
- const wchar_t *scanstr_backcW(const wchar_t *str, const wchar_t *toscan, const wchar_t *defval)
- {
- const wchar_t *s = GetLastCharactercW(str);
- if (!s || !str[0]) return defval;
- if (!toscan || !toscan[0]) return defval;
- for (;;)
- {
- const wchar_t *t = toscan;
- while (t && *t)
- {
- if (*t == *s) return s;
- t = CharNextW(t);
- }
- t = CharPrevW(str, s);
- if (t == s)
- return defval;
- s = t;
- }
- }
- char *scanstr_back(char *str, char *toscan, char *defval)
- {
- char *s = GetLastCharacter(str);
- if (!s || !str[0]) return defval;
- if (!toscan || !toscan[0]) return defval;
- for (;;)
- {
- char *t = toscan;
- while (t && *t)
- {
- if (*t == *s) return s;
- t = CharNextA(t);
- }
- t = CharPrevA(str, s);
- if (t == s)
- return defval;
- s = t;
- }
- }
- const char *scanstr_backc(const char *str, const char *toscan, const char *defval)
- {
- const char *s = GetLastCharacterc(str);
- if (!s || !str[0]) return defval;
- if (!toscan || !toscan[0]) return defval;
- for (;;)
- {
- const char *t = toscan;
- while (t && *t)
- {
- if (*t == *s) return s;
- t = CharNextA(t);
- }
- t = CharPrevA(str, s);
- if (t == s)
- return defval;
- s = t;
- }
- }
- char *extension(const char *fn)
- {
- // TODO: deal with making sure that URLs don't return .com, etc.
- // e.g. http://www.winamp.com should return nothing
- char *end = scanstr_back((char*)fn, "./\\", 0);
- if (!end)
- return (char*)(fn+lstrlenA(fn));
- if (*end == '.')
- return CharNextA(end);
- return (char*)(fn+lstrlenA(fn));
- }
- wchar_t *extensionW(const wchar_t *fn)
- {
- // TODO: deal with making sure that URLs don't return .com, etc.
- // e.g. http://www.winamp.com should return nothing
- wchar_t *end = scanstr_backW((wchar_t*)fn, L"./\\", 0);
- if (!end)
- return (wchar_t *)(fn+lstrlenW(fn));
- if (*end == L'.')
- return CharNextW(end);
- return (wchar_t*)(fn+lstrlenW(fn));
- }
- const char *extensionc(const char *fn)
- {
- return extension(fn);
- }
- const wchar_t *extensioncW(const wchar_t *fn)
- {
- return extensionW(fn);
- }
- void extension_ex(const char *fn, char *buf, int buflen)
- {
- const char *s = extensionc(fn);
- if (!PathIsURLA(fn)
- || (!strstr(s, "?") && !strstr(s, "&") && !strstr(s, "=") && *s))
- {
- lstrcpynA(buf, s, buflen);
- return ;
- }
- // s is not a terribly good extension, let's try again
- {
- char *copy = _strdup(fn);
- s = "";
- again:
- {
- char *p = scanstr_back(copy, "?", copy);
- if (p != copy)
- {
- *p = 0;
- s = extension(copy);
- if (!*s) goto again;
- }
- lstrcpynA(buf, s, buflen);
- }
- free(copy);
- }
- }
- void extension_exW(const wchar_t *fn, wchar_t *buf, int buflen)
- {
- const wchar_t *s = extensioncW(fn);
- if (!PathIsURLW(fn)
- || (!wcsstr(s, L"?") && !wcsstr(s, L"&") && !wcsstr(s, L"=") && *s))
- {
- lstrcpynW(buf, s, buflen);
- return ;
- }
- // s is not a terribly good extension, let's try again
- {
- wchar_t *copy = _wcsdup(fn);
- s = L"";
- again:
- {
- wchar_t *p = scanstr_backW(copy, L"?", copy);
- if (p != copy)
- {
- *p = 0;
- s = extensionW(copy);
- if (!*s) goto again;
- }
- lstrcpynW(buf, s, buflen);
- }
- free(copy);
- }
- }
|