/** (c) Nullsoft, Inc. C O N F I D E N T I A L ** Filename: ** Project: ** Description: ** Author: Ben Allison benski@nullsoft.com ** Created: **/ #include #include #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 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); } }