tdnf/common/strings.c

658 lines
13 KiB
C

/*
* Copyright (C) 2015-2023 VMware, Inc. All Rights Reserved.
*
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
* you may not use this file except in compliance with the License. The terms
* of the License are located in the COPYING file of this distribution.
*/
#include "includes.h"
uint32_t
TDNFAllocateString(
const char* pszSrc,
char** ppszDst
)
{
uint32_t dwError = 0;
char* pszDst = NULL;
if(!pszSrc || !ppszDst)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
if(strlen(pszSrc) > TDNF_DEFAULT_MAX_STRING_LEN)
{
dwError = ERROR_TDNF_STRING_TOO_LONG;
BAIL_ON_TDNF_ERROR(dwError);
}
pszDst = strdup(pszSrc);
if(!pszDst)
{
dwError = ERROR_TDNF_OUT_OF_MEMORY;
BAIL_ON_TDNF_ERROR(dwError);
}
*ppszDst = pszDst;
cleanup:
return dwError;
error:
if(ppszDst)
{
*ppszDst = NULL;
}
TDNF_SAFE_FREE_MEMORY(pszDst);
goto cleanup;
}
uint32_t
TDNFSafeAllocateString(
const char* pszSrc,
char** ppszDst
)
{
uint32_t dwError = 0;
char* pszDst = NULL;
if(!ppszDst)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
if(pszSrc)
{
dwError = TDNFAllocateString(pszSrc, &pszDst);
BAIL_ON_TDNF_ERROR(dwError);
}
*ppszDst = pszDst;
cleanup:
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFStringSepCount(
const char *pszBuf,
char *pszSep,
size_t *nSepCount
)
{
size_t nCount = 0;
uint32_t dwError = 0;
const char *pszTemp = NULL;
if (!pszBuf || IsNullOrEmptyString(pszSep))
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pszTemp = pszBuf;
while (*pszTemp)
{
while (*pszTemp && strchr(pszSep, *pszTemp))
{
pszTemp++;
}
if (*pszTemp == '\0')
{
break;
}
nCount++;
while(*pszTemp && !strchr(pszSep, *pszTemp))
{
pszTemp++;
}
}
*nSepCount = nCount;
error:
return dwError;
}
uint32_t
TDNFSplitStringToArray(
const char *pszBuf,
char *pszSep,
char ***pppszTokens
)
{
uint32_t dwError = 0;
char **ppszToks = NULL;
const char *p;
size_t i, n;
if (!pszBuf || IsNullOrEmptyString(pszSep) || !pppszTokens)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFStringSepCount(pszBuf, pszSep, &n);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateMemory(n + 1, sizeof(char *), (void**)&ppszToks);
BAIL_ON_TDNF_ERROR(dwError);
i = 0;
p = pszBuf;
while(*p) {
const char *p0;
while (*p && strchr(pszSep, *p))
p++;
if (!*p)
break;
p0 = p;
while (*p && !strchr(pszSep, *p))
p++;
if((ppszToks[i++] = strndup(p0, p - p0)) == NULL) {
dwError = ERROR_TDNF_OUT_OF_MEMORY;
BAIL_ON_TDNF_ERROR(dwError);
}
}
ppszToks[i] = NULL;
*pppszTokens = ppszToks;
cleanup:
return dwError;
error:
TDNFFreeStringArrayWithCount(ppszToks, n);
*pppszTokens = NULL;
goto cleanup;
}
uint32_t
TDNFJoinArrayToString(
char **ppszArray,
const char *pszSep,
int count,
char **ppszResult
)
{
uint32_t dwError = 0;
int i, p = 0;
int nSize = 0, nSepSize = 0;
char *pszResult = NULL;
if(!ppszArray || !pszSep || !ppszResult)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
nSepSize = strlen(pszSep);
nSize = nSepSize * count;
for(i = 0; i < count && ppszArray[i]; i++)
{
nSize += strlen(ppszArray[i]);
}
nSize++;
dwError = TDNFAllocateMemory(nSize, sizeof(char), (void**)&pszResult);
BAIL_ON_TDNF_ERROR(dwError);
for(i = 0; i < count && ppszArray[i]; i++)
{
strcpy(&pszResult[p], ppszArray[i]);
p += strlen(ppszArray[i]);
if (i < count-1 && ppszArray[i+1])
{
strcpy(&pszResult[p], pszSep);
p += nSepSize;
}
}
*ppszResult = pszResult;
cleanup:
return dwError;
error:
TDNF_SAFE_FREE_MEMORY(pszResult);
goto cleanup;
}
uint32_t
TDNFJoinArrayToStringSorted(
char **ppszDependencies,
const char *pszSep,
char **ppszResult
)
{
int nCount = 0, p = 0, k, i;
char **ppszLines = NULL;
uint32_t dwError = 0;
int nSepSize = 0, nSize = 0;
char *pszResult = NULL;
if (ppszDependencies)
{
for (i = 0; ppszDependencies[i]; i++);
nCount += i;
}
if (nCount > 0)
{
dwError = TDNFAllocateMemory(nCount + 1, sizeof(char *), (void**)&ppszLines);
BAIL_ON_TDNF_ERROR(dwError);
if (ppszDependencies)
{
k = 0;
for (i = 0; ppszDependencies[i]; i++)
{
ppszLines[k++] = ppszDependencies[i];
}
}
dwError = TDNFStringArraySort(ppszLines);
BAIL_ON_TDNF_ERROR(dwError);
nSepSize = strlen(pszSep);
nSize = nSepSize * (nCount + 1);
for(i = 0; ppszLines[i]; i++)
{
if(i == 0 || strcmp(ppszLines[i], ppszLines[i-1]))
nSize += strlen(ppszLines[i]);
}
nSize++;
dwError = TDNFAllocateMemory(nSize, sizeof(char), (void**)&pszResult);
BAIL_ON_TDNF_ERROR(dwError);
for (i = 0; ppszLines[i]; i++)
{
if (i == 0)
{
strcpy(&pszResult[p], ppszLines[i]);
p += strlen(ppszLines[i]);
} else if (strcmp(ppszLines[i], ppszLines[i-1]))
{
strcpy(&pszResult[p], pszSep);
p += nSepSize;
strcpy(&pszResult[p], ppszLines[i]);
p += strlen(ppszLines[i]);
}
}
}
if (pszResult) {
*ppszResult = strdup(pszResult);
} else {
*ppszResult = strdup("");
}
cleanup:
TDNF_SAFE_FREE_MEMORY(ppszLines);
TDNF_SAFE_FREE_MEMORY(pszResult);
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFAllocateStringPrintf(
char** ppszDst,
const char* pszFmt,
...
)
{
uint32_t dwError = 0;
int32_t nSize = 0;
char* pszDst = NULL;
char chDstTest = '\0';
va_list argList;
if(!ppszDst || !pszFmt)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
//Find size
va_start(argList, pszFmt);
nSize = vsnprintf(&chDstTest, 1, pszFmt, argList);
va_end(argList);
if(nSize <= 0)
{
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}
nSize++;
if(nSize > TDNF_DEFAULT_MAX_STRING_LEN)
{
dwError = ERROR_TDNF_STRING_TOO_LONG;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFAllocateMemory(1, nSize, (void**)&pszDst);
BAIL_ON_TDNF_ERROR(dwError);
va_start(argList, pszFmt);
nSize = vsnprintf(pszDst, nSize, pszFmt, argList);
va_end(argList);
if(nSize <= 0)
{
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}
*ppszDst = pszDst;
cleanup:
return dwError;
error:
if(ppszDst)
{
*ppszDst = NULL;
}
TDNF_SAFE_FREE_MEMORY(pszDst);
goto cleanup;
}
uint32_t
TDNFAllocateStringArray(
char** ppszSrc,
char*** pppszDst
)
{
uint32_t dwError = 0;
char** ppszDst = NULL;
int i, n = 0;
if(!ppszSrc || !pppszDst)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
for (i = 0; ppszSrc[i]; i++) {
n++;
}
dwError = TDNFAllocateMemory(n + 1, sizeof(char *), (void **)&ppszDst);
BAIL_ON_TDNF_ERROR(dwError);
for (i = 0; i < n; i++) {
dwError = TDNFSafeAllocateString(
ppszSrc[i],
&ppszDst[i]);
BAIL_ON_TDNF_ERROR(dwError);
}
*pppszDst = ppszDst;
cleanup:
return dwError;
error:
TDNF_SAFE_FREE_STRINGARRAY(ppszDst);
if(pppszDst) {
*pppszDst = NULL;
}
goto cleanup;
}
void
TDNFFreeStringArray(
char** ppszArray
)
{
char** ppszTemp = NULL;
if(ppszArray)
{
ppszTemp = ppszArray;
while(ppszTemp && *ppszTemp)
{
TDNF_SAFE_FREE_MEMORY(*ppszTemp);
++ppszTemp;
}
TDNFFreeMemory(ppszArray);
}
}
void
TDNFFreeStringArrayWithCount(
char **ppszArray,
int nCount
)
{
if(ppszArray)
{
while(nCount)
{
TDNFFreeMemory(ppszArray[--nCount]);
}
TDNFFreeMemory(ppszArray);
}
}
uint32_t
TDNFAllocateStringN(
const char* pszSrc,
uint32_t dwNumElements,
char** ppszDst
)
{
uint32_t dwError = 0;
char* pszDst = NULL;
uint32_t dwSrcLength = 0;
if(!pszSrc || !ppszDst)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwSrcLength = strlen(pszSrc);
if(dwNumElements > dwSrcLength)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFAllocateMemory(dwNumElements + 1, 1, (void**)&pszDst);
BAIL_ON_TDNF_ERROR(dwError);
strncpy(pszDst, pszSrc, dwNumElements);
*ppszDst = pszDst;
cleanup:
return dwError;
error:
if(ppszDst)
{
*ppszDst = NULL;
}
TDNF_SAFE_FREE_MEMORY(pszDst);
goto cleanup;
}
uint32_t
TDNFReplaceString(
const char* pszSource,
const char* pszSearch,
const char* pszReplace,
char** ppszDst
)
{
uint32_t dwError = 0;
char* pszDst = NULL;
char* pszTemp = NULL;
char* pszTempReplace = NULL;
char* pszIndex = NULL;
int nSearchLen = 0;
if(IsNullOrEmptyString(pszSource) ||
IsNullOrEmptyString(pszSearch) ||
!pszReplace ||
!ppszDst)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
nSearchLen = strlen(pszSearch);
dwError = TDNFAllocateString(pszSource, &pszDst);
BAIL_ON_TDNF_ERROR(dwError);
while((pszIndex = strstr(pszDst, pszSearch)) != NULL)
{
dwError = TDNFAllocateStringN(
pszDst,
pszIndex - pszDst,
&pszTemp);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateStringPrintf(
&pszTempReplace,
"%s%s%s",
pszTemp,
pszReplace,
pszIndex + nSearchLen);
BAIL_ON_TDNF_ERROR(dwError);
TDNF_SAFE_FREE_MEMORY(pszTemp);
TDNF_SAFE_FREE_MEMORY(pszDst);
pszDst = pszTempReplace;
pszTemp = NULL;
pszTempReplace = NULL;
}
*ppszDst = pszDst;
cleanup:
return dwError;
error:
if(ppszDst)
{
*ppszDst = NULL;
}
TDNF_SAFE_FREE_MEMORY(pszDst);
TDNF_SAFE_FREE_MEMORY(pszTemp);
TDNF_SAFE_FREE_MEMORY(pszTempReplace);
goto cleanup;
}
uint32_t TDNFTrimSuffix(char *pszSource, const char *pszSuffix)
{
char *ptr;
if (IsNullOrEmptyString(pszSource) || IsNullOrEmptyString(pszSuffix)) {
return ERROR_TDNF_INVALID_PARAMETER;
}
ptr = strstr(pszSource, pszSuffix);
if (!ptr || strcmp(ptr, pszSuffix)) {
return ERROR_TDNF_INVALID_PARAMETER;
}
*ptr = '\0';
return 0;
}
uint32_t
TDNFStringEndsWith(
char* pszSource,
const char* pszSuffix
)
{
int nSourceStrLen = 0, nSuffixStrLen = 0;
uint32_t dwError = 0;
int ret = 0;
if (IsNullOrEmptyString(pszSource) || IsNullOrEmptyString(pszSuffix))
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
nSourceStrLen = strlen(pszSource);
nSuffixStrLen = strlen(pszSuffix);
if (nSuffixStrLen > nSourceStrLen)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
ret = strncmp(pszSource + nSourceStrLen - nSuffixStrLen, pszSuffix, nSuffixStrLen);
if (ret)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
cleanup:
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFStringArrayCount(
char **ppszStringArray,
int *pnCount
)
{
uint32_t dwError = 0;
int nCount;
if (!ppszStringArray || !pnCount)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
for(nCount = 0; ppszStringArray[nCount]; nCount++);
*pnCount = nCount;
cleanup:
return dwError;
error:
goto cleanup;
}
static int
_cmpstringp(const void *p1, const void *p2)
{
return strcmp(* (char * const *) p1, * (char * const *) p2);
}
uint32_t
TDNFStringArraySort(
char **ppszArray
)
{
uint32_t dwError = 0;
int nCount;
if (!ppszArray)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
for(nCount = 0; ppszArray[nCount]; nCount++);
qsort(ppszArray, nCount, sizeof(char *), _cmpstringp);
cleanup:
return dwError;
error:
goto cleanup;
}