FreeRDP/winpr/libwinpr/crt/string.c

670 lines
10 KiB
C
Raw Normal View History

2012-05-06 06:09:08 +04:00
/**
* WinPR: Windows Portable Runtime
* String Manipulation (CRT)
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2022-02-16 12:08:00 +03:00
#include <winpr/config.h>
2022-07-01 12:26:44 +03:00
#include <winpr/assert.h>
2012-05-22 06:04:14 +04:00
#include <errno.h>
2015-12-18 11:45:44 +03:00
#include <stdio.h>
2020-11-10 10:14:56 +03:00
#include <ctype.h>
2012-05-22 06:04:14 +04:00
#include <wctype.h>
2020-11-10 10:14:56 +03:00
#include <wchar.h>
2012-05-22 06:04:14 +04:00
2012-05-06 06:09:08 +04:00
#include <winpr/crt.h>
#include <winpr/endian.h>
2012-05-06 06:09:08 +04:00
/* String Manipulation (CRT): http://msdn.microsoft.com/en-us/library/f0151s4x.aspx */
2014-08-18 19:22:22 +04:00
#include "../log.h"
#define TAG WINPR_TAG("crt")
2014-08-18 19:22:22 +04:00
2022-06-03 11:25:30 +03:00
BOOL winpr_str_append(const char* what, char* buffer, size_t size, const char* separator)
{
const size_t used = strnlen(buffer, size);
const size_t add = strnlen(what, size);
const size_t sep_len = separator ? strnlen(separator, size) : 0;
const size_t sep = (used > 0) ? sep_len : 0;
if (used + add + sep >= size)
return FALSE;
if ((used > 0) && (sep_len > 0))
strncat(buffer, separator, sep_len);
strncat(buffer, what, add);
return TRUE;
}
#ifndef _WIN32
2014-08-18 21:34:47 +04:00
char* _strdup(const char* strSource)
2012-05-06 06:09:08 +04:00
{
2014-08-18 21:34:47 +04:00
char* strDestination;
2012-05-06 06:09:08 +04:00
if (strSource == NULL)
return NULL;
strDestination = strdup(strSource);
if (strDestination == NULL)
WLog_ERR(TAG, "strdup");
2012-05-06 06:09:08 +04:00
return strDestination;
}
2014-08-18 21:34:47 +04:00
WCHAR* _wcsdup(const WCHAR* strSource)
2012-05-06 06:09:08 +04:00
{
size_t len = _wcslen(strSource);
2014-08-18 21:34:47 +04:00
WCHAR* strDestination;
2012-05-06 06:09:08 +04:00
strDestination = calloc(len + 1, sizeof(WCHAR));
2012-05-25 06:20:51 +04:00
if (strDestination != NULL)
memcpy(strDestination, strSource, len * sizeof(WCHAR));
2012-05-06 06:09:08 +04:00
if (strDestination == NULL)
WLog_ERR(TAG, "wcsdup");
2012-05-06 06:09:08 +04:00
return strDestination;
}
2014-08-18 21:34:47 +04:00
int _stricmp(const char* string1, const char* string2)
2012-07-28 23:49:16 +04:00
{
return strcasecmp(string1, string2);
}
2014-08-18 21:34:47 +04:00
int _strnicmp(const char* string1, const char* string2, size_t count)
{
return strncasecmp(string1, string2, count);
}
2012-10-29 06:16:21 +04:00
/* _wcscmp -> wcscmp */
2014-08-18 21:34:47 +04:00
int _wcscmp(const WCHAR* string1, const WCHAR* string2)
2012-10-29 06:16:21 +04:00
{
WCHAR value1, value2;
2012-10-29 06:16:21 +04:00
while (*string1 && (*string1 == *string2))
{
string1++;
string2++;
}
Data_Read_UINT16(string1, value1);
Data_Read_UINT16(string2, value2);
return (int)value1 - value2;
}
int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count)
{
for (size_t x = 0; x < count; x++)
{
const WCHAR a = string1[x];
const WCHAR b = string2[x];
if (a != b)
return (int)a - b;
}
return 0;
2012-10-29 06:16:21 +04:00
}
/* _wcslen -> wcslen */
2014-08-18 21:34:47 +04:00
size_t _wcslen(const WCHAR* str)
{
2019-11-06 17:24:51 +03:00
const WCHAR* p = (const WCHAR*)str;
if (!p)
return 0;
while (*p)
p++;
return (size_t)(p - str);
}
/* _wcsnlen -> wcsnlen */
size_t _wcsnlen(const WCHAR* str, size_t max)
{
size_t x;
if (!str)
return 0;
for (x = 0; x < max; x++)
{
if (str[x] == 0)
return x;
}
return x;
}
/* _wcschr -> wcschr */
WCHAR* _wcschr(const WCHAR* str, WCHAR value)
{
union
{
const WCHAR* cc;
WCHAR* c;
} cnv;
2021-08-02 13:13:34 +03:00
const WCHAR* p = (const WCHAR*)str;
while (*p && (*p != value))
p++;
cnv.cc = (*p == value) ? p : NULL;
return cnv.c;
}
2016-12-01 00:56:10 +03:00
/* _wcsrchr -> wcsrchr */
WCHAR* _wcsrchr(const WCHAR* str, WCHAR c)
2016-12-01 00:56:10 +03:00
{
union
{
const WCHAR* cc;
WCHAR* c;
} cnv;
const WCHAR* p = NULL;
2016-12-01 00:56:10 +03:00
2017-03-18 00:05:21 +03:00
if (!str)
return NULL;
for (; *str != '\0'; str++)
{
const WCHAR ch = *str;
2016-12-01 00:56:10 +03:00
if (ch == c)
p = str;
}
2016-12-01 00:56:10 +03:00
cnv.cc = p;
return cnv.c;
2016-12-01 00:56:10 +03:00
}
2014-08-18 21:34:47 +04:00
char* strtok_s(char* strToken, const char* strDelimit, char** context)
2012-07-30 23:21:57 +04:00
{
return strtok_r(strToken, strDelimit, context);
}
2014-08-18 21:34:47 +04:00
WCHAR* wcstok_s(WCHAR* strToken, const WCHAR* strDelimit, WCHAR** context)
{
2014-08-18 21:34:47 +04:00
WCHAR* nextToken;
WCHAR value;
if (!strToken)
strToken = *context;
Data_Read_UINT16(strToken, value);
while (*strToken && _wcschr(strDelimit, value))
{
strToken++;
Data_Read_UINT16(strToken, value);
}
if (!*strToken)
return NULL;
nextToken = strToken++;
Data_Read_UINT16(strToken, value);
while (*strToken && !(_wcschr(strDelimit, value)))
{
strToken++;
Data_Read_UINT16(strToken, value);
}
if (*strToken)
*strToken++ = 0;
*context = strToken;
return nextToken;
}
#endif
#if !defined(_WIN32) || defined(_UWP)
2012-05-22 06:04:14 +04:00
/* Windows API Sets - api-ms-win-core-string-l2-1-0.dll
* http://msdn.microsoft.com/en-us/library/hh802935/
*/
#include "casing.c"
2012-05-22 06:04:14 +04:00
LPSTR CharUpperA(LPSTR lpsz)
{
size_t i;
size_t length;
2012-05-22 06:04:14 +04:00
2013-08-29 17:30:22 +04:00
if (!lpsz)
return NULL;
2012-05-22 06:04:14 +04:00
length = strlen(lpsz);
2014-08-18 19:22:22 +04:00
2012-05-22 06:04:14 +04:00
if (length < 1)
2019-11-06 17:24:51 +03:00
return (LPSTR)NULL;
2012-05-22 06:04:14 +04:00
if (length == 1)
{
char c = *lpsz;
if ((c >= 'a') && (c <= 'z'))
2020-11-10 10:14:56 +03:00
c = c - 'a' + 'A';
2012-05-22 06:04:14 +04:00
2013-08-29 17:30:22 +04:00
*lpsz = c;
return lpsz;
2012-05-22 06:04:14 +04:00
}
for (i = 0; i < length; i++)
{
if ((lpsz[i] >= 'a') && (lpsz[i] <= 'z'))
2020-11-10 10:14:56 +03:00
lpsz[i] = lpsz[i] - 'a' + 'A';
2012-05-22 06:04:14 +04:00
}
return lpsz;
}
LPWSTR CharUpperW(LPWSTR lpsz)
{
2020-11-10 10:14:56 +03:00
size_t i;
size_t length;
if (!lpsz)
return NULL;
length = _wcslen(lpsz);
if (length < 1)
return (LPWSTR)NULL;
if (length == 1)
{
WCHAR c = *lpsz;
if ((c >= L'a') && (c <= L'z'))
c = c - L'a' + L'A';
*lpsz = c;
return lpsz;
}
for (i = 0; i < length; i++)
{
if ((lpsz[i] >= L'a') && (lpsz[i] <= L'z'))
lpsz[i] = lpsz[i] - L'a' + L'A';
}
return lpsz;
2012-05-22 06:04:14 +04:00
}
DWORD CharUpperBuffA(LPSTR lpsz, DWORD cchLength)
{
DWORD i;
2012-05-22 06:04:14 +04:00
if (cchLength < 1)
return 0;
for (i = 0; i < cchLength; i++)
{
if ((lpsz[i] >= 'a') && (lpsz[i] <= 'z'))
2020-11-10 10:14:56 +03:00
lpsz[i] = lpsz[i] - 'a' + 'A';
2012-05-22 06:04:14 +04:00
}
return cchLength;
}
DWORD CharUpperBuffW(LPWSTR lpsz, DWORD cchLength)
{
DWORD i;
WCHAR value;
2012-05-22 06:04:14 +04:00
for (i = 0; i < cchLength; i++)
{
Data_Read_UINT16(&lpsz[i], value);
value = WINPR_TOUPPERW(value);
Data_Write_UINT16(&lpsz[i], value);
2012-05-22 06:04:14 +04:00
}
return cchLength;
}
LPSTR CharLowerA(LPSTR lpsz)
{
size_t i;
size_t length;
2012-05-22 06:04:14 +04:00
2013-08-29 12:55:07 +04:00
if (!lpsz)
2019-11-06 17:24:51 +03:00
return (LPSTR)NULL;
2013-08-29 12:55:07 +04:00
length = strlen(lpsz);
2012-05-22 06:04:14 +04:00
if (length < 1)
2019-11-06 17:24:51 +03:00
return (LPSTR)NULL;
2012-05-22 06:04:14 +04:00
if (length == 1)
{
char c = *lpsz;
if ((c >= 'A') && (c <= 'Z'))
2020-11-10 10:14:56 +03:00
c = c - 'A' + 'a';
2012-05-22 06:04:14 +04:00
2013-08-29 12:55:07 +04:00
*lpsz = c;
return lpsz;
2012-05-22 06:04:14 +04:00
}
for (i = 0; i < length; i++)
{
if ((lpsz[i] >= 'A') && (lpsz[i] <= 'Z'))
2020-11-10 10:14:56 +03:00
lpsz[i] = lpsz[i] - 'A' + 'a';
2012-05-22 06:04:14 +04:00
}
return lpsz;
}
LPWSTR CharLowerW(LPWSTR lpsz)
{
2020-11-10 10:14:56 +03:00
CharLowerBuffW(lpsz, _wcslen(lpsz));
return lpsz;
2012-05-22 06:04:14 +04:00
}
DWORD CharLowerBuffA(LPSTR lpsz, DWORD cchLength)
{
DWORD i;
2012-05-22 06:04:14 +04:00
if (cchLength < 1)
return 0;
for (i = 0; i < cchLength; i++)
{
if ((lpsz[i] >= 'A') && (lpsz[i] <= 'Z'))
2020-11-10 10:14:56 +03:00
lpsz[i] = lpsz[i] - 'A' + 'a';
2012-05-22 06:04:14 +04:00
}
return cchLength;
}
DWORD CharLowerBuffW(LPWSTR lpsz, DWORD cchLength)
{
DWORD i;
WCHAR value;
2012-05-22 06:04:14 +04:00
for (i = 0; i < cchLength; i++)
{
Data_Read_UINT16(&lpsz[i], value);
value = WINPR_TOLOWERW(value);
Data_Write_UINT16(&lpsz[i], value);
2012-05-22 06:04:14 +04:00
}
return cchLength;
}
BOOL IsCharAlphaA(CHAR ch)
{
if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')))
return 1;
else
return 0;
}
BOOL IsCharAlphaW(WCHAR ch)
{
2020-11-10 10:14:56 +03:00
if (((ch >= L'a') && (ch <= L'z')) || ((ch >= L'A') && (ch <= L'Z')))
return 1;
else
return 0;
2012-05-22 06:04:14 +04:00
}
BOOL IsCharAlphaNumericA(CHAR ch)
{
if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
((ch >= '0') && (ch <= '9')))
2012-05-22 06:04:14 +04:00
return 1;
else
return 0;
}
BOOL IsCharAlphaNumericW(WCHAR ch)
{
2020-11-10 10:14:56 +03:00
if (((ch >= L'a') && (ch <= L'z')) || ((ch >= L'A') && (ch <= L'Z')) ||
((ch >= L'0') && (ch <= L'9')))
return 1;
else
return 0;
2012-05-22 06:04:14 +04:00
}
BOOL IsCharUpperA(CHAR ch)
{
if ((ch >= 'A') && (ch <= 'Z'))
return 1;
else
return 0;
}
BOOL IsCharUpperW(WCHAR ch)
{
2020-11-10 10:14:56 +03:00
if ((ch >= L'A') && (ch <= L'Z'))
return 1;
else
return 0;
2012-05-22 06:04:14 +04:00
}
BOOL IsCharLowerA(CHAR ch)
{
if ((ch >= 'a') && (ch <= 'z'))
return 1;
else
return 0;
}
BOOL IsCharLowerW(WCHAR ch)
{
2020-11-10 10:14:56 +03:00
if ((ch >= L'a') && (ch <= L'z'))
return 1;
else
return 0;
2012-05-22 06:04:14 +04:00
}
2012-06-04 00:30:15 +04:00
int lstrlenA(LPCSTR lpString)
{
2019-11-06 17:24:51 +03:00
return (int)strlen(lpString);
2012-06-04 00:30:15 +04:00
}
int lstrlenW(LPCWSTR lpString)
{
2021-08-02 13:13:34 +03:00
LPCWSTR p;
2012-06-04 00:30:15 +04:00
if (!lpString)
return 0;
2021-08-02 13:13:34 +03:00
p = (LPCWSTR)lpString;
2012-06-04 00:30:15 +04:00
while (*p)
p++;
return (int)(p - lpString);
2012-06-04 00:30:15 +04:00
}
int lstrcmpA(LPCSTR lpString1, LPCSTR lpString2)
{
return strcmp(lpString1, lpString2);
}
int lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
{
WCHAR value1, value2;
2012-06-04 00:30:15 +04:00
while (*lpString1 && (*lpString1 == *lpString2))
{
lpString1++;
lpString2++;
}
Data_Read_UINT16(lpString1, value1);
Data_Read_UINT16(lpString2, value2);
return value1 - value2;
2012-06-04 00:30:15 +04:00
}
2012-05-06 06:09:08 +04:00
#endif
int ConvertLineEndingToLF(char* str, int size)
{
int status;
char* end;
char* pInput;
char* pOutput;
end = &str[size];
pInput = pOutput = str;
while (pInput < end)
{
if ((pInput[0] == '\r') && (pInput[1] == '\n'))
{
*pOutput++ = '\n';
pInput += 2;
}
else
{
*pOutput++ = *pInput++;
}
}
status = (int)(pOutput - str);
return status;
}
char* ConvertLineEndingToCRLF(const char* str, int* size)
{
int count;
char* newStr;
char* pOutput;
const char* end;
const char* pInput;
end = &str[*size];
count = 0;
pInput = str;
while (pInput < end)
{
if (*pInput == '\n')
count++;
pInput++;
}
2019-11-06 17:24:51 +03:00
newStr = (char*)malloc(*size + (count * 2) + 1);
if (!newStr)
return NULL;
pInput = str;
pOutput = newStr;
while (pInput < end)
{
if ((*pInput == '\n') && ((pInput > str) && (pInput[-1] != '\r')))
{
*pOutput++ = '\r';
*pOutput++ = '\n';
}
else
{
*pOutput++ = *pInput;
}
pInput++;
}
*size = (int)(pOutput - newStr);
return newStr;
}
2015-06-09 16:32:50 +03:00
char* StrSep(char** stringp, const char* delim)
{
char* start = *stringp;
char* p;
p = (start != NULL) ? strpbrk(start, delim) : NULL;
if (!p)
*stringp = NULL;
else
{
*p = '\0';
*stringp = p + 1;
}
return start;
}
2015-12-18 11:45:44 +03:00
INT64 GetLine(char** lineptr, size_t* size, FILE* stream)
{
#if defined(_WIN32)
char c;
char* n;
2015-12-18 11:45:44 +03:00
size_t step = 32;
size_t used = 0;
2015-06-09 16:32:50 +03:00
2015-12-18 11:45:44 +03:00
if (!lineptr || !size)
{
errno = EINVAL;
return -1;
}
2015-06-09 16:32:50 +03:00
2015-12-18 11:45:44 +03:00
do
{
if (used + 2 >= *size)
{
*size += step;
n = realloc(*lineptr, *size);
2015-12-18 11:45:44 +03:00
if (!n)
{
return -1;
}
2015-12-18 11:45:44 +03:00
*lineptr = n;
}
c = fgetc(stream);
if (c != EOF)
(*lineptr)[used++] = c;
2019-11-06 17:24:51 +03:00
} while ((c != '\n') && (c != '\r') && (c != EOF));
(*lineptr)[used] = '\0';
2015-12-18 11:45:44 +03:00
return used;
#elif !defined(ANDROID) && !defined(IOS)
2015-12-18 11:45:44 +03:00
return getline(lineptr, size, stream);
#else
return -1;
2015-12-18 11:45:44 +03:00
#endif
}
2022-07-01 12:26:44 +03:00
#if !defined(HAVE_STRNDUP)
char* strndup(const char* src, size_t n)
2022-07-01 12:26:44 +03:00
{
char* dst = calloc(n + 1, sizeof(char));
if (dst)
strncpy(dst, src, n);
return dst;
2022-07-01 12:26:44 +03:00
}
#endif