/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <stdint.h>
#include <array>

class CRC32
{
	std::array<uint32_t, 256> m_table;
	uint32_t m_currentValue = 0;

public:
	CRC32()
	{
		uint32_t polynomial = 0xEDB88320;
		for (uint32_t i = 0; i < m_table.size(); i++)
		{
			uint32_t c = i;
			for (size_t j = 0; j < 8; j++)
			{
				if (c & 1)
				{
					c = polynomial ^ (c >> 1);
				}
				else
				{
					c >>= 1;
				}
			}
			m_table[i] = c;
		}
	}

	void Update(size_t len, const uint8_t* buf)
	{
		uint32_t c = m_currentValue ^ 0xFFFFFFFF;
		for (size_t i = 0; i < len; ++i)
		{
			c = m_table[(c ^ buf[i]) & 0xFF] ^ (c >> 8);
		}
		m_currentValue = c ^ 0xFFFFFFFF;
	}

	uint32_t GetValue() const
	{
		return m_currentValue;
	}
};