I never posted this before because I thought #PB_Any would make it redundant. It's simple but efffective and easily extended for more types of resources. Note that there are obvious improvements to be done but this was a quick hack a couple of months back and it's done me ok up to now. I'll probably improve it in the next few weeks but feel free to do any yourself.
Code: Select all
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;*** RESOURCE NUMBER MANAGER ***
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 040315 REVISE IN FUTURE TO USE MB'S INSTEAD OF STRINGS
; AND POSS ABILITY TO DEFINE NEW TYPES ON THE FLY (WOULD
; HAVE TO RESERVE X MEM BANK NUMBERS + SPARE FOR NEW TYPES
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;-ENUMS
; NB: Add to this list if required
; (idea is to keep rtype=listindex() for easy mgmnt)
Enumeration ; Resource Types
#RNM_TYPE_FILE
#RNM_TYPE_IMAGE
#RNM_TYPE_MEMBK
;#RNM_TYPE_
#RNM_TYPE_END ; This is just a marker for initialisation
EndEnumeration
;-STRUCTS
Structure rnmItemType
rtype.l ; Resource Type (see enumeration above)
asize.l ; Size of string (since initially filling with zero's)
alloc.s ; Space for bit flags (may grow but won't shrink!)
used.l ; Allocated count (to save computing on-the-fly)
EndStructure
Structure rnmT
mid.l ; Flag: Main Init Done (so can be called again)
dbg.l ; Flag: Debugging
EndStructure
;-VARS
Global rnm.rnmT
Global NewList rnmItems.rnmItemType()
Procedure rnmInit(maxnum.l)
; Init list with space for "maxnum" numbers in each item
Protected t.l
If rnm\mid: ProcedureReturn: EndIf
For t=0 To #RNM_TYPE_END-1
AddElement(rnmItems())
rnmItems()\rtype=t
rnmItems()\asize=1+maxnum/8
rnmItems()\alloc=Space(rnmItems()\asize)
;rnmItems()\alloc=ReplaceString(rnmItems()\alloc, " ", Chr(0), 2) ; Zero
RtlZeroMemory_(@rnmItems()\alloc, rnmItems()\asize)
rnmItems()\used=0
Next
rnm\mid=1
EndProcedure
Procedure.l rnmNewNum(rtype.l)
; Return a new resource number for specified resource type
Protected a.l, c.l, b.l, d.l, m.b, n.l
SelectElement(rnmItems(), rtype)
; All avail allocated?
If rnmItems()\used = 8*rnmItems()\asize ; All bits allocated
Debug "RNM: Max'ed out: "+Str(rtype)
CallDebugger
ProcedureReturn -1
EndIf
; Allocate first free number
a = @rnmItems()\alloc
For c = 0 To rnmItems()\asize-1
d = PeekB(a+c) & $FF
If d<>255 ; Found unallocated number
For b = 0 To 7
m = 1 << b: If (d & m)=0: Break 2: EndIf
Next
EndIf
Next
PokeB(a+c, d | m)
rnmItems()\used+1
n = 8*c+b
ProcedureReturn n
EndProcedure
Procedure rnmFreeNum(rtype.l, n.l)
; Free resource number for specified resource type
Protected a.l, c.l, b.l, m.l
SelectElement(rnmItems(), rtype)
c = n/8
b = n - c*8
m = (~(1 << b)) & $FF
a = @rnmItems()\alloc
PokeB(a+c, PeekB(a+c) & m)
rnmItems()\used-1
EndProcedure
Procedure rnmTest()
rnmInit(512)
Debug "Allocate several of type #RNM_TYPE_IMAGE (0..9)..."
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 0
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 1
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 2
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 3
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 4
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 5
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 6
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 7
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 8
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 9
Debug ""
Debug "Free # 3"
rnmFreeNum(#RNM_TYPE_IMAGE, 3) ; Should get re-allocated on next call
Debug ""
Debug "Allocate several more of type #RNM_TYPE_IMAGE (3, 10, 11)..."
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 3
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 10 (because 4..9 already allocated)
Debug rnmNewNum(#RNM_TYPE_IMAGE) ; 11
Debug ""
Debug "Allocate several of other type #RNM_TYPE_FILE (0..3)..."
Debug rnmNewNum(#RNM_TYPE_FILE) ; 0
Debug rnmNewNum(#RNM_TYPE_FILE) ; 1
Debug rnmNewNum(#RNM_TYPE_FILE) ; 2
Debug rnmNewNum(#RNM_TYPE_FILE) ; 3
Debug ""
Debug "Usage, (type|used)..."
ResetList(rnmItems())
While NextElement(rnmItems())
Debug Str(rnmItems()\rtype)+": "+Str(rnmItems()\used)
Wend
EndProcedure
rnmTest()

