📄 mprstring.c
字号:
/** * @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;}/***************************************************************************** Note that this VARARGS function must be NULL (not 0, this must be a pointer) terminated*/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;}/***************************************************************************** Note that this VARARGS function must be NULL (not 0, this must be a pointer) terminated*/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;}/***************************************************************************** Note that this VARARGS function must be NULL (not 0, this must be a pointer) terminated*/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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -