Option Explicit

    ' array to hold the pointers we are in charge of validating
    Private m_alpCollections() As Long

    Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cBytes&)


Public Sub AddToLookupList(ByVal lpObject&)
    ' pass this task on to the FindPointer routine
    Call FindPointer(lpObject, True)
End Sub


Public Sub RemoveFromLookupList(ByVal lpObject&)
    ' removes a pointer from the array. this function is called from the terminate event of the collection class

    Dim nItem&, nUbound&

    ' first find the location of the pointer in the array
    nItem = IsPointerValid(lpObject)

    ' if we found it, remove it and shift the rest of the items....
    If nItem > (-1) Then
    nUbound = UBound(m_alpCollections)

        If nItem < nUbound Then
            ' grab all of the items below the moved one and shift them up
            CopyMemory ByVal VarPtr(m_alpCollections(nItem)), ByVal VarPtr(m_alpCollections(nItem + 1)), (nUbound - nItem) * 4&
        End If


        If nUbound Then
            ' if there are other items in the array, preserve them
            ReDim Preserve m_alpCollections(nUbound - 1) As Long
        Else
            ' if this is the last item in the array, just redim the array and make sure the value is zero
            ReDim m_alpCollections(0) As Long
            m_alpCollections(0) = 0
        End If
    End If

End Sub


Public Function IsPointerValid(ByVal lpObject&) As Long
    ' checks whether or not the object still exists in the array. for all intents
    ' and purposes, if the object isn't in the array, it no longer exists.

    IsPointerValid = FindPointer(lpObject)
End Function


Private Function FindPointer(ByVal lpObject&, Optional ByVal bAddIfNotFound As Boolean) As Long
    ' function to provide fast lookups for pointers in the array

    Static bInitialized As Boolean

    Dim i&, nLow&, nHigh&, nUbound&

    ' make sure the array is initialized
    If bInitialized = False Then
        If bAddIfNotFound Then
            GoTo AddFirsItem
        Else
            FindPointer = (-1)
        End If
    End If


    nHigh = UBound(m_alpCollections)

    ' loop through the array looking for the object pointer.
    ' the array is in numerical order so we can do fast lookups

    Do
        ' divide and conquer! Each time we loop, divide the difference between the
        ' last items checked and search between the two indexes. This is MUCH faster
        ' than looping through the entire list when dealing with a sorted array.

        i = nLow + ((nHigh - nLow) \ 2)

        ' see how sKey relates to the current index....
        Select Case m_alpCollections(i)
            Case Is = lpObject
                FindPointer = i
                Exit Do

            Case Is > lpObject: nHigh = i - 1
            Case Is < lpObject: nLow = i + 1
        End Select


        ' if the low search bound has become greater than the high search bound, the
        ' item does not exist in the array. if the bAddIfNotFound flag is set, a new
        ' item is being added. otherwise, just return the not found value.

        If nLow > nHigh Then
            If bAddIfNotFound Then

AddFirsItem:

                ' check to see whether or not this item is initialized
                If Not bInitialized Then
                    bInitialized = True
                    ReDim m_alpCollections(0) As Long
                Else

                    If m_alpCollections(0) <> 0 Then
                    ReDim Preserve m_alpCollections(UBound(m_alpCollections) + 1) As Long
                End If

                nUbound = UBound(m_alpCollections)

                ' see whether we should add this item above or below the item at index 'i'
                Select Case m_alpCollections(i)
                    Case Is < lpObject: i = i + 1
                    Case Is > lpObject: i = i '<- included for self documentation
                End Select

                If i > nUbound Then i = nUbound

                    If i < nUbound Then
                        ' grab all of the items above the moved one and shift them down
                        CopyMemory ByVal VarPtr(m_alpCollections(i + 1)), ByVal VarPtr(m_alpCollections(i)), (nUbound - i) * 4&
                    End If ' i < nUbound
                End If

                ' place the new pointer into the position that used to be held by the target
                m_alpCollections(i) = lpObject

            End If ' bAddIfNotFound


            ' return value of KEY_NOT_FOUND tells the caller no match was found
            FindPointer = (-1)
            Exit Do

        End If ' nLow > nHigh

    Loop

End Function