Improve base64 API

Move base64Encode/base64Decode to namespace `ax::utils`
This commit is contained in:
halx99 2023-01-01 18:07:18 +08:00
parent bc491ca743
commit 0f97e3fa3a
10 changed files with 294 additions and 243 deletions

View File

@ -50,7 +50,6 @@ THE SOFTWARE.
#include "2d/CCParticleBatchNode.h"
#include "renderer/CCTextureAtlas.h"
#include "base/base64.h"
#include "base/ZipUtils.h"
#include "base/CCDirector.h"
#include "base/CCProfiling.h"
@ -637,7 +636,7 @@ bool ParticleSystem::initWithDictionary(const ValueMap& dictionary, std::string_
{
// if it fails, try to get it from the base64-gzipped data
int decodeLen =
base64Decode((unsigned char*)textureData.c_str(), (unsigned int)dataLen, &buffer);
utils::base64Decode((unsigned char*)textureData.c_str(), (unsigned int)dataLen, &buffer);
AXASSERT(buffer != nullptr, "CCParticleSystem: error decoding textureImageData");
AX_BREAK_IF(!buffer);

View File

@ -32,7 +32,6 @@ THE SOFTWARE.
#include <sstream>
// #include "2d/CCTMXTiledMap.h"
#include "base/ZipUtils.h"
#include "base/base64.h"
#include "base/CCDirector.h"
#include "platform/CCFileUtils.h"
@ -691,7 +690,7 @@ void TMXMapInfo::endElement(void* /*ctx*/, const char* name)
auto currentString = tmxMapInfo->getCurrentString();
unsigned char* buffer;
auto len =
base64Decode((unsigned char*)currentString.data(), (unsigned int)currentString.length(), &buffer);
utils::base64Decode((unsigned char*)currentString.data(), (unsigned int)currentString.length(), &buffer);
if (!buffer)
{
AXLOG("axmol: TiledMap: decode data error");

View File

@ -54,7 +54,6 @@
#include "2d/CCScene.h"
#include "platform/CCFileUtils.h"
#include "renderer/CCTextureCache.h"
#include "base/base64.h"
#include "base/ccUtils.h"
#include "base/ccUTF8.h"
@ -1551,7 +1550,7 @@ void Console::commandUpload(socket_native_type fd)
}
unsigned char* decode;
unsigned char* in = (unsigned char*)data;
int dt = base64Decode(in, 4, &decode);
int dt = utils::base64Decode(in, 4, &decode);
if (dt > 0)
{
fs->write(decode, dt);

View File

@ -50,7 +50,6 @@ THE SOFTWARE.
#include "platform/CCCommon.h"
#include "platform/CCFileUtils.h"
#include "pugixml/pugixml.hpp"
#include "base/base64.h"
#include "base/ccUtils.h"
#include "CCPosixFileStream.h"

View File

@ -1,196 +1,136 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
https://axmolengine.github.io/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "base/base64.h"
#include "base64.h"
NS_AX_BEGIN
unsigned char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
namespace base64 {
int _base64Decode(const unsigned char* input, unsigned int input_len, unsigned char* output, unsigned int* output_len)
AX_DLL char const*
get_alphabet()
{
static char inalphabet[256], decoder[256];
int c = 0, char_count, errors = 0;
unsigned int input_idx = 0;
unsigned int output_idx = 0;
auto alphabetSize = sizeof(alphabet);
for (size_t i = 0; i < alphabetSize; i++)
{
inalphabet[alphabet[i]] = 1;
decoder[alphabet[i]] = i;
}
char_count = 0;
int bits = 0;
for (input_idx = 0; input_idx < input_len; input_idx++)
{
c = input[input_idx];
if (c == '=')
break;
if (c > 255 || !inalphabet[c])
continue;
bits += decoder[c];
char_count++;
if (char_count == 4)
{
output[output_idx++] = (bits >> 16);
output[output_idx++] = ((bits >> 8) & 0xff);
output[output_idx++] = (bits & 0xff);
bits = 0;
char_count = 0;
}
else
{
bits <<= 6;
}
}
if (c == '=')
{
switch (char_count)
{
case 1:
#if (AX_TARGET_PLATFORM != AX_PLATFORM_BADA)
fprintf(stderr, "base64Decode: encoding incomplete: at least 2 bits missing");
#endif
errors++;
break;
case 2:
output[output_idx++] = (bits >> 10);
break;
case 3:
output[output_idx++] = (bits >> 16);
output[output_idx++] = ((bits >> 8) & 0xff);
break;
}
}
else if (input_idx < input_len)
{
if (char_count)
{
#if (AX_TARGET_PLATFORM != AX_PLATFORM_BADA)
fprintf(stderr, "base64 encoding incomplete: at least %d bits truncated", ((4 - char_count) * 6));
#endif
errors++;
}
}
*output_len = output_idx;
return errors;
static char constexpr tab[] = {
"ABCDEFGHIJKLMNOP"
"QRSTUVWXYZabcdef"
"ghijklmnopqrstuv"
"wxyz0123456789+/"
};
return &tab[0];
}
void _base64Encode(const unsigned char* input, unsigned int input_len, char* output)
AX_DLL signed char const*
get_inverse()
{
unsigned int char_count;
unsigned int bits;
unsigned int input_idx = 0;
unsigned int output_idx = 0;
char_count = 0;
bits = 0;
for (input_idx = 0; input_idx < input_len; input_idx++)
{
bits |= input[input_idx];
char_count++;
if (char_count == 3)
{
output[output_idx++] = alphabet[(bits >> 18) & 0x3f];
output[output_idx++] = alphabet[(bits >> 12) & 0x3f];
output[output_idx++] = alphabet[(bits >> 6) & 0x3f];
output[output_idx++] = alphabet[bits & 0x3f];
bits = 0;
char_count = 0;
}
else
{
bits <<= 8;
}
}
if (char_count)
{
if (char_count == 1)
{
bits <<= 8;
}
output[output_idx++] = alphabet[(bits >> 18) & 0x3f];
output[output_idx++] = alphabet[(bits >> 12) & 0x3f];
if (char_count > 1)
{
output[output_idx++] = alphabet[(bits >> 6) & 0x3f];
}
else
{
output[output_idx++] = '=';
}
output[output_idx++] = '=';
}
output[output_idx++] = 0;
static signed char constexpr tab[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255
};
return &tab[0];
}
int base64Decode(const unsigned char* in, unsigned int inLength, unsigned char** out)
AX_DLL std::size_t
encode(void* dest, void const* src, std::size_t len)
{
unsigned int outLength = 0;
char* out = static_cast<char*>(dest);
char const* in = static_cast<char const*>(src);
auto const tab = base64::get_alphabet();
// should be enough to store 6-bit buffers in 8-bit buffers
*out = (unsigned char*)malloc(inLength / 4 * 3 + 1);
if (*out)
for(auto n = len / 3; n--;)
{
int ret = _base64Decode(in, inLength, *out, &outLength);
*out++ = tab[ (in[0] & 0xfc) >> 2];
*out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
*out++ = tab[((in[2] & 0xc0) >> 6) + ((in[1] & 0x0f) << 2)];
*out++ = tab[ in[2] & 0x3f];
in += 3;
}
if (ret > 0)
switch(len % 3)
{
case 2:
*out++ = tab[ (in[0] & 0xfc) >> 2];
*out++ = tab[((in[0] & 0x03) << 4) + ((in[1] & 0xf0) >> 4)];
*out++ = tab[ (in[1] & 0x0f) << 2];
*out++ = '=';
break;
case 1:
*out++ = tab[ (in[0] & 0xfc) >> 2];
*out++ = tab[((in[0] & 0x03) << 4)];
*out++ = '=';
*out++ = '=';
break;
case 0:
break;
}
return out - static_cast<char*>(dest);
}
AX_DLL std::size_t
decode(void* dest, char const* src, std::size_t len)
{
char* out = static_cast<char*>(dest);
auto in = reinterpret_cast<unsigned char const*>(src);
unsigned char c3[3], c4[4] = {0,0,0,0};
int i = 0;
int j = 0;
auto const inverse = base64::get_inverse();
while(len-- && *in != '=')
{
auto const v = inverse[*in];
if(v == -1)
break;
++in;
c4[i] = v;
if(++i == 4)
{
#if (AX_TARGET_PLATFORM != AX_PLATFORM_BADA)
printf("Base64Utils: error decoding");
#endif
free(*out);
*out = nullptr;
outLength = 0;
c3[0] = (c4[0] << 2) + ((c4[1] & 0x30) >> 4);
c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
for(i = 0; i < 3; i++)
*out++ = c3[i];
i = 0;
}
}
return outLength;
}
int base64Encode(const unsigned char* in, unsigned int inLength, char** out)
{
unsigned int outLength = (inLength + 2) / 3 * 4;
// should be enough to store 8-bit buffers in 6-bit buffers
*out = (char*)malloc(outLength + 1);
if (*out)
if(i)
{
_base64Encode(in, inLength, *out);
c3[0] = ( c4[0] << 2) + ((c4[1] & 0x30) >> 4);
c3[1] = ((c4[1] & 0xf) << 4) + ((c4[2] & 0x3c) >> 2);
c3[2] = ((c4[2] & 0x3) << 6) + c4[3];
for(j = 0; j < i - 1; j++)
*out++ = c3[j];
}
return outLength;
return out - static_cast<char*>(dest);
}
} // namespace cocos2d
} // base64
NS_AX_END

View File

@ -1,62 +1,73 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
https://axmolengine.github.io/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __SUPPORT_BASE64_H__
#define __SUPPORT_BASE64_H__
/// @cond DO_NOT_SHOW
#pragma once
#include <utility>
#include "platform/CCPlatformMacros.h"
NS_AX_BEGIN
/** @file
base64 helper functions
*/
namespace base64 {
/**
* Decodes a 64base encoded memory. The decoded memory is
* expected to be freed by the caller by calling `free()`
*
* @returns the length of the out buffer
*
@since v0.8.1
*/
int AX_DLL base64Decode(const unsigned char* in, unsigned int inLength, unsigned char** out);
AX_DLL
char const*
get_alphabet();
/**
* Encodes bytes into a 64base encoded memory with terminating '\0' character.
* The encoded memory is expected to be freed by the caller by calling `free()`
*
* @returns the length of the out buffer
*
@since v2.1.4
*/
int AX_DLL base64Encode(const unsigned char* in, unsigned int inLength, char** out);
AX_DLL
signed char const*
get_inverse();
} // namespace cocos2d
/// Returns max chars needed to encode a base64 string
inline
std::size_t constexpr
encoded_size(std::size_t n)
{
return 4 * ((n + 2) / 3);
}
/// @endcond
#endif // __SUPPORT_BASE64_H__
/// Returns max bytes needed to decode a base64 string
inline
std::size_t constexpr
decoded_size(std::size_t n)
{
return n / 4 * 3; // requires n&3==0, smaller
}
/** Encode a series of octets as a padded, base64 string.
The resulting string will not be null terminated.
@par Requires
The memory pointed to by `out` points to valid memory
of at least `encoded_size(len)` bytes.
@return The number of characters written to `out`. This
will exclude any null termination.
*/
AX_DLL
std::size_t
encode(void* dest, void const* src, std::size_t len);
/** Decode a padded base64 string into a series of octets.
@par Requires
The memory pointed to by `out` points to valid memory
of at least `decoded_size(len)` bytes.
@return The number of octets written to `out`.
*/
AX_DLL
std::size_t decode(void* dest, char const* src, std::size_t len);
} // base64
NS_AX_END

View File

@ -3,7 +3,7 @@ Copyright (c) 2010 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
Copyright (c) 2020 C4games Ltd
Copyright (c) 2021 Bytedance Inc.
Copyright (c) 2021-2022 Bytedance Inc.
https://axmolengine.github.io/
@ -42,7 +42,6 @@ THE SOFTWARE.
#include "base/CCDirector.h"
#include "base/CCAsyncTaskPool.h"
#include "base/CCEventDispatcher.h"
#include "base/base64.h"
#include "base/ccConstants.h"
#include "base/ccUTF8.h"
#include "renderer/CCCustomCommand.h"
@ -57,6 +56,8 @@ THE SOFTWARE.
#include "2d/CCSprite.h"
#include "2d/CCRenderTexture.h"
#include "base/base64.h"
using namespace std::string_view_literals;
NS_AX_BEGIN
@ -74,6 +75,18 @@ int ccNextPOT(int x)
namespace utils
{
namespace base64
{
inline int encBound(int sourceLen)
{
return (sourceLen + 2) / 3 * 4;
}
inline int decBound(int sourceLen)
{
return sourceLen / 4 * 3 + 1;
}
} // namespace base64
/*
* Capture screen interface
*/
@ -406,7 +419,7 @@ std::string getDataMD5Hash(const Data& data)
return computeDigest(std::string_view{(const char*)data.getBytes(), (size_t)data.getSize()}, "md5"sv);
}
std::string computeDigest(std::string_view data, std::string_view algorithm)
std::string computeDigest(std::string_view data, std::string_view algorithm, bool toHex)
{
const EVP_MD* md = nullptr;
unsigned char mdValue[EVP_MAX_MD_SIZE] = {0};
@ -423,7 +436,8 @@ std::string computeDigest(std::string_view data, std::string_view algorithm)
EVP_DigestFinal_ex(mdctx, mdValue, &mdLen);
EVP_MD_CTX_destroy(mdctx);
return bin2hex(std::string_view{(const char*)mdValue, (size_t)mdLen});
return toHex ? bin2hex(std::string_view{(const char*)mdValue, (size_t)mdLen})
: std::string{(const char*)mdValue, (size_t)mdLen};
}
LanguageType getLanguageTypeByISO2(const char* code)
@ -781,6 +795,62 @@ std::string urlDecode(std::string_view st)
return decoded;
}
AX_DLL std::string base64Encode(std::string_view s)
{
size_t n = ax::base64::encoded_size(s.length());
if (n > 0)
{
std::string ret;
ret.resize_and_overwrite(n,
[&](char* p, size_t) {
return ax::base64::encode(p, s.data(), s.length());
});
return ret;
}
return std::string{};
}
AX_DLL std::string base64Decode(std::string_view s)
{
size_t n = ax::base64::decoded_size(s.length());
if (n > 0)
{
std::string ret;
ret.resize_and_overwrite(n, [&](char* p, size_t) {
return ax::base64::decode(p, s.data(), s.length());
});
return ret;
}
return std::string{};
}
int base64Encode(const unsigned char* in, unsigned int inLength, char** out)
{
auto n = ax::base64::encoded_size(inLength);
// should be enough to store 8-bit buffers in 6-bit buffers
*out = (char*)malloc(n + 1);
if (*out)
{
auto ret = ax::base64::encode(*out, in, inLength);
*out[ret] = '\0';
return ret;
}
return 0;
}
AX_DLL int base64Decode(const unsigned char* in, unsigned int inLength, unsigned char** out)
{
size_t n = ax::base64::decoded_size(inLength);
*out = (unsigned char*)malloc(n);
if (*out)
return static_cast<int>(ax::base64::decode(*out, (char*)in, inLength));
return 0;
}
AX_DLL uint32_t fourccValue(std::string_view str)
{
if (str.empty() || str[0] != '#')

View File

@ -3,7 +3,7 @@ Copyright (c) 2010 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
Copyright (c) 2020 C4games Ltd
Copyright (c) 2021 Bytedance Inc.
Copyright (c) 2021-2022 Bytedance Inc.
https://axmolengine.github.io/
@ -202,7 +202,7 @@ AX_DLL std::string getDataMD5Hash(const Data& data);
* @param algorithm The hash algorithm, support "md5", "sha1", "sha256", "sha512" and more
* @return The hash for the data
*/
AX_DLL std::string computeDigest(std::string_view data, std::string_view algorithm);
AX_DLL std::string computeDigest(std::string_view data, std::string_view algorithm, bool toHex = true);
/**
@brief Converts language iso 639-1 code to LanguageType enum.
@ -405,7 +405,44 @@ AX_DLL std::string urlEncode(std::string_view s);
AX_DLL std::string urlDecode(std::string_view st);
/**
* Encodes bytes into a 64base buffer
* @returns base64 encoded string
*
@since axmol-1.0.0
*/
AX_DLL std::string base64Encode(std::string_view s);
/**
* Decodes a 64base encoded buffer
* @returns palintext
*
@since axmol-1.0.0
*/
AX_DLL std::string base64Decode(std::string_view s);
/**
* Encodes bytes into a 64base encoded memory with terminating '\0' character.
* The encoded memory is expected to be freed by the caller by calling `free()`
*
* @returns the length of the out buffer
*
@since v2.1.4, axmol-1.0.0 move from namespace ax to ax::utils
*/
AX_DLL int base64Encode(const unsigned char* in, unsigned int inLength, char** out);
/**
* Decodes a 64base encoded memory. The decoded memory is
* expected to be freed by the caller by calling `free()`
*
* @returns the length of the out buffer
*
@since v0.8.1, axmol-1.0.0 move from namespace ax to ax::utils
*/
AX_DLL int base64Decode(const unsigned char* in, unsigned int inLength, unsigned char** out);
AX_DLL uint32_t fourccValue(std::string_view str);
} // namespace utils
NS_AX_END

View File

@ -31,7 +31,6 @@
# include "base/CCDirector.h"
# include "platform/CCFileUtils.h"
# include "platform/CCGLView.h"
# include "base/base64.h"
# include "ui/UIHelper.h"
# include "rapidjson/document.h"
# include "rapidjson/stringbuffer.h"
@ -219,9 +218,7 @@ static std::string getUriStringFromArgs(ArgType* args)
static std::string getDataURI(std::string_view data, std::string_view mime_type)
{
char* encodedData;
ax::base64Encode(reinterpret_cast<const unsigned char*>(data.data()), static_cast<unsigned>(data.size()),
&encodedData);
auto encodedData = utils::base64Encode(data);
return std::string{"data:"}.append(mime_type).append(";base64,").append(utils::urlEncode(encodedData));
}

View File

@ -224,7 +224,7 @@ void ConsoleUploadFile::uploadFile()
ssize_t ret = readBuffer(buffer, 3, srcFileData);
if (ret > 0)
{
int len = base64Encode(in, (unsigned int)ret, &out);
int len = utils::base64Encode(in, (unsigned int)ret, &out);
send(sfd, out, len, 0);
free(out);
if (ret < 3)