Untitled diff

Creato Il diff non scade mai
2 rimozioni
759 linee
5 aggiunte
760 linee
VERSION 1.0 CLASS
VERSION 1.0 CLASS
BEGIN
BEGIN
MultiUse = -1 'True
MultiUse = -1 'True
Persistable = 0 'NotPersistable
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
MTSTransactionMode = 0 'NotAnMTSObject
END
END
Attribute VB_Name = "clsTrickHashTable"
Attribute VB_Name = "clsTrickHashTable"
Attribute VB_GlobalNameSpace = False
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Exposed = False
' clsTrickHashTable.cls - класс Ń…ŠµŃˆ-таблицы
' clsTrickHashTable.cls - класс Ń…ŠµŃˆ-таблицы
' Ā© ŠšŃ€ŠøŠ²Š¾ŃƒŃ Анатолий ŠŠ½Š°Ń‚Š¾Š»ŃŒŠµŠ²ŠøŃ‡ (The trick), 2014
' Ā© ŠšŃ€ŠøŠ²Š¾ŃƒŃ Анатолий ŠŠ½Š°Ń‚Š¾Š»ŃŒŠµŠ²ŠøŃ‡ (The trick), 2014


Option Explicit
Option Explicit


Public Enum CompareMethod ' ŠœŠµŃ‚Š¾Š“ ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ
Public Enum CompareMethod ' ŠœŠµŃ‚Š¾Š“ ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ
BinaryCompare
BinaryCompare
TextCompare
TextCompare
End Enum
End Enum


Public Enum EnumMethod ' ŠœŠµŃ‚Š¾Š“ ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠµŠ½ŠøŃ Š“Š»Ń For each
Public Enum EnumMethod ' ŠœŠµŃ‚Š¾Š“ ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠµŠ½ŠøŃ Š“Š»Ń For each
ENUM_BY_KEY
ENUM_BY_KEY
ENUM_BY_VALUE
ENUM_BY_VALUE
End Enum
End Enum


Private Declare Function SetEnvironmentVariable Lib "kernel32" Alias "SetEnvironmentVariableW" (ByVal lpName As Long, ByVal lpValue As Long) As Long
Private Declare Function SetEnvironmentVariable Lib "kernel32" Alias "SetEnvironmentVariableW" (ByVal lpName As Long, ByVal lpValue As Long) As Long
Private Declare Function GetEnvironmentVariable Lib "kernel32" Alias "GetEnvironmentVariableW" (ByVal lpName As Long, ByVal lpBuffer As Long, ByVal nSize As Long) As Long
Private Declare Function GetEnvironmentVariable Lib "kernel32" Alias "GetEnvironmentVariableW" (ByVal lpName As Long, ByVal lpBuffer As Long, ByVal nSize As Long) As Long
Private Declare Function VirtualAlloc Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualAlloc Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFree Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function VirtualFree Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function HeapAlloc Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function HeapAlloc Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GetProcessHeap Lib "kernel32" () As Long
Private Declare Function GetProcessHeap Lib "kernel32" () As Long
Private Declare Function GetMem8 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetMem8 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetMem2 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetMem2 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetMem1 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetMem1 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleW" (ByVal lpModuleName As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleW" (ByVal lpModuleName As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function memcpy Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long) As Long
Private Declare Function memcpy Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long) As Long
Private Declare Function VarCmp Lib "oleaut32" (pvarLeft As Any, pvarRight As Any, ByVal lcid As Long, ByVal dwFlags As Long) As Long
Private Declare Function VarCmp Lib "oleaut32" (pvarLeft As Any, pvarRight As Any, ByVal lcid As Long, ByVal dwFlags As Long) As Long
Private Declare Function VariantCopy Lib "oleaut32" (pvargDest As Any, pvargSrc As Any) As Long
Private Declare Function VariantCopy Lib "oleaut32" (pvargDest As Any, pvargSrc As Any) As Long
Private Declare Function VariantCopyInd Lib "oleaut32" (pvarDest As Any, pvargSrc As Any) As Long
Private Declare Function VariantCopyInd Lib "oleaut32" (pvarDest As Any, pvargSrc As Any) As Long
Private Declare Function LCMapString Lib "kernel32" Alias "LCMapStringW" (ByVal Locale As Long, ByVal dwMapFlags As Long, lpSrcStr As Any, ByVal cchSrc As Long, lpDestStr As Any, ByVal cchDest As Long) As Long
Private Declare Function LCMapString Lib "kernel32" Alias "LCMapStringW" (ByVal Locale As Long, ByVal dwMapFlags As Long, lpSrcStr As Any, ByVal cchSrc As Long, lpDestStr As Any, ByVal cchDest As Long) As Long
Private Declare Function GetUserDefaultLCID Lib "kernel32" () As Long
Private Declare Function GetUserDefaultLCID Lib "kernel32" () As Long
Private Declare Function VarR4FromUI1 Lib "oleaut32" (value As Any, R4 As Any) As Long
Private Declare Function VarR4FromUI1 Lib "oleaut32" (value As Any, R4 As Any) As Long
Private Declare Function VarR4FromI2 Lib "oleaut32" (value As Any, R4 As Any) As Long
Private Declare Function VarR4FromI2 Lib "oleaut32" (value As Any, R4 As Any) As Long
Private Declare Function VarR4FromI4 Lib "oleaut32" (value As Any, R4 As Any) As Long
Private Declare Function VarR4FromI4 Lib "oleaut32" (value As Any, R4 As Any) As Long


Private Const LCMAP_LOWERCASE As Long = &H100
Private Const LCMAP_LOWERCASE As Long = &H100
Private Const PAGE_EXECUTE_READWRITE As Long = &H40&
Private Const PAGE_EXECUTE_READWRITE As Long = &H40&
Private Const MEM_COMMIT As Long = &H1000&
Private Const MEM_COMMIT As Long = &H1000&
Private Const MEM_RESERVE As Long = &H2000&
Private Const MEM_RESERVE As Long = &H2000&
Private Const MEM_RELEASE As Long = &H8000&
Private Const MEM_RELEASE As Long = &H8000&
Private Const HEAP_NO_SERIALIZE As Long = &H1
Private Const HEAP_NO_SERIALIZE As Long = &H1
Private Const GRANULARITY As Long = &H20
Private Const GRANULARITY As Long = &H20
Private Const HASH_SIZE As Long = 2999
Private Const HASH_SIZE As Long = 2999


