static public State32 CreateState32(uint seed) { State32 value = new State32(); ResetState32(value, seed); return(value); }
static public bool UpdateState32(State32 state, byte[] input) { if (state == null) { throw new ArgumentNullException("state"); } if (!state.IsInitialized) { ThrowStateUninitialized("state"); } if (input == null) { throw new ArgumentNullException("input"); } if (input.Rank != 1) { ThrowArrayMultiRank("input"); } if (input.GetLowerBound(0) != 0) { ThrowArrayNonZeroLowerBound("input"); } return(ErrorCode.XXH_OK == InternalUpdateState32(state, input, 0, input.Length)); }
static internal ErrorCode InternalUpdateState32(State32 state, byte[] input, int offset, int length) { InputTextStream p = new InputTextStream(input, offset); long bEnd = p.Position + length; state.total_len += (ulong)length; if (state.memsize + length < 16) /* fill in tmp buffer */ { Array.Copy(input, offset, state.mem32, state.memsize, length); state.memsize += (uint)length; return(ErrorCode.XXH_OK); } if (state.memsize > 0) /* some data left from previous update */ { Array.Copy(input, offset, state.mem32, state.memsize, 16 - state.memsize); { InputTextStream p32 = new InputTextStream(state.mem32); state.v1 = XXH32_round(state.v1, p32.ReadUInt32()); state.v2 = XXH32_round(state.v2, p32.ReadUInt32()); state.v3 = XXH32_round(state.v3, p32.ReadUInt32()); state.v4 = XXH32_round(state.v4, p32.ReadUInt32()); } p.Skip(16 - (int)state.memsize); state.memsize = 0; } if (p.Position <= bEnd - 16) { long limit = bEnd - 16; uint v1 = state.v1; uint v2 = state.v2; uint v3 = state.v3; uint v4 = state.v4; do { v1 = XXH32_round(v1, p.ReadUInt32()); v2 = XXH32_round(v2, p.ReadUInt32()); v3 = XXH32_round(v3, p.ReadUInt32()); v4 = XXH32_round(v4, p.ReadUInt32()); }while (p.Position <= limit); state.v1 = v1; state.v2 = v2; state.v3 = v3; state.v4 = v4; } if (p.Position < bEnd) { Array.Copy(input, p.Position, state.mem32, 0, bEnd - p.Position); state.memsize = (uint)(bEnd - p.Position); } return(ErrorCode.XXH_OK); }
/*** Hash feed ***/ /* These functions calculate the xxHash of an input provided in multiple smaller packets, * as opposed to an input provided as a single block. * * XXH state space must first be allocated. * * Start a new hash by initializing state with a seed, using ResetStateXX(). * * Then, feed the hash state by calling UpdateStateXX() as many times as necessary. * Obviously, input must be valid, meaning allocated and read accessible. * The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. * * Finally, you can produce a hash anytime, by using DigestStateXX(). * This function returns the final XX-bits hash. * You can nonetheless continue feeding the hash state with more input, * and therefore get some new hashes, by calling again DigestStateXX(). * * ResetState32(), * UpdateState32(), * DigestState32() : * * Original C implementation definition: * XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned seed); * XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); * unsigned int XXH32_digest (const XXH32_state_t* statePtr); * * ResetState64(), * UpdateState64(), * DigestState64() : * * Original C implementation definition: * XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); * XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); * unsigned long long XXH64_digest (const XXH64_state_t* statePtr); */ static public void ResetState32(State32 state, uint seed) { if (state == null) { throw new ArgumentNullException("state"); } InternalResetState32(state, seed); }
static internal void InternalResetState32(State32 state, uint seed) { state.seed = seed; state.v1 = seed + PRIME32_1 + PRIME32_2; state.v2 = seed + PRIME32_2; state.v3 = seed + 0; state.v4 = seed - PRIME32_1; state.total_len = 0; state.memsize = 0; state.mem32 = new Byte[16]; }
static public uint DigestState32(State32 state) { if (state == null) { throw new ArgumentNullException("state"); } if (!state.IsInitialized) { ThrowStateUninitialized("state"); } return(InternalDigestState32(state)); }
static public uint XXH32(Stream inputStream, uint seed) { State32 state = new State32(); try { ResetState32(state, seed); UpdateState32(state, inputStream); return(DigestState32(state)); } catch { throw; } }
internal static uint InternalDigestState32(State32 state) { var p = new InputTextStream(state.mem32); long bEnd = state.memsize; uint h32; if (state.total_len >= 16) { h32 = XXH_rotl32(state.v1, 1) + XXH_rotl32(state.v2, 7) + XXH_rotl32(state.v3, 12) + XXH_rotl32(state.v4, 18); } else { h32 = state.seed + PRIME32_5; } h32 += (uint)state.total_len; while (p.Position + 4 <= bEnd) { h32 += p.ReadUInt32() * PRIME32_3; h32 = XXH_rotl32(h32, 17) * PRIME32_4; } while (p.Position < bEnd) { h32 += p.ReadByte() * PRIME32_5; h32 = XXH_rotl32(h32, 11) * PRIME32_1; } h32 ^= h32 >> 15; h32 *= PRIME32_2; h32 ^= h32 >> 13; h32 *= PRIME32_3; h32 ^= h32 >> 16; return(h32); }
static public bool UpdateState32(State32 state, Stream inputStream) { if (inputStream == null) { throw new ArgumentNullException("inputStream"); } byte[] buffer = new byte[0x2000]; int size; do { size = inputStream.Read(buffer, 0, 0x2000); if (size > 0) { if (InternalUpdateState32(state, buffer, 0, size) != ErrorCode.XXH_OK) { return(false); } } } while (size > 0); return(true); }
static public bool UpdateState32(State32 state, byte[] input, int offset, int length) { if (state == null) { throw new ArgumentNullException("state"); } if (!state.IsInitialized) { ThrowStateUninitialized("state"); } if (input == null) { throw new ArgumentNullException("input"); } if (input.Rank != 1) { ThrowArrayMultiRank("input"); } if (input.GetLowerBound(0) != 0) { ThrowArrayNonZeroLowerBound("input"); } if (offset < 0) { ThrowArgumentNonNegativeNumber("offset"); } if (length < 0) { ThrowArgumentNonNegativeNumber("length"); } if (input.Length < (offset + length)) { ThrowArrayInvalidOffsetAndLength(); } return(ErrorCode.XXH_OK == InternalUpdateState32(state, input, offset, length)); }
/* * XXH32() : * Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input". * The memory between offset & offset+length in "input" must be valid (allocated and read-accessible). * "seed" can be used to alter the result predictably. * * Original C implementation definition: * unsigned int XXH32 (const void* input, size_t length, unsigned seed); * * XXH64() : * Calculate the 64-bits hash of sequence "length" bytes stored at memory address "input". * Faster on 64-bits systems. Slower on 32-bits systems. * * Original C implementation definition: * unsigned long long XXH64 (const void* input, size_t length, unsigned long long seed); */ static public uint XXH32(byte[] input, int offset, int length, uint seed) { if (input == null) { throw new ArgumentNullException("input"); } if (input.Rank != 1) { ThrowArrayMultiRank("input"); } if (input.GetLowerBound(0) != 0) { ThrowArrayNonZeroLowerBound("input"); } if (offset < 0) { ThrowArgumentNonNegativeNumber("offset"); } ; if (length < 0) { ThrowArgumentNonNegativeNumber("length"); } if (input.Length < (offset + length)) { ThrowArrayInvalidOffsetAndLength(); } #if EnableSimpleVersion /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ State32 state = new State32(); ResetState32(state, seed); UpdateState32(state, input, offset, length); return(DigestState32(state)); #else InputTextStream p = new InputTextStream(input, offset); long bEnd = p.Position + length; uint h32; if (length >= 16) { long limit = bEnd - 16; uint v1 = seed + PRIME32_1 + PRIME32_2; uint v2 = seed + PRIME32_2; uint v3 = seed + 0; uint v4 = seed - PRIME32_1; do { v1 += p.ReadUInt32() * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; v2 += p.ReadUInt32() * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; v3 += p.ReadUInt32() * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; v4 += p.ReadUInt32() * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; }while (p.Position <= limit); h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); } else { h32 = seed + PRIME32_5; } h32 += (uint)length; while (p.Position + 4 <= bEnd) { h32 += p.ReadUInt32() * PRIME32_3; h32 = XXH_rotl32(h32, 17) * PRIME32_4; } while (p.Position < bEnd) { h32 += p.ReadByte() * PRIME32_5; h32 = XXH_rotl32(h32, 11) * PRIME32_1; } h32 ^= h32 >> 15; h32 *= PRIME32_2; h32 ^= h32 >> 13; h32 *= PRIME32_3; h32 ^= h32 >> 16; return(h32); #endif }
internal static unsafe void Update32(byte *input, ref State32 state, uint len) { fixed(uint *mem32 = state.mem32) { byte *p = input; byte *bEnd = p + len; byte *bmem32 = (byte *)mem32; state.total_len_32 += len; state.large_len |= ((len >= 16) | (state.total_len_32 >= 16)); if (state.memsize + len < 16) { /* fill in tmp buffer */ Bits.MemCpy(bmem32 + state.memsize, input, len); state.memsize += len; return; // return XXH_OK; } if (state.memsize > 0) { /* some data left from previous update */ Bits.MemCpy(bmem32 + state.memsize, input, (ulong)(16 - state.memsize)); { uint *p32 = mem32; state.acc1 = round32(state.acc1, Bits.XXH_readLE32((byte *)p32)); p32++; state.acc2 = round32(state.acc2, Bits.XXH_readLE32((byte *)p32)); p32++; state.acc3 = round32(state.acc3, Bits.XXH_readLE32((byte *)p32)); p32++; state.acc4 = round32(state.acc4, Bits.XXH_readLE32((byte *)p32)); } p += 16 - state.memsize; state.memsize = 0; } if (p <= bEnd - 16) { byte *limit = bEnd - 16; uint v1 = state.acc1; uint v2 = state.acc2; uint v3 = state.acc3; uint v4 = state.acc4; do { v1 = round32(v1, Bits.XXH_readLE32(p)); p += 4; v2 = round32(v2, Bits.XXH_readLE32(p)); p += 4; v3 = round32(v3, Bits.XXH_readLE32(p)); p += 4; v4 = round32(v4, Bits.XXH_readLE32(p)); p += 4; } while (p <= limit); state.acc1 = v1; state.acc2 = v2; state.acc3 = v3; state.acc4 = v4; } if (p < bEnd) { Bits.MemCpy(bmem32, p, (ulong)(bEnd - p)); state.memsize = (uint)(bEnd - p); } } }