Update CLAUDE.md, CRC32B.pbi, _ChainedHashMap.pbi, and 1 more file
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
|
||||
EnableExplicit
|
||||
|
||||
#HashMap_InitialPower = 9
|
||||
#HashMap_InsertIterations = 100000
|
||||
|
||||
;{
|
||||
|
||||
Structure ChainedHashMapBucket
|
||||
*BucketData
|
||||
*Next.ChainedHashMapBucket
|
||||
Hash.q
|
||||
EndStructure
|
||||
|
||||
Structure ChainedHashMap
|
||||
EntryCount.i
|
||||
Capacity.i
|
||||
SizePower.a
|
||||
*Buckets.ChainedHashMapBucket[0]
|
||||
EndStructure
|
||||
|
||||
|
||||
Prototype CbFree(*Data)
|
||||
|
||||
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 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
|
||||
|
||||
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
|
||||
EndIf
|
||||
|
||||
*CHM\EntryCount = *CHM\EntryCount + 1
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
ElseIf *FreeingCallback <> #Null
|
||||
; Handling collision.
|
||||
CallFunctionFast(*FreeingCallback, *CurrentBucket\BucketData)
|
||||
*CurrentBucket\BucketData = *Data
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
; Implied else: Handling collision while forbidden to overwrite => doing nothing.
|
||||
EndIf
|
||||
|
||||
ProcedureReturn #False
|
||||
EndProcedure
|
||||
|
||||
Procedure CHM_DeleteByHash(*CHM.ChainedHashMap, Hash.q)
|
||||
|
||||
EndProcedure
|
||||
|
||||
Procedure CHM_Free(*CHM.ChainedHashMap)
|
||||
|
||||
EndProcedure
|
||||
|
||||
Procedure NoopFree(*Data) : EndProcedure
|
||||
Reference in New Issue
Block a user