Private Type tPointer ' ИнГекс в таблице Š¾Š±ŃŠŠµŠŗŃ‚ов
Private Type tPointer ' ИнГекс в таблице Š¾Š±ŃŠŠµŠŗŃ‚ов
hash As Integer ' Š„ŃŃˆ
hash As Integer ' Š„ŃŃˆ
Index As Integer ' ИнГекс
Index As Integer ' ИнГекс
End Type
End Type
Private Type tElement ' Колонка хэш таблицы
Private Type tElement ' Колонка хэш таблицы
Key As Variant ' ŠšŠ»ŃŽŃ‡
Key As Variant ' ŠšŠ»ŃŽŃ‡
value As Variant ' Значение
value As Variant ' Значение
Next As tPointer ' ИнГекс ŃŠ»ŠµŠ“ŃƒŃŽŃ‰ŠµŠ³Š¾ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š°
Next As tPointer ' ИнГекс ŃŠ»ŠµŠ“ŃƒŃŽŃ‰ŠµŠ³Š¾ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š°
Prev As tPointer ' ИнГекс ŠæŃ€ŠµŠ“Ń‹Š“ŃƒŃ‰ŠµŠ³Š¾ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š°
Prev As tPointer ' ИнГекс ŠæŃ€ŠµŠ“Ń‹Š“ŃƒŃ‰ŠµŠ³Š¾ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š°
End Type
End Type
Private Type tItem ' Дтрока хэш таблицы
Private Type tItem ' Дтрока хэш таблицы
ElementsCount As Long ' ŠšŠ¾Š»ŠøŃ‡ŠµŃŃ‚Š²Š¾ коллизий+1
ElementsCount As Long ' ŠšŠ¾Š»ŠøŃ‡ŠµŃŃ‚Š²Š¾ коллизий+1
Elements() As tElement ' Элементы
Elements() As tElement ' Элементы
End Type
End Type
Private Type enumObject ' ŠžŠ±ŃŠŠµŠŗŃ‚-ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠøŃ‚ŠµŠ»ŃŒ
Private Type enumObject ' ŠžŠ±ŃŠŠµŠŗŃ‚-ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠøŃ‚ŠµŠ»ŃŒ
vTablePtr As Long ' Š£ŠŗŠ°Š·Š°Ń‚ŠµŠ»ŃŒ на интерфейс IEnumVariant
vTablePtr As Long ' Š£ŠŗŠ°Š·Š°Ń‚ŠµŠ»ŃŒ на интерфейс IEnumVariant
Counter As Long ' Дчетчик ссылок
Counter As Long ' Дчетчик ссылок
Pointer As tPointer ' ИнГекс на Ń‚ŠµŠŗŃƒŃ‰ŠøŠ¹ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚
Pointer As tPointer ' ИнГекс на Ń‚ŠµŠŗŃƒŃ‰ŠøŠ¹ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚
DataPtr As Long ' Š£ŠŗŠ°Š·Š°Ń‚ŠµŠ»ŃŒ на List
DataPtr As Long ' Š£ŠŗŠ°Š·Š°Ń‚ŠµŠ»ŃŒ на List
First As tPointer ' ИнГекс на первый ŃŠ»ŠµŠ¼ŠµŠ½Ń‚
First As tPointer ' ИнГекс на первый ŃŠ»ŠµŠ¼ŠµŠ½Ń‚
OffsetVariant As Long ' Дмещение ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŃŠµŠ¼Š¾Š¹ переменной (key/value)
OffsetVariant As Long ' Дмещение ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŃŠµŠ¼Š¾Š¹ переменной (key/value)
End Type
End Type


Private List() As tItem ' Таблица
Private List() As tItem ' Таблица
Private mEnumMode As EnumMethod ' Š¢ŠµŠŗŃƒŃ‰ŠøŠ¹ режим ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠµŠ½ŠøŃ
Private mEnumMode As EnumMethod ' Š¢ŠµŠŗŃƒŃ‰ŠøŠ¹ режим ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠµŠ½ŠøŃ
Private mCount As Long ' Кол-во ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š²
Private mCount As Long ' Кол-во ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š²
Private mCompareMode As VbCompareMethod ' Режим ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ ŠŗŠ»ŃŽŃ‡ŠµŠ¹
Private mCompareMode As VbCompareMethod ' Режим ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ ŠŗŠ»ŃŽŃ‡ŠµŠ¹
Private First As tPointer ' ИнГекс первого ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š°
Private First As tPointer ' ИнГекс первого ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š°
Private Last As tPointer ' ИнГекс послеГнего ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š°
Private Last As tPointer ' ИнГекс послеГнего ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š°
Private locbuf() As Integer ' Š‘ŃƒŃ„ŠµŃ€ текстовой строки
Private locbuf() As Integer ' Š‘ŃƒŃ„ŠµŃ€ текстовой строки
Private lpAsm As Long
Private lpAsm As Long
Private lcid As Long
Private lcid As Long
Private decMin As Variant
Private decMin As Variant
Private decMax As Variant
Private decMax As Variant


' // ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠøŃ‚ŠµŠ»ŃŒ
' // ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠøŃ‚ŠµŠ»ŃŒ


Public Property Get NewEnum() As IUnknown
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
Attribute NewEnum.VB_MemberFlags = "40"
Dim enumObject As Long
Dim enumObject As Long
enumObject = CreateEnumObject()
enumObject = CreateEnumObject()
If enumObject = 0 Then Exit Function
If enumObject = 0 Then Exit Function
GetMem4 enumObject, ByVal NewEnum
GetMem4 enumObject, ByVal NewEnum
End Property
End Property


' // ŠŸŠ¾Š»ŃƒŃ‡Š°ŠµŃ‚/Устанавливает режим ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠøŃ‚ŠµŠ»Ń
' // ŠŸŠ¾Š»ŃƒŃ‡Š°ŠµŃ‚/Устанавливает режим ŠæŠµŃ€ŠµŃ‡ŠøŃŠ»ŠøŃ‚ŠµŠ»Ń
Public Property Get EnumMode() As EnumMethod
Public Property Get EnumMode() As EnumMethod
Attribute EnumMode.VB_Description = "ŠžŠæŃ€ŠµŠ“ŠµŠ»ŃŠµŃ‚ режим ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ в циклах For Each."
Attribute EnumMode.VB_Description = "ŠžŠæŃ€ŠµŠ“ŠµŠ»ŃŠµŃ‚ режим ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ в циклах For Each."
EnumMode = mEnumMode
EnumMode = mEnumMode
End Property
End Property
Public Property Let EnumMode(ByVal value As EnumMethod)
Public Property Let EnumMode(ByVal value As EnumMethod)
mEnumMode = value
mEnumMode = value
End Property
End Property


' // ŠŸŠ¾Š»ŃƒŃ‡Š°ŠµŃ‚/Устанавливает режим ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ ŠŗŠ»ŃŽŃ‡ŠµŠ¹
' // ŠŸŠ¾Š»ŃƒŃ‡Š°ŠµŃ‚/Устанавливает режим ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ ŠŗŠ»ŃŽŃ‡ŠµŠ¹
Public Property Get CompareMode() As CompareMethod
Public Property Get CompareMode() As CompareMethod
Attribute CompareMode.VB_Description = "Š£ŃŃ‚Š°Š½Š¾Š²ŠøŃ‚ŃŒ или ŠæŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ метоГ ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ строк.\n"
Attribute CompareMode.VB_Description = "Š£ŃŃ‚Š°Š½Š¾Š²ŠøŃ‚ŃŒ или ŠæŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ метоГ ŃŃ€Š°Š²Š½ŠµŠ½ŠøŃ строк.\n"
CompareMode = mCompareMode
CompareMode = mCompareMode
End Property
End Property
Public Property Let CompareMode(ByVal value As CompareMethod)
Public Property Let CompareMode(ByVal value As CompareMethod)
If mCount Then Err.Raise 5: Exit Property ' Только когГа ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š² нет
If mCount Then Err.Raise 5: Exit Property ' Только когГа ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š² нет
mCompareMode = value
mCompareMode = value
End Property
End Property


