ID generator : simulate #PB_Any

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

ID generator : simulate #PB_Any

Post 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
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post 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
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

Your solution is better. I'll try to improve mine.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post 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
Last edited by eddy on Tue Aug 04, 2009 10:40 pm, edited 2 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

Why all this code when #PB_Any will do it? Is #PB_Any buggy or something?
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post 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
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post 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.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post 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.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post 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.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post by Hroudtwolf »

Well. This wasn't my statement.
It is just what you read.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post 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,....)
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Post Reply