/*
* 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/uds-releases/jasper/src/uds/stringUtils.c#2 $
*/
#include "stringUtils.h"
#include "errors.h"
#include "logger.h"
#include "memoryAlloc.h"
#include "permassert.h"
#include "uds.h"
/*****************************************************************************/
int allocSprintf(const char *what, char **strp, const char *fmt, ...)
{
if (strp == NULL) {
return UDS_INVALID_ARGUMENT;
}
va_list args;
#ifdef __KERNEL__
// We want the memory allocation to use our own ALLOCATE/FREE wrappers.
va_start(args, fmt);
int count = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args);
int result = ALLOCATE(count, char, what, strp);
if (result == UDS_SUCCESS) {
va_start(args, fmt);
vsnprintf(*strp, count, fmt, args);
va_end(args);
}
#else
va_start(args, fmt);
int result = vasprintf(strp, fmt, args) == -1 ? ENOMEM : UDS_SUCCESS;
va_end(args);
#endif
if ((result != UDS_SUCCESS) && (what != NULL)) {
logError("cannot allocate %s", what);
}
return result;
}
/*****************************************************************************/
int wrapVsnprintf(const char *what, char *buf, size_t bufSize,
int error, const char *fmt, va_list ap, size_t *needed)
{
if (buf == NULL) {
static char nobuf[1];
buf = nobuf;
bufSize = 0;
}
int n = vsnprintf(buf, bufSize, fmt, ap);
if (n < 0) {
return logErrorWithStringError(UDS_UNEXPECTED_RESULT,
"%s: vsnprintf failed", what);
}
if (needed) {
*needed = n;
}
if (((size_t) n >= bufSize) && (buf != NULL) && (error != UDS_SUCCESS)) {
return logErrorWithStringError(error, "%s: string too long", what);
}
return UDS_SUCCESS;
}
/*****************************************************************************/
int fixedSprintf(const char *what,
char *buf,
size_t bufSize,
int error,
const char *fmt,
...)
{
if (buf == NULL) {
return UDS_INVALID_ARGUMENT;
}
va_list args;
va_start(args, fmt);
int result = wrapVsnprintf(what, buf, bufSize, error, fmt, args, NULL);
va_end(args);
return result;
}
/*****************************************************************************/
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;
}
/*****************************************************************************/
int stringToSignedInt(const char *nptr, int *num)
{
long value;
int result = stringToSignedLong(nptr, &value);
if (result != UDS_SUCCESS) {
return result;
}
if ((value < INT_MIN) || (value > INT_MAX)) {
return ERANGE;
}
*num = (int) value;
return UDS_SUCCESS;
}
/*****************************************************************************/
int stringToUnsignedInt(const char *nptr, unsigned int *num)
{
unsigned long value;
int result = stringToUnsignedLong(nptr, &value);
if (result != UDS_SUCCESS) {
return result;
}
if (value > UINT_MAX) {
return ERANGE;
}
*num = (unsigned int) value;
return UDS_SUCCESS;
}