' // Š”Š¾Š±Š°Š²ŠøŃ‚ŃŒ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚
' // Š”Š¾Š±Š°Š²ŠøŃ‚ŃŒ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚
Public Sub Add(Key As Variant, value As Variant)
Public Sub Add(Key As Variant, value As Variant)
Attribute Add.VB_Description = "Š”Š¾Š±Š°Š²ŠøŃ‚ŃŒ в Ń‚Š°Š±Š»ŠøŃ†Ńƒ новый ŠŗŠ»ŃŽŃ‡ Šø ŃŠ»ŠµŠ¼ŠµŠ½Ń‚.\n"
Attribute Add.VB_Description = "Š”Š¾Š±Š°Š²ŠøŃ‚ŃŒ в Ń‚Š°Š±Š»ŠøŃ†Ńƒ новый ŠŗŠ»ŃŽŃ‡ Šø ŃŠ»ŠµŠ¼ŠµŠ½Ń‚.\n"
Dim pt As tPointer
Dim pt As tPointer
If Not GetFromKey(Key, pt) Then
If Not GetFromKey(Key, pt) Then
Err.Raise 5
Err.Raise 5
Exit Sub
Exit Sub
End If
End If
If pt.Index <> -1 Then
If pt.Index <> -1 Then
Err.Raise 457
Err.Raise 457
Exit Sub
Exit Sub
End If
End If
pt.Index = List(pt.hash).ElementsCount
pt.Index = List(pt.hash).ElementsCount
Add_ pt, Key, value
Add_ pt, Key, value
End Sub
End Sub


' // Š’Š¾Š·Š²Ń€Š°Ń‚ŠøŃ‚ŃŒ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ с заГанным ŠŗŠ»ŃŽŃ‡Š¾Š¼
' // Š’Š¾Š·Š²Ń€Š°Ń‚ŠøŃ‚ŃŒ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ с заГанным ŠŗŠ»ŃŽŃ‡Š¾Š¼
Public Property Get Item(Key As Variant) As Variant
Public Property Get Item(Key As Variant) As Variant
Attribute Item.VB_Description = "Š—Š°Š“Š°Ń‚ŃŒ или ŠøŠ·Š²Š»ŠµŃ‡ŃŒ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ по заГанному ŠŗŠ»ŃŽŃ‡Ńƒ\n"
Attribute Item.VB_Description = "Š—Š°Š“Š°Ń‚ŃŒ или ŠøŠ·Š²Š»ŠµŃ‡ŃŒ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ по заГанному ŠŗŠ»ŃŽŃ‡Ńƒ\n"
Attribute Item.VB_UserMemId = 0
Attribute Item.VB_UserMemId = 0
Dim pt As tPointer
Dim pt As tPointer


If Not GetFromKey(Key, pt) Then
If Not GetFromKey(Key, pt) Then
Err.Raise 5
Err.Raise 5
Exit Property
Exit Property
End If
End If
If pt.Index = -1 Then Err.Raise 5: Exit Property
If pt.Index = -1 Then Err.Raise 5: Exit Property
VariantCopy Item, List(pt.hash).Elements(pt.Index).value
VariantCopy Item, List(pt.hash).Elements(pt.Index).value
End Property
End Property


' // ŠŸŃ€ŠøŃŠ²Š¾ŠøŃ‚ŃŒ значение ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Ńƒ с заГанным ŠŗŠ»ŃŽŃ‡Š¾Š¼
' // ŠŸŃ€ŠøŃŠ²Š¾ŠøŃ‚ŃŒ значение ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Ńƒ с заГанным ŠŗŠ»ŃŽŃ‡Š¾Š¼
Public Property Let Item(Key As Variant, value As Variant)
Public Property Let Item(Key As Variant, value As Variant)
Dim pt As tPointer
Dim pt As tPointer
If Not GetFromKey(Key, pt) Then
If Not GetFromKey(Key, pt) Then
Err.Raise 5
Err.Raise 5
Exit Property
Exit Property
End If
End If
If pt.Index = -1 Then Err.Raise 5: Exit Property
If pt.Index = -1 Then Err.Raise 5: Exit Property
List(pt.hash).Elements(pt.Index).value = value
List(pt.hash).Elements(pt.Index).value = value
End Property
End Property


' // ŠŸŃ€ŠøŃŠ²Š¾ŠøŃ‚ŃŒ Š¾Š±ŃŠŠµŠŗŃ‚Š½Š¾Šµ значение ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Ńƒ с заГанным ŠŗŠ»ŃŽŃ‡Š¾Š¼
' // ŠŸŃ€ŠøŃŠ²Š¾ŠøŃ‚ŃŒ Š¾Š±ŃŠŠµŠŗŃ‚Š½Š¾Šµ значение ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Ńƒ с заГанным ŠŗŠ»ŃŽŃ‡Š¾Š¼
Public Property Set Item(Key As Variant, value As Variant)
Public Property Set Item(Key As Variant, value As Variant)
Dim pt As tPointer
Dim pt As tPointer
If Not GetFromKey(Key, pt) Then
If Not GetFromKey(Key, pt) Then
Err.Raise 5
Err.Raise 5
Exit Property
Exit Property
End If
End If
If pt.Index = -1 Then Err.Raise 5: Exit Property
If pt.Index = -1 Then Err.Raise 5: Exit Property
Set List(pt.hash).Elements(pt.Index).value = value
Set List(pt.hash).Elements(pt.Index).value = value
End Property
End Property


' // Š—Š°Š“Š°Ń‚ŃŒ новый ŠŗŠ»ŃŽŃ‡
' // Š—Š°Š“Š°Ń‚ŃŒ новый ŠŗŠ»ŃŽŃ‡
Public Property Let Key(Key As Variant, NewKey As Variant)
Public Property Let Key(Key As Variant, NewKey As Variant)
Attribute Key.VB_Description = "Š”Š¼ŠµŠ½ŠøŃ‚ŃŒ ŠŗŠ»ŃŽŃ‡ на Š“Ń€ŃƒŠ³Š¾Š¹ ŠŗŠ»ŃŽŃ‡.\n"
Attribute Key.VB_Description = "Š”Š¼ŠµŠ½ŠøŃ‚ŃŒ ŠŗŠ»ŃŽŃ‡ на Š“Ń€ŃƒŠ³Š¾Š¹ ŠŗŠ»ŃŽŃ‡.\n"
Key_ Key, NewKey
Key_ Key, NewKey
End Property
End Property


