#include "ByteUtils.h"


bool ByteUtils::MostSignificantBitIsOne(char c)
{
    return c & (1 << 7);
}

ByteUtils::Word ByteUtils::GetWordFirstBit(const Word word)
{
    return word & ByteUtils::WORD_FIRST_BIT;
};

ByteUtils::Word ByteUtils::GetWordLastByte(const Word word)
{
    return word & ByteUtils::WORD_LAST_BYTE;
}

unsigned char ByteUtils::getHigherNBits(unsigned char input, unsigned num)
{
    return input >> (8 - num);
}

unsigned char ByteUtils::getByteN(uint32_t input, unsigned n)
{
    return (input << 8*n) >> 24;
}

uint32_t ByteUtils::mirror(uint32_t byte, unsigned length)
{
    uint32_t ret{0};
    for(unsigned idx=0; idx<length; idx++)
    {
        if (getBitN(byte, length - 1 - idx))
        {
            ret |= (0x01 << idx);
        }
    }
    return ret;
}

unsigned char ByteUtils::getLowerNBits(uint32_t input, unsigned num)
{
    switch (num)
    {
    case 1:
        return input & 0x01;
    case 2:
        return input & 0x03;
    case 3:
        return input & 0x07;
    case 4:
        return input & 0x0F;
    case 5:
        return input & 0x1F;
    case 6:
        return input & 0x3F;
    case 7:
        return input & 0x7F;
    case 8:
        return input;
    default:
        return 0;
    }
}

unsigned char ByteUtils::getTwoBitsAtN(unsigned char input, unsigned n)
{
    return (input & (0x03 << n)) >> n;
}

unsigned char ByteUtils::getMBitsAtN(unsigned char input, unsigned m, unsigned n)
{
    switch (m)
    {
    case 1:
        return (input & (0x01 << n)) >> n;
    case 2:
        return (input & (0x03 << n)) >> n;
    case 3:
        return (input & (0x07 << n)) >> n;
    case 4:
        return (input & (0x0F << n)) >> n;
    case 5:
        return (input & (0x1F << n)) >> n;
    case 6:
        return (input & (0x3F << n)) >> n;
    case 7:
        return (input & (0x7F << n)) >> n;
    case 8:
        return input;
    default:
        return 0;
    }
}

bool ByteUtils::getBitN(uint32_t input, unsigned n)
{
    return input & (1 << n);
}

unsigned char ByteUtils::getFromString(const std::string& string)
{
    unsigned char ret{0};

    if (string.length() < 8)
    {
        return ret;
    }

    for(unsigned idx=0; idx<8; idx++)
    {
        if (string[idx] == '1')
        {
            ret |= (0x01 << (7 - idx));
        }
    }
    return ret;
}

std::string ByteUtils::toString(uint32_t input, unsigned length)
{
    std::string ret;
    if (length > 8)
    {
        unsigned overshoot = length - 8;
        for(unsigned idx=0; idx<overshoot; idx++)
        {
            ret += getBitN(input, length - 1 - idx) ? '1' : '0';
        }
        ret += "-";
        for(unsigned idx=0; idx<8; idx++)
        {
            ret += getBitN(input, 7 - idx) ? '1' : '0';
        }
    }
    else
    {
        for(unsigned idx=0; idx<length; idx++)
        {
            ret += getBitN(input, 7 - idx) ? '1' : '0';
        }
    }
    return ret;
}

void ByteUtils::ReverseBuffer(char* buffer, char* reverse, unsigned size, unsigned targetSize)
{
    for(unsigned idx=0; idx<targetSize; idx++)
    {
        if (idx < size)
        {
            reverse[idx] = buffer[size - 1 -idx];
        }
        else
        {
            reverse[idx] = 0;
        }
    }
}

ByteUtils::Word ByteUtils::ToWord(char* buffer, bool reverse)
{
    return ToType<Word>(buffer, reverse);
}

ByteUtils::DWord ByteUtils::ToDWord(char* buffer, bool reverse)
{
    return ToType<DWord>(buffer, reverse);
}

ByteUtils::QWord ByteUtils::ToQWord(char* buffer, bool reverse)
{
    return ToType<QWord>(buffer, reverse);
}

bool ByteUtils::Compare(char* buffer, const char* tag, unsigned size)
{
    for(unsigned idx=0; idx<size; idx++)
    {
        if(tag[idx] != buffer[idx])
        {
            return false;
        }
    }
    return true;
}

bool ByteUtils::CompareDWords(char* buffer, const char* tag)
{
    return Compare(buffer, tag, sizeof(DWord));
}

bool ByteUtils::CompareWords(char* buffer, const char* tag)
{
    return Compare(buffer, tag, sizeof(Word));
}
