I am trying to port the following python code to c#
import os
import sys
import ctypes
FNV32_PRIME = 0xB3CB2E29
FNV32_BASIS = 0x319712C3
def uint32(v):
return ctypes.c_uint32(v).value
def fnv1a_hash(data):
hval = FNV32_BASIS
for i in range(0, len(data)):
hval = uint32(hval ^ data[i])
hval = uint32(hval * FNV32_PRIME)
return hval
print("starting")
if len(sys.argv) == 2:
input_file_path = sys.argv[1]
else: input_file_path = "dvars.txt"
with open(input_file_path, "r") as input_file:
for dvar_name in input_file:
dvar_name = dvar_name.rstrip("\r\n")
dvar_hash_1 = dvar_name.lower() + '\x00'
dvar_hash_2 = bytearray(dvar_hash_1.encode("ascii"))
dvar_hash = fnv1a_hash(dvar_hash_2)
final = "%-30s = 0x%08X" % (dvar_name, dvar_hash)
print(final)
print("done")
which works fine:
starting
con_gameMsgWindow0MsgTime = 0xFC60C821
I got this so far:
public static class Extensions
{
private const UInt32 FnvPrime = 0xB3CB2E29;private const UInt32 FnvOffsetBasis = 0x319712C3;
public static string ToHashFnv1a32(this string text, Fnv1a32 hasher = null)
{
var bytes_encoded = Encoding.UTF8.GetBytes(text); // +'\x00'
if (hasher is null) hasher = new Fnv1a32(fnvPrime: FnvPrime, fnvOffsetBasis: FnvOffsetBasis);
var byte_hash = hasher.ComputeHash(bytes_encoded);
// int decValue = int.Parse(t, System.Globalization.NumberStyles.HexNumber);
var uint32 = BitConverter.ToUInt32(byte_hash, 0);
var uint32_hex = string.Format("{0:X}", uint32);
var uint32_dec = string.Format("{0:D}", uint32);
var stringg = BitConverter.ToString(byte_hash).Replace("-", "");
var expected_hex = string.Format("{0:X}", 0xFC60C821);
var expected_dec = string.Format("{0:D}", 0xFC60C821);
return byte_hash.ToString(); //
}
}
but for some reason i get the weirdest results:
text "con_gameMsgWindow0LineCount" string
hasher {Fnv1a.Fnv1a32} Fnv1a.Fnv1a32
bytes_encoded {byte[0x0000001b]} byte[]
byte_hash {byte[0x00000004]} byte[]
uint32 0x0a65c1a8 uint
uint32_hex "A65C1A8" string
uint32_dec "174440872" string
stringg "A8C1650A" string
expected_hex "FC60C821" string
expected_dec "4234201121" string
I really am bumping my head on the table because i can't seem to figure out why it isn't calculating the right hash (i am using a modified version of https://github.com/jslicer/FNV-1a to allow me changing the base and offset)
The FNV1a-hash itself works in the C#-code. However, the C#-code differs from the Python-code in the following points regarding the processing of the input data:
\r\n
at the end.Additionally, the C#-code doesn't use the text con_gameMsgWindow0MsgTime
, but con_gameMsgWindow0LineCount
.
The solution is to add the following line at the beginning of the ToHashFnv1a32
-method of the C#-code:
text = text.TrimEnd('\r', '\n').ToLower() + "\0";
and of course the same data must be used in both codes for the test.
Note: The prime and offset basis used in the Python-code differ from the commonly used values.
User contributions licensed under CC BY-SA 3.0