' / Š—Š°Š“Š°Ń‚ŃŒ новый Š¾Š±ŃŠŠµŠŗŃ‚ный ŠŗŠ»ŃŽŃ‡
' / Š—Š°Š“Š°Ń‚ŃŒ новый Š¾Š±ŃŠŠµŠŗŃ‚ный ŠŗŠ»ŃŽŃ‡
Public Property Set Key(Key As Variant, NewKey As Variant)
Public Property Set Key(Key As Variant, NewKey As Variant)
Key_ Key, NewKey
Key_ Key, NewKey
End Property
End Property


' // Возвращает количество ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š²
' // Возвращает количество ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š²
Public Property Get Count() As Long
Public Property Get Count() As Long
Attribute Count.VB_Description = "ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ количество ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š² в таблице.\n"
Attribute Count.VB_Description = "ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ количество ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š² в таблице.\n"
Count = mCount
Count = mCount
End Property
End Property


' // Š”ŃƒŃ‰ŠµŃŃ‚Š²ŃƒŠµŃ‚ ли ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ с заГанным ŠŗŠ»ŃŽŃ‡Š¾Š¼
' // Š”ŃƒŃ‰ŠµŃŃ‚Š²ŃƒŠµŃ‚ ли ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ с заГанным ŠŗŠ»ŃŽŃ‡Š¾Š¼
Public Function Exists(Key As Variant) As Boolean
Public Function Exists(Key As Variant) As Boolean
Attribute Exists.VB_Description = "ŠžŠæŃ€ŠµŠ“ŠµŠ»ŠøŃ‚ŃŒ, ŠøŠ¼ŠµŠµŃ‚ŃŃ ли в таблице заГанный ŠŗŠ»ŃŽŃ‡.\n"
Attribute Exists.VB_Description = "ŠžŠæŃ€ŠµŠ“ŠµŠ»ŠøŃ‚ŃŒ, ŠøŠ¼ŠµŠµŃ‚ŃŃ ли в таблице заГанный ŠŗŠ»ŃŽŃ‡.\n"
Dim pt As tPointer
Dim pt As tPointer
If Not GetFromKey(Key, pt) Then
If Not GetFromKey(Key, pt) Then
Err.Raise 5
Err.Raise 5
Exit Function
Exit Function
End If
End If
Exists = pt.Index <> -1
Exists = pt.Index <> -1
End Function
End Function


' // Š£Š“Š°Š»ŠøŃ‚ŃŒ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ по ŠŗŠ»ŃŽŃ‡Ńƒ
' // Š£Š“Š°Š»ŠøŃ‚ŃŒ ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ по ŠŗŠ»ŃŽŃ‡Ńƒ
Public Sub Remove(Key As Variant)
Public Sub Remove(Key As Variant)
Attribute Remove.VB_Description = "Š£Š“Š°Š»ŠøŃ‚ŃŒ ŠŗŠ»ŃŽŃ‡ Šø ŃŠ²ŃŠ·Š°Š½Š½Ń‹Š¹ с ним ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ ŠøŠ· теблицы.\n"
Attribute Remove.VB_Description = "Š£Š“Š°Š»ŠøŃ‚ŃŒ ŠŗŠ»ŃŽŃ‡ Šø ŃŠ²ŃŠ·Š°Š½Š½Ń‹Š¹ с ним ŃŠ»ŠµŠ¼ŠµŠ½Ń‚ ŠøŠ· теблицы.\n"
Dim pt As tPointer
Dim pt As tPointer
Dim ln As tPointer
Dim ln As tPointer
Dim lp As tPointer
Dim lp As tPointer
Dim p As tPointer
Dim p As tPointer
Dim l As Long
Dim l As Long
If Not GetFromKey(Key, pt) Then
If Not GetFromKey(Key, pt) Then
Err.Raise 5
Err.Raise 5
Exit Sub
Exit Sub
End If
End If
If pt.Index = -1 Then
If pt.Index = -1 Then
Err.Raise 5
Err.Raise 5
Exit Sub
Exit Sub
End If
End If
Remove_ pt
Remove_ pt
End Sub
End Sub


' // Š£Š“Š°Š»ŠøŃ‚ŃŒ все ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Ń‹
' // Š£Š“Š°Š»ŠøŃ‚ŃŒ все ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Ń‹
Public Sub RemoveAll()
Public Sub RemoveAll()
Attribute RemoveAll.VB_Description = "ŠžŃ‡ŠøŃŃ‚ŠøŃ‚ŃŒ Ń‚Š°Š±Š»ŠøŃ†Ńƒ."
Attribute RemoveAll.VB_Description = "ŠžŃ‡ŠøŃŃ‚ŠøŃ‚ŃŒ Ń‚Š°Š±Š»ŠøŃ†Ńƒ."
Call Class_Initialize
Call Class_Initialize
End Sub
End Sub


' // ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ список ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š²
' // ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ список ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š²
Public Function Items() As Variant
Public Function Items() As Variant
Attribute Items.VB_Description = "ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ массив всех ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š² теблицы.\n"
Attribute Items.VB_Description = "ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ массив всех ŃŠ»ŠµŠ¼ŠµŠ½Ń‚Š¾Š² теблицы.\n"
Dim pt As tPointer
Dim pt As tPointer
Dim i As Long
Dim i As Long
Dim ret() As Variant
Dim ret() As Variant
If mCount = 0 Then Exit Function
If mCount = 0 Then Exit Function
pt = First
pt = First
ReDim ret(mCount - 1)
ReDim ret(mCount - 1)
Do
Do
VariantCopy ret(i), List(pt.hash).Elements(pt.Index).value
VariantCopy ret(i), List(pt.hash).Elements(pt.Index).value
pt = List(pt.hash).Elements(pt.Index).Next
pt = List(pt.hash).Elements(pt.Index).Next
i = i + 1
i = i + 1
Loop While i < mCount
Loop While i < mCount
Items = ret
Items = ret
End Function
End Function


' // ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ список ŠŗŠ»ŃŽŃ‡ŠµŠ¹
' // ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ список ŠŗŠ»ŃŽŃ‡ŠµŠ¹
Public Function Keys() As Variant()
Public Function Keys() As Variant
Attribute Keys.VB_Description = "ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ массив всех ŠŗŠ»ŃŽŃ‡ŠµŠ¹ ŃŠ»Š¾Š²Š°Ń€Ń.\n"
Attribute Keys.VB_Description = "ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ массив всех ŠŗŠ»ŃŽŃ‡ŠµŠ¹ ŃŠ»Š¾Š²Š°Ń€Ń.\n"
Dim pt As tPointer, i As Long, ret() As Variant
Dim pt As tPointer, i As Long, ret() As Variant
If mCount = 0 Then Exit Function
If mCount = 0 Then Keys = Array(): Exit Function
pt = First
pt = First
ReDim ret(mCount - 1)
ReDim ret(mCount - 1)
Do
Do
VariantCopy ret(i), List(pt.hash).Elements(pt.Index).Key
VariantCopy ret(i), List(pt.hash).Elements(pt.Index).Key
pt = List(pt.hash).Elements(pt.Index).Next
pt = List(pt.hash).Elements(pt.Index).Next
i = i + 1
i = i + 1
Loop While i < mCount
Loop While i < mCount
Keys = ret
Keys = ret
End Function
End Function


