📄 ejsvar.c
字号:
/******************************************************************************/EjsProperty *ejsSetPropertyToNumber(Ejs *ep, EjsVar *vp, const char *prop, EjsNum value){ return ejsSetPropertyAndFree(ep, vp, prop, ejsCreateNumberVar(ep, value));}/******************************************************************************/EjsProperty *ejsSetPropertyToStringCMethod(Ejs *ep, EjsVar *vp, const char *prop, EjsStringCMethod fn, void *userData, int flags){ EjsVar v; ejsInitVar(&v, EJS_TYPE_STRING_CMETHOD); v.cMethodWithStrings.fn = fn; v.cMethodWithStrings.userData = userData; v.flags = flags; return ejsSetProperty(ep, vp, prop, &v);}/******************************************************************************/EjsProperty *ejsSetPropertyToString(Ejs *ep, EjsVar *vp, const char *prop, const char *value){ EjsProperty *pp; EjsVar v; ejsInitVar(&v, EJS_TYPE_STRING); /* FUTURE OPT */ v.string = mprStrdupInternal(EJS_LOC_ARGS(ep), value); if (v.string == 0) { return 0; } v.length = strlen(v.string); v.allocatedData = 1; pp = ejsSetProperty(ep, vp, prop, &v); mprFree(v.string); return pp;}/******************************************************************************/EjsProperty *ejsSetPropertyToBinaryString(Ejs *ep, EjsVar *vp, const char *prop, const uchar *value, int len){ EjsProperty *pp; EjsVar v; ejsInitVar(&v, EJS_TYPE_STRING); /* FUTURE OPT */ v.length = dupString(MPR_LOC_ARGS(ep), &v.ustring, value, len); if (v.length < 0) { return 0; } v.allocatedData = 1; pp = ejsSetProperty(ep, vp, prop, &v); mprFree(v.ustring); return pp;}/******************************************************************************/EjsProperty *ejsSetPropertyToUndefined(Ejs *ep, EjsVar *vp, const char *prop){ EjsVar v; ejsInitVar(&v, EJS_TYPE_UNDEFINED); return ejsSetProperty(ep, vp, prop, &v);}/******************************************************************************/EjsProperty *ejsSetPropertyToPtr(Ejs *ep, EjsVar *vp, const char *prop, void *ptr, EjsDestructor destructor){ EjsVar v; ejsInitVar(&v, EJS_TYPE_PTR); v.ptr.userPtr = ptr; v.ptr.destructor = destructor; v.allocatedData = 1; return ejsSetProperty(ep, vp, prop, &v);}/******************************************************************************/EjsProperty *ejsSetPropertyToNewObj(Ejs *ep, EjsVar *vp, const char *prop, const char *className, MprArray *args){ return ejsSetPropertyAndFree(ep, vp, prop, ejsCreateObjUsingArgv(ep, 0, className, args));}/******************************************************************************/EjsProperty *ejsSetPropertyToObj(Ejs *ep, EjsVar *op, const char *prop){ return ejsSetPropertyAndFree(ep, op, prop, ejsCreateObjVar(ep));}/******************************************************************************//* * Convenience routines */EjsVar *ejsSetPropertyToObjAsVar(Ejs *ep, EjsVar *op, const char *prop){ return ejsGetVarPtr(ejsSetPropertyToObj(ep, op, prop));}/******************************************************************************//******************************************************************************//******************************************************************************//******************************************************************************//* * Create a script method */EjsProperty *ejsDefineMethod(Ejs *ep, EjsVar *vp, const char *prop, const char *body, MprArray *args){ if (vp == 0) { vp = ejsGetGlobalObj(ep); } return ejsSetPropertyToMethod(ep, vp, prop, body, args, 0);}/******************************************************************************//* * Create a C language method */EjsProperty *ejsDefineCMethod(Ejs *ep, EjsVar *vp, const char *prop, EjsCMethod fn, int flags){ if (vp == 0) { vp = ejsGetGlobalObj(ep); } return ejsSetPropertyToCMethod(ep, vp, prop, fn, 0, flags);}/******************************************************************************//* * Define accessors */EjsProperty *ejsDefineAccessors(Ejs *ep, EjsVar *vp, const char *prop, const char *getBody, const char *setBody){ EjsProperty *pp; MprArray *args; char *propName; if (vp == 0) { vp = ejsGetGlobalObj(ep); } if (ejsSetPropertyToMethod(ep, vp, prop, getBody, 0, EJS_GET_ACCESSOR) < 0){ ejsMemoryError(ep); return 0; } /* MOB -- OPT to use SLAB */ /* MOB -- need to encapsulate this logic */ if (mprAllocStrcat(MPR_LOC_ARGS(ep), &propName, EJS_MAX_ID+5, 0, "-set-", prop, NULL) < 0) { ejsMemoryError(ep); return 0; } args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); mprAddItem(args, mprStrdup(args, "value")); pp = ejsSetPropertyToMethod(ep, vp, propName, setBody, args, EJS_SET_ACCESSOR); mprFree(propName); if (pp == 0) { ejsMemoryError(ep); return 0; } return pp;}/******************************************************************************//* * Define C accessors */EjsProperty *ejsDefineCAccessors(Ejs *ep, EjsVar *vp, const char *prop, EjsCMethod getFn, EjsCMethod setFn, int flags){ EjsProperty *pp; char *propName; if (vp == 0) { vp = ejsGetGlobalObj(ep); } pp = ejsSetPropertyToCMethod(ep, vp, prop, getFn, 0, flags | EJS_GET_ACCESSOR); if (pp == 0) { ejsMemoryError(ep); return 0; } /* MOB -- OPT to use SLAB */ if (mprAllocStrcat(MPR_LOC_ARGS(ep), &propName, EJS_MAX_ID + 5, 0, "-set-", prop, NULL) < 0) { ejsMemoryError(ep); return 0; } pp = ejsSetPropertyToCMethod(ep, vp, propName, setFn, 0, flags | EJS_SET_ACCESSOR); mprFree(propName); if (pp == 0) { ejsMemoryError(ep); return 0; } return pp;}/******************************************************************************//* * Create a C language method with string arguments */EjsProperty *ejsDefineStringCMethod(Ejs *ep, EjsVar *vp, const char *prop, EjsStringCMethod fn, int flags){ if (vp == 0) { vp = ejsGetGlobalObj(ep); } return ejsSetPropertyToStringCMethod(ep, vp, prop, fn, 0, flags);}/******************************************************************************/void ejsSetCMethodUserData(EjsVar *obj, void *userData){ /* * This is a little dirty. We rely on the userData being in the same * place in the var structure. */ obj->cMethod.userData = userData;}/******************************************************************************/void ejsSetVarFlags(EjsVar *obj, int flags){ obj->flags = flags;}/******************************************************************************/void *ejsGetCMethodUserData(EjsVar *obj){ return obj->cMethod.userData;}/******************************************************************************/int ejsGetVarFlags(EjsVar *obj){ return obj->flags;}/******************************************************************************/void ejsSetObjDestructor(Ejs *ep, EjsVar *obj, EjsDestructor destructor){ obj->objectState->destructor = destructor;}/******************************************************************************/void ejsClearObjDestructor(Ejs *ep, EjsVar *obj){ obj->objectState->destructor = 0;}/******************************************************************************//* * Create a new property */static EjsProperty *allocProperty(Ejs *ep, EjsVar *op, const char *property, int propertyIndex, EjsProperty *last){ EjsProperty *prop; EjsObj *obj; obj = op->objectState; /* * Allocate the property using the memory context of the owning object */ prop = ejsAllocProperty(EJS_LOC_ARGS(obj->ejs)); if (prop == 0) { return 0; } if (mprStrcpy(prop->name, sizeof(prop->name), property) < 0) { ejsError(ep, EJS_REFERENCE_ERROR, "Property name %s is too long. Max is %d letters.", prop->name, EJS_MAX_ID); return 0; } ejsSetVarName(ep, ejsGetVarPtr(prop), &prop->name[0]); /* * Do hash linkage */ if (last) { last->hashNext = prop; } else { obj->propertyHash[propertyIndex] = prop; }#if BLD_DEBUG prop->link.propertyName = prop->name; prop->link.property = prop; prop->link.head = &obj->link;#endif /* * Inserting before the dummy head will append to the end */ linkPropertyBefore(obj, &obj->link, &prop->link); obj->numProperties++; prop->parentObj = obj; mprAssert(obj->ejs); return prop;}/******************************************************************************//* * Delete a property from this object */int ejsDeleteProperty(Ejs *ep, EjsVar *vp, const char *property){ EjsProperty *prop, *last; EjsObj *obj; int propertyIndex; mprAssert(vp); mprAssert(property && *property); mprAssert(vp->type == EJS_TYPE_OBJECT); if (vp->type != EJS_TYPE_OBJECT) { mprAssert(vp->type == EJS_TYPE_OBJECT); return MPR_ERR_BAD_ARGS; } prop = hashLookup(vp->objectState, property, &propertyIndex, &last); if (prop == (EjsProperty*) 0) { return MPR_ERR_NOT_FOUND; } obj = vp->objectState;#if FUTURE if (prop->readonly) { mprAssert(! prop->readonly); return MPR_ERR_READ_ONLY; }#endif /* * If doing enumerations, then the object will mark preventDelete to * prevent any properties being deleted and thus disturbing the * traversal. */ if (obj->preventDeleteProp) { obj->delayedDeleteProp = 1; prop->delayedDelete = 1; return 0; } /* * Remove from hash */ if (last) { last->hashNext = prop->hashNext; } else { obj->propertyHash[propertyIndex] = prop->hashNext; } unlinkProperty(obj, &prop->link); obj->numProperties--; /* * Free any property data and return to the slab */ if (prop->var.type != EJS_TYPE_OBJECT) { ejsClearVar(ep, ejsGetVarPtr(prop)); } ejsFree(ep, prop, EJS_SLAB_PROPERTY); return 0;}/******************************************************************************//* * Remove a property's value from this object. The property is set to * undefined. */EjsVar *ejsClearProperty(Ejs *ep, EjsVar *vp, const char *property){ EjsProperty *prop; mprAssert(vp); mprAssert(property && *property); mprAssert(vp->type == EJS_TYPE_OBJECT); if (vp->type != EJS_TYPE_OBJECT) { mprAssert(vp->type == EJS_TYPE_OBJECT); return 0; } prop = hashLookup(vp->objectState, property, 0, 0); if (prop == (EjsProperty*) 0) { return 0; }#if FUTURE if (prop->readonly) { mprAssert(! prop->readonly); return 0; }#endif ejsClearVar(ep, &prop->var); return &prop->var;}/******************************************************************************//* * Unlink a property from the ordered list of properties */static void unlinkProperty(EjsObj *obj, EjsPropLink *propLink){ propLink->prev->next = propLink->next; propLink->next->prev = propLink->prev;}/******************************************************************************/#if UNUSED && KEEP/* * Insert a link after a specified link. */static void linkPropertyAfter(EjsObj *obj, EjsPropLink *at, EjsPropLink *propLink){ propLink->next = at->next; propLink->prev = at; at->next->prev = propLink; at->next = propLink;}#endif/******************************************************************************//* * Insert a link before a specified link. */static void linkPropertyBefore(EjsObj *obj, EjsPropLink *at, EjsPropLink *propLink){ propLink->prev = at->prev; propLink->next = at; at->prev->next = propLink; at->prev = propLink;}/******************************************************************************//* * This routine will sort properties in an object. If propertyName is not * null, then the properties in op must be objects with a property of the * name propertyName. If propertyName is null, then the properties of op * are directly sorted. If order is 1, they are sorted in ascending order. * If -1, they are sorted in descending order. * * NOTE: arrays keep their original index values. */ void ejsSortProperties(Ejs *ep, EjsVar *op, EjsSortFn fn, const char *propertyName, int order){ EjsProperty *p1, *p2, *tmp; EjsPropLink *l1, *l2, *oldL1Spot; EjsObj *obj; obj = op->objectState; p1 = ejsGetFirstProperty(op, 0); while (p1) { if (p1->dontEnumerate) { p1 = ejsGetNextProperty(p1, 0); continue; } p2 = ejsGetFirstProperty(op, 0); while (p2 && p2 != p1) { if (p2->dontEnumerate) { p2 = ejsGetNextProperty(p2, 0); continue; } if (fn == 0) { if (propertyName) { fn = sortByProperty; } else { fn = sortAllProperties; } } if (fn(ep, p1, p2, propertyName, order) < 0) { l1 = &p1->link; l2 = &p2->link; /* * Swap the properties without disturbing the hash chains. * l1 is always after l2 in the list. Unlink l1 and remember * the one after l1. */ oldL1Spot = l1->next; unlinkProperty(obj, l1); /* * Manually reinsert l1 by replacing l2 with l1. l2 is out of * the chain. */ l2->prev->next = l1; l2->next->prev = l1; l1->prev = l2->prev; l1->next = l2->next; /* * Reinsert l2 before the spot where l1 was. */ linkPropertyBefore(obj, oldL1Spot, l2); /* * Swap the pointers so we continue to traverse correctly */ tmp = p1; p1 = p2; p2 = tmp; } p2 = ejsGetNextProperty(p2, 0); } p1 = ejsGetNextProperty(p1, 0); }}/******************************************************************************//* * Sort properties. Strings are sorted in ascending ASCII collating sequence * Numbers are sorted in increasing numerical order. */static int sortAllProperties(Ejs *ep, EjsProperty *p1, EjsProperty *p2, const char *propertyName, int order){ EjsVar *v1, *v2; char *buf1, *buf2; int rc, buf1Alloc; v1 = ejsGetVarPtr(p1); v2 = ejsGetVarPtr(p2); if (v1->type == v2->type) { /* MOB -- should support Numbers */ if (v1->type == EJS_TYPE_INT) { if (v1->integer < v2->integer) { return - order; } else if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -