📄 string.c
字号:
* StrIsIntlEqualA [SHLWAPI.@]
*
* Compare two strings.
*
* PARAMS
* bCase [I] Whether to compare case sensitively
* lpszStr [I] First string to compare
* lpszComp [I] Second string to compare
* iLen [I] Length to compare
*
* RETURNS
* TRUE If the strings are equal.
* FALSE Otherwise.
*/
BOOL WINAPI StrIsIntlEqualA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp,
int iLen)
{
DWORD dwFlags;
TRACE("(%d,%s,%s,%d)\n", bCase,
debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
/* FIXME: This flag is undocumented and unknown by our CompareString.
* We need a define for it.
*/
dwFlags = 0x10000000;
if (!bCase) dwFlags |= NORM_IGNORECASE;
return (CompareStringA(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
}
/*************************************************************************
* StrIsIntlEqualW [SHLWAPI.@]
*
* See StrIsIntlEqualA.
*/
BOOL WINAPI StrIsIntlEqualW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp,
int iLen)
{
DWORD dwFlags;
TRACE("(%d,%s,%s,%d)\n", bCase,
debugstr_w(lpszStr),debugstr_w(lpszComp), iLen);
/* FIXME: This flag is undocumented and unknown by our CompareString.
* We need a define for it.
*/
dwFlags = 0x10000000;
if (!bCase) dwFlags |= NORM_IGNORECASE;
return (CompareStringW(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL);
}
/*************************************************************************
* @ [SHLWAPI.399]
*
* Copy a string to another string, up to a maximum number of characters.
*
* PARAMS
* lpszDest [O] Destination string
* lpszSrc [I] Source string
* iLen [I] Maximum number of chars to copy
*
* RETURNS
* Success: A pointer to the last character written to lpszDest.
* Failure: lpszDest, if any arguments are invalid.
*/
LPSTR WINAPI StrCpyNXA(LPSTR lpszDest, LPCSTR lpszSrc, int iLen)
{
TRACE("(%p,%s,%i)\n", lpszDest, debugstr_a(lpszSrc), iLen);
if (lpszDest && lpszSrc && iLen > 0)
{
while ((iLen-- > 1) && *lpszSrc)
*lpszDest++ = *lpszSrc++;
if (iLen >= 0)
*lpszDest = '\0';
}
return lpszDest;
}
/*************************************************************************
* @ [SHLWAPI.400]
*
* Unicode version of StrCpyNXA.
*/
LPWSTR WINAPI StrCpyNXW(LPWSTR lpszDest, LPCWSTR lpszSrc, int iLen)
{
TRACE("(%p,%s,%i)\n", lpszDest, debugstr_w(lpszSrc), iLen);
if (lpszDest && lpszSrc && iLen > 0)
{
while ((iLen-- > 1) && *lpszSrc)
*lpszDest++ = *lpszSrc++;
if (iLen >= 0)
*lpszDest = '\0';
}
return lpszDest;
}
/*************************************************************************
* StrCmpLogicalW [SHLWAPI.@]
*
* Compare two strings, ignoring case and comparing digits as numbers.
*
* PARAMS
* lpszStr [I] First string to compare
* lpszComp [I] Second string to compare
* iLen [I] Length to compare
*
* RETURNS
* TRUE If the strings are equal.
* FALSE Otherwise.
*/
INT WINAPI StrCmpLogicalW(LPCWSTR lpszStr, LPCWSTR lpszComp)
{
INT iDiff;
TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp));
if (lpszStr && lpszComp)
{
while (*lpszStr)
{
if (!*lpszComp)
return 1;
else if (isdigitW(*lpszStr))
{
int iStr, iComp;
if (!isdigitW(*lpszComp))
return -1;
/* Compare the numbers */
StrToIntExW(lpszStr, 0, &iStr);
StrToIntExW(lpszComp, 0, &iComp);
if (iStr < iComp)
return -1;
else if (iStr > iComp)
return 1;
/* Skip */
while (isdigitW(*lpszStr))
lpszStr++;
while (isdigitW(*lpszComp))
lpszComp++;
}
else if (isdigitW(*lpszComp))
return 1;
else
{
iDiff = ChrCmpIW(*lpszStr,*lpszComp);
if (iDiff > 0)
return 1;
else if (iDiff < 0)
return -1;
lpszStr++;
lpszComp++;
}
}
if (*lpszComp)
return -1;
}
return 0;
}
/* Structure for formatting byte strings */
typedef struct tagSHLWAPI_BYTEFORMATS
{
LONGLONG dLimit;
double dDivisor;
double dNormaliser;
int nDecimals;
WCHAR wPrefix;
} SHLWAPI_BYTEFORMATS;
/*************************************************************************
* StrFormatByteSizeW [SHLWAPI.@]
*
* Create a string containing an abbreviated byte count of up to 2^63-1.
*
* PARAMS
* llBytes [I] Byte size to format
* lpszDest [I] Destination for formatted string
* cchMax [I] Size of lpszDest
*
* RETURNS
* lpszDest.
*
* NOTES
* There is no StrFormatByteSize64W function, it is called StrFormatByteSizeW().
*/
LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
{
#define KB ((ULONGLONG)1024)
#define MB (KB*KB)
#define GB (KB*KB*KB)
#define TB (KB*KB*KB*KB)
#define PB (KB*KB*KB*KB*KB)
static const SHLWAPI_BYTEFORMATS bfFormats[] =
{
{ 10*KB, 10.24, 100.0, 2, 'K' }, /* 10 KB */
{ 100*KB, 102.4, 10.0, 1, 'K' }, /* 100 KB */
{ 1000*KB, 1024.0, 1.0, 0, 'K' }, /* 1000 KB */
{ 10*MB, 10485.76, 100.0, 2, 'M' }, /* 10 MB */
{ 100*MB, 104857.6, 10.0, 1, 'M' }, /* 100 MB */
{ 1000*MB, 1048576.0, 1.0, 0, 'M' }, /* 1000 MB */
{ 10*GB, 10737418.24, 100.0, 2, 'G' }, /* 10 GB */
{ 100*GB, 107374182.4, 10.0, 1, 'G' }, /* 100 GB */
{ 1000*GB, 1073741824.0, 1.0, 0, 'G' }, /* 1000 GB */
{ 10*TB, 10485.76, 100.0, 2, 'T' }, /* 10 TB */
{ 100*TB, 104857.6, 10.0, 1, 'T' }, /* 100 TB */
{ 1000*TB, 1048576.0, 1.0, 0, 'T' }, /* 1000 TB */
{ 10*PB, 10737418.24, 100.00, 2, 'P' }, /* 10 PB */
{ 100*PB, 107374182.4, 10.00, 1, 'P' }, /* 100 PB */
{ 1000*PB, 1073741824.0, 1.00, 0, 'P' }, /* 1000 PB */
{ 0, 10995116277.76, 100.00, 2, 'E' } /* EB's, catch all */
};
WCHAR wszAdd[] = {' ','?','B',0};
double dBytes;
UINT i = 0;
TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
if (!lpszDest || !cchMax)
return lpszDest;
if (llBytes < 1024) /* 1K */
{
WCHAR wszBytesFormat[64];
LoadStringW(shlwapi_hInstance, IDS_BYTES_FORMAT, wszBytesFormat, 64);
snprintfW(lpszDest, cchMax, wszBytesFormat, (long)llBytes);
return lpszDest;
}
/* Note that if this loop completes without finding a match, i will be
* pointing at the last entry, which is a catch all for > 1000 PB
*/
while (i < sizeof(bfFormats) / sizeof(SHLWAPI_BYTEFORMATS) - 1)
{
if (llBytes < bfFormats[i].dLimit)
break;
i++;
}
/* Above 1 TB we encounter problems with FP accuracy. So for amounts above
* this number we integer shift down by 1 MB first. The table above has
* the divisors scaled down from the '< 10 TB' entry onwards, to account
* for this. We also add a small fudge factor to get the correct result for
* counts that lie exactly on a 1024 byte boundary.
*/
if (i > 8)
dBytes = (double)(llBytes >> 20) + 0.001; /* Scale down by I MB */
else
dBytes = (double)llBytes + 0.00001;
dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser;
if (!FormatDouble(dBytes, bfFormats[i].nDecimals, lpszDest, cchMax))
return NULL;
wszAdd[1] = bfFormats[i].wPrefix;
StrCatBuffW(lpszDest, wszAdd, cchMax);
return lpszDest;
}
/*************************************************************************
* StrFormatByteSize64A [SHLWAPI.@]
*
* See StrFormatByteSizeW.
*/
LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
{
WCHAR wszBuff[32];
StrFormatByteSizeW(llBytes, wszBuff, sizeof(wszBuff)/sizeof(WCHAR));
if (lpszDest)
WideCharToMultiByte(CP_ACP, 0, wszBuff, -1, lpszDest, cchMax, 0, 0);
return lpszDest;
}
/*************************************************************************
* StrFormatByteSizeA [SHLWAPI.@]
*
* Create a string containing an abbreviated byte count of up to 2^31-1.
*
* PARAMS
* dwBytes [I] Byte size to format
* lpszDest [I] Destination for formatted string
* cchMax [I] Size of lpszDest
*
* RETURNS
* lpszDest.
*
* NOTES
* The Ascii and Unicode versions of this function accept a different
* integer type for dwBytes. See StrFormatByteSize64A().
*/
LPSTR WINAPI StrFormatByteSizeA(DWORD dwBytes, LPSTR lpszDest, UINT cchMax)
{
TRACE("(%d,%p,%d)\n", dwBytes, lpszDest, cchMax);
return StrFormatByteSize64A(dwBytes, lpszDest, cchMax);
}
/*************************************************************************
* @ [SHLWAPI.162]
*
* Remove a hanging lead byte from the end of a string, if present.
*
* PARAMS
* lpStr [I] String to check for a hanging lead byte
* size [I] Length of lpStr
*
* RETURNS
* Success: The new length of the string. Any hanging lead bytes are removed.
* Failure: 0, if any parameters are invalid.
*/
DWORD WINAPI SHTruncateString(LPSTR lpStr, DWORD size)
{
if (lpStr && size)
{
LPSTR lastByte = lpStr + size - 1;
while(lpStr < lastByte)
lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
{
*lpStr = '\0';
size--;
}
return size;
}
return 0;
}
/*************************************************************************
* @ [SHLWAPI.203]
*
* Remove a single non-trailing ampersand ('&') from a string.
*
* PARAMS
* lpszStr [I/O] String to remove ampersand from.
*
* RETURNS
* The character after the first ampersand in lpszStr, or the first character
* in lpszStr if there is no ampersand in the string.
*/
char WINAPI SHStripMneumonicA(LPCSTR lpszStr)
{
LPSTR lpszIter, lpszTmp;
char ch;
TRACE("(%s)\n", debugstr_a(lpszStr));
ch = *lpszStr;
if ((lpszIter = StrChrA(lpszStr, '&')))
{
lpszTmp = CharNextA(lpszIter);
if (lpszTmp && *lpszTmp)
{
if (*lpszTmp != '&')
ch = *lpszTmp;
while (lpszIter && *lpszIter)
{
lpszTmp = CharNextA(lpszIter);
*lpszIter = *lpszTmp;
lpszIter = lpszTmp;
}
}
}
return ch;
}
/*************************************************************************
* @ [SHLWAPI.225]
*
* Unicode version of SHStripMneumonicA.
*/
WCHAR WINAPI SHStripMneumonicW(LPCWSTR lpszStr)
{
LPWSTR lpszIter, lpszTmp;
WCHAR ch;
TRACE("(%s)\n", debugstr_w(lpszStr));
ch = *lpszStr;
if ((lpszIter = StrChrW(lpszStr, '&')))
{
lpszTmp = lpszIter + 1;
if (lpszTmp && *lpszTmp)
{
if (*lpszTmp != '&')
ch = *lpszTmp;
while (lpszIter && *lpszIter)
{
lpszTmp = lpszIter + 1;
*lpszIter = *lpszTmp;
lpszIter = lpszTmp;
}
}
}
return ch;
}
/*************************************************************************
* @ [SHLWAPI.216]
*
* Convert an Ascii string to Unicode.
*
* PARAMS
* dwCp [I] Code page for the conversion
* lpSrcStr [I] Source Ascii string to convert
* lpDstStr [O] Destination for converted Unicode string
* iLen [I] Length of lpDstStr
*
* RETURNS
* The return value of the MultiByteToWideChar() function called on lpSrcStr.
*/
DWORD WINAPI SHAnsiToUnicodeCP(DWORD dwCp, LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
{
DWORD dwRet;
dwRet = MultiByteToWideChar(dwCp, 0, lpSrcStr, -1, lpDstStr, iLen);
TRACE("%s->%s,ret=%d\n", debugstr_a(lpSrcStr), debugstr_w(lpDstStr), dwRet);
return dwRet;
}
/*************************************************************************
* @ [SHLWAPI.215]
*
* Convert an Ascii string to Unicode.
*
* PARAMS
* lpSrcStr [I] Source Ascii string to convert
* lpDstStr [O] Destination for converted Unicode string
* iLen [I] Length of lpDstStr
*
* RETURNS
* The return value of the MultiByteToWideChar() function called on lpSrcStr.
*
* NOTES
* This function simply calls SHAnsiToUnicodeCP with code page CP_ACP.
*/
DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
{
return SHAnsiToUnicodeCP(CP_ACP, lpSrcStr, lpDstStr, iLen);
}
/*************************************************************************
* @ [SHLWAPI.218]
*
* Convert a Unicode string to Ascii.
*
* PARAMS
* CodePage [I] Code page to use for the conversion
* lpSrcStr [I] Source Unicode string to convert
* lpDstStr [O] Destination for converted Ascii string
* lpiLen [I/O] Input length of lpDstStr/destination for length of lpDstStr
*
* RETURNS
* Success: The number of characters that result from the conversion.
* Failure: 0.
*/
INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
LPINT lpiLen)
{
static const WCHAR emptyW[] = { '\0' };
int len , reqLen;
LPSTR mem;
if (!lpDstStr || !lpiLen)
return 0;
if (!lpSrcStr)
lpSrcStr = emptyW;
*lpDstStr = '\0';
len = strlenW(lpSrcStr) + 1;
switch (CodePage)
{
case CP_WINUNICODE:
CodePage = CP_UTF8; /* Fall through... */
case 0x0000C350: /* FIXME: CP_ #define */
case CP_UTF7:
case CP_UTF8:
{
DWORD dwMode = 0;
INT nWideCharCount = len - 1;
if (!Conver
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -