/*
Copyright (C) 2006 - 2009 Evan Teran
                   eteran@alum.rit.edu

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef MD5_20070328_H_
#define MD5_20070328_H_

#include <QtGlobal>
#include <cstddef>
#include <climits>
#include "API.h"

class EDB_EXPORT MD5 {
public:
	MD5();
	~MD5() {}
	
public:
	void update(const void *input, std::size_t input_length);
	void finalize();
	const quint8 *digest() const;
	
private:
	quint8		m_Buffer[64];	// input buffer
	quint32		m_State[4];		// current digest
	quint64		m_Count64;		// number of bits
	bool		m_Finalized;	// have we been finalized

private:
	void transform(const quint8 buffer[64]);
	
private:
	template <typename T> 
	static T rol(T v, int n) {
		static const std::size_t bits(CHAR_BIT * sizeof(T));
		const T mask(~(T(-1) << n));
		return (v << n) | ((v >> (bits - n)) & mask);
	}
	
	template <quint32 (*Fun)(quint32, quint32, quint32)>
	static void doTransform(quint32& a, quint32 b, quint32 c, quint32 d, quint32 x, quint32 s, quint32 ac) {
		a += Fun(b, c, d) + x + ac;
		a = rol(a, s) + b;
	}
	
private:						
	static quint32 F(quint32 x, quint32 y, quint32 z);
	static quint32 G(quint32 x, quint32 y, quint32 z);
	static quint32 H(quint32 x, quint32 y, quint32 z);
	static quint32 I(quint32 x, quint32 y, quint32 z);
};

#endif

