Code formatting
This commit is contained in:
496
oop.c
496
oop.c
@@ -10,7 +10,7 @@
|
||||
* or visit:
|
||||
* http://ph7.symisc.net/
|
||||
*/
|
||||
/* $SymiscID: oo.c v1.9 FeeBSD 2012-07-17 03:44 devel <chm@symisc.net> $ */
|
||||
/* $SymiscID: oo.c v1.9 FeeBSD 2012-07-17 03:44 devel <chm@symisc.net> $ */
|
||||
#include "ph7int.h"
|
||||
/*
|
||||
* This file implement an Object Oriented (OO) subsystem for the PH7 engine.
|
||||
@@ -19,29 +19,28 @@
|
||||
* Create an empty class.
|
||||
* Return a pointer to a raw class (ph7_class instance) on success. NULL otherwise.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class * PH7_NewRawClass(ph7_vm *pVm,const SyString *pName,sxu32 nLine)
|
||||
{
|
||||
PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName, sxu32 nLine) {
|
||||
ph7_class *pClass;
|
||||
char *zName;
|
||||
/* Allocate a new instance */
|
||||
pClass = (ph7_class *)SyMemBackendPoolAlloc(&pVm->sAllocator,sizeof(ph7_class));
|
||||
if( pClass == 0 ){
|
||||
pClass = (ph7_class *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class));
|
||||
if(pClass == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Zero the structure */
|
||||
SyZero(pClass,sizeof(ph7_class));
|
||||
SyZero(pClass, sizeof(ph7_class));
|
||||
/* Duplicate class name */
|
||||
zName = SyMemBackendStrDup(&pVm->sAllocator,pName->zString,pName->nByte);
|
||||
if( zName == 0 ){
|
||||
SyMemBackendPoolFree(&pVm->sAllocator,pClass);
|
||||
zName = SyMemBackendStrDup(&pVm->sAllocator, pName->zString, pName->nByte);
|
||||
if(zName == 0) {
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pClass);
|
||||
return 0;
|
||||
}
|
||||
/* Initialize fields */
|
||||
SyStringInitFromBuf(&pClass->sName,zName,pName->nByte);
|
||||
SyHashInit(&pClass->hMethod,&pVm->sAllocator,0,0);
|
||||
SyHashInit(&pClass->hAttr,&pVm->sAllocator,0,0);
|
||||
SyHashInit(&pClass->hDerived,&pVm->sAllocator,0,0);
|
||||
SySetInit(&pClass->aInterface,&pVm->sAllocator,sizeof(ph7_class *));
|
||||
SyStringInitFromBuf(&pClass->sName, zName, pName->nByte);
|
||||
SyHashInit(&pClass->hMethod, &pVm->sAllocator, 0, 0);
|
||||
SyHashInit(&pClass->hAttr, &pVm->sAllocator, 0, 0);
|
||||
SyHashInit(&pClass->hDerived, &pVm->sAllocator, 0, 0);
|
||||
SySetInit(&pClass->aInterface, &pVm->sAllocator, sizeof(ph7_class *));
|
||||
pClass->nLine = nLine;
|
||||
/* All done */
|
||||
return pClass;
|
||||
@@ -50,25 +49,24 @@ PH7_PRIVATE ph7_class * PH7_NewRawClass(ph7_vm *pVm,const SyString *pName,sxu32
|
||||
* Allocate and initialize a new class attribute.
|
||||
* Return a pointer to the class attribute on success. NULL otherwise.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_attr * PH7_NewClassAttr(ph7_vm *pVm,const SyString *pName,sxu32 nLine,sxi32 iProtection,sxi32 iFlags)
|
||||
{
|
||||
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags) {
|
||||
ph7_class_attr *pAttr;
|
||||
char *zName;
|
||||
pAttr = (ph7_class_attr *)SyMemBackendPoolAlloc(&pVm->sAllocator,sizeof(ph7_class_attr));
|
||||
if( pAttr == 0 ){
|
||||
pAttr = (ph7_class_attr *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_attr));
|
||||
if(pAttr == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Zero the structure */
|
||||
SyZero(pAttr,sizeof(ph7_class_attr));
|
||||
SyZero(pAttr, sizeof(ph7_class_attr));
|
||||
/* Duplicate attribute name */
|
||||
zName = SyMemBackendStrDup(&pVm->sAllocator,pName->zString,pName->nByte);
|
||||
if( zName == 0 ){
|
||||
SyMemBackendPoolFree(&pVm->sAllocator,pAttr);
|
||||
zName = SyMemBackendStrDup(&pVm->sAllocator, pName->zString, pName->nByte);
|
||||
if(zName == 0) {
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pAttr);
|
||||
return 0;
|
||||
}
|
||||
/* Initialize fields */
|
||||
SySetInit(&pAttr->aByteCode,&pVm->sAllocator,sizeof(VmInstr));
|
||||
SyStringInitFromBuf(&pAttr->sName,zName,pName->nByte);
|
||||
SySetInit(&pAttr->aByteCode, &pVm->sAllocator, sizeof(VmInstr));
|
||||
SyStringInitFromBuf(&pAttr->sName, zName, pName->nByte);
|
||||
pAttr->iProtection = iProtection;
|
||||
pAttr->nIdx = SXU32_HIGH;
|
||||
pAttr->iFlags = iFlags;
|
||||
@@ -81,9 +79,8 @@ PH7_PRIVATE ph7_class_attr * PH7_NewClassAttr(ph7_vm *pVm,const SyString *pName,
|
||||
* This function associate with the newly created method an automatically generated
|
||||
* random unique name.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_method * PH7_NewClassMethod(ph7_vm *pVm,ph7_class *pClass,const SyString *pName,sxu32 nLine,
|
||||
sxi32 iProtection,sxi32 iFlags,sxi32 iFuncFlags)
|
||||
{
|
||||
PH7_PRIVATE ph7_class_method *PH7_NewClassMethod(ph7_vm *pVm, ph7_class *pClass, const SyString *pName, sxu32 nLine,
|
||||
sxi32 iProtection, sxi32 iFlags, sxi32 iFuncFlags) {
|
||||
ph7_class_method *pMeth;
|
||||
SyHashEntry *pEntry;
|
||||
SyString *pNamePtr;
|
||||
@@ -91,61 +88,60 @@ PH7_PRIVATE ph7_class_method * PH7_NewClassMethod(ph7_vm *pVm,ph7_class *pClass,
|
||||
char *zName;
|
||||
sxu32 nByte;
|
||||
/* Allocate a new class method instance */
|
||||
pMeth = (ph7_class_method *)SyMemBackendPoolAlloc(&pVm->sAllocator,sizeof(ph7_class_method));
|
||||
if( pMeth == 0 ){
|
||||
pMeth = (ph7_class_method *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_method));
|
||||
if(pMeth == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Zero the structure */
|
||||
SyZero(pMeth,sizeof(ph7_class_method));
|
||||
SyZero(pMeth, sizeof(ph7_class_method));
|
||||
/* Check for an already installed method with the same name */
|
||||
pEntry = SyHashGet(&pClass->hMethod,(const void *)pName->zString,pName->nByte);
|
||||
if( pEntry == 0 ){
|
||||
pEntry = SyHashGet(&pClass->hMethod, (const void *)pName->zString, pName->nByte);
|
||||
if(pEntry == 0) {
|
||||
/* Associate an unique VM name to this method */
|
||||
nByte = sizeof(zSalt) + pName->nByte + SyStringLength(&pClass->sName)+sizeof(char)*7/*[[__'\0'*/;
|
||||
zName = (char *)SyMemBackendAlloc(&pVm->sAllocator,nByte);
|
||||
if( zName == 0 ){
|
||||
SyMemBackendPoolFree(&pVm->sAllocator,pMeth);
|
||||
nByte = sizeof(zSalt) + pName->nByte + SyStringLength(&pClass->sName) + sizeof(char) * 7/*[[__'\0'*/;
|
||||
zName = (char *)SyMemBackendAlloc(&pVm->sAllocator, nByte);
|
||||
if(zName == 0) {
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pMeth);
|
||||
return 0;
|
||||
}
|
||||
pNamePtr = &pMeth->sVmName;
|
||||
/* Generate a random string */
|
||||
PH7_VmRandomString(&(*pVm),zSalt,sizeof(zSalt));
|
||||
pNamePtr->nByte = SyBufferFormat(zName,nByte,"[__%z@%z_%.*s]",&pClass->sName,pName,sizeof(zSalt),zSalt);
|
||||
PH7_VmRandomString(&(*pVm), zSalt, sizeof(zSalt));
|
||||
pNamePtr->nByte = SyBufferFormat(zName, nByte, "[__%z@%z_%.*s]", &pClass->sName, pName, sizeof(zSalt), zSalt);
|
||||
pNamePtr->zString = zName;
|
||||
}else{
|
||||
} else {
|
||||
/* Method is condidate for 'overloading' */
|
||||
ph7_class_method *pCurrent = (ph7_class_method *)pEntry->pUserData;
|
||||
pNamePtr = &pMeth->sVmName;
|
||||
/* Use the same VM name */
|
||||
SyStringDupPtr(pNamePtr,&pCurrent->sVmName);
|
||||
SyStringDupPtr(pNamePtr, &pCurrent->sVmName);
|
||||
zName = (char *)pNamePtr->zString;
|
||||
}
|
||||
if( iProtection != PH7_CLASS_PROT_PUBLIC ){
|
||||
if( (pName->nByte == sizeof("__construct") - 1 && SyMemcmp(pName->zString,"__construct",sizeof("__construct") - 1 ) == 0)
|
||||
|| (pName->nByte == sizeof("__destruct") - 1 && SyMemcmp(pName->zString,"__destruct",sizeof("__destruct") - 1 ) == 0)
|
||||
|| SyStringCmp(pName,&pClass->sName,SyMemcmp) == 0 ){
|
||||
/* Switch to public visibility when dealing with constructor/destructor */
|
||||
iProtection = PH7_CLASS_PROT_PUBLIC;
|
||||
if(iProtection != PH7_CLASS_PROT_PUBLIC) {
|
||||
if((pName->nByte == sizeof("__construct") - 1 && SyMemcmp(pName->zString, "__construct", sizeof("__construct") - 1) == 0)
|
||||
|| (pName->nByte == sizeof("__destruct") - 1 && SyMemcmp(pName->zString, "__destruct", sizeof("__destruct") - 1) == 0)
|
||||
|| SyStringCmp(pName, &pClass->sName, SyMemcmp) == 0) {
|
||||
/* Switch to public visibility when dealing with constructor/destructor */
|
||||
iProtection = PH7_CLASS_PROT_PUBLIC;
|
||||
}
|
||||
}
|
||||
/* Initialize method fields */
|
||||
pMeth->iProtection = iProtection;
|
||||
pMeth->iFlags = iFlags;
|
||||
pMeth->nLine = nLine;
|
||||
PH7_VmInitFuncState(&(*pVm),&pMeth->sFunc,&zName[sizeof(char)*4/*[__@*/+SyStringLength(&pClass->sName)],
|
||||
pName->nByte,iFuncFlags|VM_FUNC_CLASS_METHOD,pClass);
|
||||
PH7_VmInitFuncState(&(*pVm), &pMeth->sFunc, &zName[sizeof(char) * 4/*[__@*/ + SyStringLength(&pClass->sName)],
|
||||
pName->nByte, iFuncFlags | VM_FUNC_CLASS_METHOD, pClass);
|
||||
return pMeth;
|
||||
}
|
||||
/*
|
||||
* Check if the given name have a class method associated with it.
|
||||
* Return the desired method [i.e: ph7_class_method instance] on success. NULL otherwise.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_method * PH7_ClassExtractMethod(ph7_class *pClass,const char *zName,sxu32 nByte)
|
||||
{
|
||||
PH7_PRIVATE ph7_class_method *PH7_ClassExtractMethod(ph7_class *pClass, const char *zName, sxu32 nByte) {
|
||||
SyHashEntry *pEntry;
|
||||
/* Perform a hash lookup */
|
||||
pEntry = SyHashGet(&pClass->hMethod,(const void *)zName,nByte);
|
||||
if( pEntry == 0 ){
|
||||
pEntry = SyHashGet(&pClass->hMethod, (const void *)zName, nByte);
|
||||
if(pEntry == 0) {
|
||||
/* No such entry */
|
||||
return 0;
|
||||
}
|
||||
@@ -156,12 +152,11 @@ PH7_PRIVATE ph7_class_method * PH7_ClassExtractMethod(ph7_class *pClass,const ch
|
||||
* Check if the given name is a class attribute.
|
||||
* Return the desired attribute [i.e: ph7_class_attr instance] on success.NULL otherwise.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_attr * PH7_ClassExtractAttribute(ph7_class *pClass,const char *zName,sxu32 nByte)
|
||||
{
|
||||
PH7_PRIVATE ph7_class_attr *PH7_ClassExtractAttribute(ph7_class *pClass, const char *zName, sxu32 nByte) {
|
||||
SyHashEntry *pEntry;
|
||||
/* Perform a hash lookup */
|
||||
pEntry = SyHashGet(&pClass->hAttr,(const void *)zName,nByte);
|
||||
if( pEntry == 0 ){
|
||||
pEntry = SyHashGet(&pClass->hAttr, (const void *)zName, nByte);
|
||||
if(pEntry == 0) {
|
||||
/* No such entry */
|
||||
return 0;
|
||||
}
|
||||
@@ -172,22 +167,20 @@ PH7_PRIVATE ph7_class_attr * PH7_ClassExtractAttribute(ph7_class *pClass,const c
|
||||
* Install a class attribute in the corresponding container.
|
||||
* Return SXRET_OK on success. Any other return value indicates failure.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass,ph7_class_attr *pAttr)
|
||||
{
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass, ph7_class_attr *pAttr) {
|
||||
SyString *pName = &pAttr->sName;
|
||||
sxi32 rc;
|
||||
rc = SyHashInsert(&pClass->hAttr,(const void *)pName->zString,pName->nByte,pAttr);
|
||||
rc = SyHashInsert(&pClass->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Install a class method in the corresponding container.
|
||||
* Return SXRET_OK on success. Any other return value indicates failure.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass,ph7_class_method *pMeth)
|
||||
{
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass, ph7_class_method *pMeth) {
|
||||
SyString *pName = &pMeth->sFunc.sName;
|
||||
sxi32 rc;
|
||||
rc = SyHashInsert(&pClass->hMethod,(const void *)pName->zString,pName->nByte,pMeth);
|
||||
rc = SyHashInsert(&pClass->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
@@ -207,7 +200,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass,ph7_class_method *pMe
|
||||
* {
|
||||
* echo 'Foo: ' . $string . PHP_EOL;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* public function printPHP()
|
||||
* {
|
||||
* echo 'PHP is great.' . PHP_EOL;
|
||||
@@ -223,7 +216,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass,ph7_class_method *pMe
|
||||
* $foo = new foo();
|
||||
* $bar = new bar();
|
||||
* $foo->printItem('baz'); // Output: 'Foo: baz'
|
||||
* $foo->printPHP(); // Output: 'PHP is great'
|
||||
* $foo->printPHP(); // Output: 'PHP is great'
|
||||
* $bar->printItem('baz'); // Output: 'Bar: baz'
|
||||
* $bar->printPHP(); // Output: 'PHP is great'
|
||||
*
|
||||
@@ -231,72 +224,70 @@ PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass,ph7_class_method *pMe
|
||||
* Any other return value indicates failure and the upper layer must generate an appropriate
|
||||
* error message.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_gen_state *pGen,ph7_class *pSub,ph7_class *pBase)
|
||||
{
|
||||
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_gen_state *pGen, ph7_class *pSub, ph7_class *pBase) {
|
||||
ph7_class_method *pMeth;
|
||||
ph7_class_attr *pAttr;
|
||||
SyHashEntry *pEntry;
|
||||
SyString *pName;
|
||||
sxi32 rc;
|
||||
/* Install in the derived hashtable */
|
||||
rc = SyHashInsert(&pBase->hDerived,(const void *)SyStringData(&pSub->sName),SyStringLength(&pSub->sName),pSub);
|
||||
if( rc != SXRET_OK ){
|
||||
rc = SyHashInsert(&pBase->hDerived, (const void *)SyStringData(&pSub->sName), SyStringLength(&pSub->sName), pSub);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
/* Copy public/protected attributes from the base class */
|
||||
SyHashResetLoopCursor(&pBase->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0) {
|
||||
/* Make sure the private attributes are not redeclared in the subclass */
|
||||
pAttr = (ph7_class_attr *)pEntry->pUserData;
|
||||
pName = &pAttr->sName;
|
||||
if( (pEntry = SyHashGet(&pSub->hAttr,(const void *)pName->zString,pName->nByte)) != 0 ){
|
||||
if( pAttr->iProtection == PH7_CLASS_PROT_PRIVATE &&
|
||||
((ph7_class_attr *)pEntry->pUserData)->iProtection != PH7_CLASS_PROT_PUBLIC ){
|
||||
/* Cannot redeclare private attribute */
|
||||
PH7_GenCompileError(&(*pGen),E_WARNING,((ph7_class_attr *)pEntry->pUserData)->nLine,
|
||||
"Private attribute '%z::%z' redeclared inside child class '%z'",
|
||||
&pBase->sName,pName,&pSub->sName);
|
||||
|
||||
if((pEntry = SyHashGet(&pSub->hAttr, (const void *)pName->zString, pName->nByte)) != 0) {
|
||||
if(pAttr->iProtection == PH7_CLASS_PROT_PRIVATE &&
|
||||
((ph7_class_attr *)pEntry->pUserData)->iProtection != PH7_CLASS_PROT_PUBLIC) {
|
||||
/* Cannot redeclare private attribute */
|
||||
PH7_GenCompileError(&(*pGen), E_WARNING, ((ph7_class_attr *)pEntry->pUserData)->nLine,
|
||||
"Private attribute '%z::%z' redeclared inside child class '%z'",
|
||||
&pBase->sName, pName, &pSub->sName);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* Install the attribute */
|
||||
if( pAttr->iProtection != PH7_CLASS_PROT_PRIVATE ){
|
||||
rc = SyHashInsert(&pSub->hAttr,(const void *)pName->zString,pName->nByte,pAttr);
|
||||
if( rc != SXRET_OK ){
|
||||
if(pAttr->iProtection != PH7_CLASS_PROT_PRIVATE) {
|
||||
rc = SyHashInsert(&pSub->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
SyHashResetLoopCursor(&pBase->hMethod);
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0) {
|
||||
/* Make sure the private/final methods are not redeclared in the subclass */
|
||||
pMeth = (ph7_class_method *)pEntry->pUserData;
|
||||
pName = &pMeth->sFunc.sName;
|
||||
if( (pEntry = SyHashGet(&pSub->hMethod,(const void *)pName->zString,pName->nByte)) != 0 ){
|
||||
if( pMeth->iFlags & PH7_CLASS_ATTR_FINAL ){
|
||||
if((pEntry = SyHashGet(&pSub->hMethod, (const void *)pName->zString, pName->nByte)) != 0) {
|
||||
if(pMeth->iFlags & PH7_CLASS_ATTR_FINAL) {
|
||||
/* Cannot Overwrite final method */
|
||||
rc = PH7_GenCompileError(&(*pGen),E_ERROR,((ph7_class_method *)pEntry->pUserData)->nLine,
|
||||
"Cannot Overwrite final method '%z:%z' inside child class '%z'",
|
||||
&pBase->sName,pName,&pSub->sName);
|
||||
if( rc == SXERR_ABORT ){
|
||||
rc = PH7_GenCompileError(&(*pGen), E_ERROR, ((ph7_class_method *)pEntry->pUserData)->nLine,
|
||||
"Cannot Overwrite final method '%z:%z' inside child class '%z'",
|
||||
&pBase->sName, pName, &pSub->sName);
|
||||
if(rc == SXERR_ABORT) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}else{
|
||||
if( pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT ){
|
||||
} else {
|
||||
if(pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT) {
|
||||
/* Abstract method must be defined in the child class */
|
||||
PH7_GenCompileError(&(*pGen),E_WARNING,pMeth->nLine,
|
||||
"Abstract method '%z:%z' must be defined inside child class '%z'",
|
||||
&pBase->sName,pName,&pSub->sName);
|
||||
PH7_GenCompileError(&(*pGen), E_WARNING, pMeth->nLine,
|
||||
"Abstract method '%z:%z' must be defined inside child class '%z'",
|
||||
&pBase->sName, pName, &pSub->sName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Install the method */
|
||||
if( pMeth->iProtection != PH7_CLASS_PROT_PRIVATE ){
|
||||
rc = SyHashInsert(&pSub->hMethod,(const void *)pName->zString,pName->nByte,pMeth);
|
||||
if( rc != SXRET_OK ){
|
||||
if(pMeth->iProtection != PH7_CLASS_PROT_PRIVATE) {
|
||||
rc = SyHashInsert(&pSub->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -319,39 +310,38 @@ PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_gen_state *pGen,ph7_class *pSub,ph7_class
|
||||
* Any other return value indicates failure and the upper layer must generate an appropriate
|
||||
* error message.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub,ph7_class *pBase)
|
||||
{
|
||||
PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub, ph7_class *pBase) {
|
||||
ph7_class_method *pMeth;
|
||||
ph7_class_attr *pAttr;
|
||||
SyHashEntry *pEntry;
|
||||
SyString *pName;
|
||||
sxi32 rc;
|
||||
/* Install in the derived hashtable */
|
||||
SyHashInsert(&pBase->hDerived,(const void *)SyStringData(&pSub->sName),SyStringLength(&pSub->sName),pSub);
|
||||
SyHashInsert(&pBase->hDerived, (const void *)SyStringData(&pSub->sName), SyStringLength(&pSub->sName), pSub);
|
||||
SyHashResetLoopCursor(&pBase->hAttr);
|
||||
/* Copy constants */
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0) {
|
||||
/* Make sure the constants are not redeclared in the subclass */
|
||||
pAttr = (ph7_class_attr *)pEntry->pUserData;
|
||||
pName = &pAttr->sName;
|
||||
if( SyHashGet(&pSub->hAttr,(const void *)pName->zString,pName->nByte) == 0 ){
|
||||
if(SyHashGet(&pSub->hAttr, (const void *)pName->zString, pName->nByte) == 0) {
|
||||
/* Install the constant in the subclass */
|
||||
rc = SyHashInsert(&pSub->hAttr,(const void *)pName->zString,pName->nByte,pAttr);
|
||||
if( rc != SXRET_OK ){
|
||||
rc = SyHashInsert(&pSub->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
SyHashResetLoopCursor(&pBase->hMethod);
|
||||
/* Copy methods signature */
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0) {
|
||||
/* Make sure the method are not redeclared in the subclass */
|
||||
pMeth = (ph7_class_method *)pEntry->pUserData;
|
||||
pName = &pMeth->sFunc.sName;
|
||||
if( SyHashGet(&pSub->hMethod,(const void *)pName->zString,pName->nByte) == 0 ){
|
||||
if(SyHashGet(&pSub->hMethod, (const void *)pName->zString, pName->nByte) == 0) {
|
||||
/* Install the method */
|
||||
rc = SyHashInsert(&pSub->hMethod,(const void *)pName->zString,pName->nByte,pMeth);
|
||||
if( rc != SXRET_OK ){
|
||||
rc = SyHashInsert(&pSub->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -374,30 +364,29 @@ PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub,ph7_class *pBase)
|
||||
* Any other return value indicates failure and the upper layer must generate an appropriate
|
||||
* error message.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain,ph7_class *pInterface)
|
||||
{
|
||||
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain, ph7_class *pInterface) {
|
||||
ph7_class_attr *pAttr;
|
||||
SyHashEntry *pEntry;
|
||||
SyString *pName;
|
||||
sxi32 rc;
|
||||
/* First off,copy all constants declared inside the interface */
|
||||
SyHashResetLoopCursor(&pInterface->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pInterface->hAttr)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pInterface->hAttr)) != 0) {
|
||||
/* Point to the constant declaration */
|
||||
pAttr = (ph7_class_attr *)pEntry->pUserData;
|
||||
pName = &pAttr->sName;
|
||||
/* Make sure the attribute is not redeclared in the main class */
|
||||
if( SyHashGet(&pMain->hAttr,pName->zString,pName->nByte) == 0 ){
|
||||
if(SyHashGet(&pMain->hAttr, pName->zString, pName->nByte) == 0) {
|
||||
/* Install the attribute */
|
||||
rc = SyHashInsert(&pMain->hAttr,pName->zString,pName->nByte,pAttr);
|
||||
if( rc != SXRET_OK ){
|
||||
rc = SyHashInsert(&pMain->hAttr, pName->zString, pName->nByte, pAttr);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Install in the interface container */
|
||||
SySetPut(&pMain->aInterface,(const void *)&pInterface);
|
||||
/* TICKET 1433-49/1: Symisc eXtension
|
||||
SySetPut(&pMain->aInterface, (const void *)&pInterface);
|
||||
/* TICKET 1433-49/1: Symisc eXtension
|
||||
* A class may not implemnt all declared interface methods,so there
|
||||
* is no need for a method installer loop here.
|
||||
*/
|
||||
@@ -426,7 +415,7 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain,ph7_class *pInterface)
|
||||
* In the class context, it is possible to create a new object by new self and new parent.
|
||||
* When assigning an already created instance of a class to a new variable, the new variable
|
||||
* will access the same instance as the object that was assigned. This behaviour is the same
|
||||
* when passing instances to a function. A copy of an already created object can be made by
|
||||
* when passing instances to a function. A copy of an already created object can be made by
|
||||
* cloning it.
|
||||
* Example #4 Object Assignment
|
||||
* <?php
|
||||
@@ -451,7 +440,7 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain,ph7_class *pInterface)
|
||||
* }
|
||||
* Example #5 Creating new objects
|
||||
* <?php
|
||||
* class Test
|
||||
* class Test
|
||||
* {
|
||||
* static public function getNew()
|
||||
* {
|
||||
@@ -482,39 +471,37 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain,ph7_class *pInterface)
|
||||
* };
|
||||
* Refer to the official documentation for more information.
|
||||
*/
|
||||
static ph7_class_instance * NewClassInstance(ph7_vm *pVm,ph7_class *pClass)
|
||||
{
|
||||
static ph7_class_instance *NewClassInstance(ph7_vm *pVm, ph7_class *pClass) {
|
||||
ph7_class_instance *pThis;
|
||||
/* Allocate a new instance */
|
||||
pThis = (ph7_class_instance *)SyMemBackendPoolAlloc(&pVm->sAllocator,sizeof(ph7_class_instance));
|
||||
if( pThis == 0 ){
|
||||
pThis = (ph7_class_instance *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_instance));
|
||||
if(pThis == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Zero the structure */
|
||||
SyZero(pThis,sizeof(ph7_class_instance));
|
||||
SyZero(pThis, sizeof(ph7_class_instance));
|
||||
/* Initialize fields */
|
||||
pThis->iRef = 1;
|
||||
pThis->pVm = pVm;
|
||||
pThis->pClass = pClass;
|
||||
SyHashInit(&pThis->hAttr,&pVm->sAllocator,0,0);
|
||||
SyHashInit(&pThis->hAttr, &pVm->sAllocator, 0, 0);
|
||||
return pThis;
|
||||
}
|
||||
/*
|
||||
* Wrapper around the NewClassInstance() function defined above.
|
||||
* See the block comment above for more information.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_instance * PH7_NewClassInstance(ph7_vm *pVm,ph7_class *pClass)
|
||||
{
|
||||
PH7_PRIVATE ph7_class_instance *PH7_NewClassInstance(ph7_vm *pVm, ph7_class *pClass) {
|
||||
ph7_class_instance *pNew;
|
||||
sxi32 rc;
|
||||
pNew = NewClassInstance(&(*pVm),&(*pClass));
|
||||
if( pNew == 0 ){
|
||||
pNew = NewClassInstance(&(*pVm), &(*pClass));
|
||||
if(pNew == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Associate a private VM frame with this class instance */
|
||||
rc = PH7_VmCreateClassInstanceFrame(&(*pVm),pNew);
|
||||
if( rc != SXRET_OK ){
|
||||
SyMemBackendPoolFree(&pVm->sAllocator,pNew);
|
||||
rc = PH7_VmCreateClassInstanceFrame(&(*pVm), pNew);
|
||||
if(rc != SXRET_OK) {
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pNew);
|
||||
return 0;
|
||||
}
|
||||
return pNew;
|
||||
@@ -523,11 +510,10 @@ PH7_PRIVATE ph7_class_instance * PH7_NewClassInstance(ph7_vm *pVm,ph7_class *pCl
|
||||
* Extract the value of a class instance [i.e: Object in the PHP jargon] attribute.
|
||||
* This function never fail.
|
||||
*/
|
||||
static ph7_value * ExtractClassAttrValue(ph7_vm *pVm,VmClassAttr *pAttr)
|
||||
{
|
||||
static ph7_value *ExtractClassAttrValue(ph7_vm *pVm, VmClassAttr *pAttr) {
|
||||
/* Extract the value */
|
||||
ph7_value *pValue;
|
||||
pValue = (ph7_value *)SySetAt(&pVm->aMemObj,pAttr->nIdx);
|
||||
pValue = (ph7_value *)SySetAt(&pVm->aMemObj, pAttr->nIdx);
|
||||
return pValue;
|
||||
}
|
||||
/*
|
||||
@@ -539,14 +525,14 @@ static ph7_value * ExtractClassAttrValue(ph7_vm *pVm,VmClassAttr *pAttr)
|
||||
* According to PHP language reference manual.
|
||||
* Creating a copy of an object with fully replicated properties is not always the wanted behavior.
|
||||
* A good example of the need for copy constructors. Another example is if your object holds a reference
|
||||
* to another object which it uses and when you replicate the parent object you want to create
|
||||
* to another object which it uses and when you replicate the parent object you want to create
|
||||
* a new instance of this other object so that the replica has its own separate copy.
|
||||
* An object copy is created by using the clone keyword (which calls the object's __clone() method if possible).
|
||||
* An object's __clone() method cannot be called directly.
|
||||
* $copy_of_object = clone $object;
|
||||
* When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties.
|
||||
* Any properties that are references to other variables, will remain references.
|
||||
* Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method
|
||||
* Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method
|
||||
* will be called, to allow any necessary properties that need to be changed.
|
||||
* Example #1 Cloning an object
|
||||
* <?php
|
||||
@@ -563,7 +549,7 @@ static ph7_value * ExtractClassAttrValue(ph7_vm *pVm,VmClassAttr *pAttr)
|
||||
* $this->instance = ++self::$instances;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*
|
||||
* class MyCloneable
|
||||
* {
|
||||
* public $object1;
|
||||
@@ -614,8 +600,7 @@ static ph7_value * ExtractClassAttrValue(ph7_vm *pVm,VmClassAttr *pAttr)
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_instance * PH7_CloneClassInstance(ph7_class_instance *pSrc)
|
||||
{
|
||||
PH7_PRIVATE ph7_class_instance *PH7_CloneClassInstance(ph7_class_instance *pSrc) {
|
||||
ph7_class_instance *pClone;
|
||||
ph7_class_method *pMethod;
|
||||
SyHashEntry *pEntry2;
|
||||
@@ -624,41 +609,41 @@ PH7_PRIVATE ph7_class_instance * PH7_CloneClassInstance(ph7_class_instance *pSrc
|
||||
sxi32 rc;
|
||||
/* Allocate a new instance */
|
||||
pVm = pSrc->pVm;
|
||||
pClone = NewClassInstance(pVm,pSrc->pClass);
|
||||
if( pClone == 0 ){
|
||||
pClone = NewClassInstance(pVm, pSrc->pClass);
|
||||
if(pClone == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Associate a private VM frame with this class instance */
|
||||
rc = PH7_VmCreateClassInstanceFrame(pVm,pClone);
|
||||
if( rc != SXRET_OK ){
|
||||
SyMemBackendPoolFree(&pVm->sAllocator,pClone);
|
||||
rc = PH7_VmCreateClassInstanceFrame(pVm, pClone);
|
||||
if(rc != SXRET_OK) {
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pClone);
|
||||
return 0;
|
||||
}
|
||||
/* Duplicate object values */
|
||||
SyHashResetLoopCursor(&pSrc->hAttr);
|
||||
SyHashResetLoopCursor(&pClone->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pSrc->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pClone->hAttr)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pSrc->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pClone->hAttr)) != 0) {
|
||||
VmClassAttr *pSrcAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
VmClassAttr *pDestAttr = (VmClassAttr *)pEntry2->pUserData;
|
||||
/* Duplicate non-static attribute */
|
||||
if( (pSrcAttr->pAttr->iFlags & (PH7_CLASS_ATTR_STATIC|PH7_CLASS_ATTR_CONSTANT)) == 0 ){
|
||||
ph7_value *pvSrc,*pvDest;
|
||||
pvSrc = ExtractClassAttrValue(pVm,pSrcAttr);
|
||||
pvDest = ExtractClassAttrValue(pVm,pDestAttr);
|
||||
if( pvSrc && pvDest ){
|
||||
PH7_MemObjStore(pvSrc,pvDest);
|
||||
if((pSrcAttr->pAttr->iFlags & (PH7_CLASS_ATTR_STATIC | PH7_CLASS_ATTR_CONSTANT)) == 0) {
|
||||
ph7_value *pvSrc, *pvDest;
|
||||
pvSrc = ExtractClassAttrValue(pVm, pSrcAttr);
|
||||
pvDest = ExtractClassAttrValue(pVm, pDestAttr);
|
||||
if(pvSrc && pvDest) {
|
||||
PH7_MemObjStore(pvSrc, pvDest);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* call the __clone method on the cloned object if available */
|
||||
pMethod = PH7_ClassExtractMethod(pClone->pClass,"__clone",sizeof("__clone")-1);
|
||||
if( pMethod ){
|
||||
if( pMethod->iCloneDepth < 16 ){
|
||||
pMethod = PH7_ClassExtractMethod(pClone->pClass, "__clone", sizeof("__clone") - 1);
|
||||
if(pMethod) {
|
||||
if(pMethod->iCloneDepth < 16) {
|
||||
pMethod->iCloneDepth++;
|
||||
PH7_VmCallClassMethod(pVm,pClone,pMethod,0,0,0);
|
||||
}else{
|
||||
PH7_VmCallClassMethod(pVm, pClone, pMethod, 0, 0, 0);
|
||||
} else {
|
||||
/* Nesting limit reached */
|
||||
PH7_VmThrowError(pVm,0,PH7_CTX_ERR,"Object clone limit reached,no more call to __clone()");
|
||||
PH7_VmThrowError(pVm, 0, PH7_CTX_ERR, "Object clone limit reached,no more call to __clone()");
|
||||
}
|
||||
/* Reset the cursor */
|
||||
pMethod->iCloneDepth = 0;
|
||||
@@ -672,13 +657,12 @@ PH7_PRIVATE ph7_class_instance * PH7_CloneClassInstance(ph7_class_instance *pSrc
|
||||
* This routine is invoked as soon as there are no other references to a particular
|
||||
* class instance.
|
||||
*/
|
||||
static void PH7_ClassInstanceRelease(ph7_class_instance *pThis)
|
||||
{
|
||||
static void PH7_ClassInstanceRelease(ph7_class_instance *pThis) {
|
||||
ph7_class_method *pDestr;
|
||||
SyHashEntry *pEntry;
|
||||
ph7_class *pClass;
|
||||
ph7_vm *pVm;
|
||||
if( pThis->iFlags & CLASS_INSTANCE_DESTROYED ){
|
||||
if(pThis->iFlags & CLASS_INSTANCE_DESTROYED) {
|
||||
/*
|
||||
* Already destroyed,return immediately.
|
||||
* This could happend if someone perform unset($this) in the destructor body.
|
||||
@@ -690,33 +674,32 @@ static void PH7_ClassInstanceRelease(ph7_class_instance *pThis)
|
||||
/* Invoke any defined destructor if available */
|
||||
pVm = pThis->pVm;
|
||||
pClass = pThis->pClass;
|
||||
pDestr = PH7_ClassExtractMethod(pClass,"__destruct",sizeof("__destruct")-1);
|
||||
if( pDestr ){
|
||||
pDestr = PH7_ClassExtractMethod(pClass, "__destruct", sizeof("__destruct") - 1);
|
||||
if(pDestr) {
|
||||
/* Invoke the destructor */
|
||||
pThis->iRef = 2; /* Prevent garbage collection */
|
||||
PH7_VmCallClassMethod(pVm,pThis,pDestr,0,0,0);
|
||||
PH7_VmCallClassMethod(pVm, pThis, pDestr, 0, 0, 0);
|
||||
}
|
||||
/* Release non-static attributes */
|
||||
SyHashResetLoopCursor(&pThis->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
|
||||
VmClassAttr *pVmAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
if( (pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_STATIC|PH7_CLASS_ATTR_CONSTANT)) == 0 ){
|
||||
PH7_VmUnsetMemObj(pVm,pVmAttr->nIdx,TRUE);
|
||||
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_STATIC | PH7_CLASS_ATTR_CONSTANT)) == 0) {
|
||||
PH7_VmUnsetMemObj(pVm, pVmAttr->nIdx, TRUE);
|
||||
}
|
||||
SyMemBackendPoolFree(&pVm->sAllocator,pVmAttr);
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pVmAttr);
|
||||
}
|
||||
/* Release the whole structure */
|
||||
SyHashRelease(&pThis->hAttr);
|
||||
SyMemBackendPoolFree(&pVm->sAllocator,pThis);
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pThis);
|
||||
}
|
||||
/*
|
||||
* Decrement the reference count of a class instance [i.e Object in the PHP jargon].
|
||||
* If the reference count reaches zero,release the whole instance.
|
||||
*/
|
||||
PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis)
|
||||
{
|
||||
PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis) {
|
||||
pThis->iRef--;
|
||||
if( pThis->iRef < 1 ){
|
||||
if(pThis->iRef < 1) {
|
||||
/* No more reference to this instance */
|
||||
PH7_ClassInstanceRelease(&(*pThis));
|
||||
}
|
||||
@@ -765,7 +748,7 @@ PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis)
|
||||
* $this->flag = $flag;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*
|
||||
* $o = new Flag();
|
||||
* $p = new Flag();
|
||||
* $q = $o;
|
||||
@@ -798,21 +781,20 @@ PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis)
|
||||
* This function return 0 if the objects are equals according to the comprison rules defined above.
|
||||
* Any other return values indicates difference.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft,ph7_class_instance *pRight,int bStrict,int iNest)
|
||||
{
|
||||
SyHashEntry *pEntry,*pEntry2;
|
||||
ph7_value sV1,sV2;
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft, ph7_class_instance *pRight, int bStrict, int iNest) {
|
||||
SyHashEntry *pEntry, *pEntry2;
|
||||
ph7_value sV1, sV2;
|
||||
sxi32 rc;
|
||||
if( iNest > 31 ){
|
||||
if(iNest > 31) {
|
||||
/* Nesting limit reached */
|
||||
PH7_VmThrowError(pLeft->pVm,0,PH7_CTX_ERR,"Nesting limit reached: Infinite recursion?");
|
||||
PH7_VmThrowError(pLeft->pVm, 0, PH7_CTX_ERR, "Nesting limit reached: Infinite recursion?");
|
||||
return 1;
|
||||
}
|
||||
/* Comparison is performed only if the objects are instance of the same class */
|
||||
if( pLeft->pClass != pRight->pClass ){
|
||||
if(pLeft->pClass != pRight->pClass) {
|
||||
return 1;
|
||||
}
|
||||
if( bStrict ){
|
||||
if(bStrict) {
|
||||
/*
|
||||
* According to the PHP language reference manual:
|
||||
* when using the identity operator (===), object variables
|
||||
@@ -824,35 +806,35 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft,ph7_class_insta
|
||||
/*
|
||||
* Attribute comparison.
|
||||
* According to the PHP reference manual:
|
||||
* When using the comparison operator (==), object variables are compared
|
||||
* When using the comparison operator (==), object variables are compared
|
||||
* in a simple manner, namely: Two object instances are equal if they have
|
||||
* the same attributes and values, and are instances of the same class.
|
||||
* the same attributes and values, and are instances of the same class.
|
||||
*/
|
||||
if( pLeft == pRight ){
|
||||
if(pLeft == pRight) {
|
||||
/* Same instance,don't bother processing,object are equals */
|
||||
return 0;
|
||||
}
|
||||
SyHashResetLoopCursor(&pLeft->hAttr);
|
||||
SyHashResetLoopCursor(&pRight->hAttr);
|
||||
PH7_MemObjInit(pLeft->pVm,&sV1);
|
||||
PH7_MemObjInit(pLeft->pVm,&sV2);
|
||||
PH7_MemObjInit(pLeft->pVm, &sV1);
|
||||
PH7_MemObjInit(pLeft->pVm, &sV2);
|
||||
sV1.nIdx = sV2.nIdx = SXU32_HIGH;
|
||||
while((pEntry = SyHashGetNextEntry(&pLeft->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pRight->hAttr)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pLeft->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pRight->hAttr)) != 0) {
|
||||
VmClassAttr *p1 = (VmClassAttr *)pEntry->pUserData;
|
||||
VmClassAttr *p2 = (VmClassAttr *)pEntry2->pUserData;
|
||||
/* Compare only non-static attribute */
|
||||
if( (p1->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT|PH7_CLASS_ATTR_STATIC)) == 0 ){
|
||||
ph7_value *pL,*pR;
|
||||
pL = ExtractClassAttrValue(pLeft->pVm,p1);
|
||||
pR = ExtractClassAttrValue(pRight->pVm,p2);
|
||||
if( pL && pR ){
|
||||
PH7_MemObjLoad(pL,&sV1);
|
||||
PH7_MemObjLoad(pR,&sV2);
|
||||
if((p1->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
|
||||
ph7_value *pL, *pR;
|
||||
pL = ExtractClassAttrValue(pLeft->pVm, p1);
|
||||
pR = ExtractClassAttrValue(pRight->pVm, p2);
|
||||
if(pL && pR) {
|
||||
PH7_MemObjLoad(pL, &sV1);
|
||||
PH7_MemObjLoad(pR, &sV2);
|
||||
/* Compare the two values now */
|
||||
rc = PH7_MemObjCmp(&sV1,&sV2,bStrict,iNest+1);
|
||||
rc = PH7_MemObjCmp(&sV1, &sV2, bStrict, iNest + 1);
|
||||
PH7_MemObjRelease(&sV1);
|
||||
PH7_MemObjRelease(&sV2);
|
||||
if( rc != 0 ){
|
||||
if(rc != 0) {
|
||||
/* Not equals */
|
||||
return rc;
|
||||
}
|
||||
@@ -871,60 +853,59 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft,ph7_class_insta
|
||||
* This function SXRET_OK on success. Any other return value including
|
||||
* SXERR_LIMIT(infinite recursion) indicates failure.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut,ph7_class_instance *pThis,int ShowType,int nTab,int nDepth)
|
||||
{
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis, int ShowType, int nTab, int nDepth) {
|
||||
SyHashEntry *pEntry;
|
||||
ph7_value *pValue;
|
||||
sxi32 rc;
|
||||
int i;
|
||||
if( nDepth > 31 ){
|
||||
if(nDepth > 31) {
|
||||
static const char zInfinite[] = "Nesting limit reached: Infinite recursion?";
|
||||
/* Nesting limit reached..halt immediately*/
|
||||
SyBlobAppend(&(*pOut),zInfinite,sizeof(zInfinite)-1);
|
||||
if( ShowType ){
|
||||
SyBlobAppend(&(*pOut),")",sizeof(char));
|
||||
SyBlobAppend(&(*pOut), zInfinite, sizeof(zInfinite) - 1);
|
||||
if(ShowType) {
|
||||
SyBlobAppend(&(*pOut), ")", sizeof(char));
|
||||
}
|
||||
return SXERR_LIMIT;
|
||||
}
|
||||
rc = SXRET_OK;
|
||||
if( !ShowType ){
|
||||
SyBlobAppend(&(*pOut),"Object(",sizeof("Object(")-1);
|
||||
if(!ShowType) {
|
||||
SyBlobAppend(&(*pOut), "Object(", sizeof("Object(") - 1);
|
||||
}
|
||||
/* Append class name */
|
||||
SyBlobFormat(&(*pOut),"%z) {",&pThis->pClass->sName);
|
||||
SyBlobFormat(&(*pOut), "%z) {", &pThis->pClass->sName);
|
||||
#ifdef __WINNT__
|
||||
SyBlobAppend(&(*pOut),"\r\n",sizeof("\r\n")-1);
|
||||
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
|
||||
#else
|
||||
SyBlobAppend(&(*pOut),"\n",sizeof(char));
|
||||
SyBlobAppend(&(*pOut), "\n", sizeof(char));
|
||||
#endif
|
||||
/* Dump object attributes */
|
||||
SyHashResetLoopCursor(&pThis->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0){
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
|
||||
VmClassAttr *pVmAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT|PH7_CLASS_ATTR_STATIC)) == 0 ){
|
||||
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
|
||||
/* Dump non-static/constant attribute only */
|
||||
for( i = 0 ; i < nTab ; i++ ){
|
||||
SyBlobAppend(&(*pOut)," ",sizeof(char));
|
||||
for(i = 0 ; i < nTab ; i++) {
|
||||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
pValue = ExtractClassAttrValue(pThis->pVm,pVmAttr);
|
||||
if( pValue ){
|
||||
SyBlobFormat(&(*pOut),"['%z'] =>",&pVmAttr->pAttr->sName);
|
||||
pValue = ExtractClassAttrValue(pThis->pVm, pVmAttr);
|
||||
if(pValue) {
|
||||
SyBlobFormat(&(*pOut), "['%z'] =>", &pVmAttr->pAttr->sName);
|
||||
#ifdef __WINNT__
|
||||
SyBlobAppend(&(*pOut),"\r\n",sizeof("\r\n")-1);
|
||||
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
|
||||
#else
|
||||
SyBlobAppend(&(*pOut),"\n",sizeof(char));
|
||||
SyBlobAppend(&(*pOut), "\n", sizeof(char));
|
||||
#endif
|
||||
rc = PH7_MemObjDump(&(*pOut),pValue,ShowType,nTab+1,nDepth,0);
|
||||
if( rc == SXERR_LIMIT ){
|
||||
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth, 0);
|
||||
if(rc == SXERR_LIMIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for( i = 0 ; i < nTab ; i++ ){
|
||||
SyBlobAppend(&(*pOut)," ",sizeof(char));
|
||||
for(i = 0 ; i < nTab ; i++) {
|
||||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
SyBlobAppend(&(*pOut),"}",sizeof(char));
|
||||
SyBlobAppend(&(*pOut), "}", sizeof(char));
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
@@ -975,31 +956,30 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCallMagicMethod(
|
||||
const char *zMethod, /* Magic method name [i.e: __toString()]*/
|
||||
sxu32 nByte, /* zMethod length*/
|
||||
const SyString *pAttrName /* Attribute name */
|
||||
)
|
||||
{
|
||||
ph7_value *apArg[2] = { 0 , 0 };
|
||||
) {
|
||||
ph7_value *apArg[2] = { 0, 0 };
|
||||
ph7_class_method *pMeth;
|
||||
ph7_value sAttr; /* cc warning */
|
||||
sxi32 rc;
|
||||
int nArg;
|
||||
/* Make sure the magic method is available */
|
||||
pMeth = PH7_ClassExtractMethod(&(*pClass),zMethod,nByte);
|
||||
if( pMeth == 0 ){
|
||||
pMeth = PH7_ClassExtractMethod(&(*pClass), zMethod, nByte);
|
||||
if(pMeth == 0) {
|
||||
/* No such method,return immediately */
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
nArg = 0;
|
||||
/* Copy arguments */
|
||||
if( pAttrName ){
|
||||
PH7_MemObjInitFromString(pVm,&sAttr,pAttrName);
|
||||
if(pAttrName) {
|
||||
PH7_MemObjInitFromString(pVm, &sAttr, pAttrName);
|
||||
sAttr.nIdx = SXU32_HIGH; /* Mark as constant */
|
||||
apArg[0] = &sAttr;
|
||||
nArg = 1;
|
||||
}
|
||||
/* Call the magic method now */
|
||||
rc = PH7_VmCallClassMethod(pVm,&(*pThis),pMeth,0,nArg,apArg);
|
||||
rc = PH7_VmCallClassMethod(pVm, &(*pThis), pMeth, 0, nArg, apArg);
|
||||
/* Clean up */
|
||||
if( pAttrName ){
|
||||
if(pAttrName) {
|
||||
PH7_MemObjRelease(&sAttr);
|
||||
}
|
||||
return rc;
|
||||
@@ -1008,11 +988,10 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCallMagicMethod(
|
||||
* Extract the value of a class instance [i.e: Object in the PHP jargon].
|
||||
* This function is simply a wrapper on ExtractClassAttrValue().
|
||||
*/
|
||||
PH7_PRIVATE ph7_value * PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pThis,VmClassAttr *pAttr)
|
||||
{
|
||||
/* Extract the attribute value */
|
||||
ph7_value *pValue;
|
||||
pValue = ExtractClassAttrValue(pThis->pVm,pAttr);
|
||||
PH7_PRIVATE ph7_value *PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pThis, VmClassAttr *pAttr) {
|
||||
/* Extract the attribute value */
|
||||
ph7_value *pValue;
|
||||
pValue = ExtractClassAttrValue(pThis->pVm, pAttr);
|
||||
return pValue;
|
||||
}
|
||||
/*
|
||||
@@ -1025,7 +1004,7 @@ PH7_PRIVATE ph7_value * PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pT
|
||||
*
|
||||
* The following example:
|
||||
* class Test {
|
||||
* public $A = 25<<1; // 50
|
||||
* public $A = 25<<1; // 50
|
||||
* public $c = rand_str(3); // Random string of length 3
|
||||
* public $d = rand() & 1023; // Random number between 0..1023
|
||||
* }
|
||||
@@ -1042,10 +1021,9 @@ PH7_PRIVATE ph7_value * PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pT
|
||||
* You have noticed that PH7 allow class attributes [i.e: $a,$c,$d in the example above]
|
||||
* have any complex expression (even function calls/Annonymous functions) as their default
|
||||
* value unlike the standard PHP engine.
|
||||
* This is a very powerful feature that you have to look at.
|
||||
* This is a very powerful feature that you have to look at.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceToHashmap(ph7_class_instance *pThis,ph7_hashmap *pMap)
|
||||
{
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceToHashmap(ph7_class_instance *pThis, ph7_hashmap *pMap) {
|
||||
SyHashEntry *pEntry;
|
||||
SyString *pAttrName;
|
||||
VmClassAttr *pAttr;
|
||||
@@ -1053,18 +1031,18 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceToHashmap(ph7_class_instance *pThis,ph7_hashm
|
||||
ph7_value sName;
|
||||
/* Reset the loop cursor */
|
||||
SyHashResetLoopCursor(&pThis->hAttr);
|
||||
PH7_MemObjInitFromString(pThis->pVm,&sName,0);
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0 ){
|
||||
PH7_MemObjInitFromString(pThis->pVm, &sName, 0);
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
|
||||
/* Point to the current attribute */
|
||||
pAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
/* Extract attribute value */
|
||||
pValue = ExtractClassAttrValue(pThis->pVm,pAttr);
|
||||
if( pValue ){
|
||||
pValue = ExtractClassAttrValue(pThis->pVm, pAttr);
|
||||
if(pValue) {
|
||||
/* Build attribute name */
|
||||
pAttrName = &pAttr->pAttr->sName;
|
||||
PH7_MemObjStringAppend(&sName,pAttrName->zString,pAttrName->nByte);
|
||||
PH7_MemObjStringAppend(&sName, pAttrName->zString, pAttrName->nByte);
|
||||
/* Perform the insertion */
|
||||
PH7_HashmapInsert(pMap,&sName,pValue);
|
||||
PH7_HashmapInsert(pMap, &sName, pValue);
|
||||
/* Reset the string cursor */
|
||||
SyBlobReset(&sName.sBlob);
|
||||
}
|
||||
@@ -1073,9 +1051,9 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceToHashmap(ph7_class_instance *pThis,ph7_hashm
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Iterate throw class attributes and invoke the given callback [i.e: xWalk()] for each
|
||||
* Iterate throw class attributes and invoke the given callback [i.e: xWalk()] for each
|
||||
* retrieved attribute.
|
||||
* Note that argument are passed to the callback by copy. That is,any modification to
|
||||
* Note that argument are passed to the callback by copy. That is,any modification to
|
||||
* the attribute value in the callback body will not alter the real attribute value.
|
||||
* If the callback wishes to abort processing [i.e: it's invocation] it must return
|
||||
* a value different from PH7_OK.
|
||||
@@ -1083,10 +1061,9 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceToHashmap(ph7_class_instance *pThis,ph7_hashm
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceWalk(
|
||||
ph7_class_instance *pThis, /* Target object */
|
||||
int (*xWalk)(const char *,ph7_value *,void *), /* Walker callback */
|
||||
int (*xWalk)(const char *, ph7_value *, void *), /* Walker callback */
|
||||
void *pUserData /* Last argument to xWalk() */
|
||||
)
|
||||
{
|
||||
) {
|
||||
SyHashEntry *pEntry; /* Hash entry */
|
||||
VmClassAttr *pAttr; /* Pointer to the attribute */
|
||||
ph7_value *pValue; /* Attribute value */
|
||||
@@ -1094,19 +1071,19 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceWalk(
|
||||
int rc;
|
||||
/* Reset the loop cursor */
|
||||
SyHashResetLoopCursor(&pThis->hAttr);
|
||||
PH7_MemObjInit(pThis->pVm,&sValue);
|
||||
PH7_MemObjInit(pThis->pVm, &sValue);
|
||||
/* Start the walk process */
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0 ){
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
|
||||
/* Point to the current attribute */
|
||||
pAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
/* Extract attribute value */
|
||||
pValue = ExtractClassAttrValue(pThis->pVm,pAttr);
|
||||
if( pValue ){
|
||||
PH7_MemObjLoad(pValue,&sValue);
|
||||
pValue = ExtractClassAttrValue(pThis->pVm, pAttr);
|
||||
if(pValue) {
|
||||
PH7_MemObjLoad(pValue, &sValue);
|
||||
/* Invoke the supplied callback */
|
||||
rc = xWalk(SyStringData(&pAttr->pAttr->sName),&sValue,pUserData);
|
||||
rc = xWalk(SyStringData(&pAttr->pAttr->sName), &sValue, pUserData);
|
||||
PH7_MemObjRelease(&sValue);
|
||||
if( rc != PH7_OK){
|
||||
if(rc != PH7_OK) {
|
||||
/* User callback request an operation abort */
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
@@ -1123,23 +1100,22 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceWalk(
|
||||
* will return NULL in case someone (host-application code) try to extract
|
||||
* a static/constant attribute.
|
||||
*/
|
||||
PH7_PRIVATE ph7_value * PH7_ClassInstanceFetchAttr(ph7_class_instance *pThis,const SyString *pName)
|
||||
{
|
||||
PH7_PRIVATE ph7_value *PH7_ClassInstanceFetchAttr(ph7_class_instance *pThis, const SyString *pName) {
|
||||
SyHashEntry *pEntry;
|
||||
VmClassAttr *pAttr;
|
||||
/* Query the attribute hashtable */
|
||||
pEntry = SyHashGet(&pThis->hAttr,(const void *)pName->zString,pName->nByte);
|
||||
if( pEntry == 0 ){
|
||||
pEntry = SyHashGet(&pThis->hAttr, (const void *)pName->zString, pName->nByte);
|
||||
if(pEntry == 0) {
|
||||
/* No such attribute */
|
||||
return 0;
|
||||
}
|
||||
/* Point to the class atrribute */
|
||||
pAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
/* Check if we are dealing with a static/constant attribute */
|
||||
if( pAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT|PH7_CLASS_ATTR_STATIC) ){
|
||||
if(pAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) {
|
||||
/* Access is forbidden */
|
||||
return 0;
|
||||
}
|
||||
/* Return the attribute value */
|
||||
return ExtractClassAttrValue(pThis->pVm,pAttr);
|
||||
return ExtractClassAttrValue(pThis->pVm, pAttr);
|
||||
}
|
||||
|
Reference in New Issue
Block a user