mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 17:38:59 +00:00
merged new xmlrpc-c revision 1472 from https://xmlrpc-c.svn.sourceforge.net/svnroot/xmlrpc-c/trunk
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8545 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
226
libs/xmlrpc-c/lib/util/string_parser.c
Normal file
226
libs/xmlrpc-c/lib/util/string_parser.c
Normal file
@@ -0,0 +1,226 @@
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "int.h"
|
||||
#include "girstring.h"
|
||||
#include "casprintf.h"
|
||||
|
||||
#include "string_parser.h"
|
||||
|
||||
static const char *
|
||||
strippedSubstring(const char * const string) {
|
||||
|
||||
const char * p;
|
||||
|
||||
for (p = &string[0]; isspace(*p); ++p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
interpretUll(const char * const string,
|
||||
uint64_t * const ullP,
|
||||
const char ** const errorP) {
|
||||
|
||||
/* strtoull() has the same disappointing weaknesses of strtoul().
|
||||
See interpretUint().
|
||||
*/
|
||||
|
||||
const char * const strippedString = strippedSubstring(string);
|
||||
|
||||
if (strippedString[0] == '\0')
|
||||
casprintf(errorP, "Null (or all whitespace) string.");
|
||||
else if (!isdigit(strippedString[0]))
|
||||
casprintf(errorP, "First non-blank character is '%c', not a digit.",
|
||||
strippedString[0]);
|
||||
else {
|
||||
/* strtoull() does a bizarre thing where if the number is out
|
||||
of range, it returns a clamped value but tells you about it
|
||||
by setting errno = ERANGE. If it is not out of range,
|
||||
strtoull() leaves errno alone.
|
||||
*/
|
||||
char * tail;
|
||||
|
||||
errno = 0; /* So we can tell if strtoull() overflowed */
|
||||
|
||||
*ullP = strtoull(strippedString, &tail, 10);
|
||||
|
||||
if (tail[0] != '\0')
|
||||
casprintf(errorP, "Non-digit stuff in string: %s", tail);
|
||||
else if (errno == ERANGE)
|
||||
casprintf(errorP, "Number too large");
|
||||
else
|
||||
*errorP = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
interpretLl(const char * const string,
|
||||
int64_t * const llP,
|
||||
const char ** const errorP) {
|
||||
|
||||
if (string[0] == '\0')
|
||||
casprintf(errorP, "Null string.");
|
||||
else {
|
||||
/* strtoll() does a bizarre thing where if the number is out
|
||||
of range, it returns a clamped value but tells you about it
|
||||
by setting errno = ERANGE. If it is not out of range,
|
||||
strtoll() leaves errno alone.
|
||||
*/
|
||||
char * tail;
|
||||
|
||||
errno = 0; /* So we can tell if strtoll() overflowed */
|
||||
|
||||
*llP = strtoll(string, &tail, 10);
|
||||
|
||||
if (tail[0] != '\0')
|
||||
casprintf(errorP, "Non-digit stuff in string: %s", tail);
|
||||
else if (errno == ERANGE)
|
||||
casprintf(errorP, "Number too large");
|
||||
else
|
||||
*errorP = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
interpretUint(const char * const string,
|
||||
uint * const uintP,
|
||||
const char ** const errorP) {
|
||||
|
||||
/* strtoul() does a lousy job of dealing with invalid numbers. A null
|
||||
string is just zero; a negative number is a large positive one; a
|
||||
positive (cf unsigned) number is accepted. strtoul is inconsistent
|
||||
in its treatment of the tail; if there is no valid number at all,
|
||||
it returns the entire string as the tail, including leading white
|
||||
space and sign, which are not themselves invalid.
|
||||
*/
|
||||
|
||||
const char * const strippedString = strippedSubstring(string);
|
||||
|
||||
if (strippedString[0] == '\0')
|
||||
casprintf(errorP, "Null (or all whitespace) string.");
|
||||
else if (!isdigit(strippedString[0]))
|
||||
casprintf(errorP, "First non-blank character is '%c', not a digit.",
|
||||
strippedString[0]);
|
||||
else {
|
||||
/* strtoul() does a bizarre thing where if the number is out
|
||||
of range, it returns a clamped value but tells you about it
|
||||
by setting errno = ERANGE. If it is not out of range,
|
||||
strtoul() leaves errno alone.
|
||||
*/
|
||||
char * tail;
|
||||
unsigned long ulongValue;
|
||||
|
||||
errno = 0; /* So we can tell if strtoul() overflowed */
|
||||
|
||||
ulongValue = strtoul(strippedString, &tail, 10);
|
||||
|
||||
if (tail[0] != '\0')
|
||||
casprintf(errorP, "Non-digit stuff in string: %s", tail);
|
||||
else if (errno == ERANGE)
|
||||
casprintf(errorP, "Number too large");
|
||||
else if (ulongValue > UINT_MAX)
|
||||
casprintf(errorP, "Number too large");
|
||||
else {
|
||||
*uintP = ulongValue;
|
||||
*errorP = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
interpretInt(const char * const string,
|
||||
int * const intP,
|
||||
const char ** const errorP) {
|
||||
|
||||
if (string[0] == '\0')
|
||||
casprintf(errorP, "Null string.");
|
||||
else {
|
||||
/* strtol() does a bizarre thing where if the number is out
|
||||
of range, it returns a clamped value but tells you about it
|
||||
by setting errno = ERANGE. If it is not out of range,
|
||||
strtol() leaves errno alone.
|
||||
*/
|
||||
char * tail;
|
||||
long longValue;
|
||||
|
||||
errno = 0; /* So we can tell if strtol() overflowed */
|
||||
|
||||
longValue = strtol(string, &tail, 10);
|
||||
|
||||
if (tail[0] != '\0')
|
||||
casprintf(errorP, "Non-digit stuff in string: %s", tail);
|
||||
else if (errno == ERANGE)
|
||||
casprintf(errorP, "Number too large");
|
||||
else if (longValue > INT_MAX)
|
||||
casprintf(errorP, "Number too large");
|
||||
else if (longValue < INT_MIN)
|
||||
casprintf(errorP, "Number too negative");
|
||||
else {
|
||||
*intP = longValue;
|
||||
*errorP = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
interpretBinUint(const char * const string,
|
||||
uint64_t * const valueP,
|
||||
const char ** const errorP) {
|
||||
|
||||
char * tailptr;
|
||||
long const mantissa_long = strtol(string, &tailptr, 10);
|
||||
|
||||
if (errno == ERANGE)
|
||||
casprintf(errorP,
|
||||
"Numeric value out of range for computation: '%s'. "
|
||||
"Try a smaller number with a K, M, G, etc. suffix.",
|
||||
string);
|
||||
else {
|
||||
int64_t const mantissa = mantissa_long;
|
||||
|
||||
int64_t argNumber;
|
||||
|
||||
*errorP = NULL; /* initial assumption */
|
||||
|
||||
if (*tailptr == '\0')
|
||||
/* There's no suffix. A pure number */
|
||||
argNumber = mantissa * 1;
|
||||
else if (stripcaseeq(tailptr, "K"))
|
||||
argNumber = mantissa * 1024;
|
||||
else if (stripcaseeq(tailptr, "M"))
|
||||
argNumber = mantissa * 1024 * 1024;
|
||||
else if (stripcaseeq(tailptr, "G"))
|
||||
argNumber = mantissa * 1024 * 1024 * 1024;
|
||||
else if (stripcaseeq(tailptr, "T"))
|
||||
argNumber = mantissa * 1024 * 1024 * 1024 * 1024;
|
||||
else if (stripcaseeq(tailptr, "P"))
|
||||
argNumber = mantissa * 1024 * 1024 * 1024 * 1024 * 1024;
|
||||
else {
|
||||
argNumber = 0; /* quiet compiler warning */
|
||||
casprintf(errorP, "Garbage suffix '%s' on number", tailptr);
|
||||
}
|
||||
if (!*errorP) {
|
||||
if (argNumber < 0)
|
||||
casprintf(errorP, "Unsigned numeric value is "
|
||||
"negative: %" PRId64, argNumber);
|
||||
else
|
||||
*valueP = (uint64_t) argNumber;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user