#include "common.h"
#include <QTextStream>
#include <QDebug>

#define CRC32_CHAR_BIT 8
static uint32_t crc32Table[256];


uint32_t crc32_reflect(uint32_t value, uint8_t bits)
{
    uint32_t reflection = 0;

    for(uint8_t i = 0; i < bits ; i++)
    {
        if (value & (1u << i))
            reflection |= 1 << (bits - 1 - i);
    }

    return reflection;
}

/* crc32 初始化. */
void crc32_table_init(void)
{
    uint32_t int1 = 1;
    uint32_t const value_high_bit = int1 << 31u;
    uint8_t dividend = 0;

    do
    {
        uint32_t remainder = 0;
        for(uint8_t mask = 1u << (CRC32_CHAR_BIT - 1u); mask; mask >>= 1)
        {
            if (dividend & mask)
                remainder ^= value_high_bit;

            if (remainder & value_high_bit)
            {
                remainder <<= 1;
                remainder ^= 0x04C11DB7u;
            }
            else
                remainder <<= 1;
        }

        crc32Table[crc32_reflect(dividend, CRC32_CHAR_BIT)] = crc32_reflect(remainder, 32);
    }
    while(++dividend);
}


uint32_t crc32(void const *buf, uint32_t byte_count)
{
    uint32_t rem = 0xFFFFFFFF;
    uint8_t const * const b_begin = (uint8_t*)buf;
    uint8_t const * const b_end = b_begin + byte_count;

    for(uint8_t const *p = b_begin; p < b_end; p++)
    {
        uint8_t const byte_index = *p ^ rem;
        rem >>= CRC32_CHAR_BIT;
        rem ^= crc32Table[ byte_index ];
        //char *nptr = (char *)&rem;
        //printHexArray(nptr, 4);
    }
    return ~rem;
}

int32_t stringToChar(QString str, char *buf, uint32_t len)
{
    if (nullptr == buf)
    {
        return -1;
    }

    QByteArray ba = str.toLatin1();

    if (ba.length() <= 0
        || ba.length() >= len)
    {
        return -2;
    }

    memset(buf, 0, len);
    memcpy(buf, ba.data(), ba.length());
    return 0;
}


void printHexArray(const char *msg, const char *array, int length)
{
    QTextStream out(stdout);
    out << msg << "###printHexArray" << "(len:" << length << ")\n";
    for (int i = 0; i < length; ++i)
    {
        out << QString::number(static_cast<unsigned char>(array[i]), 16)
            .toUpper().rightJustified(2, '0'); // 转换为16进制并且前面补0
        if (i < length - 1)
        {
            out << " "; // 每个元素之间加空格
        }

        if ((i+1) % 16 == 0)
            out << "\n"; // 换行
    }
    out << "\n"; // 换行
}


