Page 1 of 1
ID generator : simulate #PB_Any
Posted: Thu Jul 30, 2009 12:39 am
by eddy
Code: Select all
CompilerIf #PB_Compiler_Debugger
Import ""
CompilerIf Defined(PB_DEBUGGER_SendWarning, #PB_Procedure)=0
PB_DEBUGGER_SendWarning(Message.p-ascii)
CompilerEndIf
CompilerIf Defined(PB_DEBUGGER_SendError, #PB_Procedure)=0
PB_DEBUGGER_SendError(Message.p-ascii)
CompilerEndIf
EndImport
CompilerElse
Macro PB_DEBUGGER_SendWarning(Message)
EndMacro
Macro PB_DEBUGGER_SendError(Message)
EndMacro
CompilerEndIf
Structure OBJ
ID.i
type.s{256}
*handle
;
; HERE YOUR CUSTOM PARAMETERS...
;
a.i
b.i
c.i
EndStructure
Global NewList OBJ.OBJ()
#OBJ_TYPE$="Custom Object Type"
Procedure.i CreateObjectHandle(a, b, c)
;
; HERE YOUR CUSTOM HANDLE MAKER...
;
*handle=AllocateMemory(1000)
PokeS(*handle, Str(a+b+c))
ProcedureReturn *handle
EndProcedure
Procedure.i CreateObject(ID, a, b, c)
Protected result
If ID>=0 And ID<=100000
AddElement(OBJ())
OBJ()\ID=ID
OBJ()\handle=CreateObjectHandle(a, b, c)
OBJ()\type=#OBJ_TYPE$
result=OBJ()\handle
ElseIf ID=#PB_Any
OBJ()\ID=AddElement(OBJ())
OBJ()\handle=CreateObjectHandle(a, b, c)
OBJ()\type=#OBJ_TYPE$
result=OBJ()\ID
Else
PB_DEBUGGER_SendError("#ID is out of range (0-100000)")
ProcedureReturn #False
EndIf
;
; HERE SAVE YOUR CUSTOM PARAMETERS
;
OBJ()\a=a
OBJ()\b=b
OBJ()\c=c
ProcedureReturn result
EndProcedure
Procedure.i IsObject(ID)
If ListSize(OBJ())
If ID>=FirstElement(OBJ())
;quick search (#PB_ANY)
ChangeCurrentElement(OBJ(), ID)
If OBJ()\type=#OBJ_TYPE$
ProcedureReturn @OBJ()
EndIf
Else
;slow search
If OBJ()\ID=ID And OBJ()\type=#OBJ_TYPE$
ProcedureReturn @OBJ()
Else
ForEach OBJ()
If OBJ()\ID=ID And OBJ()\type=#OBJ_TYPE$
ProcedureReturn @OBJ()
EndIf
Next
EndIf
EndIf
EndIf
ProcedureReturn #False
EndProcedure
Procedure.i ObjectID(ID)
*ThisObj.OBJ=IsObject(ID)
If *ThisObj
ProcedureReturn *ThisObj\handle
Else
ProcedureReturn #False
EndIf
EndProcedure
*ObjectID=CreateObject(10, 1, 2, 3)
Debug *ObjectID
Debug ObjectID(10)
Debug PeekS(*ObjectID) ;<--- 6
Debug PeekS(ObjectID(10)) ;<--- 6
*ThisObj.OBJ=IsObject(10)
Debug *ThisObj\a
Debug *ThisObj\b
Debug *ThisObj\c
Debug ""
ID=CreateObject(#PB_Any, 10, 20, 30)
*ThisObj.OBJ=IsObject(ID)
Debug *ThisObj\a
Debug *ThisObj\b
Debug *ThisObj\c
Debug PeekS(*ThisObj\handle) ;<--- 60
Debug PeekS(ObjectID(ID)) ;<--- 60
Debug ""
;*ObjectID=CreateObject(10000000000, 1, 2, 3) <--- test error message
Posted: Fri Jul 31, 2009 5:17 am
by Hroudtwolf
Hi,
Thats a cool idea and a good solution.
But not very dynamicly and therefore only for single usage usable.
Once, I developed a dynamic solution.
Code: Select all
EnableExplicit
#OBJECT_ANY = -1
Prototype.i pCallOnRelease ( *ptrObject , iParam.i )
Structure tObjectManager_Item
*ptrObject
blInUse .l
*CallOnRelease .pCallOnRelease
iParamOnRelease.i
EndStructure
Structure tObjectManager
Object .tObjectManager_Item [ $FFFF ]
nObjects .l
EndStructure
Procedure eObjectManager_CreateEnvironment ()
ProcedureReturn AllocateMemory ( SizeOf ( tObjectManager ) )
EndProcedure
Procedure.i eObjectManager_Alloc ( *Env.tObjectManager , iID.i ,*ptrObject , *CallOnRelease = #Null , iParamOnRelease.i = #Null )
Protected nCount.l
If iID > $FFFE
ProcedureReturn #Null
EndIf
If Not ( iID = #OBJECT_ANY )
If *Env\Object [ iID ]\blInUse And *Env\Object [ iID ]\CallOnRelease
*Env\Object [ iID ]\CallOnRelease ( *Env\Object [ iID ]\ptrObject , *Env\Object [ iID ]\iParamOnRelease )
EndIf
*Env\Object [ iID ]\ptrObject = *ptrObject
*Env\Object [ iID ]\CallOnRelease = *CallOnRelease
*Env\Object [ iID ]\iParamOnRelease = iParamOnRelease
ProcedureReturn #True
EndIf
For nCount = 0 To $FFFE
If Not *Env\Object [ nCount ]\blInUse
*Env\Object [ nCount ]\ptrObject = *ptrObject
*Env\Object [ nCount ]\CallOnRelease = *CallOnRelease
*Env\Object [ nCount ]\iParamOnRelease = iParamOnRelease
*Env\Object [ nCount ]\blInUse = #True
ProcedureReturn *ptrObject
EndIf
Next nCount
ProcedureReturn #Null
EndProcedure
Procedure.i eObjectManager_GetObject ( *Env.tObjectManager , iID.i )
Protected nCount.l
If iID > $FFFE
For nCount = 0 To $FFFE
If *Env\Object [ nCount ]\ptrObject = iID And *Env\Object [ nCount ]\blInUse
ProcedureReturn *Env\Object [ nCount ]\ptrObject
EndIf
Next nCount
ProcedureReturn #Null
EndIf
ProcedureReturn *Env\Object [ iID ]\ptrObject
EndProcedure
Procedure.l eObjectManager_FreeObject ( *Env.tObjectManager , iID.i )
Protected nCount.l
If iID > $FFFE
For nCount = 0 To $FFFE
If *Env\Object [ nCount ]\ptrObject = iID And *Env\Object [ nCount ]\blInUse
If *Env\Object [ nCount ]\CallOnRelease
*Env\Object [ nCount ]\CallOnRelease ( *Env\Object [ nCount ]\ptrObject , *Env\Object [ nCount ]\iParamOnRelease )
EndIf
*Env\Object [ nCount ]\blInUse = #False
ProcedureReturn #True
EndIf
Next nCount
ProcedureReturn #Null
EndIf
If *Env\Object [ iID ]\CallOnRelease
*Env\Object [ iID ]\CallOnRelease ( *Env\Object [ iID ]\ptrObject , *Env\Object [ iID ]\iParamOnRelease )
EndIf
*Env\Object [ iID ]\blInUse = #False
ProcedureReturn #True
EndProcedure
Procedure.i eObjectManager_CloneObject ( *Env.tObjectManager , iID.i )
Protected *Object.tObjectManager_Item = eObjectManager_GetObject ( *Env, iID )
If Not *Object
ProcedureReturn #False
EndIf
ProcedureReturn eObjectManager_Alloc ( *Env , #OBJECT_ANY , *Object\ptrObject , *Object\CallOnRelease , *Object\iParamOnRelease )
EndProcedure
;---- Testlib
Procedure _Test_LibraryProc ()
Static *Environment
If Not *Environment
*Environment = eObjectManager_CreateEnvironment ()
EndIf
ProcedureReturn *Environment
EndProcedure
Procedure _Test_FreeProc ( *ptrObject , iParam.i )
Debug "Object freigegeben."
FreeMemory ( *ptrObject )
ProcedureReturn #Null
EndProcedure
Procedure.i Test_Create ( iID.i , sParameter.s )
Protected *Environment = _Test_LibraryProc ()
Protected *ptrObject = AllocateMemory ( MemoryStringLength ( @ sParameter ) ) ; Just a testobject
PokeS ( *ptrObject , sParameter )
ProcedureReturn eObjectManager_Alloc ( *Environment , iID , *ptrObject , @ _Test_FreeProc () , #Null )
EndProcedure
Procedure.s Test_Get ( iID.i )
Protected *Environment = _Test_LibraryProc ()
Protected *ptrObject = eObjectManager_GetObject ( *Environment , iID )
If Not *ptrObject
ProcedureReturn ""
EndIf
ProcedureReturn PeekS ( *ptrObject )
EndProcedure
Procedure.l Test_Free ( iID.i )
Protected *Environment = _Test_LibraryProc ()
ProcedureReturn eObjectManager_FreeObject ( *Environment , iID )
EndProcedure
Define.i iID0
Define.i iID1
Define.i iID2
iID0 = Test_Create ( #OBJECT_ANY , "Hallo Welt" )
iID1 = Test_Create ( #OBJECT_ANY , "Ola mundo" )
iID2 = Test_Create ( #OBJECT_ANY , "Ciao mondo" )
Test_Create ( 3 , "Hallo Welt" )
Debug Test_Get ( iID0 )
Debug Test_Get ( iID1 )
Debug Test_Get ( iID2 )
Debug Test_Get ( 3 )
Test_Free ( iID0 )
Test_Free ( iID1 )
Test_Free ( iID2 )
Best regards
Wolf
Posted: Fri Jul 31, 2009 9:55 pm
by eddy
Your solution is better. I'll try to improve mine.
Posted: Fri Jul 31, 2009 11:41 pm
by eddy
Code: Select all
CompilerIf Defined(MANAGER_ManageObjects, #PB_Procedure)=0
EnableExplicit
CompilerIf #PB_Compiler_Debugger
Import ""
CompilerIf Defined(PB_DEBUGGER_SendWarning, #PB_Procedure)=0
PB_DEBUGGER_SendWarning(Message.p-ascii)
CompilerEndIf
CompilerIf Defined(PB_DEBUGGER_SendError, #PB_Procedure)=0
PB_DEBUGGER_SendError(Message.p-ascii)
CompilerEndIf
EndImport
CompilerElse
Macro PB_DEBUGGER_SendWarning(Message)
EndMacro
Macro PB_DEBUGGER_SendError(Message)
EndMacro
CompilerEndIf
Macro MANAGER_ManageObjects(OBJECT, MAX=$FFFF)
Structure MANAGER_#OBJECT
*handle.OBJECT[2*MAX+1]
used.b[2*MAX+1]
count.i
last.i
anyfirst.i
anylast.i
current.i
EndStructure
Global MANAGER_#OBJECT.MANAGER_#OBJECT
MANAGER_#OBJECT\last=MAX
MANAGER_#OBJECT\anyfirst=MAX+1
MANAGER_#OBJECT\anylast=2*MAX
EndMacro
Macro MANAGER_GetObjectHandle(OBJECT, ID)
MANAGER_#OBJECT\handle[ID]
EndMacro
Macro MANAGER_GetObjectCount(OBJECT)
MANAGER_#OBJECT\count
EndMacro
Macro MANAGER_GetObjectCurrent(OBJECT)
MANAGER_#OBJECT\current
EndMacro
Macro MANAGER_CountObjects(OBJECT)
ProcedureReturn MANAGER_#OBJECT\count
EndMacro
Macro MANAGER_IsObject(OBJECT, ID)
If ID>=0 And ID<=MANAGER_#OBJECT\anylast
ProcedureReturn MANAGER_#OBJECT\used[ID]
EndIf
EndMacro
Macro MANAGER_UseObject(OBJECT, ID, NotValidError="[#ID={0}] : the specified object #ID is not valid!")
If (ID>=0 And ID<=MANAGER_#OBJECT\anylast) And MANAGER_#OBJECT\used[ID]
MANAGER_#OBJECT\current=ID
ProcedureReturn MANAGER_#OBJECT\current
ElseIf ID=#PB_Ignore
ProcedureReturn MANAGER_#OBJECT\current
Else
PB_DEBUGGER_SendError(ReplaceString(NotValidError, "{0}", Str(ID)))
EndIf
EndMacro
Macro MANAGER_ObjectID(OBJECT, ID, NotInitializedError="[#ID={0}] : the specified object #ID is not initialized!")
If (ID>=0 And ID<=MANAGER_#OBJECT\anylast) And MANAGER_#OBJECT\used[ID]
ProcedureReturn MANAGER_#OBJECT\handle[ID]
Else
PB_DEBUGGER_SendError(ReplaceString(NotInitializedError, "{0}", Str(ID)))
EndIf
EndMacro
Macro MANAGER_FreeObject(OBJECT, ID)
FreeMemory(MANAGER_#OBJECT\handle[ID])
MANAGER_#OBJECT\handle[ID]=#Null
MANAGER_#OBJECT\used[ID]=#False
MANAGER_#OBJECT\count-1
EndMacro
Macro MANAGER_CreateObject(OBJECT, ID, RESULT, FreeObject, OutOfRangeError="[#ID={0}] : #ID object number is out of range (0 - {1})")
Protected RESULT=#Null
If ID=#PB_Any
For ID=MANAGER_#OBJECT\anyfirst To MANAGER_#OBJECT\anylast
If Not MANAGER_#OBJECT\used[ID]
MANAGER_#OBJECT\used[ID]=#True
MANAGER_#OBJECT\handle[ID]=AllocateMemory(SizeOf(OBJECT))
MANAGER_#OBJECT\count+1
RESULT=ID
Break
EndIf
Next
ElseIf ID>=0 And ID<=MANAGER_#OBJECT\last
If MANAGER_#OBJECT\used[ID]
FreeObject(ID)
EndIf
MANAGER_#OBJECT\used[ID]=#True
MANAGER_#OBJECT\handle[ID]=AllocateMemory(SizeOf(OBJECT))
MANAGER_#OBJECT\count+1
RESULT=MANAGER_#OBJECT\handle[ID]
Else
PB_DEBUGGER_SendError(ReplaceString(ReplaceString(OutOfRangeError, "{0}", Str(ID)), "{1}", Str(MANAGER_#OBJECT\last)))
EndIf
EndMacro
CompilerEndIf
; **************************
; Test Lib
; **************************
Structure THING
a.i
b.i
content.s
EndStructure
MANAGER_ManageObjects(THING, 5000)
Procedure.i CountThings()
MANAGER_CountObjects(THING)
EndProcedure
Procedure.i ThingID(ID)
MANAGER_ObjectID(THING, ID)
EndProcedure
Procedure.i UseThing(ID=#PB_Ignore)
MANAGER_UseObject(THING, ID)
EndProcedure
Procedure.b IsThing(ID)
MANAGER_IsObject(THING, ID)
EndProcedure
Procedure FreeThing(ID)
;
; HERE : CODE BEFORE OBJECT DELETION
;
Protected *ThingHandle.THING=MANAGER_GetObjectHandle(THING, ID)
Debug "FreeThing : Content = "+*ThingHandle\content
MANAGER_FreeObject(THING, ID)
EndProcedure
Procedure CreateThing(ID, a, b)
;
; HERE : CODE TO VALIDATE ALL PARAMETERS
;
If a=0 And b=0
ProcedureReturn #Null
EndIf
MANAGER_CreateObject(THING, ID, result, FreeThing)
If result
;
; HERE : CODE TO CUSTOMIZE AND SAVE OBJECT HANDLE
;
Protected *ThingHandle.THING=MANAGER_GetObjectHandle(THING, ID)
*ThingHandle\a=a
*ThingHandle\b=b
*ThingHandle\content="{a -> "+Str(a)+", b ->"+Str(b)+"}"
Debug "CreateThing : Content = "+*ThingHandle\content
ProcedureReturn result
EndIf
EndProcedure
Debug CreateThing(100, 1, 0)
Debug CreateThing(100, 0, 2)
Debug ThingID(100)
Debug "count="+Str(CountThings())
Debug IsThing(100)
FreeThing(100)
Debug "count="+Str(CountThings())
Debug IsThing(100)
Debug ""
Debug CreateThing(#PB_Any, 1, 2)
Global newID=CreateThing(#PB_Any, 1, 1)
If IsThing(newID)
Debug newID
Debug ThingID(newID)
Global *ThingHandle.THING=ThingID(newID)
Debug *ThingHandle\content
Debug "count="+Str(CountThings())
EndIf
Posted: Sat Aug 01, 2009 5:41 am
by PB
Why all this code when #PB_Any will do it? Is #PB_Any buggy or something?
Posted: Sat Aug 01, 2009 7:30 am
by Hroudtwolf
First, why not?
And...
A self-coded solution ever is custom-made.
Also, nobody is realy able to anticipate the changes by development of the internal PureBasic objectmanager.
So, such solutions are resistent for longer time.
A proper man will built his house by him-self.
Regards
Wolf
Posted: Sat Aug 01, 2009 11:07 am
by PB
> First, why not?
Because it's re-inventing the wheel?
> nobody is realy able to anticipate the changes by development of the
> internal PureBasic objectmanager
:roll: So, what, are you going to replace OpenWindow with an API solution
too, just in case OpenWindow has some unknown future changes? It's
not going to change in the alarmist manner that you're describing. Relax.
But I agree that yes, it's a good programming exercise. I just don't think
it's necessarily something that needs to be done to future-proof your app.
If you were using a third-party library, then yes, but not PureBasic's code.
BTW, I'm only bringing this up for the benefit of newbies and lurkers who
may be reading this thread, because such comments by yourself can give
them a false view of the language, which is not good advertising.
Posted: Sat Aug 01, 2009 11:22 am
by Hroudtwolf
BTW, I'm only bringing this up for the benefit of newbies and lurkers who
may be reading this thread, because such comments by yourself can give
them a false view of the language, which is not good advertising.
I am amazed.
'Cause, the codes in this thread shows a lot of possibilities with purebasic.
Posted: Sat Aug 01, 2009 11:24 am
by PB
Yes, the code shows the possibilities, but people might read your comments
about the development changes and decide that PureBasic is too unstable
to buy. That's all I meant. If I read that, that's what I'd think.
Posted: Sat Aug 01, 2009 11:42 am
by Hroudtwolf
Well. This wasn't my statement.
It is just what you read.
Posted: Sat Aug 01, 2009 12:10 pm
by eddy
Code: Select all
Why all this code when #PB_Any will do it? Is #PB_Any buggy or something?
Because I'm coding a custom sprite 3D lib and I need a #PB_any-like functionality.
CreateCustomSprite(PB_any,....)