C++ base94 实现(二)

参考:(2条消息) C/C++ 0x20 ~ 0x7e 可打印字节编码二进制加解密算法,仅供参考,感兴趣的朋友欢迎提供可改善意见。_liulilittle的博客-CSDN博客

头文件:

#pragma once

#include 

class base94
{
public:
    static bool encode(const void* data, int data_size, ppp::io::Stream& bytes, int& bytes_size) noexcept;
    static bool decode(const void* data, int data_size, ppp::io::Stream& bytes, int& bytes_size) noexcept;
};

 源文件:

#include "base94.h"

using namespace std;
using namespace ppp::io;

/* 96 printable characters(include tab)	*/
/* remove \ for compatibility			*/
/* remove tab for uniformity			*/
/* luckly, 11/9 > log(256)/log(94)		*/

enum
{
    BASE94_SYMBOL_COUNT = 94,
    BASE94_INPUT_BLOCK_SIZE = 9,
    BASE94_OUTPUT_BLOCK_SIZE = 11,
};

static constexpr void base94_decimalToBase94(uint64_t num, uint8_t base94[10], int& base94_size) noexcept
{
    uint64_t n = num;
    base94_size = 0;
    do {
        n /= 94;
        base94_size++;
    } while (n > 0);

    int k = 0;
    n = num;
    do {
        uint8_t c = (n % 94) + 0x20;
        n /= 94;
        base94[base94_size - ++k] = c;
    } while (n > 0);
}

static constexpr uint64_t base94_base94ToDecimal(uint8_t*& p, int size) noexcept
{
    uint64_t n = 0;
    for (uint8_t* k = p + size; p != k; )
    {
        uint8_t v = (*p++ - 0x20);
        n = n * 94 + v;
    }
    return n;
}

template 
static constexpr void base94_decimalToBase94(Stream& bytes, uint8_t*& p, int mode) noexcept
{
    uint8_t base94[BASE94_OUTPUT_BLOCK_SIZE];
    int base94_size;
    base94_decimalToBase94(*(T*)p, base94, base94_size);
    p += sizeof(T);

    uint8_t h = base94_size | mode << 4;
    h += 0x20;

    bytes.WriteByte(h);
    bytes.Write(base94, 0, base94_size);
}

template 
static constexpr bool base94_base94ToDecimal(Stream& bytes, uint8_t*& p) noexcept
{
    uint8_t n1 = (*p++) - 0x20;
    if (n1 < 1)
    {
        return false;
    }

    uint8_t n2 = n1 >> 4;
    if (n2 < 1 || n2 > 4)
    {
        return false;
    }
    else
    {
        n1 = n1 & 0x0f;
        n2 = 1 << (n2 - 1);
    }

    if (n1 > BASE94_OUTPUT_BLOCK_SIZE)
    {
        return false;
    }

    T v = base94_base94ToDecimal(p, n1);
    bytes.Write(&v, 0, n2);
    return true;
}

bool base94::encode(const void* data, int data_size, Stream& bytes, int& bytes_size) noexcept
{
    uint8_t* stream = (uint8_t*)data;
    bytes_size = data_size * ceil((double)BASE94_OUTPUT_BLOCK_SIZE / (double)BASE94_INPUT_BLOCK_SIZE) + 1;
    bytes.SetLength(bytes_size);

    int stream_size = data_size >> 3;
    data_size %= sizeof(uint64_t);
    for (int i = 0; i < stream_size; i++)
    {
        base94_decimalToBase94(bytes, stream, 4);
    }

    stream_size = data_size >> 2;
    data_size %= sizeof(uint32_t);
    for (int i = 0; i < stream_size; i++)
    {
        base94_decimalToBase94(bytes, stream, 3);
    }

    stream_size = data_size >> 1;
    data_size %= sizeof(uint16_t);
    for (int i = 0; i < stream_size; i++)
    {
        base94_decimalToBase94(bytes, stream, 2);
    }

    stream_size = data_size;
    data_size = 0;
    for (int i = 0; i < stream_size; i++)
    {
        base94_decimalToBase94(bytes, stream, 1);
    }

    bytes_size = bytes.GetPosition();
    return true;
}

bool base94::decode(const void* data, int data_size, Stream& bytes, int& bytes_size) noexcept
{
    uint8_t* stream = (uint8_t*)data;
    bytes_size = data_size * ceil((double)BASE94_INPUT_BLOCK_SIZE / (double)BASE94_OUTPUT_BLOCK_SIZE) + 1;
    bytes.SetLength(bytes_size);

    int stream_size = data_size >> 3;
    data_size %= sizeof(uint64_t);
    for (int i = 0; i < stream_size; i++)
    {
        if (!base94_base94ToDecimal(bytes, stream))
        {
            return false;
        }
    }

    stream_size = data_size >> 2;
    data_size %= sizeof(uint32_t);
    for (int i = 0; i < stream_size; i++)
    {
        if (!base94_base94ToDecimal(bytes, stream))
        {
            return false;
        }
    }

    stream_size = data_size >> 1;
    data_size %= sizeof(uint16_t);
    for (int i = 0; i < stream_size; i++)
    {
        if (!base94_base94ToDecimal(bytes, stream))
        {
            return false;
        }
    }

    stream_size = data_size;
    data_size = 0;
    for (int i = 0; i < stream_size; i++)
    {
        if (!base94_base94ToDecimal(bytes, stream))
        {
            return false;
        }
    }

    bytes_size = bytes.GetPosition();
    return true;
}

你可能感兴趣的:(C/C++,c++,开发语言)