Russian Qt Forum
Сентябрь 30, 2024, 08:31 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: GetHashCode32 на C [ решено ]  (Прочитано 2190 раз)
joffadark
Гость
« : Январь 12, 2015, 21:52 »

Здравствуйте, уважаемые форумчане.

Есть описание функции GetHashCode32 на C#, которая считает - как не трудно догадаться - хэш от строки (она, вроде бы, даже встроенная). Необходимо её переделать на C++ / QT.

Код:
public static unsafe int GetHashCode32(string input)
        {
            fixed (char* str = input.ToCharArray())
            {
                char* chPtr = str;
                int num = 0x15051505;
                int num2 = num;
                int* numPtr = (int*)chPtr;
                for (int i = input.Length; i > 0; i -= 4)
                {
                    num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
                    if (i <= 2)
                    {
                        break;
                    }
                    num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
                    numPtr += 2;
                }
                return (num + (num2 * 0x5d588b65));
            }
        }

Я понимаю, что в C# используется 2 байта на символ (UTF?). Пытался адаптировать функцию на QT / QString при помощи метода toStdWString().c_str(); Пытался так же и через QString(string.toUtf8).toStdWString().c_str()[index].
Но результат отличается от тех значений, что должны быть (мне известно очень маленькое количество константных значений уже рассчитанных давным давно, но нужно будет использовать новые значения и в будущем).

От строки "CS.Environment.Protocol.Messages.LogonMessage.Answer" (без кавычек) хэш должен быть 784129781

Никак не могу понять, как трансформировать этот алгоритм на QT / C++ / QString

« Последнее редактирование: Январь 13, 2015, 15:12 от joffadark » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4744



Просмотр профиля WWW
« Ответ #1 : Январь 12, 2015, 23:11 »

у меня стабильно выдает -297025856 (3997941440 если возвращать уинт)...

https://gist.github.com/gerriten/7542231 этот код более понятный.
Код
C++ (Qt)
int GetHashCode32(const QString &input)
{
   auto unichars = input.utf16();
   auto num1 = 0x15051505, num2 = num1;
   for (auto i = 0; i < input.length(); ++i)
   {
       auto &num = i % 2 ? num2 : num1;
       num = (((num << 5) + num) + (num >> 0x1b)) ^ unichars[i];
   }
   return num1 + num2 * 0x5d588b65;
}
« Последнее редактирование: Январь 12, 2015, 23:26 от kambala » Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
joffadark
Гость
« Ответ #2 : Январь 13, 2015, 12:55 »

Всё оказалось проще, чем кажется. Оказывается, при формировании данных хэшей константных, использовалась строка C# в кодировке UTF-16.
Всё, что нужно было сделать - конвертировать в UTF-16 QString.

Вот код:

Код
C++ (Qt)
int32_t GetHashCode32(const QString &input)
{
   QTextCodec *codec = QTextCodec::codecForName("UTF-16");
   QTextEncoder *encoderWithoutBom = codec->makeEncoder( QTextCodec::IgnoreHeader );
   QByteArray ba  = encoderWithoutBom ->fromUnicode( input );
 
   int num = 0x15051505;
   int num2 = num;
   int* numPtr = (int*)ba.data();  // serializing "wide char" array to "int" array
 
   //
   for (int i = input.length(); i > 0; i -= 4)
   {
       num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
       if (i <= 2)
       {
           break;
       }
       num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
       numPtr += 2;
   }
   return (num + (num2 * 0x5d588b65));
}
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.098 секунд. Запросов: 22.