' // Š’Ń‹Ń‡ŠøŃŠ»ŠøŃ‚ŃŒ Ń…ŠµŃˆ
' // Š’Ń‹Ń‡ŠøŃŠ»ŠøŃ‚ŃŒ Ń…ŠµŃˆ
Public Function HashValue(value As Variant) As Long
Public Function HashValue(value As Variant) As Long
Attribute HashValue.VB_Description = "ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ значение Ń…ŠµŃˆ-Ń„ŃƒŠ½ŠŗŃ†ŠøŠø от заГанного ŠŗŠ»ŃŽŃ‡Š°."
Attribute HashValue.VB_Description = "ŠŸŠ¾Š»ŃƒŃ‡ŠøŃ‚ значение Ń…ŠµŃˆ-Ń„ŃƒŠ½ŠŗŃ†ŠøŠø от заГанного ŠŗŠ»ŃŽŃ‡Š°."
Dim hash As Long
Dim hash As Long
hash = CalcHash(value)
hash = CalcHash(value)
If hash < 0 Then
If hash < 0 Then
Err.Raise 5
Err.Raise 5
Exit Function
Exit Function
End If
End If
HashValue = hash
HashValue = hash
End Function
End Function


' //
' //


Private Sub Add_(pt As tPointer, Key As Variant, value As Variant)
Private Sub Add_(pt As tPointer, Key As Variant, value As Variant)


If pt.Index Then
If pt.Index Then
If pt.Index > UBound(List(pt.hash).Elements) Then
If pt.Index > UBound(List(pt.hash).Elements) Then
ReDim Preserve List(pt.hash).Elements(UBound(List(pt.hash).Elements) + GRANULARITY)
ReDim Preserve List(pt.hash).Elements(UBound(List(pt.hash).Elements) + GRANULARITY)
End If
End If
Else
Else
ReDim Preserve List(pt.hash).Elements(GRANULARITY - 1)
ReDim Preserve List(pt.hash).Elements(GRANULARITY - 1)
End If
End If
List(pt.hash).ElementsCount = pt.Index + 1
List(pt.hash).ElementsCount = pt.Index + 1
VariantCopyInd List(pt.hash).Elements(pt.Index).value, value
VariantCopyInd List(pt.hash).Elements(pt.Index).value, value
VariantCopyInd List(pt.hash).Elements(pt.Index).Key, Key
VariantCopyInd List(pt.hash).Elements(pt.Index).Key, Key
If Last.hash >= 0 Then
If Last.hash >= 0 Then
List(Last.hash).Elements(Last.Index).Next = pt
List(Last.hash).Elements(Last.Index).Next = pt
List(pt.hash).Elements(pt.Index).Prev = Last
List(pt.hash).Elements(pt.Index).Prev = Last
Else
Else
List(pt.hash).Elements(pt.Index).Prev.hash = -1
List(pt.hash).Elements(pt.Index).Prev.hash = -1
List(pt.hash).Elements(pt.Index).Prev.Index = -1
List(pt.hash).Elements(pt.Index).Prev.Index = -1
First = pt
First = pt
End If
End If
List(pt.hash).Elements(pt.Index).Next.hash = -1
List(pt.hash).Elements(pt.Index).Next.hash = -1
List(pt.hash).Elements(pt.Index).Next.Index = -1
List(pt.hash).Elements(pt.Index).Next.Index = -1
Last = pt
Last = pt
mCount = mCount + 1
mCount = mCount + 1
End Sub
End Sub


Private Sub Remove_(pt As tPointer)
Private Sub Remove_(pt As tPointer)
Dim ln As tPointer
Dim ln As tPointer
Dim lp As tPointer
Dim lp As tPointer
Dim p As tPointer
Dim p As tPointer
Dim l As Long
Dim l As Long


lp = List(pt.hash).Elements(pt.Index).Prev
lp = List(pt.hash).Elements(pt.Index).Prev
ln = List(pt.hash).Elements(pt.Index).Next
ln = List(pt.hash).Elements(pt.Index).Next
For l = pt.Index To List(pt.hash).ElementsCount - 2
For l = pt.Index To List(pt.hash).ElementsCount - 2
List(pt.hash).Elements(l) = List(pt.hash).Elements(l + 1)
List(pt.hash).Elements(l) = List(pt.hash).Elements(l + 1)
' ŠŸŃ€Š°Š²ŠøŠ¼ ссылки на ŃŠ»ŠµŠ¼ŠµŠ½Ń‚
' ŠŸŃ€Š°Š²ŠøŠ¼ ссылки на ŃŠ»ŠµŠ¼ŠµŠ½Ń‚
p = List(pt.hash).Elements(l).Prev
p = List(pt.hash).Elements(l).Prev
If p.Index >= 0 Then List(p.hash).Elements(p.Index).Next.Index = List(p.hash).Elements(p.Index).Next.Index - 1
If p.Index >= 0 Then List(p.hash).Elements(p.Index).Next.Index = List(p.hash).Elements(p.Index).Next.Index - 1
p = List(pt.hash).Elements(l).Next
p = List(pt.hash).Elements(l).Next
If p.Index >= 0 Then List(p.hash).Elements(p.Index).Prev.Index = List(p.hash).Elements(p.Index).Prev.Index - 1
If p.Index >= 0 Then List(p.hash).Elements(p.Index).Prev.Index = List(p.hash).Elements(p.Index).Prev.Index - 1
Next
Next
l = List(pt.hash).ElementsCount - 1: List(pt.hash).ElementsCount = l
l = List(pt.hash).ElementsCount - 1: List(pt.hash).ElementsCount = l
If l Then
If l Then
If (l Mod GRANULARITY) = 0 Then ReDim Preserve List(pt.hash).Elements(l - 1)
If (l Mod GRANULARITY) = 0 Then ReDim Preserve List(pt.hash).Elements(l - 1)
Else
Else
Erase List(pt.hash).Elements()
Erase List(pt.hash).Elements()
End If
End If
If lp.Index >= 0 Then List(lp.hash).Elements(lp.Index).Next = ln
If lp.Index >= 0 Then List(lp.hash).Elements(lp.Index).Next = ln
If ln.Index >= 0 Then List(ln.hash).Elements(ln.Index).Prev = lp
If ln.Index >= 0 Then List(ln.hash).Elements(ln.Index).Prev = lp
If lp.Index = -1 Then First = ln
If lp.Index = -1 Then First = ln
If ln.Index = -1 Then Last = lp
If ln.Index = -1 Then Last = lp
mCount = mCount - 1
mCount = mCount - 1
End Sub
End Sub


Private Sub Key_(Key As Variant, NewKey As Variant)
Private Sub Key_(Key As Variant, NewKey As Variant)
Dim pt1 As tPointer
Dim pt1 As tPointer
Dim pt2 As tPointer
Dim pt2 As tPointer
Dim value As Variant
Dim value As Variant
If Not GetFromKey(Key, pt1) Then
If Not GetFromKey(Key, pt1) Then
Err.Raise 5
Err.Raise 5
Exit Sub
Exit Sub
End If
End If
If pt1.Index = -1 Then Err.Raise 5: Exit Sub
If pt1.Index = -1 Then Err.Raise 5: Exit Sub
If Not GetFromKey(NewKey, pt2) Then
If Not GetFromKey(NewKey, pt2) Then
Err.Raise 5
Err.Raise 5
Exit Sub
Exit Sub
End If
End If
If pt2.Index <> -1 Then Err.Raise 457: Exit Sub
If pt2.Index <> -1 Then Err.Raise 457: Exit Sub


