wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -0,0 +1,727 @@
|
||||
/**
|
||||
* @file mprString.c
|
||||
* @brief String routines safe for embedded programming
|
||||
* @overview This module provides safe replacements for the standard
|
||||
* string library.
|
||||
* @remarks Most routines in this file are not thread-safe. It is the callers
|
||||
* responsibility to perform all thread synchronization.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @copy default
|
||||
*
|
||||
* Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
|
||||
*
|
||||
* This software is distributed under commercial and open source licenses.
|
||||
* You may use the GPL open source license described below or you may acquire
|
||||
* a commercial license from Mbedthis Software. You agree to be fully bound
|
||||
* by the terms of either license. Consult the LICENSE.TXT distributed with
|
||||
* this software for full details.
|
||||
*
|
||||
* This software is open source; 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. See the GNU General Public License for more
|
||||
* details at: http://www.mbedthis.com/downloads/gplLicense.html
|
||||
*
|
||||
* This program is distributed WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* This GPL license does NOT permit incorporating this software into
|
||||
* proprietary programs. If you are unable to comply with the GPL, you must
|
||||
* acquire a commercial license to use this software. Commercial licenses
|
||||
* for this software and support services are available from Mbedthis
|
||||
* Software at http://www.mbedthis.com
|
||||
*
|
||||
* @end
|
||||
*/
|
||||
|
||||
#include "mpr.h"
|
||||
|
||||
/********************************** Includes **********************************/
|
||||
/*
|
||||
* We need to use the underlying str(cpy) routines to implement our safe
|
||||
* alternatives
|
||||
*/
|
||||
#if !DOXYGEN
|
||||
#define UNSAFE_FUNCTIONS_OK 1
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/**************************** Safe String Handling ****************************/
|
||||
/******************************************************************************/
|
||||
|
||||
int mprStrcpy(char *dest, int destMax, const char *src)
|
||||
{
|
||||
int len;
|
||||
|
||||
mprAssert(dest);
|
||||
mprAssert(destMax >= 0);
|
||||
mprAssert(src);
|
||||
|
||||
len = strlen(src);
|
||||
if (destMax > 0 && len >= destMax && len > 0) {
|
||||
return MPR_ERR_WONT_FIT;
|
||||
}
|
||||
if (len > 0) {
|
||||
memcpy(dest, src, len);
|
||||
dest[len] = '\0';
|
||||
} else {
|
||||
*dest = '\0';
|
||||
len = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int mprAllocStrcpy(MPR_LOC_DEC(ctx, loc), char **dest, int destMax,
|
||||
const char *src)
|
||||
{
|
||||
int len;
|
||||
|
||||
mprAssert(dest);
|
||||
mprAssert(destMax >= 0);
|
||||
mprAssert(src);
|
||||
|
||||
len = strlen(src);
|
||||
if (destMax > 0 && len >= destMax) {
|
||||
mprAssert(0);
|
||||
return MPR_ERR_WONT_FIT;
|
||||
}
|
||||
if (len > 0) {
|
||||
*dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), len);
|
||||
memcpy(*dest, src, len);
|
||||
(*dest)[len] = '\0';
|
||||
} else {
|
||||
*dest = (char*) mprAlloc(ctx, 1);
|
||||
*dest = '\0';
|
||||
len = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int mprMemcpy(char *dest, int destMax, const char *src, int nbytes)
|
||||
{
|
||||
mprAssert(dest);
|
||||
mprAssert(destMax <= 0 || destMax >= nbytes);
|
||||
mprAssert(src);
|
||||
mprAssert(nbytes >= 0);
|
||||
|
||||
if (destMax > 0 && nbytes > destMax) {
|
||||
mprAssert(0);
|
||||
return MPR_ERR_WONT_FIT;
|
||||
}
|
||||
if (nbytes > 0) {
|
||||
memcpy(dest, src, nbytes);
|
||||
return nbytes;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int mprAllocMemcpy(MPR_LOC_DEC(ctx, loc), char **dest, int destMax,
|
||||
const void *src, int nbytes)
|
||||
{
|
||||
mprAssert(dest);
|
||||
mprAssert(src);
|
||||
mprAssert(nbytes > 0);
|
||||
mprAssert(destMax <= 0 || destMax >= nbytes);
|
||||
|
||||
if (destMax > 0 && nbytes > destMax) {
|
||||
mprAssert(0);
|
||||
return MPR_ERR_WONT_FIT;
|
||||
}
|
||||
if (nbytes > 0) {
|
||||
*dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx,loc), nbytes);
|
||||
if (*dest == 0) {
|
||||
return MPR_ERR_MEMORY;
|
||||
}
|
||||
memcpy(*dest, src, nbytes);
|
||||
} else {
|
||||
*dest = (char*) mprAlloc(ctx, 1);
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int mprCoreStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax,
|
||||
int existingLen, const char *delim, const char *src, va_list args)
|
||||
{
|
||||
va_list ap;
|
||||
char *dest, *str, *dp;
|
||||
int sepLen, addBytes, required;
|
||||
|
||||
mprAssert(destp);
|
||||
mprAssert(destMax >= 0);
|
||||
mprAssert(src);
|
||||
|
||||
dest = *destp;
|
||||
sepLen = (delim) ? strlen(delim) : 0;
|
||||
|
||||
#ifdef __va_copy
|
||||
__va_copy(ap, args);
|
||||
#else
|
||||
ap = args;
|
||||
#endif
|
||||
addBytes = 0;
|
||||
if (existingLen > 0) {
|
||||
addBytes += sepLen;
|
||||
}
|
||||
str = (char*) src;
|
||||
|
||||
while (str) {
|
||||
addBytes += strlen(str);
|
||||
str = va_arg(ap, char*);
|
||||
if (str) {
|
||||
addBytes += sepLen;
|
||||
}
|
||||
}
|
||||
|
||||
required = existingLen + addBytes + 1;
|
||||
if (destMax > 0 && required >= destMax) {
|
||||
mprAssert(0);
|
||||
return MPR_ERR_WONT_FIT;
|
||||
}
|
||||
|
||||
if (ctx != 0) {
|
||||
if (dest == 0) {
|
||||
dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), required);
|
||||
} else {
|
||||
dest = (char*) mprReallocBlock(MPR_LOC_PASS(ctx, loc), dest,
|
||||
required);
|
||||
}
|
||||
} else {
|
||||
dest = (char*) *destp;
|
||||
}
|
||||
|
||||
dp = &dest[existingLen];
|
||||
if (delim && existingLen > 0) {
|
||||
strcpy(dp, delim);
|
||||
dp += sepLen;
|
||||
}
|
||||
|
||||
if (addBytes > 0) {
|
||||
#ifdef __va_copy
|
||||
__va_copy(ap, args);
|
||||
#else
|
||||
ap = args;
|
||||
#endif
|
||||
str = (char*) src;
|
||||
while (str) {
|
||||
strcpy(dp, str);
|
||||
dp += strlen(str);
|
||||
str = va_arg(ap, char*);
|
||||
if (delim && str) {
|
||||
strcpy(dp, delim);
|
||||
dp += sepLen;
|
||||
}
|
||||
}
|
||||
} else if (dest == 0) {
|
||||
dest = (char*) mprAlloc(ctx, 1);
|
||||
}
|
||||
*dp = '\0';
|
||||
|
||||
*destp = dest;
|
||||
mprAssert(dp < &dest[required]);
|
||||
return required - 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int mprStrcat(char *dest, int destMax, const char *delim, const char *src, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int rc;
|
||||
|
||||
mprAssert(dest);
|
||||
mprAssert(src);
|
||||
|
||||
va_start(ap, src);
|
||||
rc = mprCoreStrcat(MPR_LOC_ARGS(0), &dest, destMax, strlen(dest),
|
||||
delim, src, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int mprAllocStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax,
|
||||
const char *delim, const char *src, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int rc;
|
||||
|
||||
mprAssert(destp);
|
||||
mprAssert(src);
|
||||
|
||||
*destp = 0;
|
||||
va_start(ap, src);
|
||||
rc = mprCoreStrcat(MPR_LOC_PASS(ctx, loc), destp, destMax, 0, delim,
|
||||
src, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int mprReallocStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax,
|
||||
int existingLen, const char *delim, const char *src,...)
|
||||
{
|
||||
va_list ap;
|
||||
int rc;
|
||||
|
||||
va_start(ap, src);
|
||||
rc = mprCoreStrcat(MPR_LOC_PASS(ctx, loc), destp, destMax, existingLen,
|
||||
delim, src, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int mprStrlen(const char *src, int max)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(src);
|
||||
if (len >= max) {
|
||||
mprAssert(0);
|
||||
return MPR_ERR_WONT_FIT;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
char *mprStrTrim(char *str, const char *set)
|
||||
{
|
||||
int len, i;
|
||||
|
||||
if (str == 0 || set == 0) {
|
||||
return str;
|
||||
}
|
||||
|
||||
i = strspn(str, set);
|
||||
str += i;
|
||||
|
||||
len = strlen(str);
|
||||
while (strspn(&str[len - 1], set) > 0) {
|
||||
str[len - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Map a string to lower case (overwrites original string)
|
||||
*/
|
||||
|
||||
char *mprStrLower(char *str)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
mprAssert(str);
|
||||
|
||||
if (str == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (cp = str; *cp; cp++) {
|
||||
if (isupper(*cp)) {
|
||||
*cp = (char) tolower(*cp);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Map a string to upper case (overwrites buffer)
|
||||
*/
|
||||
|
||||
char *mprStrUpper(char *str)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
mprAssert(str);
|
||||
if (str == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (cp = str; *cp; cp++) {
|
||||
if (islower(*cp)) {
|
||||
*cp = (char) toupper(*cp);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Case insensitive string comparison. Stop at the end of str1.
|
||||
*/
|
||||
|
||||
int mprStrcmpAnyCase(const char *str1, const char *str2)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (str1 == 0 || str2 == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (str1 == str2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (rc = 0; *str1 && rc == 0; str1++, str2++) {
|
||||
rc = tolower(*str1) - tolower(*str2);
|
||||
}
|
||||
if (*str2) {
|
||||
return -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Case insensitive string comparison. Limited by length
|
||||
*/
|
||||
|
||||
int mprStrcmpAnyCaseCount(const char *str1, const char *str2, int len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (str1 == 0 || str2 == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (str1 == str2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (rc = 0; len-- > 0 && *str1 && rc == 0; str1++, str2++) {
|
||||
rc = tolower(*str1) - tolower(*str2);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Return the last portion of a pathname
|
||||
*/
|
||||
|
||||
const char *mprGetBaseName(const char *name)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
cp = strrchr(name, '/');
|
||||
|
||||
if (cp == 0) {
|
||||
cp = strrchr(name, '\\');
|
||||
if (cp == 0) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
if (cp == name) {
|
||||
if (cp[1] == '\0') {
|
||||
return name;
|
||||
}
|
||||
} else {
|
||||
if (cp[1] == '\0') {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
return &cp[1];
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Return the directory portion of a pathname into the users buffer.
|
||||
*/
|
||||
|
||||
char *mprGetDirName(char *buf, int bufsize, const char *path)
|
||||
{
|
||||
char *cp;
|
||||
int dlen;
|
||||
|
||||
mprAssert(path);
|
||||
mprAssert(buf);
|
||||
mprAssert(bufsize > 0);
|
||||
|
||||
cp = strrchr(path, '/');
|
||||
if (cp == 0) {
|
||||
#if WIN
|
||||
cp = strrchr(path, '\\');
|
||||
if (cp == 0)
|
||||
#endif
|
||||
{
|
||||
buf[0] = '\0';
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
if (cp == path && cp[1] == '\0') {
|
||||
strcpy(buf, ".");
|
||||
return buf;
|
||||
}
|
||||
|
||||
dlen = cp - path;
|
||||
if (dlen < bufsize) {
|
||||
if (dlen == 0) {
|
||||
dlen++;
|
||||
}
|
||||
mprMemcpy(buf, bufsize, path, dlen);
|
||||
buf[dlen] = '\0';
|
||||
return buf;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Thread-safe wrapping of strtok. Note "str" is modifed as per strtok()
|
||||
*/
|
||||
|
||||
char *mprStrTok(char *str, const char *delim, char **last)
|
||||
{
|
||||
char *start, *end;
|
||||
int i;
|
||||
|
||||
start = str ? str : *last;
|
||||
|
||||
if (start == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = strspn(start, delim);
|
||||
start += i;
|
||||
if (*start == '\0') {
|
||||
*last = 0;
|
||||
return 0;
|
||||
}
|
||||
end = strpbrk(start, delim);
|
||||
if (end) {
|
||||
*end++ = '\0';
|
||||
i = strspn(end, delim);
|
||||
end += i;
|
||||
}
|
||||
*last = end;
|
||||
return start;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Split the buffer into word tokens
|
||||
*/
|
||||
|
||||
char *mprGetWordTok(char *buf, int bufsize, const char *str, const char *delim,
|
||||
const char **tok)
|
||||
{
|
||||
const char *start, *end;
|
||||
int i, len;
|
||||
|
||||
start = str ? str : *tok;
|
||||
|
||||
if (start == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = strspn(start, delim);
|
||||
start += i;
|
||||
if (*start =='\0') {
|
||||
*tok = 0;
|
||||
return 0;
|
||||
}
|
||||
end = strpbrk(start, delim);
|
||||
if (end) {
|
||||
len = min(end - start, bufsize - 1);
|
||||
mprMemcpy(buf, bufsize, start, len);
|
||||
buf[len] = '\0';
|
||||
} else {
|
||||
if (mprStrcpy(buf, bufsize, start) < 0) {
|
||||
buf[bufsize - 1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
buf[bufsize - 1] = '\0';
|
||||
}
|
||||
*tok = end;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Format a number as a string.
|
||||
*/
|
||||
|
||||
char *mprItoa(char *buf, int size, int value)
|
||||
{
|
||||
char numBuf[16];
|
||||
char *cp, *dp, *endp;
|
||||
int negative;
|
||||
|
||||
cp = &numBuf[sizeof(numBuf)];
|
||||
*--cp = '\0';
|
||||
|
||||
if (value < 0) {
|
||||
negative = 1;
|
||||
value = -value;
|
||||
size--;
|
||||
} else {
|
||||
negative = 0;
|
||||
}
|
||||
|
||||
do {
|
||||
*--cp = '0' + (value % 10);
|
||||
value /= 10;
|
||||
} while (value > 0);
|
||||
|
||||
if (negative) {
|
||||
*--cp = '-';
|
||||
}
|
||||
|
||||
dp = buf;
|
||||
endp = &buf[size];
|
||||
while (dp < endp && *cp) {
|
||||
*dp++ = *cp++;
|
||||
}
|
||||
*dp++ = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Parse an ascii number. Supports radix 10 or 16.
|
||||
*/
|
||||
|
||||
int mprAtoi(const char *str, int radix)
|
||||
{
|
||||
int c, val, negative;
|
||||
|
||||
mprAssert(radix == 10 || radix == 16);
|
||||
|
||||
if (str == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = 0;
|
||||
if (radix == 10 && *str == '-') {
|
||||
negative = 1;
|
||||
str++;
|
||||
} else {
|
||||
negative = 0;
|
||||
}
|
||||
|
||||
if (radix == 10) {
|
||||
while (*str && isdigit(*str)) {
|
||||
val = (val * radix) + *str - '0';
|
||||
str++;
|
||||
}
|
||||
} else if (radix == 16) {
|
||||
if (*str == '0' && tolower(str[1]) == 'x') {
|
||||
str += 2;
|
||||
}
|
||||
while (*str) {
|
||||
c = tolower(*str);
|
||||
if (isdigit(c)) {
|
||||
val = (val * radix) + c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
val = (val * radix) + c - 'a' + 10;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
return (negative) ? -val: val;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Make an argv array. Caller must free by calling mprFree(argv) to free
|
||||
* everything.
|
||||
*/
|
||||
|
||||
int mprMakeArgv(MprCtx ctx, const char *program, const char *cmd,
|
||||
char ***argvp, int *argcp)
|
||||
{
|
||||
char *cp, **argv, *buf, *args;
|
||||
int size, argc;
|
||||
|
||||
/*
|
||||
* Allocate one buffer for argv and the actual args themselves
|
||||
*/
|
||||
size = strlen(cmd) + 1;
|
||||
|
||||
buf = (char*) mprAlloc(ctx, (MPR_MAX_ARGC * sizeof(char*)) + size);
|
||||
if (buf == 0) {
|
||||
return MPR_ERR_MEMORY;
|
||||
}
|
||||
|
||||
args = &buf[MPR_MAX_ARGC * sizeof(char*)];
|
||||
strcpy(args, cmd);
|
||||
argv = (char**) buf;
|
||||
|
||||
argc = 0;
|
||||
if (program) {
|
||||
argv[argc++] = (char*) mprStrdup(ctx, program);
|
||||
}
|
||||
|
||||
for (cp = args; cp && *cp != '\0'; argc++) {
|
||||
if (argc >= MPR_MAX_ARGC) {
|
||||
mprAssert(argc < MPR_MAX_ARGC);
|
||||
mprFree(buf);
|
||||
*argvp = 0;
|
||||
if (argcp) {
|
||||
*argcp = 0;
|
||||
}
|
||||
return MPR_ERR_TOO_MANY;
|
||||
}
|
||||
while (isspace(*cp)) {
|
||||
cp++;
|
||||
}
|
||||
if (*cp == '\0') {
|
||||
break;
|
||||
}
|
||||
if (*cp == '"') {
|
||||
cp++;
|
||||
argv[argc] = cp;
|
||||
while ((*cp != '\0') && (*cp != '"')) {
|
||||
cp++;
|
||||
}
|
||||
} else {
|
||||
argv[argc] = cp;
|
||||
while (*cp != '\0' && !isspace(*cp)) {
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
if (*cp != '\0') {
|
||||
*cp++ = '\0';
|
||||
}
|
||||
}
|
||||
argv[argc] = 0;
|
||||
|
||||
if (argcp) {
|
||||
*argcp = argc;
|
||||
}
|
||||
*argvp = argv;
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim:tw=78
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
Reference in New Issue
Block a user