Преобразование хэш-алгоритма Delphi ELF-32 в C # - PullRequest
0 голосов
/ 26 июня 2018

У меня есть функция Delphi для преобразования в C #. Я нашел примеры C # ELF-32 и, похоже, работает как в Delphi, но у меня есть сомнения с возвращаемым типом ...

Вот функции / процедуры Delphi (результат в дайджесте, Buf - строка для хеширования ...):

Type
 TByteArray = array[0..32767] of Byte;

procedure HashELF(var Digest : LongInt; const Buf;  BufSize : LongInt);
var
  I, X  : LongInt;
begin
  Digest := 0;
  for I := 0 to BufSize - 1 do begin
    Digest := (Digest shl 4) + TByteArray(Buf)[I];                   {!!.01}
    X := Digest and $F0000000;
    if (X <> 0) then
      Digest := Digest xor (X shr 24);
    Digest := Digest and (not X);
  end;
end;

procedure StringHashELF(var Digest : LongInt; const Str : string);
begin
  HashELF(Digest, Str[1], Length(Str));
end;

function MyHashELF(buffer : string): LongInt;
var
    ELFDigest : LongInt;
begin
     StringHashELF(ELFDigest, buffer);
     result := ELFDigest;
end;

«Возвращаемое значение» имеет тип LONGINT (от –2147483648 до 2147483647)

Я нашел какой-то эквивалент в сети в C #

private static UInt32 MyHashELF(string buffer)
{
    UInt32 hash = 0;
    for (int i = 0; i < buffer.Length; i++)
    {
        hash = (hash << 4) + (byte)buffer[i];
        UInt32 work = (hash & 0xf0000000);
        if (work != 0)
            hash ^= (work >> 24);
        hash &= ~work;
    }
    return hash;
}

Но тип возвращаемого значения - Uint32 (от 0 до 4294967295), и если я хочу изменить Uint32 в Int32, я получаю следующую ошибку (для 0xf0000000):

Постоянное значение «4026531840» не может быть преобразовано в «int» (используйте «непроверенный» синтаксис для переопределения)

Я провел несколько тестов, и на данный момент он работает все время так же, как Delphi, но я думаю, что возможны ошибки из-за разницы типов (нет?). Что мне нужно сделать, чтобы быть на 100% совместимым с кодом Delphi?

P.S. Мне нужно использовать эти 4 байта, возвращенные как есть, как часть строки (своего рода ключи) для дальнейшей обработки ...

Спасибо

1 Ответ

0 голосов
/ 26 июня 2018

Результат 4 байта будет таким же. Разница между Delphi longint и C # UInt32 заключается в том, как он интерпретирует эти 4 байта: как если бы это было целочисленное значение со знаком (longint) или без знака (UInt32).

Так что, если вам действительно нужны эти 4 байта, лежащие в основе переменной, вы можете использовать код C #, как он есть сейчас.

Если вы храните эти 4 байта в их числовом представлении где-то, то вам придется немного изменить реализацию C #, чтобы сделать ее совместимой с числовым значением, которое было бы возвращено функцией Delphi , Компилятор C # предпочитает значения без знака для констант, представленных в шестнадцатеричном формате, поэтому вам нужно будет сказать, что он должен рассматривать его как подписанное. Просто сделайте так, как предлагает компилятор (добавьте unchecked для переопределения). Измените строку на:

Int32 work = (hash & unchecked((Int32)0xf0000000));

(и, конечно, все другие вхождения UInt32 должны быть изменены на Int32). Это должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...