VariantCopy value, List(pt1.hash).Elements(pt1.Index).value
VariantCopy value, List(pt1.hash).Elements(pt1.Index).value
Remove_ pt1
Remove_ pt1
pt2.Index = List(pt2.hash).ElementsCount
pt2.Index = List(pt2.hash).ElementsCount
Add_ pt2, NewKey, value
Add_ pt2, NewKey, value
End Sub
End Sub


Private Function GetFromKey(Key As Variant, Pointer As tPointer) As Boolean
Private Function GetFromKey(Key As Variant, Pointer As tPointer) As Boolean
Dim i As Long
Dim i As Long
Dim hash As Long
Dim hash As Long
Dim typ As Integer
Dim typ As Integer
Dim keyi As Variant
Dim keyi As Variant
Dim lPtr As Long
Dim lPtr As Long
hash = CalcHash(Key)
hash = CalcHash(Key)
If hash >= 0 Then
If hash >= 0 Then
Pointer.hash = hash
Pointer.hash = hash
GetFromKey = True
GetFromKey = True
VariantCopyInd keyi, Key
VariantCopyInd keyi, Key
lPtr = VarPtr(keyi)
lPtr = VarPtr(keyi)
GetMem2 ByVal lPtr, typ
GetMem2 ByVal lPtr, typ
Select Case typ
Select Case typ
Case vbString
Case vbString
For i = 0 To List(hash).ElementsCount - 1
For i = 0 To List(hash).ElementsCount - 1
If VarCmp(List(hash).Elements(i).Key, keyi, lcid, mCompareMode) = 1 Then
If VarCmp(List(hash).Elements(i).Key, keyi, lcid, mCompareMode) = 1 Then
Pointer.Index = i
Pointer.Index = i
Exit Function
Exit Function
End If
End If
Next
Next
Case vbObject, vbDataObject
Case vbObject, vbDataObject
GetMem4 ByVal lPtr + 8, lPtr
GetMem4 ByVal lPtr + 8, lPtr
For i = 0 To List(hash).ElementsCount - 1
For i = 0 To List(hash).ElementsCount - 1
GetMem2 List(hash).Elements(i).Key, typ
GetMem2 List(hash).Elements(i).Key, typ
If typ = vbObject Or typ = vbDataObject Then
If typ = vbObject Or typ = vbDataObject Then
If List(hash).Elements(i).Key Is keyi Then
If List(hash).Elements(i).Key Is keyi Then
Pointer.Index = i
Pointer.Index = i
Exit Function
Exit Function
End If
End If
End If
End If


Next
Next
Case vbNull
Case vbNull
For i = 0 To List(hash).ElementsCount - 1
For i = 0 To List(hash).ElementsCount - 1


If IsNull(List(hash).Elements(i).Key) Then
If IsNull(List(hash).Elements(i).Key) Then
Pointer.Index = i
Pointer.Index = i
Exit Function
Exit Function
End If
End If
Next
Next
Case vbEmpty
Case vbEmpty
For i = 0 To List(hash).ElementsCount - 1
For i = 0 To List(hash).ElementsCount - 1


If IsEmpty(List(hash).Elements(i).Key) Then
If IsEmpty(List(hash).Elements(i).Key) Then
Pointer.Index = i
Pointer.Index = i
Exit Function
Exit Function
End If
End If
Next
Next
Case Else
Case Else
For i = 0 To List(hash).ElementsCount - 1
For i = 0 To List(hash).ElementsCount - 1
If List(hash).Elements(i).Key = keyi Then
If List(hash).Elements(i).Key = keyi Then
Pointer.Index = i
Pointer.Index = i
Exit Function
Exit Function
End If
End If
Next
Next
End Select
End Select
End If
End If
Pointer.Index = -1
Pointer.Index = -1
End Function
End Function


Private Function CalcHash(value As Variant) As Long
Private Function CalcHash(value As Variant) As Long
Dim i As Long
Dim i As Long
Dim typ As Integer
Dim typ As Integer
Dim ptr As Long
Dim ptr As Long
Dim length As Long
Dim length As Long
Dim dbl As Double
Dim dbl As Double
Dim cur As Currency
Dim cur As Currency
Dim sgl As Single
Dim sgl As Single
ptr = VarPtr(value)
ptr = VarPtr(value)
GetMem2 ByVal ptr, typ
GetMem2 ByVal ptr, typ
Do While typ = &H400C
Do While typ = &H400C
GetMem2 ByVal ptr + 8, ptr
GetMem2 ByVal ptr + 8, ptr
GetMem2 ByVal ptr, typ
GetMem2 ByVal ptr, typ
Loop
Loop
ptr = ptr + 8
ptr = ptr + 8
If typ And &H4000 Then
If typ And &H4000 Then
GetMem4 ByVal ptr, ptr
GetMem4 ByVal ptr, ptr
typ = typ And &HBFFF&
typ = typ And &HBFFF&
End If
End If
Select Case typ
Select Case typ
Case vbString
Case vbString
GetMem4 ByVal ptr, ptr
GetMem4 ByVal ptr, ptr
If ptr = 0 Then CalcHash = 0: Exit Function
GetMem4 ByVal ptr - 4, length
GetMem4 ByVal ptr - 4, length
length = length \ 2
length = length \ 2
If length >= UBound(locbuf) Then
If length >= UBound(locbuf) Then
ReDim locbuf(length + 1)
ReDim locbuf(length + 1)
End If
End If
If mCompareMode = vbTextCompare Then
If mCompareMode = vbTextCompare Then
LCMapString lcid, LCMAP_LOWERCASE, ByVal ptr, length, locbuf(0), length
LCMapString lcid, LCMAP_LOWERCASE, ByVal ptr, length, locbuf(0), length
Else
Else
memcpy locbuf(0), ByVal ptr, length * 2
memcpy locbuf(0), ByVal ptr, length * 2&
End If
End If
For i = 0 To length - 1
For i = 0 To length - 1
CalcHash = (CalcHash * 37 + locbuf(i) And &HFFFF&)
CalcHash = (CalcHash * 37& + locbuf(i) And &HFFFF&)
Next
Next
Case vbByte
Case vbByte
GetMem1 ByVal ptr, CalcHash
GetMem1 ByVal ptr, CalcHash
VarR4FromUI1 ByVal CalcHash, CalcHash
VarR4FromUI1 ByVal CalcHash, CalcHash
Case vbInteger, vbBoolean
Case vbInteger, vbBoolean


