VB6, как получить C-подобный переполнение целых чисел

Я хочу передать этот простой алгоритм хеширования на VB6.

Я придумал:

Public Function simpleHash(hashString As String) As Long
Dim hash As Long
Dim c As Long
Dim i As Integer

    On Local Error Resume Next

    hash = 5381
    For i = 1 To Len(hashString)
        c = AscW(Mid$(hashString, i, 1))
        hash = hash * 33 + c
    Next i

    simpleHash = hash
End Function

Проблема заключается в том, что, несмотря на мой оператор On Error, который подавляет исключения Error 6: Overflow, переменная hash больше не обновляется, если происходит переполнение.

Как я могу исправить это или реализовать этот алгоритм по-другому?

Ответ 1

Я бы поставил под вопрос, имеет ли смысл хэш UTF-16LE ( "Юникод" ) таким образом. Это может сделать гораздо более целесообразным преобразование VB String в UTF-8, а затем хэш.

Пока я не могу найти тестовые векторы для djb2 для проверки моей собственной реализации, она работает довольно быстро:

Private Type CURRENCY_CURRENCY
    Value As Currency
End Type

Private Type CURRENCY_2LONGS
    ValueLo As Long
    ValueHi As Long
End Type

Public Function djb2(ByVal StringToHash As String) As Long
    Dim C2L As CURRENCY_2LONGS
    Dim CC As CURRENCY_CURRENCY
    Dim I As Long

    C2L.ValueLo = 5381
    For I = 1 To Len(StringToHash)
        LSet CC = C2L
        CC.Value = CC.Value * [email protected] + CCur(AscW(Mid$(StringToHash, I, 1))) / [email protected]
        LSet C2L = CC
        C2L.ValueHi = 0
    Next I

    djb2 = C2L.ValueLo
End Function

Ответ 2

Я нашел обходное решение с использованием валюты и сам выполнил математику переполнения (и оказывается, что оператор 0 Mod также не работает на Currency):

Const pow2_32 As Currency = [email protected] ^ 32
Const signed32Max As Currency = [email protected] ^ 31 - 1

Public Function simpleHash(hashString As String) As Long
Dim hash As Currency
Dim i As Long

    hash = 5381
    For i = 1 To Len(hashString)
        hash = hash * [email protected] + CCur(AscW(Mid$(hashString, i, 1)))
        While hash >= pow2_32
            hash = hash - pow2_32
        Wend
    Next i

    If hash > signed32Max Then
        hash = hash - pow2_32
    End If

    simpleHash = CLng(hash)
End Function

Однако см. ответ Bob77 для решения, которое почти в два раза быстрее моего.