|
Packit Service |
75d76b |
/*
|
|
Packit Service |
75d76b |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
75d76b |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
75d76b |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
75d76b |
* of the License, or (at your option) any later version.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
75d76b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
75d76b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
75d76b |
* GNU General Public License for more details.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
75d76b |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
75d76b |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
75d76b |
* 02110-1301, USA.
|
|
Packit Service |
75d76b |
*
|
|
Packit Service |
75d76b |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/kernel/vdoStringUtils.c#1 $
|
|
Packit Service |
75d76b |
*/
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "vdoStringUtils.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "errors.h"
|
|
Packit Service |
75d76b |
#include "logger.h"
|
|
Packit Service |
75d76b |
#include "memoryAlloc.h"
|
|
Packit Service |
75d76b |
#include "stringUtils.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
#include "statusCodes.h"
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
char *vAppendToBuffer(char *buffer,
|
|
Packit Service |
75d76b |
char *bufEnd,
|
|
Packit Service |
75d76b |
const char *fmt,
|
|
Packit Service |
75d76b |
va_list args)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
size_t n = vsnprintf(buffer, bufEnd - buffer, fmt, args);
|
|
Packit Service |
75d76b |
if (n >= (size_t) (bufEnd - buffer)) {
|
|
Packit Service |
75d76b |
buffer = bufEnd;
|
|
Packit Service |
75d76b |
} else {
|
|
Packit Service |
75d76b |
buffer += n;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
return buffer;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
char *appendToBuffer(char *buffer, char *bufEnd, const char *fmt, ...)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
va_list ap;
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
va_start(ap, fmt);
|
|
Packit Service |
75d76b |
char *pos = vAppendToBuffer(buffer, bufEnd, fmt, ap);
|
|
Packit Service |
75d76b |
va_end(ap);
|
|
Packit Service |
75d76b |
return pos;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
void freeStringArray(char **stringArray)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
for (unsigned int offset = 0; stringArray[offset] != NULL; offset++) {
|
|
Packit Service |
75d76b |
FREE(stringArray[offset]);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
FREE(stringArray);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
int splitString(const char *string, char separator, char ***substringArrayPtr)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
unsigned int substringCount = 1;
|
|
Packit Service |
75d76b |
for (const char *s = string; *s != 0; s++) {
|
|
Packit Service |
75d76b |
if (*s == separator) {
|
|
Packit Service |
75d76b |
substringCount++;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
char **substrings;
|
|
Packit Service |
75d76b |
int result = ALLOCATE(substringCount + 1, char *, "string-splitting array",
|
|
Packit Service |
75d76b |
&substrings);
|
|
Packit Service |
75d76b |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
unsigned int currentSubstring = 0;
|
|
Packit Service |
75d76b |
for (const char *s = string; *s != 0; s++) {
|
|
Packit Service |
75d76b |
if (*s == separator) {
|
|
Packit Service |
75d76b |
ptrdiff_t length = s - string;
|
|
Packit Service |
75d76b |
result = ALLOCATE(length + 1, char, "split string",
|
|
Packit Service |
75d76b |
&substrings[currentSubstring]);
|
|
Packit Service |
75d76b |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
75d76b |
freeStringArray(substrings);
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
// Trailing NUL is already in place after allocation; deal with
|
|
Packit Service |
75d76b |
// the zero or more non-NUL bytes in the string.
|
|
Packit Service |
75d76b |
if (length > 0) {
|
|
Packit Service |
75d76b |
memcpy(substrings[currentSubstring], string, length);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
string = s + 1;
|
|
Packit Service |
75d76b |
currentSubstring++;
|
|
Packit Service |
75d76b |
BUG_ON(currentSubstring >= substringCount);
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
// Process final string, with no trailing separator.
|
|
Packit Service |
75d76b |
BUG_ON(currentSubstring != (substringCount - 1));
|
|
Packit Service |
75d76b |
ptrdiff_t length = strlen(string);
|
|
Packit Service |
75d76b |
result = ALLOCATE(length + 1, char, "split string",
|
|
Packit Service |
75d76b |
&substrings[currentSubstring]);
|
|
Packit Service |
75d76b |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
75d76b |
freeStringArray(substrings);
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
memcpy(substrings[currentSubstring], string, length);
|
|
Packit Service |
75d76b |
currentSubstring++;
|
|
Packit Service |
75d76b |
// substrings[currentSubstring] is NULL already
|
|
Packit Service |
75d76b |
*substringArrayPtr = substrings;
|
|
Packit Service |
75d76b |
return UDS_SUCCESS;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
int joinStrings(char **substringArray,
|
|
Packit Service |
75d76b |
size_t arrayLength,
|
|
Packit Service |
75d76b |
char separator,
|
|
Packit Service |
75d76b |
char **stringPtr)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
size_t stringLength = 0;
|
|
Packit Service |
75d76b |
for (size_t i = 0; (i < arrayLength) && (substringArray[i] != NULL); i++) {
|
|
Packit Service |
75d76b |
stringLength += strlen(substringArray[i]) + 1;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
char *output;
|
|
Packit Service |
75d76b |
int result = ALLOCATE(stringLength, char, __func__, &output);
|
|
Packit Service |
75d76b |
if (result != VDO_SUCCESS) {
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
char *currentPosition = &output[0];
|
|
Packit Service |
75d76b |
for (size_t i = 0; (i < arrayLength) && (substringArray[i] != NULL); i++) {
|
|
Packit Service |
75d76b |
currentPosition = appendToBuffer(currentPosition, output + stringLength,
|
|
Packit Service |
75d76b |
"%s", substringArray[i]);
|
|
Packit Service |
75d76b |
*currentPosition = separator;
|
|
Packit Service |
75d76b |
currentPosition++;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
// We output one too many separators; replace the last with a zero byte.
|
|
Packit Service |
75d76b |
if (currentPosition != output) {
|
|
Packit Service |
75d76b |
*(currentPosition - 1) = '\0';
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
*stringPtr = output;
|
|
Packit Service |
75d76b |
return UDS_SUCCESS;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
/**********************************************************************/
|
|
Packit Service |
75d76b |
int stringToUInt(const char *input, unsigned int *valuePtr)
|
|
Packit Service |
75d76b |
{
|
|
Packit Service |
75d76b |
unsigned long longValue;
|
|
Packit Service |
75d76b |
int result = kstrtoul(input, 10, &longValue);
|
|
Packit Service |
75d76b |
if (result != 0) {
|
|
Packit Service |
75d76b |
return result;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
if (longValue > UINT_MAX) {
|
|
Packit Service |
75d76b |
return -ERANGE;
|
|
Packit Service |
75d76b |
}
|
|
Packit Service |
75d76b |
|
|
Packit Service |
75d76b |
*valuePtr = longValue;
|
|
Packit Service |
75d76b |
return UDS_SUCCESS;
|
|
Packit Service |
75d76b |
}
|