GetMem2 ByVal ptr, CalcHash
GetMem2 ByVal ptr, CalcHash
VarR4FromI2 ByVal CalcHash, CalcHash
VarR4FromI2 ByVal CalcHash, CalcHash
Case vbLong, vbError
Case vbLong, vbError
GetMem4 ByVal ptr, i
GetMem4 ByVal ptr, i
If i > 9999999 Or i < -9999999 Then
If i > 9999999 Or i < -9999999 Then
CalcHash = 0
CalcHash = 0
Else
Else
VarR4FromI4 ByVal CalcHash, CalcHash
VarR4FromI4 ByVal CalcHash, CalcHash
End If
End If
Case vbSingle
Case vbSingle
GetMem8 ByVal ptr, sgl
GetMem8 ByVal ptr, sgl
If sgl > 9999999 Or sgl < -9999999 Then
If sgl > 9999999 Or sgl < -9999999 Then
CalcHash = 0
CalcHash = 0
Else
Else
GetMem4 sgl, CalcHash
GetMem4 sgl, CalcHash
End If
End If
Case vbObject, vbDataObject
Case vbObject, vbDataObject
GetMem4 ByVal ptr, CalcHash
GetMem4 ByVal ptr, CalcHash
Case vbDouble, vbDate
Case vbDouble, vbDate
GetMem8 ByVal ptr, dbl
GetMem8 ByVal ptr, dbl
If dbl > 9999999 Or dbl < -9999999 Then
If dbl > 9999999 Or dbl < -9999999 Then
CalcHash = 0
CalcHash = 0
Else
Else
GetMem4 CSng(dbl), CalcHash
GetMem4 CSng(dbl), CalcHash
End If
End If
Case vbCurrency
Case vbCurrency
GetMem8 ByVal ptr, cur
GetMem8 ByVal ptr, cur
If dbl > 9999999@ Or dbl < -9999999@ Then
If dbl > 9999999@ Or dbl < -9999999@ Then
CalcHash = 0
CalcHash = 0
Else
Else
GetMem4 CSng(cur), CalcHash
GetMem4 CSng(cur), CalcHash
End If
End If
Case vbDecimal
Case vbDecimal
If value > decMax Or value < decMin Then
If value > decMax Or value < decMin Then
CalcHash = 0
CalcHash = 0
Else
Else
GetMem4 CSng(value), CalcHash
GetMem4 CSng(value), CalcHash
End If
End If
Case vbNull, vbEmpty
Case vbNull, vbEmpty
CalcHash = 0
CalcHash = 0
Case Else
Case Else
CalcHash = -1
CalcHash = -1
Exit Function
Exit Function
End Select
End Select
CalcHash = (CalcHash And &H7FFFFFFF) Mod HASH_SIZE
CalcHash = (CalcHash And &H7FFFFFFF) Mod HASH_SIZE
End Function
End Function


Private Function CreateEnumObject() As Long
Private Function CreateEnumObject() As Long
If lpAsm = 0 Then
If lpAsm = 0 Then


lpAsm = GetEnumInterface()
lpAsm = GetEnumInterface()
If lpAsm = 0 Then Exit Function
If lpAsm = 0 Then Exit Function
End If
End If
Dim newObject As enumObject
Dim newObject As enumObject
Dim lpObject As Long
Dim lpObject As Long
newObject.Counter = 1
newObject.Counter = 1
newObject.DataPtr = VarPtr(List(0))
newObject.DataPtr = VarPtr(List(0))
newObject.vTablePtr = lpAsm + &HEC
newObject.vTablePtr = lpAsm + &HEC
newObject.Pointer = First
newObject.Pointer = First
newObject.First = First
newObject.First = First
newObject.OffsetVariant = IIf(mEnumMode = ENUM_BY_KEY, 0, &H10)
newObject.OffsetVariant = IIf(mEnumMode = ENUM_BY_KEY, 0, &H10)
lpObject = HeapAlloc(GetProcessHeap(), HEAP_NO_SERIALIZE, Len(newObject))
lpObject = HeapAlloc(GetProcessHeap(), HEAP_NO_SERIALIZE, Len(newObject))
memcpy ByVal lpObject, newObject, Len(newObject)
memcpy ByVal lpObject, newObject, Len(newObject)
CreateEnumObject = lpObject
CreateEnumObject = lpObject
End Function
End Function


Private Function GetEnumInterface() As Long
Private Function GetEnumInterface() As Long
Dim sHex As String
Dim sHex As String
sHex = Space(&H8)
sHex = Space(&H8)
If GetEnvironmentVariable(StrPtr("TrickHashEnumerationInterface"), StrPtr(sHex), Len(sHex) + 1) = 0 Then
If GetEnvironmentVariable(StrPtr("TrickHashEnumerationInterface"), StrPtr(sHex), Len(sHex) + 1) = 0 Then
GetEnumInterface = CreateAsm()
GetEnumInterface = CreateAsm()
Else
Else
GetEnumInterface = CLng("&H" & sHex)
GetEnumInterface = CLng("&H" & sHex)
End If
End If
End Function
End Function


