summaryrefslogtreecommitdiff
path: root/source4/lib/appweb/ejs-2.0/mpr/mprString.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/appweb/ejs-2.0/mpr/mprString.c')
-rw-r--r--source4/lib/appweb/ejs-2.0/mpr/mprString.c727
1 files changed, 727 insertions, 0 deletions
diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprString.c b/source4/lib/appweb/ejs-2.0/mpr/mprString.c
new file mode 100644
index 0000000000..b688667bcc
--- /dev/null
+++ b/source4/lib/appweb/ejs-2.0/mpr/mprString.c
@@ -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
+ */