Skip to content
Snippets Groups Projects
bit_converter.cpp 3.43 KiB
Newer Older
  • Learn to ignore specific revisions
  • theazgra's avatar
    theazgra committed
    /**
     * This implementation is inspired by BitConverter from .NET
     * https://referencesource.microsoft.com/#mscorlib/system/bitconverter.cs
     */
    #include <assert.h>
    #include <vector>
    #include <endian.h>
    #include <string>
    #include "custom_types.h"
    
    
    theazgra's avatar
    theazgra committed
    #include <boost/locale.hpp>
    
    
    theazgra's avatar
    theazgra committed
    short bytes_to_short(const std::vector<byte> &bytes, const uint fromIndex = 0)
    {
        assert(bytes.size() >= 2);
        assert(fromIndex <= bytes.size() - 2);
    
        // Little endian
        auto bit = &bytes[fromIndex];
    
        if (fromIndex % 2 == 0)
        {
            return (*((short *)bit));
        }
        else
        {
            return (short)((*bit) | (*(bit + 1) << 8));
        }
    }
    
    int bytes_to_int(const std::vector<byte> &bytes, const uint fromIndex = 0)
    {
        assert(bytes.size() >= 4);
        assert(fromIndex <= bytes.size() - 4);
    
        // Little endian
        auto bit = &bytes[fromIndex];
    
        if (fromIndex % 4 == 0)
        {
            return (*((int *)bit));
        }
        else
        {
            return (*bit | (*(bit + 1) << 8) | (*(bit + 2) << 16) | (*(bit + 3) << 24));
        }
    }
    
    int bytes_to_long(const std::vector<byte> &bytes, const uint fromIndex = 0)
    {
        assert(bytes.size() >= 8);
        assert(fromIndex <= bytes.size() - 8);
    
        // Little endian
        auto bit = &bytes[fromIndex];
        if (fromIndex % 8 == 0)
        {
            return (*((long *)bit));
        }
        else
        {
            int i1 = (*bit) | (*(bit + 1) << 8) | (*(bit + 2) << 16) | (*(bit + 3) << 24);
            int i2 = (*(bit + 4)) | (*(bit + 5) << 8) | (*(bit + 6) << 16) | (*(bit + 7) << 24);
            return ((uint)i1 | ((long)i2 << 32));
        }
    }
    
    ushort bytes_to_ushort(const std::vector<byte> &bytes, const uint fromIndex)
    {
        return ((ushort)bytes_to_short(bytes, fromIndex));
    }
    
    uint bytes_to_uint(const std::vector<byte> &bytes, const uint fromIndex)
    {
        return ((uint)bytes_to_int(bytes, fromIndex));
    }
    
    ulong bytes_to_ulong(const std::vector<byte> &bytes, const uint fromIndex)
    {
        return ((ulong)bytes_to_long(bytes, fromIndex));
    }
    
    char get_hex_value(int x)
    {
        assert(x >= 0 && x < 16);
        return (x < 10) ? ((char)(x + '0')) : ((char)((x - 10) + 'A'));
    }
    
    std::string bytes_to_string(const std::vector<byte> &bytes, const uint fromIndex, const uint byteCount)
    {
        assert((fromIndex >= 0) && (fromIndex <= bytes.size() - byteCount));
    
        if (bytes.size() == 0)
            return std::string();
    
        int stringLen = byteCount * 3;
        std::vector<char> characters;
        characters.resize(stringLen);
    
        int index = fromIndex;
        for (int i = 0; i < stringLen; i++)
        {
            byte b = bytes[index++];
            characters[i] = get_hex_value(b / 16);
            characters[i + 1] = get_hex_value(b % 16);
            characters[i + 2] = '-';
        }
        return std::string(characters.begin(), characters.end() - 1);
    }
    
    std::string bytes_to_raw_string(const std::vector<byte> &bytes, const uint fromIndex, const uint byteCount)
    {
        assert((fromIndex >= 0) && (fromIndex <= bytes.size() - byteCount));
    
        if (bytes.size() == 0)
            return std::string();
    
        std::vector<byte> stringBytes(bytes.begin() + fromIndex, bytes.begin() + fromIndex + byteCount);
        std::string result(reinterpret_cast<const char *>(stringBytes.data()));
        return result;
    
    theazgra's avatar
    theazgra committed
    }
    
    std::string utf8bytes_to_string(const std::vector<byte> &bytes, const uint fromIndex, const uint byteCount)
    {
        auto fromIt = bytes.begin() + fromIndex;
        std::vector<byte> stringBytes(fromIt, fromIt + byteCount);
        std::string result = boost::locale::conv::from_utf<char>((char *)stringBytes.data(), "UTF-8");
        return result;