diff --git a/harbour/ChangeLog.txt b/harbour/ChangeLog.txt index 7f65c19152..c0a48bb455 100644 --- a/harbour/ChangeLog.txt +++ b/harbour/ChangeLog.txt @@ -10,6 +10,47 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2013-02-05 23:04 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * harbour/include/hboo.ch + * added small comment + + * harbour/include/hbapirdd.h + * harbour/src/rdd/workarea.c + * fixed typo in parameter name + + * harbour/include/hbapi.h + * harbour/src/vm/arrays.c + + added to new C functions: hb_arraySetCPtr() and hb_arraySetCConst() + + * harbour/src/vm/classes.c + + added support for passing assign type restrictions to in + HB_OO_MSG_PROPERTY and HB_OO_MSG_CLASSPROPERTY in __clsAddMsg() + It can be done by new option 7-th parameter. + + added support for super class casting in __objGetIVars() and + __objSetIVars(). Now this functions can be used to serialize + all object instance variables also overloaded by other classes + so they can be accessed only with super class casting or by + nonvirtual messages. It means that above functions create fully + functional serialization system and can be used as backed for + HB_SERIALIZE() and HB_VALTOEXP() when objects are serialized. + Such serialization consumes more time and needs more memory but + objects can be deserialized by modified code which uses slightly + different raw object representation. The original HB_SERIALIZE()/ + HB_VALTOEXP() format is very fast and compact but it needs exactly + the same raw object representation in the program which serialized + object and in the program which later desrialize it. It may create + serious problems if programmer modify the code, i.e adding new + instance variables or changing their order in the object class or + or in one of its ancestors and then tries to restore some objects + serialized by previous program version. + * updated some comments and few typos in local names + + * harbour/src/rtl/valtoexp.prg + * modified HB_VALTOEXP() to use be default __objGetIVars() and + __objSetIVars() to serialize objects. + + added 2-nd parameter to HB_VALTOEXP(). By default it's .F. + Setting it to .T. forces all raw serialization format. + 2013-02-05 13:01 UTC+0100 Viktor Szakats (harbour syenar.net) * utils/hbmk2/hbmk2.prg * utils/hbmk2/hbmk2.es_PE.po diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index c2dc64cbbb..ffca725e94 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -840,7 +840,9 @@ extern HB_EXPORT HB_BOOL hb_arraySetNInt( PHB_ITEM pArray, HB_SIZE nIndex, extern HB_EXPORT HB_BOOL hb_arraySetND( PHB_ITEM pArray, HB_SIZE nIndex, double dNumber ); extern HB_EXPORT HB_BOOL hb_arraySetC( PHB_ITEM pArray, HB_SIZE nIndex, const char * szText ); extern HB_EXPORT HB_BOOL hb_arraySetCL( PHB_ITEM pArray, HB_SIZE nIndex, const char * szText, HB_SIZE nLen ); +extern HB_EXPORT HB_BOOL hb_arraySetCPtr( PHB_ITEM pArray, HB_SIZE nIndex, char * szText ); extern HB_EXPORT HB_BOOL hb_arraySetCLPtr( PHB_ITEM pArray, HB_SIZE nIndex, char * szText, HB_SIZE nLen ); +extern HB_EXPORT HB_BOOL hb_arraySetCConst( PHB_ITEM pArray, HB_SIZE nIndex, const char * szText ); extern HB_EXPORT HB_BOOL hb_arraySetPtr( PHB_ITEM pArray, HB_SIZE nIndex, void * pValue ); extern HB_EXPORT HB_BOOL hb_arraySetPtrGC( PHB_ITEM pArray, HB_SIZE nIndex, void * pValue ); extern HB_EXPORT HB_BOOL hb_arraySetSymbol( PHB_ITEM pArray, HB_SIZE nIndex, PHB_SYMB pSymbol ); diff --git a/harbour/include/hbapirdd.h b/harbour/include/hbapirdd.h index 87fa3aa756..d772e085cb 100644 --- a/harbour/include/hbapirdd.h +++ b/harbour/include/hbapirdd.h @@ -1178,7 +1178,7 @@ extern HB_EXPORT void hb_rddReleaseCurrentArea( void ); extern HB_EXPORT int hb_rddRegister( const char * szDriver, HB_USHORT uiType ); extern HB_EXPORT HB_ERRCODE hb_rddInherit( RDDFUNCS * pTable, const RDDFUNCS * pSubTable, RDDFUNCS * pSuperTable, const char * szDrvName ); extern HB_EXPORT HB_ERRCODE hb_rddInheritEx( RDDFUNCS * pTable, const RDDFUNCS * pSubTable, RDDFUNCS * pSuperTable, const char * szDrvName, HB_USHORT * puiSuperRddId ); -extern HB_EXPORT HB_BOOL hb_rddIsDerivedFrom( HB_USHORT uiRddID, HB_USHORT uiSupperRddID ); +extern HB_EXPORT HB_BOOL hb_rddIsDerivedFrom( HB_USHORT uiRddID, HB_USHORT uiSuperRddID ); extern HB_EXPORT LPRDDNODE hb_rddGetNode( HB_USHORT uiNode ); extern HB_EXPORT LPRDDNODE hb_rddFindNode( const char * szDriver, HB_USHORT * uiIndex ); extern HB_EXPORT HB_USHORT hb_rddFieldIndex( AREAP pArea, const char * szName ); diff --git a/harbour/include/hboo.ch b/harbour/include/hboo.ch index 5e67e5c5d0..7124a864b7 100644 --- a/harbour/include/hboo.ch +++ b/harbour/include/hboo.ch @@ -103,7 +103,7 @@ #define HB_OO_MSG_CLSACCESS 11 #define HB_OO_MSG_REALCLASS 12 #define HB_OO_MSG_DESTRUCTOR 13 -#define HB_OO_MSG_INITIALIZED 14 +#define HB_OO_MSG_INITIALIZED 14 /* initialized class data: HB_OO_MSG_CLASSDATA */ #define HB_OO_MSG_PERFORM 15 #define HB_OO_MSG_DELEGATE 16 diff --git a/harbour/src/rdd/workarea.c b/harbour/src/rdd/workarea.c index b19c6adf17..53255083c0 100644 --- a/harbour/src/rdd/workarea.c +++ b/harbour/src/rdd/workarea.c @@ -2204,14 +2204,14 @@ int hb_rddRegister( const char * szDriver, HB_USHORT uiType ) */ HB_ERRCODE hb_rddInheritEx( RDDFUNCS * pTable, const RDDFUNCS * pSubTable, RDDFUNCS * pSuperTable, const char * szDrvName, - HB_USHORT * puiSupperRddId ) + HB_USHORT * puiSuperRddId ) { LPRDDNODE pRddNode; HB_USHORT uiCount; DBENTRYP_V * pFunction; const DBENTRYP_V * pSubFunction; - HB_TRACE( HB_TR_DEBUG, ( "hb_rddInheritEx(%p, %p, %p, %s, %p)", pTable, pSubTable, pSuperTable, szDrvName, puiSupperRddId ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_rddInheritEx(%p, %p, %p, %s, %p)", pTable, pSubTable, pSuperTable, szDrvName, puiSuperRddId ) ); if( ! pTable ) { @@ -2224,8 +2224,8 @@ HB_ERRCODE hb_rddInheritEx( RDDFUNCS * pTable, const RDDFUNCS * pSubTable, /* no name for inherited driver - use the default one */ memcpy( pTable, &waTable, sizeof( RDDFUNCS ) ); memcpy( pSuperTable, &waTable, sizeof( RDDFUNCS ) ); - if( puiSupperRddId ) - *puiSupperRddId = ( HB_USHORT ) -1; + if( puiSuperRddId ) + *puiSuperRddId = ( HB_USHORT ) -1; } else { @@ -2238,8 +2238,8 @@ HB_ERRCODE hb_rddInheritEx( RDDFUNCS * pTable, const RDDFUNCS * pSubTable, memcpy( pTable, &pRddNode->pTable, sizeof( RDDFUNCS ) ); memcpy( pSuperTable, &pRddNode->pTable, sizeof( RDDFUNCS ) ); - if( puiSupperRddId ) - *puiSupperRddId = pRddNode->rddID; + if( puiSuperRddId ) + *puiSuperRddId = pRddNode->rddID; } /* Copy the non NULL entries from pSubTable into pTable */ @@ -2263,15 +2263,15 @@ HB_ERRCODE hb_rddInherit( RDDFUNCS * pTable, const RDDFUNCS * pSubTable, return hb_rddInheritEx( pTable, pSubTable, pSuperTable, szDrvName, NULL ); } -HB_BOOL hb_rddIsDerivedFrom( HB_USHORT uiRddID, HB_USHORT uiSupperRddID ) +HB_BOOL hb_rddIsDerivedFrom( HB_USHORT uiRddID, HB_USHORT uiSuperRddID ) { - if( uiRddID == uiSupperRddID ) + if( uiRddID == uiSuperRddID ) return HB_TRUE; while( uiRddID < s_uiRddCount ) { uiRddID = s_RddList[ uiRddID ]->rddSuperID; - if( uiRddID == uiSupperRddID ) + if( uiRddID == uiSuperRddID ) return HB_TRUE; } return HB_FALSE; diff --git a/harbour/src/rtl/valtoexp.prg b/harbour/src/rtl/valtoexp.prg index 83c9604bfd..e461c01a5c 100644 --- a/harbour/src/rtl/valtoexp.prg +++ b/harbour/src/rtl/valtoexp.prg @@ -75,15 +75,17 @@ FUNCTION hb_CStr( xVal ) RETURN "???:" + v -REQUEST __objSetClass +REQUEST __objSetClass, __objGetIVars, __objSetIVars -FUNCTION hb_ValToExp( xVal ) +FUNCTION hb_ValToExp( xVal, lRaw ) - RETURN s_valToExp( xVal ) + hb_default( @lRaw, .F. ) -STATIC FUNCTION s_valToExp( xVal, cInd, hRefs, cRefs ) + RETURN s_valToExp( xVal, lRaw ) - LOCAL cVal, cKey +STATIC FUNCTION s_valToExp( xVal, lRaw, cInd, hRefs, cRefs ) + + LOCAL cVal, cKey, cClass LOCAL tmp LOCAL v := ValType( xVal ) @@ -95,8 +97,12 @@ STATIC FUNCTION s_valToExp( xVal, cInd, hRefs, cRefs ) CASE "T" ; RETURN 't"' + hb_TSToStr( xVal, .T. ) + '"' CASE "L" ; RETURN iif( xVal, ".T.", ".F." ) CASE "S" ; RETURN "@" + xVal:name + "()" - CASE "A" CASE "O" + cClass := xVal:className() + IF !lRaw + xVal := __objGetIVars( xVal ) + ENDIF + CASE "A" CASE "H" tmp := __vmItemID( xVal ) IF cInd == NIL @@ -119,10 +125,10 @@ STATIC FUNCTION s_valToExp( xVal, cInd, hRefs, cRefs ) ELSE cVal := "{" FOR EACH tmp IN xVal - cKey := s_valToExp( tmp:__enumKey() ) + cKey := s_valToExp( tmp:__enumKey(), lRaw ) cVal += iif( tmp:__enumIndex() == 1, "", ", " ) + ; cKey + "=>" + ; - s_valToExp( tmp, cInd + cKey, hRefs, @cRefs ) + s_valToExp( tmp, lRaw, cInd + cKey, hRefs, @cRefs ) NEXT cVal += "}" ENDIF @@ -130,7 +136,7 @@ STATIC FUNCTION s_valToExp( xVal, cInd, hRefs, cRefs ) cVal := "{" FOR EACH tmp IN xVal cVal += iif( tmp:__enumIndex() == 1, "", ", " ) + ; - s_valToExp( tmp, cInd + hb_ntos( tmp:__enumIndex() ), hRefs, @cRefs ) + s_valToExp( tmp, lRaw, cInd + hb_ntos( tmp:__enumIndex() ), hRefs, @cRefs ) NEXT cVal += "}" ENDIF @@ -139,7 +145,11 @@ STATIC FUNCTION s_valToExp( xVal, cInd, hRefs, cRefs ) cVal := "__itemSetRef( " + cVal + ", {" + cRefs + "} )" ENDIF IF v == "O" - cVal := "__objSetClass( " + cVal + ", '" + xVal:className() + "' )" + IF lRaw + cVal := "__objSetClass( " + cVal + ", '" + cClass + "' )" + ELSE + cVal := "__objSetIVars( '" + cClass + "', " + cVal + " )" + ENDIF ENDIF EXIT CASE "P" ; RETURN "" diff --git a/harbour/src/vm/arrays.c b/harbour/src/vm/arrays.c index 615effd981..8af5987350 100644 --- a/harbour/src/vm/arrays.c +++ b/harbour/src/vm/arrays.c @@ -891,6 +891,19 @@ HB_BOOL hb_arraySetCL( PHB_ITEM pArray, HB_SIZE nIndex, const char * szText, HB_ return HB_FALSE; } +HB_BOOL hb_arraySetCPtr( PHB_ITEM pArray, HB_SIZE nIndex, char * szText ) +{ + HB_TRACE( HB_TR_DEBUG, ( "hb_arraySetCLPtr(%p, %" HB_PFS "u, %p)", pArray, nIndex, szText ) ); + + if( HB_IS_ARRAY( pArray ) && nIndex > 0 && nIndex <= pArray->item.asArray.value->nLen ) + { + hb_itemPutCPtr( pArray->item.asArray.value->pItems + nIndex - 1, szText ); + return HB_TRUE; + } + else + return HB_FALSE; +} + HB_BOOL hb_arraySetCLPtr( PHB_ITEM pArray, HB_SIZE nIndex, char * szText, HB_SIZE nLen ) { HB_TRACE( HB_TR_DEBUG, ( "hb_arraySetCLPtr(%p, %" HB_PFS "u, %p, %" HB_PFS "u)", pArray, nIndex, szText, nLen ) ); @@ -904,6 +917,19 @@ HB_BOOL hb_arraySetCLPtr( PHB_ITEM pArray, HB_SIZE nIndex, char * szText, HB_SIZ return HB_FALSE; } +HB_BOOL hb_arraySetCConst( PHB_ITEM pArray, HB_SIZE nIndex, const char * szText ) +{ + HB_TRACE( HB_TR_DEBUG, ( "hb_arraySetCConst(%p, %" HB_PFS "u, %p)", pArray, nIndex, szText ) ); + + if( HB_IS_ARRAY( pArray ) && nIndex > 0 && nIndex <= pArray->item.asArray.value->nLen ) + { + hb_itemPutCConst( pArray->item.asArray.value->pItems + nIndex - 1, szText ); + return HB_TRUE; + } + else + return HB_FALSE; +} + HB_BOOL hb_arraySetPtr( PHB_ITEM pArray, HB_SIZE nIndex, void * pValue ) { HB_TRACE( HB_TR_DEBUG, ( "hb_arraySetPtr(%p, %" HB_PFS "u, %p)", pArray, nIndex, pValue ) ); diff --git a/harbour/src/vm/classes.c b/harbour/src/vm/classes.c index 55080a0a3a..6a3e3775ab 100644 --- a/harbour/src/vm/classes.c +++ b/harbour/src/vm/classes.c @@ -764,16 +764,17 @@ static HB_BOOL hb_clsHasParentClass( PCLASS pClass, HB_USHORT uiParentCls ) */ } -static HB_BOOL hb_clsHasParent( PCLASS pClass, PHB_DYNS pParentSym ) +static HB_USHORT hb_clsGetParent( PCLASS pClass, PHB_DYNS pParentSym ) { HB_USHORT uiCount = pClass->uiSuperClasses; while( uiCount ) { - if( s_pClasses[ pClass->pSuperClasses[ --uiCount ].uiClass ]->pClassSym == pParentSym ) - return HB_TRUE; + HB_USHORT uiClass = pClass->pSuperClasses[ --uiCount ].uiClass; + if( s_pClasses[ uiClass ]->pClassSym == pParentSym ) + return uiClass; } - return HB_FALSE; + return 0; /* alternative method but can give wrong results * if user overloads super casting method, [druzus]. @@ -948,6 +949,9 @@ static HB_BOOL hb_clsUpdateHiddenMessages( PMETHOD pSrcMethod, PMETHOD pDstMetho PCLASS pSrcClass = s_pClasses[ pDstMethod->uiSprClass ]; HB_USHORT uiData; + /* check if we already have corresponding access or assign + * message for this class var to reuse its index + */ uiData = hb_clsFindClassDataOffset( pDstClass, pDstMethod ); if( uiData == 0 ) @@ -970,9 +974,9 @@ static HB_BOOL hb_clsUpdateHiddenMessages( PMETHOD pSrcMethod, PMETHOD pDstMetho return HB_FALSE; } -static void hb_clsAddSupperClass( PCLASS pClass, HB_USHORT uiSuperCls, HB_USHORT uiOffset ) +static void hb_clsAddSuperClass( PCLASS pClass, HB_USHORT uiSuperCls, HB_USHORT uiOffset ) { - HB_TRACE( HB_TR_DEBUG, ( "hb_clsAddSupperClass(%p,%hu,%hu)", pClass, uiSuperCls, uiOffset ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_clsAddSuperClass(%p,%hu,%hu)", pClass, uiSuperCls, uiOffset ) ); pClass->pSuperClasses = ( PHB_CLSCAST ) hb_xrealloc( pClass->pSuperClasses, ( pClass->uiSuperClasses + 1 ) * sizeof( HB_CLSCAST ) ); @@ -980,12 +984,12 @@ static void hb_clsAddSupperClass( PCLASS pClass, HB_USHORT uiSuperCls, HB_USHORT pClass->pSuperClasses[ pClass->uiSuperClasses++ ].uiOffset = uiOffset; } -static void hb_clsDefineSupperClass( PCLASS pClass, HB_USHORT uiSuperCls, HB_BOOL fNew ) +static void hb_clsDefineSuperClass( PCLASS pClass, HB_USHORT uiSuperCls, HB_BOOL fNew ) { PMETHOD pMethod; PCLASS pSprCls; - HB_TRACE( HB_TR_DEBUG, ( "hb_clsDefineSupperClass(%p,%hu,%d)", pClass, uiSuperCls, fNew ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_clsDefineSuperClass(%p,%hu,%d)", pClass, uiSuperCls, fNew ) ); pSprCls = s_pClasses[ uiSuperCls ]; @@ -993,11 +997,11 @@ static void hb_clsDefineSupperClass( PCLASS pClass, HB_USHORT uiSuperCls, HB_BOO { if( fNew ) { - hb_clsAddSupperClass( pClass, uiSuperCls, pClass->uiDatas ); + hb_clsAddSuperClass( pClass, uiSuperCls, pClass->uiDatas ); pClass->uiDatas += pSprCls->uiDatas - pSprCls->uiDataFirst; } else - hb_clsAddSupperClass( pClass, uiSuperCls, pSprCls->uiDataFirst ); + hb_clsAddSuperClass( pClass, uiSuperCls, pSprCls->uiDataFirst ); } pMethod = hb_clsAllocMsg( pClass, pSprCls->pClassSym ); @@ -1088,7 +1092,7 @@ static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc ) memcpy( pClsDst->pSuperClasses, pClsSrc->pSuperClasses, pClsSrc->uiSuperClasses * sizeof( HB_CLSCAST ) ); } - hb_clsDefineSupperClass( pClsDst, pClsSrc->uiClass, HB_FALSE ); + hb_clsDefineSuperClass( pClsDst, pClsSrc->uiClass, HB_FALSE ); pMethod = pClsDst->pMethods; do @@ -1376,7 +1380,7 @@ HB_BOOL hb_clsIsParent( HB_USHORT uiClass, const char * szParentName ) PHB_DYNS pMsg = hb_dynsymFindName( szParentName ); if( pMsg ) - return hb_clsHasParent( pClass, pMsg ); + return hb_clsGetParent( pClass, pMsg ) != 0; } } @@ -1542,25 +1546,35 @@ const char * hb_clsMethodName( HB_USHORT uiClass, HB_USHORT uiMethod ) return NULL; } -HB_SIZE hb_clsGetVarIndex( HB_USHORT uiClass, PHB_DYNS pVarSym ) +static HB_SIZE hb_clsGetVarIndexEx( HB_USHORT uiClass, PHB_DYNS pVarSym, + HB_USHORT uiSuper ) { - if( uiClass && uiClass <= s_uiClasses ) + PMETHOD pMethod = hb_clsFindMsg( s_pClasses[ uiSuper ], pVarSym ); + if( pMethod ) { - PMETHOD pMethod = hb_clsFindMsg( s_pClasses[ uiClass ], pVarSym ); - if( pMethod ) + PHB_SYMB pFuncSym = pMethod->pFuncSym; + + if( pFuncSym == &s___msgSync || pFuncSym == &s___msgSyncClass ) + pFuncSym = pMethod->pRealSym; + + if( pFuncSym == &s___msgSetData || pFuncSym == &s___msgGetData ) { - PHB_SYMB pFuncSym = pMethod->pFuncSym; - - if( pFuncSym == &s___msgSync || pFuncSym == &s___msgSyncClass ) - pFuncSym = pMethod->pRealSym; - - if( pFuncSym == &s___msgSetData || pFuncSym == &s___msgGetData ) - return pMethod->uiData + pMethod->uiOffset; + return ( HB_SIZE ) pMethod->uiData + ( uiClass != uiSuper ? + hb_clsParentInstanceOffset( s_pClasses[ uiClass ], uiSuper ) : + pMethod->uiOffset ); } } return 0; } +HB_SIZE hb_clsGetVarIndex( HB_USHORT uiClass, PHB_DYNS pVarSym ) +{ + if( uiClass && uiClass <= s_uiClasses ) + return hb_clsGetVarIndexEx( uiClass, pVarSym, uiClass ); + else + return 0; +} + HB_USHORT hb_clsFindClass( const char * szClass, const char * szFunc ) { HB_USHORT uiClass; @@ -2317,9 +2331,9 @@ HB_BOOL hb_clsHasDestructor( HB_USHORT uiClass ) } /* - * Call all known supper destructors + * Call all known super destructors */ -static void hb_objSupperDestructorCall( PHB_ITEM pObject, PCLASS pClass ) +static void hb_objSuperDestructorCall( PHB_ITEM pObject, PCLASS pClass ) { #if 0 HB_STACK_TLS_PRELOAD @@ -2337,8 +2351,8 @@ static void hb_objSupperDestructorCall( PHB_ITEM pObject, PCLASS pClass ) { if( pMethod->pFuncSym == &s___msgSuper ) { - PCLASS pSupperClass = s_pClasses[ pMethod->uiData ]; - if( pSupperClass->fHasDestructor && pSupperClass != pClass ) + PCLASS pSuperClass = s_pClasses[ pMethod->uiData ]; + if( pSuperClass->fHasDestructor && pSuperClass != pClass ) pcClasses[ pMethod->uiData ] |= 1; } else if( pMethod->pMessage == s___msgDestructor.pDynSym ) @@ -2382,9 +2396,9 @@ static void hb_objSupperDestructorCall( PHB_ITEM pObject, PCLASS pClass ) if( uiParentCls != uiDtorClass && uiParentCls != pClass->uiClass ) { - PCLASS pSupperClass = s_pClasses[ uiParentCls ]; + PCLASS pSuperClass = s_pClasses[ uiParentCls ]; - if( pSupperClass->fHasDestructor ) + if( pSuperClass->fHasDestructor ) { PMETHOD pDestructor = hb_clsFindMsg( s_pClasses[ uiParentCls ], s___msgDestructor.pDynSym ); @@ -2420,7 +2434,7 @@ void hb_objDestructorCall( PHB_ITEM pObject ) hb_vmPush( pObject ); hb_vmSend( 0 ); if( hb_vmRequestQuery() == 0 ) - hb_objSupperDestructorCall( pObject, pClass ); + hb_objSuperDestructorCall( pObject, pClass ); hb_vmRequestRestore(); } } @@ -2877,11 +2891,11 @@ static HB_TYPE hb_clsGetItemType( PHB_ITEM pItem, HB_TYPE nDefault ) * HB_OO_MSG_ONERROR : > Pointer to function * HB_OO_MSG_DESTRUCTOR : / * HB_OO_MSG_INLINE : Code block - * HB_OO_MSG_ASSIGN : Index to instance area array + * HB_OO_MSG_ASSIGN : Index to instance area array 1 based (without offset) * HB_OO_MSG_ACCESS : / * HB_OO_MSG_CLSASSIGN : Index class data array * HB_OO_MSG_CLSACCESS : / - * HB_OO_MSG_SUPER : Handle of super class + * HB_OO_MSG_SUPER : Instance area offset for class casting * HB_OO_MSG_DELEGATE : Delegated message symbol * * HB_OO_MSG_ACCESS : Optional initializer for (Class)DATA @@ -3175,6 +3189,9 @@ static HB_BOOL hb_clsAddMsg( HB_USHORT uiClass, const char * szMessage, { if( hb_arrayLen( pClass->pClassDatas ) < ( HB_SIZE ) pNewMeth->uiData ) hb_arraySize( pClass->pClassDatas, pNewMeth->uiData ); + /* uiOffset is used to copy ancestor class data initializaers when + * new class is created + */ pNewMeth->uiOffset = hb_clsAddInitValue( pClass, pInit, HB_OO_MSG_CLASSDATA, pNewMeth->uiData, 0, uiClass ); pNewMeth->pFuncSym = &s___msgGetClsData; @@ -3262,7 +3279,7 @@ static HB_BOOL hb_clsAddMsg( HB_USHORT uiClass, const char * szMessage, } /* - * __clsAddMsg( , , , , [xInit], ) + * __clsAddMsg( , , , , [xInit], , [xType] ) * * Add a message to the class. * @@ -3308,6 +3325,9 @@ static HB_BOOL hb_clsAddMsg( HB_USHORT uiClass, const char * szMessage, * HB_OO_CLSTP_NONVIRTUAL 512 : Class method constructor * HB_OO_CLSTP_OVERLOADED 1024 : Class method constructor * HB_OO_CLSTP_SYNC 2048 : message synchronized by object or class mutex + * + * HB_OO_MSG_PROPERTY : > optional item type restriction in assignment + * HB_OO_MSG_CLASSPROPERTY : / */ HB_FUNC( __CLSADDMSG ) @@ -3335,6 +3355,7 @@ HB_FUNC( __CLSADDMSG ) else if( nType == HB_OO_MSG_PROPERTY || nType == HB_OO_MSG_CLASSPROPERTY ) { + PHB_ITEM pType = hb_param( 7, HB_IT_ANY ); char szAssign[ HB_SYMBOL_NAME_LEN + 1 ]; int iLen = ( int ) hb_parclen( 2 ); if( iLen >= HB_SYMBOL_NAME_LEN ) @@ -3349,14 +3370,14 @@ HB_FUNC( __CLSADDMSG ) { hb_clsAddMsg( uiClass, szAssign, HB_OO_MSG_ASSIGN, ( HB_USHORT ) ( uiScope & ~HB_OO_CLSTP_PERSIST ), - pFunction, pInit ); + pFunction, pType ); nType = HB_OO_MSG_ACCESS; } else { hb_clsAddMsg( uiClass, szAssign, HB_OO_MSG_CLSASSIGN, ( HB_USHORT ) ( uiScope & ~HB_OO_CLSTP_PERSIST ), - pFunction, pInit ); + pFunction, pType ); nType = HB_OO_MSG_CLSACCESS; } } @@ -3452,8 +3473,8 @@ static HB_USHORT hb_clsNew( const char * szClassName, HB_USHORT uiDatas, /* Copy super class handles */ for( uiCount = 0; uiCount < pSprCls->uiSuperClasses; ++uiCount ) - hb_clsDefineSupperClass( pNewCls, pSprCls->pSuperClasses[ uiCount ].uiClass, HB_TRUE ); - hb_clsDefineSupperClass( pNewCls, uiSuperCls, HB_TRUE ); + hb_clsDefineSuperClass( pNewCls, pSprCls->pSuperClasses[ uiCount ].uiClass, HB_TRUE ); + hb_clsDefineSuperClass( pNewCls, uiSuperCls, HB_TRUE ); /* Copy instance area init data */ if( pSprCls->uiInitDatas ) @@ -3571,7 +3592,7 @@ static HB_USHORT hb_clsNew( const char * szClassName, HB_USHORT uiDatas, /* add self class casting */ pNewCls->uiDataFirst = pNewCls->uiDatas; - hb_clsDefineSupperClass( pNewCls, pNewCls->uiClass, HB_FALSE ); + hb_clsDefineSuperClass( pNewCls, pNewCls->uiClass, HB_FALSE ); pNewCls->uiDatas += uiDatas; if( pNewCls->uiMutexOffset ) pNewCls->uiMutexOffset = pNewCls->uiDatas + 1; @@ -5085,110 +5106,157 @@ HB_FUNC( __GETMSGPRF ) /* profiler: returns a method called and consumed times * hb_storvnl( 0, -1, 2 ); } +typedef struct +{ + PMETHOD pMethod; + HB_USHORT uiClass; + HB_USHORT uiStatus; +} +HB_IVARINFO, * PHB_IVARINFO; + +static PHB_ITEM hb_objGetIVars( PHB_ITEM pObject, + HB_USHORT uiScope, HB_BOOL fChanged ) +{ + PHB_IVARINFO pIndex, pInfo; + PCLASS pClass; + PMETHOD pMethod; + PHB_ITEM pReturn, pItem; + HB_SIZE nLimit, nLen, nCount, nSize, nIndex, nOffset; + HB_USHORT uiClass, uiSuperClasses; + + if( !pObject || !HB_IS_OBJECT( pObject ) ) + return NULL; + + uiClass = pObject->item.asArray.value->uiClass; + pClass = s_pClasses[ uiClass ]; + nLen = nCount = hb_arrayLen( pObject ); + nSize = 0; + pIndex = ( PHB_IVARINFO ) hb_xgrab( nLen * sizeof( HB_IVARINFO ) ); + memset( pIndex, 0, nLen * sizeof( HB_IVARINFO ) ); + + if( fChanged && pClass->uiInitDatas ) + { + PINITDATA pInitData = pClass->pInitData; + + nLimit = pClass->uiInitDatas; + do + { + if( pInitData->uiType == HB_OO_MSG_DATA ) + { + nIndex = pInitData->uiData + pInitData->uiOffset; + pItem = hb_arrayGetItemPtr( pObject, nIndex ); + if( pItem ) + { + if( hb_itemEqual( pItem, pInitData->pInitValue ) ) + { + pIndex[ nIndex - 1 ].uiStatus = 3; + --nCount; + } + else + pIndex[ nIndex - 1 ].uiStatus = 1; + } + } + ++pInitData; + } + while( --nLimit ); + } + + uiSuperClasses = pClass->uiSuperClasses; + nOffset = hb_clsParentInstanceOffset( pClass, uiClass ); + nLimit = hb_clsMthNum( pClass ); + pMethod = pClass->pMethods; + while( nCount && nLimit ) + { + if( pMethod->pMessage && + ( uiScope == 0 || ( pMethod->uiScope & uiScope ) != 0 ) && + ( uiClass == pClass->uiClass || pMethod->uiSprClass == uiClass ) ) + { + PHB_SYMB pFuncSym = pMethod->pFuncSym; + + if( pFuncSym == &s___msgSync || pFuncSym == &s___msgSyncClass ) + pFuncSym = pMethod->pRealSym; + + if( pFuncSym == &s___msgGetData || pFuncSym == &s___msgSetData ) + { + HB_USHORT uiStatus = pFuncSym == &s___msgGetData ? 3 : 2; + + nIndex = ( uiClass == pClass->uiClass ? + ( HB_SIZE ) pMethod->uiOffset : nOffset ) + pMethod->uiData; + if( nIndex == 0 || nIndex > nLen ) + hb_errInternal( HB_EI_CLSINVMETHOD, NULL, "__objGetIVars()", NULL ); + + pInfo = &pIndex[ nIndex - 1 ]; + if( pInfo->uiStatus < uiStatus ) + { + pItem = hb_arrayGetItemPtr( pObject, nIndex ); + if( !pItem || ( pInfo->uiStatus == 0 && HB_IS_NIL( pItem ) ) ) + uiStatus = 3; + else + { + if( !pInfo->pMethod ) + ++nSize; + pInfo->pMethod = pMethod; + pInfo->uiClass = uiClass; + } + pInfo->uiStatus = uiStatus; + if( uiStatus == 3 ) + --nCount; + } + } + } + ++pMethod; + if( --nLimit == 0 ) + { + if( uiSuperClasses ) + { + uiClass = pClass->pSuperClasses[ --uiSuperClasses ].uiClass; + nOffset = hb_clsParentInstanceOffset( pClass, uiClass ); + nLimit = hb_clsMthNum( s_pClasses[ uiClass ] ); + pMethod = s_pClasses[ uiClass ]->pMethods; + } + } + } + + nCount = 0; + pReturn = hb_itemArrayNew( nSize ); + for( nIndex = 1; nIndex <= nLen && nCount < nSize; ++nIndex ) + { + pInfo = &pIndex[ nIndex - 1 ]; + if( pInfo->pMethod ) + { + const char * pszVar = pInfo->pMethod->pMessage->pSymbol->szName; + PHB_ITEM pValue = hb_arrayGetItemPtr( pReturn, ++nCount ); + + pItem = hb_arrayGetItemPtr( pObject, nIndex ); + hb_arrayNew( pValue, 2 ); + if( pInfo->uiClass != pClass->uiClass ) + { + char * pszCast = hb_xstrcpy( NULL, s_pClasses[ pInfo->uiClass ]->szName, + ":", pszVar, NULL ); + hb_arraySetCPtr( pValue, 1, pszCast ); + } + else + hb_arraySetCConst( pValue, 1, pszVar ); + hb_arraySet( pValue, 2, pItem ); + } + } + + hb_xfree( pIndex ); + + return pReturn; +} + + /* __objGetIVars( , [], [] ) * -> { { , }, ... } */ HB_FUNC( __OBJGETIVARS ) { PHB_ITEM pObject = hb_param( 1, HB_IT_OBJECT ); + HB_USHORT uiScope = ( HB_USHORT ) hb_parni( 2 ); + HB_BOOL fChanged = hb_parldef( 3, HB_TRUE ); - if( pObject && pObject->item.asArray.value->uiClass != 0 ) - { - HB_STACK_TLS_PRELOAD - PHB_ITEM pReturn = hb_stackReturnItem(), pItem; - PCLASS pClass = s_pClasses[ pObject->item.asArray.value->uiClass ]; - PMETHOD pMethod; - PHB_SYMB pDataSym; - HB_USHORT uiScope = ( HB_USHORT ) hb_parni( 2 ); - HB_BOOL fChanged = hb_parldef( 3, HB_TRUE ); - HB_SIZE nLen, nLimit, nIndex; - - nLen = hb_arrayLen( pObject ); - hb_arrayNew( pReturn, nLen ); - if( nLen > 0 ) - { - char * pnIndex; - - pnIndex = ( char * ) hb_xgrab( nLen ); - memset( pnIndex, fChanged ? 0 : 1, nLen ); - - if( fChanged && pClass->uiInitDatas ) - { - PINITDATA pInitData = pClass->pInitData; - - nLimit = pClass->uiInitDatas; - do - { - if( pInitData->uiType == HB_OO_MSG_DATA ) - { - nIndex = pInitData->uiData + pInitData->uiOffset; - pItem = hb_arrayGetItemPtr( pObject, nIndex ); - if( pItem ) - { - pnIndex[ nIndex - 1 ] = - hb_itemEqual( pItem, pInitData->pInitValue ) ? 2 : 1; - } - } - ++pInitData; - } - while( --nLimit ); - } - - nLen = 0; - nLimit = hb_clsMthNum( pClass ); - pMethod = pClass->pMethods; - pDataSym = &s___msgGetData; - do - { - if( pMethod->pMessage && - ( uiScope == 0 || ( pMethod->uiScope & uiScope ) != 0 ) ) - { - PHB_SYMB pFuncSym = pMethod->pFuncSym; - - if( pFuncSym == &s___msgSync || pFuncSym == &s___msgSyncClass ) - pFuncSym = pMethod->pRealSym; - - if( pFuncSym == pDataSym ) - { - /* TODO: add support for nonvirtual members */ - nIndex = pMethod->uiData + pMethod->uiOffset; - pItem = hb_arrayGetItemPtr( pObject, nIndex ); - if( pItem && pnIndex[ nIndex - 1 ] != 2 && - ( pnIndex[ nIndex - 1 ] == 1 || !HB_IS_NIL( pItem ) ) ) - { - PHB_ITEM pValue = hb_arrayGetItemPtr( pReturn, nLen + 1 ); - if( pValue ) - { - hb_arrayNew( pValue, 2 ); - hb_arraySetC( pValue, 1, pMethod->pMessage->pSymbol->szName + - ( pFuncSym == &s___msgSetData ? 1 : 0 ) ); - hb_arraySet( pValue, 2, pItem ); - pnIndex[ nIndex - 1 ] = 2; - ++nLen; - } - else - break; - } - } - } - ++pMethod; - if( --nLimit == 0 ) - { - if( pDataSym == &s___msgGetData ) - { - nLimit = hb_clsMthNum( pClass ); - pMethod = pClass->pMethods; - pDataSym = &s___msgSetData; - } - } - } - while( nLimit ); - - hb_xfree( pnIndex ); - - hb_arraySize( pReturn, nLen ); - } - } + hb_itemReturnRelease( hb_objGetIVars( pObject, uiScope, fChanged ) ); } /* __objSetIVars( | | | , @@ -5215,16 +5283,40 @@ HB_FUNC( __OBJSETIVARS ) if( pObject && pArray && pArray->item.asArray.value->uiClass == 0 ) { HB_USHORT uiClass = pObject->item.asArray.value->uiClass; - HB_SIZE nPos, nIndex; + HB_SIZE nPos, nIndex, nLen; nPos = 0; while( ( pValue = hb_arrayGetItemPtr( pArray, ++nPos ) ) != NULL ) { - PHB_DYNS pVarSym = hb_dynsymFindName( hb_arrayGetCPtr( pValue, 1 ) ); + const char * pszMethod = hb_arrayGetCPtr( pValue, 1 ); + PHB_DYNS pVarSym = hb_dynsymFind( pszMethod ); PHB_ITEM pNewVal = hb_arrayGetItemPtr( pValue, 2 ); + HB_USHORT uiSuper = uiClass; - if( pNewVal && pVarSym && - ( nIndex = hb_clsGetVarIndex( uiClass, pVarSym ) ) != 0 ) + if( !pVarSym ) + { + const char * pszClass = strchr( pszMethod, ':' ); + if( pszClass ) + { + nLen = pszClass - pszMethod; + if( nLen ) + { + PHB_DYNS pParentSym; + char szClassName[ HB_SYMBOL_NAME_LEN + 1 ]; + + memcpy( szClassName, pszMethod, nLen ); + szClassName[ nLen ] = '\0'; + pParentSym = hb_dynsymFindName( szClassName ); + uiSuper = pParentSym == NULL ? 0 : + hb_clsGetParent( s_pClasses[ uiClass ], pParentSym ); + } + pVarSym = hb_dynsymFindName( pszClass + 1 ); + } + else + pVarSym = hb_dynsymFindName( pszMethod ); + } + if( uiSuper && pNewVal && pVarSym && + ( nIndex = hb_clsGetVarIndexEx( uiClass, pVarSym, uiSuper ) ) != 0 ) { hb_arraySet( pObject, nIndex, pNewVal ); } @@ -5309,7 +5401,7 @@ HB_FUNC( __CLSGETPROPERTIES ) hb_itemReturnRelease( pReturn ); } -/* __clsGetAncestors( ) -> { , , ... } +/* __clsGetAncestors( ) -> { , , ... } */ HB_FUNC( __CLSGETANCESTORS ) {