Update .gitignore, _ChainedHashMap.pbi, HashMap.pbi, and 4 more files
This commit is contained in:
@@ -1,121 +1,131 @@
|
||||
|
||||
EnableExplicit
|
||||
DeclareModule ChainedHashMap
|
||||
EnableExplicit
|
||||
|
||||
#HashMap_InitialPower = 9
|
||||
#HashMap_InsertIterations = 100000
|
||||
#InitialPower = 9
|
||||
#InsertIterations = 100000
|
||||
|
||||
;{
|
||||
Structure Bucket
|
||||
*BucketData
|
||||
*Next.Bucket
|
||||
Hash.q
|
||||
EndStructure
|
||||
|
||||
Structure ChainedHashMapBucket
|
||||
*BucketData
|
||||
*Next.ChainedHashMapBucket
|
||||
Hash.q
|
||||
EndStructure
|
||||
Structure HashMap
|
||||
EntryCount.i
|
||||
Capacity.i
|
||||
SizePower.a
|
||||
*Buckets.Bucket[0]
|
||||
EndStructure
|
||||
|
||||
Structure ChainedHashMap
|
||||
EntryCount.i
|
||||
Capacity.i
|
||||
SizePower.a
|
||||
*Buckets.ChainedHashMapBucket[0]
|
||||
EndStructure
|
||||
Prototype CbFree(*Data)
|
||||
|
||||
Declare.i Create(SizePower.b)
|
||||
Declare.i GetByHash(*CHM.HashMap, Hash.q)
|
||||
Declare.b OverwriteByHash(*CHM.HashMap, *Data, Hash.q, *FreeingCallback.CbFree = #Null)
|
||||
Declare DeleteByHash(*CHM.HashMap, Hash.q)
|
||||
Declare Free(*CHM.HashMap)
|
||||
Declare NoopFree(*Data)
|
||||
EndDeclareModule
|
||||
|
||||
Prototype CbFree(*Data)
|
||||
Module ChainedHashMap
|
||||
EnableExplicit
|
||||
|
||||
Procedure.l MakeBitMask(BitCount.b)
|
||||
EnableASM
|
||||
MOV eax, $00000001
|
||||
MOV cl, BitCount
|
||||
SHL eax, cl
|
||||
DEC eax
|
||||
ProcedureReturn
|
||||
DisableASM
|
||||
EndProcedure
|
||||
Procedure.l MakeBitMask(BitCount.b)
|
||||
EnableASM
|
||||
MOV eax, $00000001
|
||||
MOV cl, BitCount
|
||||
SHL eax, cl
|
||||
DEC eax
|
||||
ProcedureReturn
|
||||
DisableASM
|
||||
EndProcedure
|
||||
|
||||
Procedure.i CHM_Create(SizePower.b)
|
||||
Protected *CHM.ChainedHashMap = AllocateMemory(SizeOf(ChainedHashMap) + (SizeOf(Integer) * (MakeBitMask(SizePower) + 1)))
|
||||
|
||||
If *CHM <> #Null
|
||||
*CHM\EntryCount = 0
|
||||
*CHM\SizePower = SizePower
|
||||
|
||||
Protected iBucket
|
||||
For iBucket = 0 To MakeBitMask(SizePower)
|
||||
*CHM\Buckets[iBucket] = #Null
|
||||
Next
|
||||
EndIf
|
||||
|
||||
ProcedureReturn *CHM
|
||||
EndProcedure
|
||||
Procedure.i Create(SizePower.b)
|
||||
Protected *CHM.HashMap = AllocateMemory(SizeOf(HashMap) + (SizeOf(Integer) * (MakeBitMask(SizePower) + 1)))
|
||||
|
||||
Procedure.i CHM_GetByHash(*CHM.ChainedHashMap, Hash.q)
|
||||
If *CHM <> #Null
|
||||
Protected *CurrentBucket.ChainedHashMapBucket = *CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))]
|
||||
|
||||
While *CurrentBucket <> #Null
|
||||
If *CurrentBucket\Hash = Hash
|
||||
ProcedureReturn *CurrentBucket\BucketData
|
||||
EndIf
|
||||
*CurrentBucket = *CurrentBucket\Next
|
||||
Wend
|
||||
EndIf
|
||||
|
||||
ProcedureReturn #Null
|
||||
EndProcedure
|
||||
If *CHM <> #Null
|
||||
*CHM\EntryCount = 0
|
||||
*CHM\SizePower = SizePower
|
||||
|
||||
Procedure.b CHM_OverwriteByHash(*CHM.ChainedHashMap, *Data, Hash.q, *FreeingCallback.CbFree = #Null)
|
||||
If *CHM <> #Null
|
||||
Protected *PreviousBucket.ChainedHashMapBucket = #Null
|
||||
Protected *CurrentBucket.ChainedHashMapBucket = *CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))]
|
||||
|
||||
; We iterate over the bucket chain until we find a collision or an in-between.
|
||||
While *CurrentBucket <> #Null
|
||||
If *CurrentBucket\Hash >= Hash
|
||||
Break
|
||||
EndIf
|
||||
*PreviousBucket = *CurrentBucket
|
||||
*CurrentBucket = *CurrentBucket\Next
|
||||
Wend
|
||||
|
||||
If *CurrentBucket = #Null Or *CurrentBucket\Hash <> Hash
|
||||
; We either reached the end of the list, or no buckets was in the current slot.
|
||||
; Or, we have an in-between, or we are at the start of the list.
|
||||
Protected *NewBucket.ChainedHashMapBucket = AllocateMemory(SizeOf(ChainedHashMapBucket))
|
||||
|
||||
If *NewBucket <> #Null
|
||||
*NewBucket\Next = *CurrentBucket
|
||||
*NewBucket\BucketData = *Data
|
||||
*NewBucket\Hash = Hash
|
||||
|
||||
If *PreviousBucket <> #Null
|
||||
; In-between, or we are at the start of the List.
|
||||
*PreviousBucket\Next = *NewBucket
|
||||
Else
|
||||
; Start of the list.
|
||||
*CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))] = *NewBucket
|
||||
Protected iBucket
|
||||
For iBucket = 0 To MakeBitMask(SizePower)
|
||||
*CHM\Buckets[iBucket] = #Null
|
||||
Next
|
||||
EndIf
|
||||
|
||||
ProcedureReturn *CHM
|
||||
EndProcedure
|
||||
|
||||
Procedure.i GetByHash(*CHM.HashMap, Hash.q)
|
||||
If *CHM <> #Null
|
||||
Protected *CurrentBucket.Bucket = *CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))]
|
||||
|
||||
While *CurrentBucket <> #Null
|
||||
If *CurrentBucket\Hash = Hash
|
||||
ProcedureReturn *CurrentBucket\BucketData
|
||||
EndIf
|
||||
|
||||
*CHM\EntryCount = *CHM\EntryCount + 1
|
||||
*CurrentBucket = *CurrentBucket\Next
|
||||
Wend
|
||||
EndIf
|
||||
|
||||
ProcedureReturn #Null
|
||||
EndProcedure
|
||||
|
||||
Procedure.b OverwriteByHash(*CHM.HashMap, *Data, Hash.q, *FreeingCallback.CbFree = #Null)
|
||||
If *CHM <> #Null
|
||||
Protected *PreviousBucket.Bucket = #Null
|
||||
Protected *CurrentBucket.Bucket = *CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))]
|
||||
|
||||
; We iterate over the bucket chain until we find a collision or an in-between.
|
||||
While *CurrentBucket <> #Null
|
||||
If *CurrentBucket\Hash >= Hash
|
||||
Break
|
||||
EndIf
|
||||
*PreviousBucket = *CurrentBucket
|
||||
*CurrentBucket = *CurrentBucket\Next
|
||||
Wend
|
||||
|
||||
If *CurrentBucket = #Null Or *CurrentBucket\Hash <> Hash
|
||||
; We either reached the end of the list, or no buckets was in the current slot.
|
||||
; Or, we have an in-between, or we are at the start of the list.
|
||||
Protected *NewBucket.Bucket = AllocateMemory(SizeOf(Bucket))
|
||||
|
||||
If *NewBucket <> #Null
|
||||
*NewBucket\Next = *CurrentBucket
|
||||
*NewBucket\BucketData = *Data
|
||||
*NewBucket\Hash = Hash
|
||||
|
||||
If *PreviousBucket <> #Null
|
||||
; In-between, or we are at the start of the List.
|
||||
*PreviousBucket\Next = *NewBucket
|
||||
Else
|
||||
; Start of the list.
|
||||
*CHM\Buckets[(Hash & MakeBitMask(*CHM\SizePower))] = *NewBucket
|
||||
EndIf
|
||||
|
||||
*CHM\EntryCount = *CHM\EntryCount + 1
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
ElseIf *FreeingCallback <> #Null
|
||||
; Handling collision.
|
||||
CallFunctionFast(*FreeingCallback, *CurrentBucket\BucketData)
|
||||
*CurrentBucket\BucketData = *Data
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
ElseIf *FreeingCallback <> #Null
|
||||
; Handling collision.
|
||||
CallFunctionFast(*FreeingCallback, *CurrentBucket\BucketData)
|
||||
*CurrentBucket\BucketData = *Data
|
||||
ProcedureReturn #True
|
||||
; Implied else: Handling collision while forbidden to overwrite => doing nothing.
|
||||
EndIf
|
||||
; Implied else: Handling collision while forbidden to overwrite => doing nothing.
|
||||
EndIf
|
||||
|
||||
ProcedureReturn #False
|
||||
EndProcedure
|
||||
|
||||
Procedure CHM_DeleteByHash(*CHM.ChainedHashMap, Hash.q)
|
||||
|
||||
EndProcedure
|
||||
ProcedureReturn #False
|
||||
EndProcedure
|
||||
|
||||
Procedure CHM_Free(*CHM.ChainedHashMap)
|
||||
|
||||
EndProcedure
|
||||
Procedure DeleteByHash(*CHM.HashMap, Hash.q)
|
||||
|
||||
Procedure NoopFree(*Data) : EndProcedure
|
||||
EndProcedure
|
||||
|
||||
Procedure Free(*CHM.HashMap)
|
||||
|
||||
EndProcedure
|
||||
|
||||
Procedure NoopFree(*Data) : EndProcedure
|
||||
EndModule
|
||||
|
||||
Reference in New Issue
Block a user