#include "crc32i.h"

uint32_t crc32qw_r(uint32_t crc, const unsigned char *message, size_t sz)
{
	while (sz >= 4) {
		union {
			unsigned char b[4];
			uint32_t w;
		} w;

#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
		/* Tell GCC that we will be aliasing */
		w.w = *(__attribute__((__may_alias__)) uint32_t *)message;
#else
		/* ... */
		w.b[0] = message[0];
		w.b[1] = message[1];
		w.b[2] = message[2];
		w.b[3] = message[3];
#endif

		crc ^= w.w;

		crc = (crc >> 8) ^ crc32_tab[crc & 0xFF];
		crc = (crc >> 8) ^ crc32_tab[crc & 0xFF];
		crc = (crc >> 8) ^ crc32_tab[crc & 0xFF];
		crc = (crc >> 8) ^ crc32_tab[crc & 0xFF];

		message += 4;
		sz -= 4;
	}

	if (!sz) return crc;

	return crc32c_r(crc, message, sz);
}
