📄 ejsvar.c
字号:
/** * @file ejsVar.c * @brief Mbedthis Portable Runtime Universal Variable Type *//* * @copy default * * Copyright (c) Mbedthis Software LLC, 2003-2006. 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 methods. * Properties are indexed by a character name. *//********************************** Includes **********************************/#include "ejs.h"/***************************** Forward Declarations ***************************/static EjsProperty *allocProperty(Ejs *ep, EjsVar *op, const char *property, int propertyIndex, EjsProperty *last);static EjsVar *copyVar(EJS_LOC_DEC(ep, loc), EjsVar *dest, const EjsVar *src, EjsCopyDepth copyDepth);static EjsObj *createObj(EJS_LOC_DEC(ep, loc));static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen);static int hash(const char *property);static void unlinkProperty(EjsObj *obj, EjsPropLink *propLink);static void linkPropertyBefore(EjsObj *obj, EjsPropLink *at, EjsPropLink *propLink);static int sortAllProperties(Ejs *ep, EjsProperty *p1, EjsProperty *p2, const char *propertyName, int order);static int sortByProperty(Ejs *ep, EjsProperty *p1, EjsProperty *p2, const char *propertyName, int order);static int dupString(MPR_LOC_DEC(ctx, loc), uchar **dest, const void *src, int nbytes);#if UNUSED && KEEPstatic void linkPropertyAfter(EjsObj *obj, EjsPropLink *at, EjsPropLink *propLink);#endifstatic EjsProperty *hashLookup(EjsObj *obj, const char *property, int *propertyIndex, EjsProperty **hashTail);/******************************************************************************//********************************** Var Routines ******************************//******************************************************************************/EjsType ejsGetVarType(EjsVar *vp){ mprAssert(vp); return vp->type;}/******************************************************************************/void ejsFreeVar(Ejs *ep, EjsVar *vp){ if (vp) { ejsClearVar(ep, vp); ejsFree(ep, vp, EJS_SLAB_VAR); }}/******************************************************************************/#if UNUSED/* * Clear the value by freeing any allocated data. This will release objects * so that later garbage collection can reclaim storage if there are no other * object references. */void ejsZeroVar(Ejs *ep, EjsVar *vp){ vp->type = EJS_TYPE_UNDEFINED; vp->objectState = 0; vp->method.body = 0; vp->method.args = 0; vp->callsSuper = 0; vp->ptr.destructor = 0; vp->allocatedData = 0;}#endif/******************************************************************************//* * Clear the value by freeing any allocated data. This will release objects * so that later garbage collection can reclaim storage if there are no other * object references. */void ejsClearVar(Ejs *ep, EjsVar *vp){ MprArray *argList; int i; mprAssert(vp); mprAssert(ep); if (! vp->allocatedData) { vp->type = EJS_TYPE_UNDEFINED; return; } if (vp->type == EJS_TYPE_UNDEFINED) { return; } switch (vp->type) { default: break; case EJS_TYPE_STRING: mprFree(vp->string); vp->string = 0; break; case EJS_TYPE_OBJECT: /* * Set the "alive" bit so that the GC will cleanup if no * other references. */ if (vp->objectState) { vp->objectState->alive = 1; } vp->objectState = 0; break; case EJS_TYPE_METHOD: argList = vp->method.args; /* * MOB OPT -- should be able to do just one mprFree(vp->method.args) */ mprFree(vp->method.body); if (argList) { for (i = 0; i < argList->length; i++) { mprFree(argList->items[i]); } mprFree(vp->method.args); } vp->method.args = 0; vp->method.body = 0; vp->callsSuper = 0; break; case EJS_TYPE_PTR: if (vp->ptr.destructor) { (vp->ptr.destructor)(ep, vp); } break; } vp->type = EJS_TYPE_UNDEFINED; vp->allocatedData = 0;}/******************************************************************************//* * Initialize an undefined value. */EjsVar *ejsCreateUndefinedVar(Ejs *ep){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_UNDEFINED; } return vp;}/******************************************************************************//* * Initialize an null value. */EjsVar *ejsCreateNullVar(Ejs *ep){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_NULL; } return vp;}/******************************************************************************/EjsVar *ejsCreateBoolVar(Ejs *ep, int value){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_BOOL; vp->boolean = value; } return vp;}/******************************************************************************//* * Initialize a C method. */EjsVar *ejsCreateCMethodVar(Ejs *ep, EjsCMethod fn, void *userData, int flags){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_CMETHOD; vp->cMethod.fn = fn; vp->cMethod.userData = userData; vp->flags = flags; } return vp;}/******************************************************************************//* * Initialize a C method. */EjsVar *ejsCreateStringCMethodVar(Ejs *ep, EjsStringCMethod fn, void *userData, int flags){ EjsVar *vp; mprAssert(ep); mprAssert(fn); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_STRING_CMETHOD; vp->cMethodWithStrings.fn = fn; vp->cMethodWithStrings.userData = userData; vp->flags = flags; } return vp;}/******************************************************************************//* * Initialize an opaque pointer. */EjsVar *ejsCreatePtrVar(Ejs *ep, void *ptr, EjsDestructor destructor){ EjsVar *vp; mprAssert(ep); mprAssert(ptr); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_PTR; vp->ptr.userPtr = ptr; vp->ptr.destructor = destructor; vp->allocatedData = 1; } return vp;}/******************************************************************************/#if BLD_FEATURE_FLOATING_POINT/* * Initialize a floating value. */EjsVar *ejsCreateFloatVar(Ejs *ep, double value){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_FLOAT; vp->floating = value; } return vp;}#endif/******************************************************************************//* * Initialize an integer value. */EjsVar *ejsCreateIntegerVar(Ejs *ep, int value){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_INT; vp->integer = value; } return vp;}/******************************************************************************/#if BLD_FEATURE_INT64/* * Initialize a 64-bit integer value. */EjsVar *ejsCreateInteger64Var(Ejs *ep, int64 value){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_INT64; vp->integer64 = value; } return vp;}#endif /* BLD_FEATURE_INT64 *//******************************************************************************//* * Initialize an number variable. Type is defined by configure. */EjsVar *ejsCreateNumberVar(Ejs *ep, EjsNum value){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); mprAssert(vp); if (vp) { vp->type = BLD_FEATURE_NUM_TYPE_ID;#if BLD_FEATURE_NUM_TYPE_ID == EJS_TYPE_INT64 vp->integer64 = value;#elif BLD_FEATURE_NUM_TYPE_ID == EJS_TYPE_FLOAT vp->float = value;#else vp->integer = value;#endif } return vp;}/******************************************************************************//* * Initialize a (bare) JavaScript method. args and body can be null. */EjsVar *ejsCreateMethodVar(Ejs *ep, const char *body, MprArray *args, int flags){ EjsVar *vp; int i; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); mprAssert(vp); if (vp == 0) { return 0; } vp->type = EJS_TYPE_METHOD; vp->allocatedData = 1; vp->method.args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); if (vp->method.args == 0) { mprAssert(vp->method.args); ejsFreeVar(ep, vp); return 0; } if (args) { for (i = 0; i < args->length; i++) { mprAddItem(vp->method.args, mprStrdup(vp->method.args, mprGetItem(args, i))); } } vp->method.body = mprStrdup(vp->method.args, body); if (vp->method.body == 0) { ejsFreeVar(ep, vp); return 0; } vp->flags = flags; return vp;}/******************************************************************************//* * Initialize an object variable. */EjsVar *ejsCreateObjVarInternal(EJS_LOC_DEC(ep, loc)){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_PASS(ep, loc)); mprAssert(vp); if (vp) { vp->type = EJS_TYPE_OBJECT; vp->objectState = createObj(EJS_LOC_PASS(ep, loc)); if (vp->objectState == 0) { ejsFreeVar(ep, vp); return 0; } vp->allocatedData = 1; } return vp;}/******************************************************************************//* * Initialize a string value. */EjsVar *ejsCreateStringVarInternal(EJS_LOC_DEC(ep, loc), const char *value){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_PASS(ep, loc)); mprAssert(vp); if (vp) { vp->type = EJS_TYPE_STRING; vp->string = mprStrdupInternal(EJS_LOC_PASS(ep, loc), value); if (vp->string == 0) { ejsFreeVar(ep, vp); return 0; } vp->length = strlen(vp->string); vp->allocatedData = 1; } return vp;}/******************************************************************************//* * Initialize a binary string value. */EjsVar *ejsCreateBinaryStringVar(Ejs *ep, const uchar *value, int len){ EjsVar *vp; mprAssert(ep); vp = ejsAllocVar(EJS_LOC_ARGS(ep)); if (vp) { vp->type = EJS_TYPE_STRING; vp->length = dupString(MPR_LOC_ARGS(ep), &vp->ustring, value, len); if (vp->length < 0) { ejsFreeVar(ep, vp); return 0; } vp->allocatedData = 1; } return vp;}/******************************************************************************/void ejsSetClassName(Ejs *ep, EjsVar *vp, const char *name){ EjsObj *obj; if (vp == 0 || !ejsVarIsObject(vp) || vp->objectState == 0) { mprAssert(0); return; } obj = vp->objectState; if (obj->className) { mprFree(obj->className); } obj->className = mprStrdup(ep, name);}/******************************************************************************/EjsVar *ejsDupVarInternal(EJS_LOC_DEC(ep, loc), EjsVar *src, EjsCopyDepth copyDepth){ EjsVar *vp; vp = ejsAllocVar(EJS_LOC_PASS(ep, loc)); if (vp == 0) { return 0; } vp->type = EJS_TYPE_UNDEFINED; return copyVar(EJS_LOC_PASS(ep, loc), vp, src, copyDepth);}/******************************************************************************//* * Set a var to a new value */EjsVar *ejsWriteVarInternal(EJS_LOC_DEC(ep, loc), EjsVar *dest, const EjsVar *src, EjsCopyDepth copyDepth){ mprAssert(dest); mprAssert(src); return copyVar(EJS_LOC_PASS(ep, loc), dest, src, copyDepth);}/******************************************************************************//* * Set a var using a new bool value */EjsVar *ejsWriteVarAsBoolean(Ejs *ep, EjsVar *dest, int value){ mprAssert(dest); if (dest->type != EJS_TYPE_UNDEFINED) { ejsClearVar(ep, dest); } dest->type = EJS_TYPE_BOOL; dest->boolean = value; dest->allocatedData = 0; dest->flags = 0; return dest;}/******************************************************************************//* * Set a var using a new C Method */EjsVar *ejsWriteVarAsCMethod(Ejs *ep, EjsVar *dest, EjsCMethod fn, void *userData, int flags){ mprAssert(dest); if (dest->type != EJS_TYPE_UNDEFINED) { ejsClearVar(ep, dest); } dest->type = EJS_TYPE_CMETHOD; dest->cMethod.fn = fn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -