diff options
Diffstat (limited to 'source4/lib/appweb/mpr')
-rw-r--r-- | source4/lib/appweb/mpr/miniMpr.c | 522 | ||||
-rw-r--r-- | source4/lib/appweb/mpr/miniMpr.h | 301 | ||||
-rw-r--r-- | source4/lib/appweb/mpr/var.c | 2215 | ||||
-rw-r--r-- | source4/lib/appweb/mpr/var.h | 487 |
4 files changed, 0 insertions, 3525 deletions
diff --git a/source4/lib/appweb/mpr/miniMpr.c b/source4/lib/appweb/mpr/miniMpr.c deleted file mode 100644 index 381815eb23..0000000000 --- a/source4/lib/appweb/mpr/miniMpr.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * @file miniMpr.cpp - * @brief Mini Mbedthis Portable Runtime (MPR) - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. 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 "miniMpr.h" -#include "param/param.h" -#include "lib/events/events.h" - -/************************************ Code ************************************/ -#if !BLD_APPWEB -#if !BLD_GOAHEAD_WEBSERVER - -static void *mpr_ctx; - -/* set the memory context to be used for all ejs variables */ -void mprSetCtx(TALLOC_CTX *ctx) -{ - mpr_ctx = ctx; -} - -/* return the memory context being used for all ejs variables */ -void *mprMemCtx(void) -{ - return mpr_ctx; -} - -struct event_context *mprEventCtx(void) -{ - return event_context_find(mprMemCtx()); -} - -/* return the loadparm context being used for all ejs variables */ -struct loadparm_context *mprLpCtx(void) -{ - return global_loadparm; -} - -void mprFree(void *ptr) -{ - talloc_free(ptr); -} - -void *mprMalloc(uint size) -{ - return talloc_size(mpr_ctx, size); -} - -/******************************************************************************/ - -void *mprRealloc(void *ptr, uint size) -{ - return talloc_realloc_size(mpr_ctx, ptr, size); -} - -/******************************************************************************/ - -char *mprStrdup(const char *str) -{ - if (str == 0) { - str = ""; - } - return talloc_strdup(mpr_ctx, str); -} - -/*****************************************************************************/ - -int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) -{ - va_list args; - char *buf; - int count; - - va_start(args, fmt); - buf = mprMalloc(maxSize + 1); - count = mtVsprintf(buf, maxSize, fmt, args); - *msgbuf = buf; - va_end(args); - return count; -} - -/*****************************************************************************/ - -int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args) -{ - char *buf; - int count; - - buf = mprMalloc(maxSize + 1); - count = mtVsprintf(buf, maxSize, fmt, args); - *msgbuf = buf; - return count; -} - - -/*****************************************************************************/ -/* - * Format a number as a string. FUTURE -- reverse args to be standard. - * ie. mprItoa(char *userBuf, int bufsize, int value); - */ - -char *mprItoa(int value, char *buf, int width) -{ - char numBuf[16]; - char *cp, *dp, *endp; - int negative; - - cp = &numBuf[sizeof(numBuf)]; - *--cp = '\0'; - - if (value < 0) { - negative = 1; - value = -value; - width--; - } else { - negative = 0; - } - - do { - *--cp = '0' + (value % 10); - value /= 10; - } while (value > 0); - - if (negative) { - *--cp = '-'; - } - - dp = buf; - endp = &buf[width]; - while (dp < endp && *cp) { - *dp++ = *cp++; - } - *dp++ = '\0'; - return buf; -} - -/*****************************************************************************/ - -void mprLog(int level, const char *fmt, ...) -{ - va_list args; - char *buf; - - if (DEBUGLVL(level)) { - va_start(args, fmt); - mprAllocVsprintf(&buf, MPR_MAX_STRING, fmt, args); - va_end(args); - DEBUG(level, ("mprLog: %s", buf)); - mprFree(buf); - } -} - -/*****************************************************************************/ - -void mprBreakpoint(const char *file, int line, const char *cond) -{ - char *buf; - mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", - file, line, cond); - ejs_exception(buf); -} - -#endif /* !BLD_GOAHEAD_WEBSERVER */ -/*****************************************************************************/ -/* - * Create a general growable array structure - */ - -MprArray *mprCreateArray() -{ - MprArray *array; - int size; - - array = (MprArray*) mprMalloc(sizeof(MprArray)); - if (array == 0) { - return 0; - } - memset(array, 0, sizeof(MprArray)); - - size = MPR_ARRAY_INCR * sizeof(void*); - array->handles = (void**) mprMalloc(size); - if (array->handles == 0) { - mprFree(array); - return 0; - } - memset(array->handles, 0, size); - array->max = MPR_ARRAY_INCR; - array->used = 0; - return array; -} - -/*****************************************************************************/ -/* - * Dispose of the array. Callers responsibility to dispose of handle entries. - */ - -void mprDestroyArray(MprArray *array) -{ - mprAssert(array); - mprAssert(array->max >= 0); - mprAssert(array->used >= 0); - - mprFree(array->handles); - mprFree(array); -} - -/*****************************************************************************/ -/* - * Add an item to the array - */ - -int mprAddToArray(MprArray *array, void *item) -{ - int memsize, idx, len; - - mprAssert(array); - mprAssert(array->max >= 0); - mprAssert(array->used >= 0); - - if (array->used < array->max) { - idx = array->used++; - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] == 0); - array->handles[idx] = item; - return idx; - } - - for (idx = array->used; idx < array->max; idx++) { - if (array->handles[idx] == 0) { - array->used++; - mprAssert(array->handles[idx] == 0); - array->handles[idx] = item; - return idx; - } - } - - len = array->max + MPR_ARRAY_INCR; - memsize = len * sizeof(void*); - array->handles = (void**) mprRealloc((void*) array->handles, memsize); - if (array->handles == NULL) { - return -1; - } - memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR); - array->max = len; - array->used++; - - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] == 0); - - array->handles[idx] = item; - return idx; -} - -/*****************************************************************************/ -/* - * Remove from the array - */ - -int mprRemoveFromArray(MprArray *array, int idx) -{ - mprAssert(array); - mprAssert(array->max > 0); - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] != 0); - mprAssert(array->used > 0); - - array->handles[idx] = 0; - return --array->used; -} - -/*****************************************************************************/ -/* - * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok() - */ - -char *mprStrTok(char *str, const char *delim, char **tok) -{ - char *start, *end; - int i; - - 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) { - *end++ = '\0'; - i = strspn(end, delim); - end += i; - } - *tok = end; - return start; -} - -/*****************************************************************************/ - -static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, - const char *delim, const char *src, va_list args) -{ - va_list ap; - char *dest, *dp; - const char *str; - int sepLen, addBytes, required; - - mprAssert(destp); - mprAssert(destMax > 0); - mprAssert(src); - - dest = *destp; - sepLen = (delim) ? strlen(delim) : 0; - - va_copy(ap, args); - addBytes = 0; - str = src; - while (str) { - addBytes += strlen(str) + sepLen; - str = va_arg(ap, const char*); - } - va_end(ap); - - if (existingLen > 0) { - addBytes += sepLen; - } - required = existingLen + addBytes + 1; - if (required >= destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - - if (alloc) { - if (dest == 0) { - dest = (char*) mprMalloc(required); - } else { - dest = (char*) mprRealloc(dest, required); - } - } else { - dest = (char*) *destp; - } - - dp = &dest[existingLen]; - if (delim) { - strcpy(dp, delim); - dp += sepLen; - } - - if (addBytes > 0) { - va_copy(ap, args); - str = src; - while (str) { - strcpy(dp, str); - dp += strlen(str); - str = va_arg(ap, char*); - if (delim && str) { - strcpy(dp, delim); - dp += sepLen; - } - } - va_end(ap); - } else if (dest == 0) { - dest = (char*) mprMalloc(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 mprReallocStrcat(char **destp, int destMax, int existingLen, - const char *delim, const char *src,...) -{ - va_list ap; - int rc; - - va_start(ap, src); - rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap); - va_end(ap); - return rc; -} - -/*****************************************************************************/ -/* - * Return the directory portion of a pathname into the users buffer. - */ - -int mprGetDirName(char *buf, int bufsize, 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 0; - } - } - - if (cp == path && cp[1] == '\0') { - strcpy(buf, "."); - return 0; - } - - dlen = cp - path; - if (dlen < bufsize) { - if (dlen == 0) { - dlen++; - } - mprMemcpy(buf, bufsize, path, dlen); - buf[dlen] = '\0'; - return 0; - } - return MPR_ERR_WONT_FIT; -} - -/*****************************************************************************/ - -int mprStrcpy(char *dest, int destMax, const char *src) -{ - int len; - - mprAssert(dest); - mprAssert(destMax > 0); - mprAssert(src); - - len = strlen(src); - if (len >= destMax && len > 0) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (len > 0) { - memcpy(dest, src, len); - dest[len] = '\0'; - } else { - *dest = '\0'; - len = 0; - } - return len; -} - -/*****************************************************************************/ - -int mprMemcpy(char *dest, int destMax, const char *src, int nbytes) -{ - mprAssert(dest); - mprAssert(destMax > nbytes); - mprAssert(src); - mprAssert(nbytes > 0); - - if (nbytes > destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (nbytes > 0) { - memcpy(dest, src, nbytes); - return nbytes; - } else { - return 0; - } -} - -/*****************************************************************************/ -#else -void miniMprDummy() {} -#endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER - -/* - * 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 - */ diff --git a/source4/lib/appweb/mpr/miniMpr.h b/source4/lib/appweb/mpr/miniMpr.h deleted file mode 100644 index 2b8ff0af6a..0000000000 --- a/source4/lib/appweb/mpr/miniMpr.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * @file miniMpr.h - * @brief Mini Mbedthis Portable Runtime (MPR) Environment. - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. 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 - */ -#ifndef _h_MINI_MPR -#define _h_MINI_MPR 1 - -/********************************** Includes **********************************/ -/* - * Find out about our configuration - */ -#ifndef _INCLUDES_H - #include "includes.h" -#endif - -/* allow this library to use strcpy() */ -#undef strcpy - #include "lib/appweb/ejs/config.h" - -#if BLD_APPWEB - /* - * If building within AppWeb, use the full MPR - */ - #include "mpr.h" -#else - - #include <ctype.h> - #include <fcntl.h> - #include <stdarg.h> - #include <stdlib.h> - #include <stdio.h> - #include <string.h> - #include <sys/stat.h> - -#if !WIN - #include <unistd.h> -#endif - -#if CE - #include <io.h> - #include "CE/wincompat.h" -#endif - -#if LYNX - #include <unistd.h> -#endif - -#if QNX4 - #include <dirent.h> -#endif -#ifdef HAVE_MATH_H - #include <math.h> -#endif -/********************************** Defines ***********************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#if BLD_FEATURE_SQUEEZE -/* - * Reasonable length of a file path name to use in most cases where you know - * the expected file name and it is certain to be less than this limit. - */ -#define MPR_MAX_FNAME 128 -#define MPR_MAX_STRING 512 -#define MPR_DEFAULT_HASH_SIZE 23 /* Default size of hash table index */ -#define MPR_MAX_HEAP_SIZE (32 * 1024) -#else -#define MPR_MAX_FNAME 256 -#define MPR_MAX_STRING 4096 -#define MPR_DEFAULT_HASH_SIZE 43 /* Default size of hash table index */ -#define MPR_MAX_HEAP_SIZE (64 * 1024) -#endif - -/* - * Useful for debugging - */ -#define MPR_L __FILE__, __LINE__ - -#if BLD_FEATURE_ASSERT -#define mprAssert(C) \ - if (C) ; else mprBreakpoint(__FILE__, __LINE__, #C) -#else - #define mprAssert(C) if (1) ; else -#endif - -/* - * Standard MPR return and error codes - */ -#define MPR_ERR_BASE (-200) /* Error code */ -#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) /* Error code */ -#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) /* Error code */ -#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) /* Error code */ -#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) /* Error code */ -#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) /* Error code */ -#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) /* Error code */ -#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) /* Error code */ -#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) /* Error code */ -#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) /* Error code */ -#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) /* Error code */ -#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) /* Error code */ -#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) /* Error code */ -#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) /* Error code */ -#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) /* Error code */ -#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) /* Error code */ -#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) /* Error code */ -#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) /* Error code */ -#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) /* Error code */ -#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) /* Error code */ -#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) /* Error code */ -#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) /* Error code */ -#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) /* Error code */ -#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) /* Error code */ -#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) /* Error code */ -#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) /* Error code */ -#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) /* Error code */ -#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) /* Error code */ -#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) /* Error code */ -#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) /* Error code */ -#define MPR_ERR_MAX (MPR_ERR_BASE - 30) /* Error code */ - -/* - * Standard error severity and trace levels. These are ored with the error - * severities below. The MPR_LOG_MASK is used to extract the trace level - * from a flags word. We expect most apps to run with level 2 trace. - */ -#define MPR_FATAL 0 /* Fatal error. Cant continue. */ -#define MPR_ERROR 1 /* Hard error */ -#define MPR_WARN 2 /* Soft warning */ -#define MPR_CONFIG 2 /* Essential configuration settings */ -#define MPR_INFO 3 /* Informational only */ -#define MPR_DEBUG 4 /* Debug information */ -#define MPR_VERBOSE 9 /* Highest level of trace */ -#define MPR_LOG_MASK 0xf /* Level mask */ - -/* - * Error flags. Specify where the error should be sent to. Note that the - * product.xml setting "headless" will modify how errors are reported. - * Assert errors are trapped when in DEV mode. Otherwise ignored. - */ -#define MPR_TRAP 0x10 /* Assert error -- trap in debugger */ -#define MPR_LOG 0x20 /* Log the error in the O/S event log */ -#define MPR_USER 0x40 /* Display to the user */ -#define MPR_ALERT 0x80 /* Send a management alert */ -#define MPR_TRACE 0x100 /* Trace */ - -/* - * Error format flags - */ -#define MPR_RAW 0x200 /* Raw trace output */ - -/* - * Error line number information - */ -#define MPR_L __FILE__, __LINE__ - -typedef char* MprStr; - -#ifndef __cplusplus -typedef unsigned char uchar; -#endif - -/* - * Porters: put other operating system type defines here - */ -#if WIN - typedef unsigned int uint; - typedef __int64 int64; - typedef unsigned __int64 uint64; -#else -#define O_BINARY 0 -#ifndef uint - #define uint unsigned -#endif - #define int64 int64_t - #define uint64 uint64_t -#endif - -/* - * Flexible array data type - */ -typedef struct { - int max; /* Size of the handles array */ - int used; /* Count of used entries in handles */ - void **handles; -} MprArray; - -#if BLD_FEATURE_SQUEEZE -#define MPR_ARRAY_INCR 8 -#else -#define MPR_ARRAY_INCR 16 -#endif - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -/********************************* Prototypes *********************************/ -/* - * If running in the GoAhead WebServer, map some MPR routines to WebServer - * equivalents. - */ - -#if BLD_GOAHEAD_WEBSERVER -#include "uemf.h" -#define mprMalloc(size) balloc(B_L, size) -#define mprFree(ptr) bfreeSafe(B_L, ptr) -#define mprRealloc(ptr, size) brealloc(B_L, ptr, size) -#define mprStrdup(ptr) bstrdup(B_L, ptr) -#define mprAllocSprintf fmtAlloc -#define mprAllocVsprintf fmtValloc -#define mprSprintf fmtStatic -#define mprItoa stritoa -#define mprLog trace -#define mprBreakpoint(file, line, cond) \ - error(file, line, E_BLD_FEATURE_ASSERT, T("%s"), cond) - -#else /* !BLD_GOAHEAD_WEBSERVER */ -/* #define mprMalloc malloc */ -#define mprSprintf snprintf -#define mtVsprintf vsnprintf -extern void *mprMalloc(uint size); -extern void *mprRealloc(void *ptr, uint size); -extern void mprFree(void *ptr); -extern char *mprStrdup(const char *str); -extern int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, - va_list args) PRINTF_ATTRIBUTE(3,0); -extern int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -extern char *mprItoa(int num, char *buf, int width); -extern void mprLog(int level, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -extern void mprBreakpoint(const char *file, int line, const char *msg) _NORETURN_; -#endif /* BLD_GOAHEAD_WEBSERVER */ - -extern MprArray *mprCreateArray(void); -extern void mprDestroyArray(MprArray *array); -extern int mprAddToArray(MprArray *array, void *item); -extern int mprRemoveFromArray(MprArray *array, int idx); -extern char *mprStrTok(char *str, const char *delim, char **tok); - -extern int mprGetDirName(char *buf, int bufsize, char *path); -extern int mprReallocStrcat(char **dest, int max, int existingLen, - const char *delim, const char *src, ...); -extern int mprStrcpy(char *dest, int destMax, const char *src); -extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); - -extern void mprSetCtx(void *ctx); -extern void *mprMemCtx(void); -struct loadparm_context; -extern struct loadparm_context *mprLpCtx(void); -struct event_context; -extern struct event_context *mprEventCtx(void); - -/* This function needs to be provided by anyone using ejs */ -void ejs_exception(const char *reason); - -#define mprStrCmpAnyCase(s1, s2) strcasecmp_m(s1, s2) - -#ifdef __cplusplus -} -#endif -#endif /* !BLD_APPWEB */ -#endif /* _h_MINI_MPR */ - -/*****************************************************************************/ - -/* - * 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 - */ diff --git a/source4/lib/appweb/mpr/var.c b/source4/lib/appweb/mpr/var.c deleted file mode 100644 index e73da773ea..0000000000 --- a/source4/lib/appweb/mpr/var.c +++ /dev/null @@ -1,2215 +0,0 @@ -/* - * @file var.c - * @brief MPR Universal Variable Type - * @overview - * - * @copy default.m - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. 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 - */ - -/******************************* Documentation ********************************/ - -/* - * This module is NOT multithreaded. - * - * Properties are variables that are stored in an object type variable. - * Properties can be primitive data types, other objects or functions. - * Properties are indexed by a character name. - */ - -/********************************** Includes **********************************/ - -#include "var.h" - -/*********************************** Locals ***********************************/ -#if VAR_DEBUG - -static MprProperties objectList; /* Dummy head of objects list */ -static int objectCount = -1; /* Count of objects */ - -#endif -/***************************** Forward Declarations ***************************/ - -static int adjustRefCount(MprProperties *pp, int adj); -static int adjustVarRefCount(MprVar *vp, int adj); -static MprVar *allocProperty(const char *propertyName); -static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth); -static MprProperties - *createProperties(const char *name, int hashSize); -static bool freeVar(MprVar *vp, int force); -static bool freeVarStorage(MprVar *vp, int force); -static MprVar *getObjChain(MprProperties *pp, const char *property); -static int hash(MprProperties *pp, const char *property); -static bool releaseProperties(MprProperties *pp, int force); - -/*********************************** Code *************************************/ -/* - * Destroy a variable and all referenced variables. Release any referenced - * object regardless of whether other users still have references. Be VERY - * careful using this routine. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -bool mprDestroyAllVars(MprVar *vp) -{ - mprAssert(vp); - - if (vp->trigger) { - if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) - == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Free the actual value. If this var refers to an object, we will - * recurse through all the properties freeing all vars. - */ - return freeVar(vp, 1); -} - -/******************************************************************************/ -/* - * Destroy a variable. Release any referenced object (destroy if no other - * users are referencing). - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -bool mprDestroyVar(MprVar *vp) -{ - mprAssert(vp); - - if (vp->trigger) { - if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) - == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Free the actual value. If this var refers to an object, we will - * recurse through all the properties freeing all that have no other - * references. - */ - return freeVar(vp, 0); -} - -/******************************************************************************/ -/* - * Free the value in a variable for primitive types. Release objects. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -static bool freeVar(MprVar *vp, int force) -{ - bool freed; - - mprAssert(vp); - - freed = freeVarStorage(vp, force); - - mprFree(vp->name); - mprFree(vp->fullName); - - if (vp->allocatedVar) { - mprFree(vp); - } else { - vp->name = 0; - vp->fullName = 0; - vp->type = MPR_TYPE_UNDEFINED; - } - return freed; -} - -/******************************************************************************/ -/* - * Free the value in a variable for primitive types. Release objects. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -static bool freeVarStorage(MprVar *vp, int force) -{ - MprArray *argList; - bool freed; - int i; - - freed = 1; - mprAssert(vp); - - switch (vp->type) { - default: - break; - - case MPR_TYPE_STRING: - if (vp->allocatedData && vp->string != 0) { - mprFree(vp->string); - vp->string = 0; - vp->allocatedData = 0; - } - break; - - case MPR_TYPE_PTR: - if (vp->allocatedData) { - vp->allocatedData = 0; - mprFree(vp->ptr); - } - break; - - case MPR_TYPE_OBJECT: -#if VAR_DEBUG - /* - * Recurse through all properties and release / delete. Release the - * properties hash table. - */ - if (vp->properties->refCount > 1) { - mprLog(7, "freeVar: ACT \"%s\", 0x%x, ref %d, force %d\n", - vp->name, vp->properties, vp->properties->refCount, force); - } else { - mprLog(7, "freeVar: DEL \"%s\", 0x%x, ref %d, force %d\n", - vp->name, vp->properties, vp->properties->refCount, force); - } -#endif - if (vp->allocatedData) { - freed = releaseProperties(vp->properties, force); - } - vp->properties = 0; - break; - - case MPR_TYPE_FUNCTION: - if (vp->allocatedData) { - argList = vp->function.args; - for (i = 0; i < argList->max; i++) { - if (argList->handles[i] != 0) { - mprFree(argList->handles[i]); - } - } - mprDestroyArray(argList); - vp->function.args = 0; - mprFree(vp->function.body); - vp->function.body = 0; - } - break; - } - - vp->type = MPR_TYPE_UNDEFINED; - return freed; -} - -/******************************************************************************/ -/* - * Adjust the object reference count and return the currrent count of - * users. - */ - -static int adjustVarRefCount(MprVar *vp, int adj) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - mprAssert(vp->type == MPR_TYPE_OBJECT); - return 0; - } - return adjustRefCount(vp->properties, adj); -} - -/******************************************************************************/ -/* - * Get the object reference count - */ - -int mprGetVarRefCount(MprVar *vp) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - mprAssert(vp->type == MPR_TYPE_OBJECT); - return 0; - } - return adjustRefCount(vp->properties, 0); -} - -/******************************************************************************/ -/* - * Update the variable's name - */ - -void mprSetVarName(MprVar *vp, char *name) -{ - mprAssert(vp); - - mprFree(vp->name); - vp->name = mprStrdup(name); -} - -/******************************************************************************/ -/* - * Append to the variable's full name - */ - -void mprSetVarFullName(MprVar *vp, char *name) -{ -#if VAR_DEBUG - mprAssert(vp); - - mprFree(vp->fullName); - vp->fullName = mprStrdup(name); - if (vp->type == MPR_TYPE_OBJECT) { - if (strcmp(vp->properties->name, "this") == 0) { - mprStrcpy(vp->properties->name, sizeof(vp->properties->name), name); - } - } -#endif -} - -/******************************************************************************/ -/* - * Make a var impervious to recursive forced deletes. - */ - -void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect) -{ - mprAssert(vp); - - if (vp->type == MPR_TYPE_OBJECT && vp->properties) { - vp->properties->deleteProtect = deleteProtect; - } -} - -/******************************************************************************/ -/* - * Make a variable readonly. Can still be deleted. - */ - -void mprSetVarReadonly(MprVar *vp, int readonly) -{ - mprAssert(vp); - - vp->readonly = readonly; -} - -/******************************************************************************/ - -MprVarTrigger mprAddVarTrigger(MprVar *vp, MprVarTrigger fn) -{ - MprVarTrigger oldTrigger; - - mprAssert(vp); - mprAssert(fn); - - oldTrigger = vp->trigger; - vp->trigger = fn; - return oldTrigger; -} - -/******************************************************************************/ - -MprType mprGetVarType(MprVar *vp) -{ - mprAssert(vp); - - return vp->type; -} - -/******************************************************************************/ -/********************************** Properties ********************************/ -/******************************************************************************/ -/* - * Create a property in an object with a defined value. If the property - * already exists in the object, then just write its value. - */ - -MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, - MprVar *newValue) -{ - MprVar *prop, *last; - int bucketIndex; - - mprAssert(obj); - mprAssert(propertyName && *propertyName); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - /* - * See if property already exists and locate the bucket to hold the - * property reference. - */ - last = 0; - bucketIndex = hash(obj->properties, propertyName); - prop = obj->properties->buckets[bucketIndex]; - - /* - * Find the property in the hash chain if it exists - */ - for (last = 0; prop; last = prop, prop = prop->forw) { - if (prop->name[0] == propertyName[0] && - strcmp(prop->name, propertyName) == 0) { - break; - } - } - - if (prop) { - /* FUTURE -- remove. Just for debug. */ - mprAssert(prop == 0); - mprLog(0, "Attempting to create property %s in object %s\n", - propertyName, obj->name); - return 0; - } - - if (obj->trigger) { - if ((obj->trigger)(MPR_VAR_CREATE_PROPERTY, obj->properties, prop, - newValue, 0) == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Create a new property - */ - prop = allocProperty(propertyName); - if (prop == 0) { - mprAssert(prop); - return 0; - } - - copyVarCore(prop, newValue, MPR_SHALLOW_COPY); - - prop->bucketIndex = bucketIndex; - if (last) { - last->forw = prop; - } else { - obj->properties->buckets[bucketIndex] = prop; - } - prop->parentProperties = obj->properties; - - /* - * Update the item counts - */ - obj->properties->numItems++; - if (! mprVarIsFunction(prop->type)) { - obj->properties->numDataItems++; - } - - return prop; -} - -/******************************************************************************/ -/* - * Create a property in an object with a defined value. If the property - * already exists in the object, then just write its value. Same as - * mprCreateProperty except that the new value is passed by value rather than - * by pointer. - */ - -MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, - MprVar newValue) -{ - return mprCreateProperty(obj, propertyName, &newValue); -} - -/******************************************************************************/ -/* - * Create a new property - */ - -static MprVar *allocProperty(const char *propertyName) -{ - MprVar *prop; - - prop = (MprVar*) mprMalloc(sizeof(MprVar)); - if (prop == 0) { - mprAssert(prop); - return 0; - } - memset(prop, 0, sizeof(MprVar)); - prop->allocatedVar = 1; - prop->name = mprStrdup(propertyName); - prop->forw = (MprVar*) 0; - - return prop; -} - -/******************************************************************************/ -/* - * Update a property in an object with a defined value. Create the property - * if it doesn not already exist. - */ - -MprVar *mprSetProperty(MprVar *obj, const char *propertyName, MprVar *newValue) -{ - MprVar *prop, triggerValue; - int rc; - - mprAssert(obj); - mprAssert(propertyName && *propertyName); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(0); - return 0; - } - - prop = mprGetProperty(obj, propertyName, 0); - if (prop == 0) { - return mprCreateProperty(obj, propertyName, newValue); - } - - if (obj->trigger) { - /* - * Call the trigger before the update and pass it the new value. - */ - triggerValue = *newValue; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (obj->trigger)(MPR_VAR_WRITE, obj->properties, obj, - &triggerValue, 0); - if (rc == MPR_TRIGGER_ABORT) { - return 0; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - /* - * Trigger must copy to triggerValue a variable that is not - * a structure copy of the existing data. - */ - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return prop; - } - } - copyVarCore(prop, newValue, MPR_SHALLOW_COPY); - return prop; -} - -/******************************************************************************/ -/* - * Update a property in an object with a defined value. Create the property - * if it does not already exist. Same as mprSetProperty except that the - * new value is passed by value rather than by pointer. - */ - -MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, - MprVar newValue) -{ - return mprSetProperty(obj, propertyName, &newValue); -} - -/******************************************************************************/ -/* - * Delete a property from this object - */ - -int mprDeleteProperty(MprVar *obj, const char *property) -{ - MprVar *prop, *last; - char *cp; - int bucketIndex; - - mprAssert(obj); - mprAssert(property && *property); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - last = 0; - bucketIndex = hash(obj->properties, property); - if ((prop = obj->properties->buckets[bucketIndex]) != 0) { - for ( ; prop; prop = prop->forw) { - cp = prop->name; - if (cp[0] == property[0] && strcmp(cp, property) == 0) { - break; - } - last = prop; - } - } - if (prop == (MprVar*) 0) { - mprAssert(prop); - return MPR_ERR_NOT_FOUND; - } - if (prop->readonly) { - mprAssert(! prop->readonly); - return MPR_ERR_READ_ONLY; - } - - if (obj->trigger) { - if ((obj->trigger)(MPR_VAR_DELETE_PROPERTY, obj->properties, prop, 0, 0) - == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - } - } - - if (last) { - last->forw = prop->forw; - } else { - obj->properties->buckets[bucketIndex] = prop->forw; - } - - obj->properties->numItems--; - if (! mprVarIsFunction(prop->type)) { - obj->properties->numDataItems--; - } - - mprDestroyVar(prop); - - return 0; -} - -/******************************************************************************/ -/* - * Find a property in an object and return a pointer to it. If a value arg - * is supplied, then copy the data into the var. - */ - -MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) -{ - MprVar *prop, triggerValue; - int rc; - - if (obj == 0 || obj->type != MPR_TYPE_OBJECT || property == 0 || - *property == '\0') { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - } - - for (prop = getObjChain(obj->properties, property); prop; - prop = prop->forw) { - if (prop->name && - prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { - break; - } - } - if (prop == 0) { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - } - if (value) { - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - /* - * Pass the trigger the current read value and may receive - * a new value. - */ - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, 0); - if (rc == MPR_TRIGGER_ABORT) { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - } - } - /* - * Clone. No copy. - */ - *value = *prop; - } - return prop; -} - -/******************************************************************************/ -/* - * Read a properties value. This returns the property's value. It does not - * copy object/string data but returns a pointer directly into the variable. - * The caller does not and should not call mprDestroy on the returned value. - * If value is null, just read the property and run triggers. - */ - -int mprReadProperty(MprVar *prop, MprVar *value) -{ - MprVar triggerValue; - int rc; - - mprAssert(prop); - - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, 0); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - } - if (value) { - *value = *prop; - - /* - * Just so that if the user calls mprDestroyVar on value, it will do no - * harm. - */ - value->allocatedVar = 0; - value->allocatedData = 0; - } - return 0; -} - -/******************************************************************************/ -/* - * Read a properties value. This returns a copy of the property variable. - * However, if the property is an object or string, it returns a copy of the - * reference to the underlying data. If copyDepth is set to MPR_DEEP_COPY, - * then the underlying objects and strings data will be copied as well. If - * copyDepth is set to MPR_SHALLOW_COPY, then only strings will be copied. If - * it is set to MPR_NO_COPY, then no data will be copied. In all cases, the - * user must call mprDestroyVar to free resources. This routine will run any - * registered triggers which may modify the value the user receives (without - * updating the properties real value). - * - * WARNING: the args are reversed to most other APIs. This conforms to the - * strcpy(dest, src) standard instead. - */ - -int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth) -{ - MprVar triggerValue; - int rc; - - mprAssert(prop); - mprAssert(dest); - - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, copyDepth); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(dest, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - } - mprCopyVar(dest, prop, copyDepth); - return 0; -} - -/******************************************************************************/ -/* - * Write a new value into an existing property in an object. - */ - -int mprWriteProperty(MprVar *vp, MprVar *value) -{ - MprVar triggerValue; - int rc; - - mprAssert(vp); - mprAssert(value); - - if (vp->readonly) { - return MPR_ERR_READ_ONLY; - } - - if (vp->trigger) { - triggerValue = *value; - - rc = (vp->trigger)(MPR_VAR_WRITE, vp->parentProperties, vp, - &triggerValue, 0); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(vp, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - /* Fall through */ - } - - copyVarCore(vp, value, MPR_SHALLOW_COPY); - return 0; -} - -/******************************************************************************/ -/* - * Write a new value into an existing property in an object. - */ - -int mprWritePropertyValue(MprVar *vp, MprVar value) -{ - mprAssert(vp); - - return mprWriteProperty(vp, &value); -} - -/******************************************************************************/ -/* - * Get the count of properties. - */ - -int mprGetPropertyCount(MprVar *vp, int includeFlags) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - return 0; - } - if (includeFlags == MPR_ENUM_DATA) { - return vp->properties->numDataItems; - } else { - return vp->properties->numItems; - } -} - -/******************************************************************************/ -/* - * Get the first property in an object. Used for walking all properties in an - * object. - */ - -MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags) -{ - MprVar *prop; - int i; - - mprAssert(obj); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - for (i = 0; i < (int) obj->properties->hashSize; i++) { - for (prop = obj->properties->buckets[i]; prop; prop = prop->forw) { - if (prop) { - if (mprVarIsFunction(prop->type)) { - if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { - continue; - } - } else { - if (!(includeFlags & MPR_ENUM_DATA)) { - continue; - } - } - return prop; - } - break; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Get the next property in sequence. - */ - -MprVar *mprGetNextProperty(MprVar *obj, MprVar *last, int includeFlags) -{ - MprProperties *properties; - int i; - - mprAssert(obj); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - properties = obj->properties; - - if (last->forw) { - return last->forw; - } - - for (i = last->bucketIndex + 1; i < (int) properties->hashSize; i++) { - for (last = properties->buckets[i]; last; last = last->forw) { - if (mprVarIsFunction(last->type)) { - if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { - continue; - } - } else { - if (!(includeFlags & MPR_ENUM_DATA)) { - continue; - } - } - return last; - } - } - return 0; -} - -/******************************************************************************/ -/************************** Internal Support Routines *************************/ -/******************************************************************************/ -/* - * Create an hash table to hold and index properties. Properties are just - * variables which may contain primitive data types, functions or other - * objects. The hash table is the essence of an object. HashSize specifies - * the size of the hash table to use and should be a prime number. - */ - -static MprProperties *createProperties(const char *name, int hashSize) -{ - MprProperties *pp; - - if (hashSize < 7) { - hashSize = 7; - } - if ((pp = (MprProperties*) mprMalloc(sizeof(MprProperties))) == NULL) { - mprAssert(0); - return 0; - } - mprAssert(pp); - memset(pp, 0, sizeof(MprProperties)); - - pp->numItems = 0; - pp->numDataItems = 0; - pp->hashSize = hashSize; - pp->buckets = (MprVar**) mprMalloc(pp->hashSize * sizeof(MprVar*)); - mprAssert(pp->buckets); - memset(pp->buckets, 0, pp->hashSize * sizeof(MprVar*)); - pp->refCount = 1; - -#if VAR_DEBUG - if (objectCount == -1) { - objectCount = 0; - objectList.next = objectList.prev = &objectList; - } - - mprStrcpy(pp->name, sizeof(pp->name), name); - pp->next = &objectList; - pp->prev = objectList.prev; - objectList.prev->next = pp; - objectList.prev = pp; - objectCount++; -#endif - return pp; -} - -/******************************************************************************/ -/* - * Release an object's properties hash table. If this is the last person - * using it, free it. Return TRUE if the object is released. - */ - -static bool releaseProperties(MprProperties *obj, int force) -{ - MprProperties *pp; - MprVar *prop, *forw; - int i; - - mprAssert(obj); - mprAssert(obj->refCount > 0); - -#if VAR_DEBUG - /* - * Debug sanity check - */ - mprAssert(obj->refCount < 20); -#endif - - if (--obj->refCount > 0 && !force) { - return 0; - } - -#if VAR_DEBUG - mprAssert(obj->prev); - mprAssert(obj->next); - mprAssert(obj->next->prev); - mprAssert(obj->prev->next); - obj->next->prev = obj->prev; - obj->prev->next = obj->next; - objectCount--; -#endif - - for (i = 0; i < (int) obj->hashSize; i++) { - for (prop = obj->buckets[i]; prop; prop = forw) { - forw = prop->forw; - if (prop->type == MPR_TYPE_OBJECT) { - - if (prop->properties == obj) { - /* Self reference */ - continue; - } - pp = prop->properties; - if (pp->visited) { - continue; - } - - pp->visited = 1; - if (! freeVar(prop, pp->deleteProtect ? 0 : force)) { - pp->visited = 0; - } - - } else { - freeVar(prop, force); - } - } - } - - mprFree((void*) obj->buckets); - mprFree((void*) obj); - - return 1; -} - -/******************************************************************************/ -/* - * Adjust the reference count - */ - -static int adjustRefCount(MprProperties *pp, int adj) -{ - mprAssert(pp); - - /* - * Debug sanity check - */ - mprAssert(pp->refCount < 20); - - return pp->refCount += adj; -} - -/******************************************************************************/ -#if VAR_DEBUG -/* - * Print objects held - */ - -void mprPrintObjects(char *msg) -{ - MprProperties *pp, *np; - MprVar *prop, *forw; - char *buf; - int i; - - mprLog(7, "%s: Object Store. %d objects.\n", msg, objectCount); - pp = objectList.next; - while (pp != &objectList) { - mprLog(7, "%s: 0x%x, refCount %d, properties %d\n", - pp->name, pp, pp->refCount, pp->numItems); - for (i = 0; i < (int) pp->hashSize; i++) { - for (prop = pp->buckets[i]; prop; prop = forw) { - forw = prop->forw; - if (prop->properties == pp) { - /* Self reference */ - continue; - } - mprVarToString(&buf, MPR_MAX_STRING, 0, prop); - if (prop->type == MPR_TYPE_OBJECT) { - np = objectList.next; - while (np != &objectList) { - if (prop->properties == np) { - break; - } - np = np->next; - } - if (prop->properties == np) { - mprLog(7, " %s: OBJECT 0x%x, <%s>\n", - prop->name, prop->properties, prop->fullName); - } else { - mprLog(7, " %s: OBJECT NOT FOUND, %s <%s>\n", - prop->name, buf, prop->fullName); - } - } else { - mprLog(7, " %s: <%s> = %s\n", prop->name, - prop->fullName, buf); - } - mprFree(buf); - } - } - pp = pp->next; - } -} - -/******************************************************************************/ - -void mprPrintObjRefCount(MprVar *vp) -{ - mprLog(7, "OBJECT 0x%x, refCount %d\n", vp->properties, - vp->properties->refCount); -} - -#endif -/******************************************************************************/ -/* - * Get the bucket chain containing a property. - */ - -static MprVar *getObjChain(MprProperties *obj, const char *property) -{ - mprAssert(obj); - - return obj->buckets[hash(obj, property)]; -} - -/******************************************************************************/ -/* - * Fast hash. The history of this algorithm is part of lost computer science - * folk lore. - */ - -static int hash(MprProperties *pp, const char *property) -{ - uint sum; - - mprAssert(pp); - mprAssert(property); - - sum = 0; - while (*property) { - sum += (sum * 33) + *property++; - } - - return sum % pp->hashSize; -} - -/******************************************************************************/ -/*********************************** Constructors *****************************/ -/******************************************************************************/ -/* - * Initialize an undefined value. - */ - -MprVar mprCreateUndefinedVar() -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_UNDEFINED; - return v; -} - -/******************************************************************************/ -/* - * Initialize an null value. - */ - -MprVar mprCreateNullVar() -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_NULL; - return v; -} - -/******************************************************************************/ - -MprVar mprCreateBoolVar(bool value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_BOOL; - v.boolean = value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a C function. - */ - -MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_CFUNCTION; - v.cFunction.fn = fn; - v.cFunction.thisPtr = thisPtr; - v.flags = flags; - - return v; -} - -/******************************************************************************/ -/* - * Initialize a C function. - */ - -MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, - int flags) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_STRING_CFUNCTION; - v.cFunctionWithStrings.fn = fn; - v.cFunctionWithStrings.thisPtr = thisPtr; - v.flags = flags; - - return v; -} - -/******************************************************************************/ -/* - * Initialize an opaque pointer. - */ - -MprVar mprCreatePtrVar(void *ptr) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_PTR; - v.ptr = ptr; - - return v; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Initialize a floating value. - */ - -MprVar mprCreateFloatVar(double value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_FLOAT; - v.floating = value; - return v; -} - -#endif -/******************************************************************************/ -/* - * Initialize an integer value. - */ - -MprVar mprCreateIntegerVar(int value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_INT; - v.integer = value; - return v; -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Initialize a 64-bit integer value. - */ - -MprVar mprCreateInteger64Var(int64 value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_INT64; - v.integer64 = value; - return v; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Initialize an number variable. Type is defined by configure. - */ - -MprVar mprCreateNumberVar(MprNum value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = BLD_FEATURE_NUM_TYPE_ID; -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - v.integer64 = value; -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - v.float = value; -#else - v.integer = value; -#endif - return v; -} - -/******************************************************************************/ -/* - * Initialize a (bare) JavaScript function. args and body can be null. - */ - -MprVar mprCreateFunctionVar(char *args, char *body, int flags) -{ - MprVar v; - char *cp, *arg, *last; - int aid; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_FUNCTION; - v.flags = flags; - - v.function.args = mprCreateArray(); - - if (args) { - args = mprStrdup(args); - arg = mprStrTok(args, ",", &last); - while (arg) { - while (isspace((int) *arg)) - arg++; - for (cp = &arg[strlen(arg) - 1]; cp > arg; cp--) { - if (!isspace((int) *cp)) { - break; - } - } - cp[1] = '\0'; - - aid = mprAddToArray(v.function.args, mprStrdup(arg)); - arg = mprStrTok(0, ",", &last); - } - mprFree(args); - } - - if (body) { - v.function.body = mprStrdup(body); - } - v.allocatedData = 1; - return v; -} - -/******************************************************************************/ -/* - * Initialize an object variable. Return type == MPR_TYPE_UNDEFINED if the - * memory allocation for the properties table failed. - */ - -MprVar mprCreateObjVar(const char *name, int hashSize) -{ - MprVar v; - - mprAssert(name && *name); - - memset(&v, 0x0, sizeof(MprVar)); - v.type = MPR_TYPE_OBJECT; - if (hashSize <= 0) { - hashSize = MPR_DEFAULT_HASH_SIZE; - } - v.properties = createProperties(name, hashSize); - if (v.properties == 0) { - /* Indicate failed memory allocation */ - v.type = MPR_TYPE_UNDEFINED; - } - v.allocatedData = 1; - v.name = mprStrdup(name); - mprLog(7, "mprCreateObjVar %s, 0x%p\n", name, v.properties); - return v; -} - -/******************************************************************************/ -/* - * Initialize a string value. - */ - -MprVar mprCreateStringVar(const char *value, bool allocate) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_STRING; - if (value == 0) { - v.string = (char*) ""; - } else if (allocate) { - v.string = mprStrdup(value); - v.allocatedData = 1; - } else { - v.string = (char*) value; - } - return v; -} - -/******************************************************************************/ -/* - * Copy an objects core value (only). This preserves the destination object's - * name. This implements copy by reference for objects and copy by value for - * strings and other types. Caller must free dest prior to calling. - */ - -static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) -{ - MprVarTrigger saveTrigger; - MprVar *srcProp, *destProp, *last; - char **srcArgs; - int i; - - mprAssert(dest); - mprAssert(src); - - if (dest == src) { - return; - } - - /* - * FUTURE: we should allow read-only triggers where the value is never - * stored in the object. Currently, triggers override the readonly - * status. - */ - - if (dest->type != MPR_TYPE_UNDEFINED && dest->readonly && !dest->trigger) { - mprAssert(0); - return; - } - - if (dest->type != MPR_TYPE_UNDEFINED) { - saveTrigger = dest->trigger; - freeVarStorage(dest, 0); - } else { - saveTrigger = 0; - } - - switch (src->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - break; - - case MPR_TYPE_BOOL: - dest->boolean = src->boolean; - break; - - case MPR_TYPE_PTR: - /* we have to reference here so talloc structures survive a - copy */ - if (src->allocatedData) { - dest->ptr = talloc_reference(mprMemCtx(), src->ptr); - dest->allocatedData = 1; - } else { - dest->ptr = src->ptr; - } - break; - - case MPR_TYPE_STRING_CFUNCTION: - dest->cFunctionWithStrings = src->cFunctionWithStrings; - break; - - case MPR_TYPE_CFUNCTION: - dest->cFunction = src->cFunction; - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - dest->floating = src->floating; - break; -#endif - - case MPR_TYPE_INT: - dest->integer = src->integer; - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - dest->integer64 = src->integer64; - break; -#endif - - case MPR_TYPE_OBJECT: - if (copyDepth == MPR_DEEP_COPY) { - - dest->properties = createProperties(src->name, - src->properties->hashSize); - dest->allocatedData = 1; - - for (i = 0; i < (int) src->properties->hashSize; i++) { - last = 0; - for (srcProp = src->properties->buckets[i]; srcProp; - srcProp = srcProp->forw) { - if (srcProp->visited) { - continue; - } - destProp = allocProperty(srcProp->name); - if (destProp == 0) { - mprAssert(destProp); - return; - } - - destProp->bucketIndex = i; - if (last) { - last->forw = destProp; - } else { - dest->properties->buckets[i] = destProp; - } - destProp->parentProperties = dest->properties; - - /* - * Recursively copy the object - */ - srcProp->visited = 1; - copyVarCore(destProp, srcProp, copyDepth); - srcProp->visited = 0; - last = destProp; - } - } - dest->properties->numItems = src->properties->numItems; - dest->properties->numDataItems = src->properties->numDataItems; - dest->allocatedData = 1; - - } else if (copyDepth == MPR_SHALLOW_COPY) { - dest->properties = src->properties; - adjustVarRefCount(src, 1); - dest->allocatedData = 1; - - } else { - dest->properties = src->properties; - dest->allocatedData = 0; - } - break; - - case MPR_TYPE_FUNCTION: - if (copyDepth != MPR_NO_COPY) { - dest->function.args = mprCreateArray(); - srcArgs = (char**) src->function.args->handles; - for (i = 0; i < src->function.args->max; i++) { - if (srcArgs[i]) { - mprAddToArray(dest->function.args, mprStrdup(srcArgs[i])); - } - } - dest->function.body = mprStrdup(src->function.body); - dest->allocatedData = 1; - } else { - dest->function.args = src->function.args; - dest->function.body = src->function.body; - dest->allocatedData = 0; - } - break; - - case MPR_TYPE_STRING: - if (src->string && copyDepth != MPR_NO_COPY) { - dest->string = mprStrdup(src->string); - dest->allocatedData = 1; - } else { - dest->string = src->string; - dest->allocatedData = 0; - } - break; - } - - dest->type = src->type; - dest->flags = src->flags; - dest->trigger = saveTrigger; - - /* - * Just for safety - */ - dest->spare = 0; -} - -/******************************************************************************/ -/* - * Copy an entire object including name. - */ - -void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth) -{ - mprAssert(dest); - mprAssert(src); - - copyVarCore(dest, src, copyDepth); - - mprFree(dest->name); - dest->name = mprStrdup(src->name); - -#if VAR_DEBUG - if (src->type == MPR_TYPE_OBJECT) { - - mprFree(dest->fullName); - dest->fullName = mprStrdup(src->fullName); - - mprLog(7, "mprCopyVar: object \"%s\", FDQ \"%s\" 0x%x, refCount %d\n", - dest->name, dest->fullName, dest->properties, - dest->properties->refCount); - } -#endif -} - -/******************************************************************************/ -/* - * Copy an entire object including name. - */ - -void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth) -{ - mprAssert(dest); - - mprCopyVar(dest, &src, copyDepth); -} - -/******************************************************************************/ -/* - * Copy an object. This implements copy by reference for objects and copy by - * value for strings and other types. Caller must free dest prior to calling. - */ - -MprVar *mprDupVar(MprVar *src, int copyDepth) -{ - MprVar *dest; - - mprAssert(src); - - dest = (MprVar*) mprMalloc(sizeof(MprVar)); - memset(dest, 0, sizeof(MprVar)); - - mprCopyVar(dest, src, copyDepth); - return dest; -} - -/******************************************************************************/ -/* - * Convert a value to a text based representation of its value - * FUTURE -- conver this to use the format string in all cases. Allow - * arbitrary format strings. - */ - -void mprVarToString(char** out, int size, char *fmt, MprVar *obj) -{ - char *src; - - mprAssert(out); - - *out = NULL; - - if (obj->trigger) { - mprReadProperty(obj, 0); - } - - switch (obj->type) { - case MPR_TYPE_UNDEFINED: - /* FUTURE -- spec says convert to "undefined" */ - *out = mprStrdup(""); - break; - - case MPR_TYPE_NULL: - *out = mprStrdup("null"); - break; - - case MPR_TYPE_PTR: - mprAllocSprintf(out, size, "[Opaque Pointer %p]", obj->ptr); - break; - - case MPR_TYPE_BOOL: - if (obj->boolean) { - *out = mprStrdup("true"); - } else { - *out = mprStrdup("false"); - } - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (fmt == NULL || *fmt == '\0') { - mprAllocSprintf(out, size, "%f", obj->floating); - } else { - mprAllocSprintf(out, size, fmt, obj->floating); - } - break; -#endif - - case MPR_TYPE_INT: - if (fmt == NULL || *fmt == '\0') { - mprAllocSprintf(out, size, "%d", obj->integer); - } else { - mprAllocSprintf(out, size, fmt, obj->integer); - } - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - if (fmt == NULL || *fmt == '\0') { -#if BLD_GOAHEAD_WEBSERVER - mprAllocSprintf(out, size, "%d", (int) obj->integer64); -#else - mprAllocSprintf(out, size, "%lld", (long long)obj->integer64); -#endif - } else { - mprAllocSprintf(out, size, fmt, obj->integer64); - } - break; -#endif - - case MPR_TYPE_CFUNCTION: - mprAllocSprintf(out, size, "[C Function]"); - break; - - case MPR_TYPE_STRING_CFUNCTION: - mprAllocSprintf(out, size, "[C StringFunction]"); - break; - - case MPR_TYPE_FUNCTION: - mprAllocSprintf(out, size, "[JavaScript Function]"); - break; - - case MPR_TYPE_OBJECT: - /* FUTURE -- really want: [object class: name] */ - mprAllocSprintf(out, size, "[object %s]", obj->name); - break; - - case MPR_TYPE_STRING: - src = obj->string; - - mprAssert(src); - if (fmt && *fmt) { - mprAllocSprintf(out, size, fmt, src); - - } else if (src == NULL) { - *out = mprStrdup("null"); - - } else { - *out = mprStrdup(src); - } - break; - - default: - mprAssert(0); - } -} - -/******************************************************************************/ -/* - * Parse a string based on formatting instructions and intelligently - * create a variable. - */ - -MprVar mprParseVar(char *buf, MprType preferredType) -{ - MprType type; - char *cp; - - mprAssert(buf); - - type = preferredType; - - if (preferredType == MPR_TYPE_UNDEFINED) { - if (*buf == '-') { - type = MPR_NUM_VAR; - - } else if (!isdigit((int) *buf)) { - if (strcmp(buf, "true") == 0 || strcmp(buf, "false") == 0) { - type = MPR_TYPE_BOOL; - } else { - type = MPR_TYPE_STRING; - } - - } else if (isdigit((int) *buf)) { - type = MPR_NUM_VAR; - cp = buf; - if (*cp && tolower(cp[1]) == 'x') { - cp = &cp[2]; - } - for (cp = buf; *cp; cp++) { - if (! isdigit((int) *cp)) { - break; - } - } - - if (*cp != '\0') { -#if BLD_FEATURE_FLOATING_POINT - if (*cp == '.' || tolower(*cp) == 'e') { - type = MPR_TYPE_FLOAT; - } else -#endif - { - type = MPR_NUM_VAR; - } - } - } - } - - switch (type) { - case MPR_TYPE_OBJECT: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_PTR: - default: - break; - - case MPR_TYPE_BOOL: - return mprCreateBoolVar(buf[0] == 't' ? 1 : 0); - - case MPR_TYPE_INT: - return mprCreateIntegerVar(mprParseInteger(buf)); - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return mprCreateInteger64Var(mprParseInteger64(buf)); -#endif - - case MPR_TYPE_STRING: - if (strcmp(buf, "null") == 0) { - return mprCreateNullVar(); - } else if (strcmp(buf, "undefined") == 0) { - return mprCreateUndefinedVar(); - } - - return mprCreateStringVar(buf, 1); - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - return mprCreateFloatVar(atof(buf)); -#endif - - } - return mprCreateUndefinedVar(); -} - -/******************************************************************************/ -/* - * Convert the variable to a boolean. Only for primitive types. - */ - -bool mprVarToBool(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - return 0; - - case MPR_TYPE_PTR: - return (vp->ptr != NULL); - - case MPR_TYPE_BOOL: - return vp->boolean; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - return (vp->floating != 0 && !mprIsNan(vp->floating)); -#endif - - case MPR_TYPE_INT: - return (vp->integer != 0); - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (vp->integer64 != 0); -#endif - - case MPR_TYPE_STRING: - mprAssert(vp->string); - return (vp->string[0] != '\0'); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the variable to a floating point number. Only for primitive types. - */ - -double mprVarToFloat(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1.0 : 0.0; - - case MPR_TYPE_FLOAT: - return vp->floating; - - case MPR_TYPE_INT: - return (double) vp->integer; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (double) vp->integer64; -#endif - - case MPR_TYPE_STRING: - mprAssert(vp->string); - return atof(vp->string); - } - - /* Not reached */ - return 0; -} - -#endif -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -MprNum mprVarToNumber(const MprVar *vp) -{ -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - return mprVarToInteger64(vp); -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - return mprVarToFloat(vp); -#else - return mprVarToInteger(vp); -#endif -} - -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -MprNum mprParseNumber(char *s) -{ -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - return mprParseInteger64(s); -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - return mprParseFloat(s); -#else - return mprParseInteger(s); -#endif -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Convert the variable to an Integer64 type. Only works for primitive types. - */ - -int64 mprVarToInteger64(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (mprIsNan(vp->floating)) { - return 0; - } - return (int64) vp->floating; -#endif - - case MPR_TYPE_INT: - return vp->integer; - - case MPR_TYPE_INT64: - return vp->integer64; - - case MPR_TYPE_STRING: - return mprParseInteger64(vp->string); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -/* - * Convert the string buffer to an Integer64. - */ - -int64 mprParseInteger64(char *str) -{ - char *cp; - int64 num64; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num64 = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num64 = (*cp - '0') + (num64 * 10); - cp++; - } - } else { - cp++; - if (tolower(*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower(*cp); - if (isdigit(c)) { - num64 = (c - '0') + (num64 * radix); - } else if (c >= 'a' && c <= 'f') { - num64 = (c - ('a' - 10)) + (num64 * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower(*cp); - if (isdigit(c) && c < '8') { - num64 = (c - '0') + (num64 * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num64; - } - return num64; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Convert the variable to an Integer type. Only works for primitive types. - */ - -int mprVarToInteger(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (mprIsNan(vp->floating)) { - return 0; - } - return (int) vp->floating; -#endif - - case MPR_TYPE_INT: - return vp->integer; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (int) vp->integer64; -#endif - - case MPR_TYPE_STRING: - return mprParseInteger(vp->string); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -/* - * Convert the string buffer to an Integer. - */ - -int mprParseInteger(char *str) -{ - char *cp; - int num; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num = (*cp - '0') + (num * 10); - cp++; - } - } else { - cp++; - if (tolower(*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower(*cp); - if (isdigit(c)) { - num = (c - '0') + (num * radix); - } else if (c >= 'a' && c <= 'f') { - num = (c - ('a' - 10)) + (num * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower(*cp); - if (isdigit(c) && c < '8') { - num = (c - '0') + (num * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num; - } - return num; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the string buffer to an Floating. - */ - -double mprParseFloat(char *str) -{ - return atof(str); -} - -/******************************************************************************/ - -bool mprIsNan(double f) -{ -#if WIN - return _isnan(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#elif defined(FP_NAN) - return (f == FP_NAN); -#else - return 0; -#endif -} -/******************************************************************************/ - -bool mprIsInfinite(double f) -{ -#if WIN - return !_finite(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#elif defined(FP_INFINITE) - return (f == FP_INFINITE); -#else - return 0; -#endif -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ - -/* - * 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 - */ diff --git a/source4/lib/appweb/mpr/var.h b/source4/lib/appweb/mpr/var.h deleted file mode 100644 index 98313c0476..0000000000 --- a/source4/lib/appweb/mpr/var.h +++ /dev/null @@ -1,487 +0,0 @@ -/* - * @file var.h - * @brief MPR Universal Variable Type - * @copy default.m - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. 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 - */ - -/******************************* Documentation ********************************/ -/* - * Variables can efficiently store primitive types and can hold references to - * objects. Objects can store properties which are themselves variables. - * Properties can be primitive data types, other objects or functions. - * Properties are indexed by a character name. A variable may store one of - * the following types: - * - * string, integer, integer-64bit, C function, C function with string args, - * Javascript function, Floating point number, boolean value, Undefined - * value and the Null value. - * - * Variables have names while objects may be referenced by multiple variables. - * Objects use reference counting for garbage collection. - * - * This module is not thread safe for performance and compactness. It relies - * on upper modules to provide thread synchronization as required. The API - * provides primitives to get variable/object references or to get copies of - * variables which will help minimize required lock times. - */ - -#ifndef _h_MPR_VAR -#define _h_MPR_VAR 1 - -/********************************* Includes ***********************************/ - -#include "miniMpr.h" - -/********************************** Defines ***********************************/ - -/* - * Define VAR_DEBUG if you want to track objects. However, this code is not - * thread safe and you need to run the server single threaded. - * - * #define VAR_DEBUG 1 - */ - -#ifdef __cplusplus -extern "C" { -#endif -/* - * Forward declare types - */ -struct MprProperties; -struct MprVar; - -/* - * Possible variable types. Don't use enum because we need to be able to - * do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID. - */ -typedef int MprType; -#define MPR_TYPE_UNDEFINED 0 /* Undefined. No value has been set. */ -#define MPR_TYPE_NULL 1 /* Value defined to be null. */ -#define MPR_TYPE_BOOL 2 /* Boolean type. */ -#define MPR_TYPE_CFUNCTION 3 /* C function or C++ method */ -#define MPR_TYPE_FLOAT 4 /* Floating point number */ -#define MPR_TYPE_INT 5 /* Integer number */ -#define MPR_TYPE_INT64 6 /* 64-bit Integer number */ -#define MPR_TYPE_OBJECT 7 /* Object reference */ -#define MPR_TYPE_FUNCTION 8 /* JavaScript function */ -#define MPR_TYPE_STRING 9 /* String (immutable) */ -#define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ -#define MPR_TYPE_PTR 11 /* Opaque pointer */ - -/* - * Create a type for the default number type - * Config.h will define the default number type. For example: - * - * BLD_FEATURE_NUM_TYPE=int - * BLD_FEATURE_NUM_TYPE_ID=MPR_TYPE_INT - */ - -/** - * Set to the type used for MPR numeric variables. Will equate to int, int64 - * or double. - */ -typedef BLD_FEATURE_NUM_TYPE MprNum; - -/** - * Set to the MPR_TYPE used for MPR numeric variables. Will equate to - * MPR_TYPE_INT, MPR_TYPE_INT64 or MPR_TYPE_FLOAT. - */ -#define MPR_NUM_VAR BLD_FEATURE_NUM_TYPE_ID -#define MPR_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID - -/* - * Return TRUE if a variable is a function type - */ -#define mprVarIsFunction(type) \ - (type == MPR_TYPE_FUNCTION || type == MPR_TYPE_STRING_CFUNCTION || \ - type == MPR_TYPE_CFUNCTION) - -/* - * Return TRUE if a variable is a numeric type - */ -#define mprVarIsNumber(type) \ - (type == MPR_TYPE_INT || type == MPR_TYPE_INT64 || type == MPR_TYPE_FLOAT) - -/* - * Return TRUE if a variable is a boolean - */ -#define mprVarIsBoolean(type) \ - (type == MPR_TYPE_BOOL) -#define mprVarIsString(type) \ - (type == MPR_TYPE_STRING) -#define mprVarIsObject(type) \ - (type == MPR_TYPE_OBJECT) -#define mprVarIsFloating(type) \ - (type == MPR_TYPE_FLOAT) -#define mprVarIsPtr(type) \ - (type == MPR_TYPE_PTR) -#define mprVarIsUndefined(var) \ - ((var)->type == MPR_TYPE_UNDEFINED) -#define mprVarIsNull(var) \ - ((var)->type == MPR_TYPE_NULL) -#define mprVarIsValid(var) \ - (((var)->type != MPR_TYPE_NULL) && ((var)->type != MPR_TYPE_UNDEFINED)) - -#define MPR_VAR_MAX_RECURSE 5 /* Max object loops */ - -#if BLD_FEATURE_SQUEEZE -#define MPR_MAX_VAR 64 /* Max var full name */ -#else -#define MPR_MAX_VAR 512 -#endif - -/* - * Function signatures - */ -typedef int MprVarHandle; -typedef int (*MprCFunction)(MprVarHandle userHandle, int argc, - struct MprVar **argv); -typedef int (*MprStringCFunction)(MprVarHandle userHandle, int argc, - char **argv); - -/* - * Triggers - */ -typedef enum { - MPR_VAR_WRITE, /* This property is being updated */ - MPR_VAR_READ, /* This property is being read */ - MPR_VAR_CREATE_PROPERTY, /* A property is being created */ - MPR_VAR_DELETE_PROPERTY, /* A property is being deleted */ - MPR_VAR_DELETE /* This object is being deleted */ -} MprVarTriggerOp; - -/* - * Trigger function return codes. - */ -typedef enum { - MPR_TRIGGER_ABORT, /* Abort the current operation */ - MPR_TRIGGER_USE_NEW_VALUE, /* Proceed and use the newValue */ - MPR_TRIGGER_PROCEED /* Proceed with the operation */ -} MprVarTriggerStatus; - -/* - * The MprVarTrigger arguments have the following meaning: - * - * op The operation being performed. See MprVarTriggerOp. - * parentProperties Pointer to the MprProperties structure. - * vp Pointer to the property that registered the trigger. - * newValue New value (see below for more details). - * copyDepth Specify what data items to copy. - * - * For VAR_READ, newVar is set to a temporary variable that the trigger - * function may assign a value to be returned instead of the actual - * property value. - * For VAR_WRITE, newValue holds the new value. The old existing value may be - * accessed via vp. - * For DELETE_PROPERTY, vp is the property being deleted. newValue is null. - * For ADD_PROPERTY, vp is set to the property being added and newValue holds - * the new value. - */ -typedef MprVarTriggerStatus (*MprVarTrigger)(MprVarTriggerOp op, - struct MprProperties *parentProperties, struct MprVar *vp, - struct MprVar *newValue, int copyDepth); - -/* - * mprCreateFunctionVar flags - */ -/** Use the alternate handle on function callbacks */ -#define MPR_VAR_ALT_HANDLE 0x1 - -/** Use the script handle on function callbacks */ -#define MPR_VAR_SCRIPT_HANDLE 0x2 - -/* - * Useful define for the copyDepth argument - */ -/** Don't copy any data. Copy only the variable name */ -#define MPR_NO_COPY 0 - -/** Copy strings. Increment object reference counts. */ -#define MPR_SHALLOW_COPY 1 - -/** Copy strings and do complete object copies. */ -#define MPR_DEEP_COPY 2 - -/* - * GetFirst / GetNext flags - */ -/** Step into data properties. */ -#define MPR_ENUM_DATA 0x1 - -/** Step into functions properties. */ -#define MPR_ENUM_FUNCTIONS 0x2 - -/* - * Collection type to hold properties in an object - */ -typedef struct MprProperties { /* Collection of properties */ -#if VAR_DEBUG - struct MprProperties *next; /* Linked list */ - struct MprProperties *prev; /* Linked list */ - char name[32]; /* Debug name */ -#endif - struct MprVar **buckets; /* Hash chains */ - int numItems; /* Total count of items */ - /* FUTURE - Better way of doing this */ - int numDataItems; /* Enumerable data items */ - uint hashSize : 8; /* Size of the hash table */ - /* FUTURE -- increase size of refCount */ - uint refCount : 8; /* References to this property*/ - /* FUTURE - make these flags */ - uint deleteProtect : 8; /* Don't recursively delete */ - uint visited : 8; /* Node has been processed */ -} MprProperties; - -/* - * Universal Variable Type - */ -typedef struct MprVar { - /* FUTURE - remove name to outside reference */ - MprStr name; /* Property name */ - /* FUTURE - remove */ - MprStr fullName; /* Full object name */ - /* FUTURE - make part of the union */ - MprProperties *properties; /* Pointer to properties */ - - /* - * Packed bit field - */ - MprType type : 8; /* Selector into union */ - uint bucketIndex : 8; /* Copy of bucket index */ - - uint flags : 5; /* Type specific flags */ - uint allocatedData : 1; /* Data needs freeing */ - uint readonly : 1; /* Unmodifiable */ - uint deleteProtect : 1; /* Don't recursively delete */ - - uint visited : 1; /* Node has been processed */ - uint allocatedVar : 1; /* Var needs freeing */ - uint spare : 6; /* Unused */ - - struct MprVar *forw; /* Hash table linkage */ - MprVarTrigger trigger; /* Trigger function */ - -#if UNUSED && KEEP - struct MprVar *baseClass; /* Pointer to class object */ -#endif - MprProperties *parentProperties; /* Pointer to parent object */ - - /* - * Union of primitive types. When debugging on Linux, don't use unions - * as the gdb debugger can't display them. - */ -#if 0 && !BLD_DEBUG && !LINUX && !VXWORKS - union { -#endif - bool boolean; -#if BLD_FEATURE_FLOATING_POINT - double floating; -#endif - int integer; -#if BLD_FEATURE_INT64 - int64 integer64; -#endif - struct { /* Javascript functions */ - MprArray *args; /* Null terminated */ - char *body; - } function; - struct { /* Function with MprVar args */ - MprCFunction fn; - void *thisPtr; - } cFunction; - struct { /* Function with string args */ - MprStringCFunction fn; - void *thisPtr; - } cFunctionWithStrings; - MprStr string; /* Allocated string */ - void *ptr; /* Opaque pointer */ -#if 0 && !BLD_DEBUG && !LINUX && !VXWORKS - }; -#endif -} MprVar; - -/* - * Define a field macro so code an use numbers in a "generic" fashion. - */ -#if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN -/* Default numeric type */ -#define mprNumber integer -#endif -#if MPR_NUM_VAR == MPR_TYPE_INT64 -/* Default numeric type */ -#define mprNumber integer64 -#endif -#if MPR_NUM_VAR == MPR_TYPE_FLOAT -/* Default numeric type */ -#define mprNumber floating -#endif - -typedef BLD_FEATURE_NUM_TYPE MprNumber; - -/********************************* Prototypes *********************************/ -/* - * Variable constructors and destructors - */ -extern MprVar mprCreateObjVar(const char *name, int hashSize); -extern MprVar mprCreateBoolVar(bool value); -extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, - int flags); -#if BLD_FEATURE_FLOATING_POINT -extern MprVar mprCreateFloatVar(double value); -#endif -extern MprVar mprCreateIntegerVar(int value); -#if BLD_FEATURE_INT64 -extern MprVar mprCreateInteger64Var(int64 value); -#endif -extern MprVar mprCreateFunctionVar(char *args, char *body, int flags); -extern MprVar mprCreateNullVar(void); -extern MprVar mprCreateNumberVar(MprNumber value); -extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, - void *thisPtr, int flags); -extern MprVar mprCreateStringVar(const char *value, bool allocate); -extern MprVar mprCreateUndefinedVar(void); -extern MprVar mprCreatePtrVar(void *ptr); -extern bool mprDestroyVar(MprVar *vp); -extern bool mprDestroyAllVars(MprVar* vp); -extern MprType mprGetVarType(MprVar *vp); - -/* - * Copy - */ -extern void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth); -extern void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth); -extern MprVar *mprDupVar(MprVar *src, int copyDepth); - -/* - * Manage vars - */ -extern MprVarTrigger - mprAddVarTrigger(MprVar *vp, MprVarTrigger fn); -extern int mprGetVarRefCount(MprVar *vp); -extern void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect); -extern void mprSetVarFullName(MprVar *vp, char *name); -extern void mprSetVarReadonly(MprVar *vp, int readonly); -extern void mprSetVarName(MprVar *vp, char *name); - -/* - * Create properties and return a reference to the property. - */ -extern MprVar *mprCreateProperty(MprVar *obj, const char *property, - MprVar *newValue); -extern MprVar *mprCreatePropertyValue(MprVar *obj, const char *property, - MprVar newValue); -extern int mprDeleteProperty(MprVar *obj, const char *property); - -/* - * Get/Set properties. Set will update/create. - */ -extern MprVar *mprGetProperty(MprVar *obj, const char *property, - MprVar *value); -extern MprVar *mprSetProperty(MprVar *obj, const char *property, - MprVar *value); -extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, - MprVar value); - -/* - * Directly read/write property values (the property must already exist) - * For mprCopyProperty, mprDestroyVar must always called on the var. - */ -extern int mprReadProperty(MprVar *prop, MprVar *value); -extern int mprWriteProperty(MprVar *prop, MprVar *newValue); -extern int mprWritePropertyValue(MprVar *prop, MprVar newValue); - -/* - * Copy a property. NOTE: reverse of most other args: (dest, src) - */ -extern int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth); - -/* - * Enumerate properties - */ -extern MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags); -extern MprVar *mprGetNextProperty(MprVar *obj, MprVar *currentProperty, - int includeFlags); - -/* - * Query properties characteristics - */ -extern int mprGetPropertyCount(MprVar *obj, int includeFlags); - -/* - * Conversion routines - */ -extern MprVar mprParseVar(char *str, MprType prefType); -extern MprNum mprVarToNumber(const MprVar *vp); -extern int mprVarToInteger(const MprVar *vp); -#if BLD_FEATURE_INT64 -extern int64 mprVarToInteger64(const MprVar *vp); -#endif -extern bool mprVarToBool(const MprVar *vp); -#if BLD_FEATURE_FLOATING_POINT -extern double mprVarToFloat(const MprVar *vp); -#endif -extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp); - -/* - * Parsing and utility routines - */ -extern MprNum mprParseNumber(char *str); -extern int mprParseInteger(char *str); - -#if BLD_FEATURE_INT64 -extern int64 mprParseInteger64(char *str); -#endif - -#if BLD_FEATURE_FLOATING_POINT -extern double mprParseFloat(char *str); -extern bool mprIsInfinite(double f); -extern bool mprIsNan(double f); -#endif - -#if VAR_DEBUG -extern void mprPrintObjects(char *msg); -extern void mprPrintObjRefCount(MprVar *vp); -#endif - -#ifdef __cplusplus -} -#endif - -/*****************************************************************************/ -#endif /* _h_MPR_VAR */ - -/* - * 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 - */ |