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