Private Function CreateAsm() As Long
Private Function CreateAsm() As Long
Dim lpAddr As Long
Dim lpAddr As Long
Dim dat(58) As Long
Dim dat(58) As Long
Dim hLib As Long
Dim hLib As Long
Dim lpProc As Long
Dim lpProc As Long
dat(0) = &H424448B: dat(1) = &H8B0440FF: dat(2) = &H890C244C: dat(3) = &HC2C03101: dat(4) = &H448B000C:
dat(0) = &H424448B: dat(1) = &H8B0440FF: dat(2) = &H890C244C: dat(3) = &HC2C03101: dat(4) = &H448B000C:
dat(5) = &H40FF0424: dat(6) = &H4408B04: dat(7) = &H8B0004C2: dat(8) = &HFF042444: dat(9) = &H6740448:
dat(5) = &H40FF0424: dat(6) = &H4408B04: dat(7) = &H8B0004C2: dat(8) = &HFF042444: dat(9) = &H6740448:
dat(10) = &HC204408B: dat(11) = &H6A500004: dat(12) = &H5642E801: dat(13) = &HE8501234: dat(14) = &H1234563C:
dat(10) = &HC204408B: dat(11) = &H6A500004: dat(12) = &H5642E801: dat(13) = &HE8501234: dat(14) = &H1234563C:
dat(15) = &H4C2C031: dat(16) = &H56575300: dat(17) = &H1024748B: dat(18) = &H14245C8B: dat(19) = &H18247C8B:
dat(15) = &H4C2C031: dat(16) = &H56575300: dat(17) = &H1024748B: dat(18) = &H14245C8B: dat(19) = &H18247C8B:
dat(20) = &H846BF0F: dat(21) = &H482F7440: dat(22) = &H8B0C4E8B: dat(23) = &HF04C14C: dat(24) = &H660A46B7:
dat(20) = &H846BF0F: dat(21) = &H482F7440: dat(22) = &H8B0C4E8B: dat(23) = &HF04C14C: dat(24) = &H660A46B7:
dat(25) = &HF28C06B: dat(26) = &H498BC0B7: dat(27) = &H10C8D0C: dat(28) = &H320418B: dat(29) = &H4689144E:
dat(25) = &HF28C06B: dat(26) = &H498BC0B7: dat(27) = &H10C8D0C: dat(28) = &H320418B: dat(29) = &H4689144E:
dat(30) = &HE8575108: dat(31) = &H123455F8: dat(32) = &H4B10C783: dat(33) = &HDB85CA75: dat(34) = &HFC2950F:
dat(30) = &HE8575108: dat(31) = &H123455F8: dat(32) = &H4B10C783: dat(33) = &HDB85CA75: dat(34) = &HFC2950F:
dat(35) = &H7C8BF2B6: dat(36) = &HFF851C24: dat(37) = &H448B0874: dat(38) = &HD8291424: dat(39) = &HF0890789:
dat(35) = &H7C8BF2B6: dat(36) = &HFF851C24: dat(37) = &H448B0874: dat(38) = &HD8291424: dat(39) = &HF0890789:
dat(40) = &HC25B5F5E: dat(41) = &H548B0010: dat(42) = &H428B0424: dat(43) = &HC528B08: dat(44) = &H1F744066:
dat(40) = &HC25B5F5E: dat(41) = &H548B0010: dat(42) = &H428B0424: dat(43) = &HC528B08: dat(44) = &H1F744066:
dat(45) = &HB70F4866: dat(46) = &HCA4C8BC8: dat(47) = &H10E8C104: dat(48) = &H28C06B66: dat(49) = &H8B0C498B:
dat(45) = &HB70F4866: dat(46) = &HCA4C8BC8: dat(47) = &H10E8C104: dat(48) = &H28C06B66: dat(49) = &H8B0C498B:
dat(50) = &HFF200144: dat(51) = &H7508244C: dat(52) = &H85D231DF: dat(53) = &HC2950FD2: dat(54) = &H8C2D089:
dat(50) = &HFF200144: dat(51) = &H7508244C: dat(52) = &H85D231DF: dat(53) = &HC2950FD2: dat(54) = &H8C2D089:
dat(55) = &H24448B00: dat(56) = &H10508B04: dat(57) = &H31085089: dat(58) = &H4C2C0
dat(55) = &H24448B00: dat(56) = &H10508B04: dat(57) = &H31085089: dat(58) = &H4C2C0


lpAddr = VirtualAlloc(ByVal 0&, &H104, MEM_COMMIT Or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
lpAddr = VirtualAlloc(ByVal 0&, &H104, MEM_COMMIT Or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
If lpAddr = 0 Then Exit Function
If lpAddr = 0 Then Exit Function
memcpy ByVal lpAddr, dat(0), &HEC
memcpy ByVal lpAddr, dat(0), &HEC
hLib = GetModuleHandle(StrPtr("kernel32"))
hLib = GetModuleHandle(StrPtr("kernel32"))
If hLib = 0 Then GoTo Clear
If hLib = 0 Then GoTo Clear
lpProc = GetProcAddress(hLib, "GetProcessHeap")
lpProc = GetProcAddress(hLib, "GetProcessHeap")
If lpProc = 0 Then GoTo Clear
If lpProc = 0 Then GoTo Clear
GetMem4 lpProc - (lpAddr + &H32 + 4), ByVal lpAddr + &H32
GetMem4 lpProc - (lpAddr + &H32 + 4), ByVal lpAddr + &H32
lpProc = GetProcAddress(hLib, "HeapFree")
lpProc = GetProcAddress(hLib, "HeapFree")
If lpProc = 0 Then GoTo Clear
If lpProc = 0 Then GoTo Clear
GetMem4 lpProc - (lpAddr + &H38 + 4), ByVal lpAddr + &H38
GetMem4 lpProc - (lpAddr + &H38 + 4), ByVal lpAddr + &H38
hLib = GetModuleHandle(StrPtr("oleaut32"))
hLib = GetModuleHandle(StrPtr("oleaut32"))
If hLib = 0 Then GoTo Clear
If hLib = 0 Then GoTo Clear
lpProc = GetProcAddress(hLib, "VariantCopy")
lpProc = GetProcAddress(hLib, "VariantCopy")
If lpProc = 0 Then GoTo Clear
If lpProc = 0 Then GoTo Clear
GetMem4 lpProc - (lpAddr + &H7C + 4), ByVal lpAddr + &H7C
GetMem4 lpProc - (lpAddr + &H7C + 4), ByVal lpAddr + &H7C
GetMem4 lpAddr, ByVal lpAddr + &HEC ' IUnknown::QueryInterface
GetMem4 lpAddr, ByVal lpAddr + &HEC ' IUnknown::QueryInterface
GetMem4 lpAddr + &H12, ByVal lpAddr + &HF0 ' IUnknown::AddRef
GetMem4 lpAddr + &H12, ByVal lpAddr + &HF0 ' IUnknown::AddRef
GetMem4 lpAddr + &H1F, ByVal lpAddr + &HF4 ' IUnknown::Release
GetMem4 lpAddr + &H1F, ByVal lpAddr + &HF4 ' IUnknown::Release
GetMem4 lpAddr + &H41, ByVal lpAddr + &HF8 ' IEnumVariant::Next
GetMem4 lpAddr + &H41, ByVal lpAddr + &HF8 ' IEnumVariant::Next
GetMem4 lpAddr + &HA6, ByVal lpAddr + &HFC ' IEnumVariant::Skip
GetMem4 lpAddr + &HA6, ByVal lpAddr + &HFC ' IEnumVariant::Skip
GetMem4 lpAddr + &HDD, ByVal lpAddr + &H100 ' IEnumVariant::Reset
GetMem4 lpAddr + &HDD, ByVal lpAddr + &H100 ' IEnumVariant::Reset
If SetEnvironmentVariable(StrPtr("TrickHashEnumerationInterface"), StrPtr(Hex(lpAddr))) = 0 Then GoTo Clear
If SetEnvironmentVariable(StrPtr("TrickHashEnumerationInterface"), StrPtr(Hex(lpAddr))) = 0 Then GoTo Clear
CreateAsm = lpAddr
CreateAsm = lpAddr
Exit Function
Exit Function
Clear:
Clear:
VirtualFree ByVal lpAddr, &H104, MEM_RELEASE
VirtualFree ByVal lpAddr, &H104, MEM_RELEASE
End Function
End Function


Private Sub Class_Initialize()
Private Sub Class_Initialize()


ReDim List(HASH_SIZE - 1)
ReDim List(HASH_SIZE - 1)
ReDim locbuf(255)
ReDim locbuf(255)
First.hash = -1
First.hash = -1
First.Index = -1
First.Index = -1
Last.hash = -1
Last.hash = -1
Last.Index = -1
Last.Index = -1
mCount = 0
mCount = 0
lcid = GetUserDefaultLCID()
lcid = GetUserDefaultLCID()
decMin = CDec(-9999999)
decMin = CDec(-9999999)
decMax = CDec(9999999)
decMax = CDec(9999999)
End Sub
End Sub


Private Sub Class_Terminate()
Private Sub Class_Terminate()
Erase List()
Erase List()
End Sub
End Sub