var.c

来自「samba最新软件」· C语言 代码 · 共 2,216 行 · 第 1/4 页

C
2,216
字号
/* *	@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_DEBUGstatic 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) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?