Blame source/vdo/kernel/vdoStringUtils.c

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
}