//******************************************************************************************************
// Adler32.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 04/11/2012 - Stephen C. Wills
// Generated original version of source code.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
namespace GSF.IO.Checksums
{
///
/// Generates an Adler-32 checksum calculation.
///
public sealed class Adler32
{
#region [ Members ]
// Constants
private const uint AdlerMod = 65521u;
private const int MaxLoops = 5552;
// Fields
private uint m_a;
private uint m_b;
private int m_loopCount;
#endregion
#region [ Constructors ]
///
/// Creates a new instance of the class.
///
public Adler32()
{
Reset();
}
#endregion
#region [ Properties ]
///
/// Returns the Adler-32 data checksum computed so far.
///
public uint Value
{
get
{
ApplyMod();
return m_a | (m_b << 16);
}
set
{
m_a = value & 0xFFFF;
m_b = value >> 16;
ApplyMod();
}
}
#endregion
#region [ Methods ]
///
/// Resets the Adler-32 data checksum as if no update was ever called.
///
public void Reset()
{
m_a = 1;
m_b = 0;
m_loopCount = 0;
}
///
/// Updates the checksum with the byte value.
///
/// The value to use for the update.
public void Update(byte value)
{
if (m_loopCount >= MaxLoops)
ApplyMod();
m_a += value;
m_b += m_a;
m_loopCount++;
}
///
/// Updates the checksum with the bytes taken from the array.
///
/// buffer an array of bytes
public void Update(byte[] buffer)
{
Update(buffer, 0, buffer.Length);
}
///
/// Adds the byte array to the data checksum.
///
/// The buffer which contains the data
/// The offset in the buffer where the data starts
/// The number of data bytes to update the checksum with.
public void Update(byte[] buffer, int offset, int count)
{
int remainingLoops;
int numLoops;
int i = 0;
while (i < count)
{
if (m_loopCount >= MaxLoops)
ApplyMod();
remainingLoops = MaxLoops - m_loopCount;
numLoops = Math.Min(remainingLoops, count - i);
for (int loopCtr = 0; loopCtr < numLoops; loopCtr++)
{
m_a += buffer[offset + i];
m_b += m_a;
i++;
}
m_loopCount += numLoops;
}
}
// Applies the modulus operation
// to the checksum components.
private void ApplyMod()
{
m_a %= AdlerMod;
m_b %= AdlerMod;
m_loopCount = 0;
}
#endregion
}
}