mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-22 22:16:37 +08:00
added encoding/Base64
This commit is contained in:
parent
5957798e0e
commit
a512c7360a
191
encoding/Base64.cpp
Normal file
191
encoding/Base64.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi, <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "Base64.hpp"
|
||||
|
||||
namespace oatpp { namespace encoding {
|
||||
|
||||
v_char8 Base64::getAlphabetCharIndex(v_char8 a, const char* auxiliaryChars) {
|
||||
if(a >= 'A' && a <='Z') {
|
||||
return a - 'A';
|
||||
}
|
||||
if(a >= 'a' && a <='z') {
|
||||
return a - 'a' + 26;
|
||||
}
|
||||
if(a >= '0' && a <='9') {
|
||||
return a - '0' + 52;
|
||||
}
|
||||
if(a == auxiliaryChars[0]) {
|
||||
return 62;
|
||||
}
|
||||
if(a == auxiliaryChars[1]) {
|
||||
return 63;
|
||||
}
|
||||
return 255;
|
||||
}
|
||||
|
||||
v_int32 Base64::calcEncodedStringSize(v_int32 size) {
|
||||
v_int32 size3 = size / 3;
|
||||
v_int32 rSize = size3 * 3;
|
||||
if(rSize < size){
|
||||
rSize += 4;
|
||||
}
|
||||
return rSize + size3; // resultSize = (size3 * 3 + size3) = size3 * 4
|
||||
}
|
||||
|
||||
v_int32 Base64::calcDecodedStringSize(const char* data, v_int32 size, v_int32& base64StrLength, const char* auxiliaryChars) {
|
||||
|
||||
base64StrLength = size;
|
||||
|
||||
v_char8 auxChar1 = auxiliaryChars[0];
|
||||
v_char8 auxChar2 = auxiliaryChars[1];
|
||||
v_char8 paddingChar = auxiliaryChars[2];
|
||||
|
||||
v_int32 i = 0;
|
||||
while (i < size) {
|
||||
|
||||
v_char8 a = data[i];
|
||||
|
||||
bool isValidChar = (a >= 'A' && a <='Z') || (a >= 'a' && a <='z') || (a >= '0' && a <='9') || (a == auxChar1) || (a == auxChar2);
|
||||
if(!isValidChar) {
|
||||
if(a == paddingChar){
|
||||
base64StrLength = i;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
v_int32 size4 = i >> 2;
|
||||
v_int32 size4d = i - (size4 << 2);
|
||||
v_int32 resultSize = size4 * 3;
|
||||
if(size4d > 0) {
|
||||
resultSize += size4d - 1;
|
||||
}
|
||||
return resultSize;
|
||||
|
||||
}
|
||||
|
||||
bool Base64::isBase64String(const char* data, v_int32 size, const char* auxiliaryChars) {
|
||||
v_int32 base64StrLength;
|
||||
return (calcDecodedStringSize(data, size, base64StrLength, auxiliaryChars) >= 0);
|
||||
}
|
||||
|
||||
oatpp::String Base64::encode(const void* data, v_int32 size, const char* alphabet) {
|
||||
|
||||
auto resultSize = calcEncodedStringSize(size);
|
||||
|
||||
auto result = oatpp::String(resultSize);
|
||||
|
||||
p_char8 bdata = (p_char8) data;
|
||||
p_char8 resultData = result->getData();
|
||||
|
||||
v_int32 pos = 0;
|
||||
while (pos + 2 < size) {
|
||||
|
||||
v_char8 b0 = bdata[pos];
|
||||
v_char8 b1 = bdata[pos + 1];
|
||||
v_char8 b2 = bdata[pos + 2];
|
||||
resultData[0] = alphabet[(b0 & 252) >> 2];
|
||||
resultData[1] = alphabet[((b0 & 3) << 4) | ((b1 >> 4) & 15)];
|
||||
resultData[2] = alphabet[((b1 & 15) << 2) | ((b2 >> 6) & 3)];
|
||||
resultData[3] = alphabet[(b2 & 63)];
|
||||
resultData += 4;
|
||||
pos += 3;
|
||||
|
||||
}
|
||||
|
||||
if(pos + 1 < size) {
|
||||
v_char8 b0 = bdata[pos];
|
||||
v_char8 b1 = bdata[pos + 1];
|
||||
resultData[0] = alphabet[(b0 & 252) >> 2];
|
||||
resultData[1] = alphabet[((b0 & 3) << 4) | ((b1 >> 4) & 15)];
|
||||
resultData[2] = alphabet[((b1 & 15) << 2)];
|
||||
resultData[3] = alphabet[64];
|
||||
} else if(pos < size) {
|
||||
v_char8 b0 = bdata[pos];
|
||||
resultData[0] = alphabet[(b0 & 252) >> 2];
|
||||
resultData[1] = alphabet[(b0 & 3) << 4];
|
||||
resultData[2] = alphabet[64];
|
||||
resultData[3] = alphabet[64];
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
oatpp::String Base64::encode(const oatpp::String& data, const char* alphabet) {
|
||||
return encode(data->getData(), data->getSize(), alphabet);
|
||||
}
|
||||
|
||||
oatpp::String Base64::decode(const char* data, v_int32 size, const char* auxiliaryChars) {
|
||||
|
||||
v_int32 base64StrLength;
|
||||
auto resultSize = calcDecodedStringSize(data, size, base64StrLength, auxiliaryChars);
|
||||
if(resultSize < 0) {
|
||||
throw DecodingError("Data is no base64 string. Make sure that auxiliaryChars match with encoder alphabet");
|
||||
}
|
||||
|
||||
auto result = oatpp::String(resultSize);
|
||||
p_char8 resultData = result->getData();
|
||||
v_int32 pos = 0;
|
||||
while (pos + 3 < base64StrLength) {
|
||||
v_char8 b0 = getAlphabetCharIndex(data[pos], auxiliaryChars);
|
||||
v_char8 b1 = getAlphabetCharIndex(data[pos + 1], auxiliaryChars);
|
||||
v_char8 b2 = getAlphabetCharIndex(data[pos + 2], auxiliaryChars);
|
||||
v_char8 b3 = getAlphabetCharIndex(data[pos + 3], auxiliaryChars);
|
||||
|
||||
resultData[0] = (b0 << 2) | ((b1 >> 4) & 3);
|
||||
resultData[1] = ((b1 & 15) << 4) | ((b2 >> 2) & 15);
|
||||
resultData[2] = ((b2 & 3) << 6) | b3;
|
||||
|
||||
resultData += 3;
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
v_int32 posDiff = base64StrLength - pos;
|
||||
if(posDiff == 3) {
|
||||
v_char8 b0 = getAlphabetCharIndex(data[pos], auxiliaryChars);
|
||||
v_char8 b1 = getAlphabetCharIndex(data[pos + 1], auxiliaryChars);
|
||||
v_char8 b2 = getAlphabetCharIndex(data[pos + 2], auxiliaryChars);
|
||||
resultData[0] = (b0 << 2) | ((b1 >> 4) & 3);
|
||||
resultData[1] = ((b1 & 15) << 4) | ((b2 >> 2) & 15);
|
||||
} else if(posDiff == 2) {
|
||||
v_char8 b0 = getAlphabetCharIndex(data[pos], auxiliaryChars);
|
||||
v_char8 b1 = getAlphabetCharIndex(data[pos + 1], auxiliaryChars);
|
||||
resultData[0] = (b0 << 2) | ((b1 >> 4) & 3);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
oatpp::String Base64::decode(const oatpp::String& data, const char* auxiliaryChars) {
|
||||
return decode((const char*)data->getData(), data->getSize(), auxiliaryChars);
|
||||
}
|
||||
|
||||
}}
|
108
encoding/Base64.hpp
Normal file
108
encoding/Base64.hpp
Normal file
@ -0,0 +1,108 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi, <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_encoding_Base64_hpp
|
||||
#define oatpp_encoding_Base64_hpp
|
||||
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
namespace oatpp { namespace encoding {
|
||||
|
||||
class Base64 {
|
||||
public:
|
||||
|
||||
class DecodingError : public std::runtime_error {
|
||||
public:
|
||||
|
||||
DecodingError(const char* message)
|
||||
:std::runtime_error(message)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static v_char8 getAlphabetCharIndex(v_char8 a, const char* auxiliaryChars);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Alphabet is array of 65 chars. 64 chars encoding chars, and 65th padding char
|
||||
*/
|
||||
constexpr static const char* ALPHABET_BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
constexpr static const char* ALPHABET_BASE64_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=";
|
||||
constexpr static const char* ALPHABET_BASE64_URL_SAFE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-";
|
||||
|
||||
/**
|
||||
* alphabet auxiliary chars - last 3 chars of alphabet including padding char.
|
||||
*/
|
||||
constexpr static const char* ALPHABET_BASE64_AUXILIARY_CHARS = "+/=";
|
||||
constexpr static const char* ALPHABET_BASE64_URL_AUXILIARY_CHARS = "-_=";
|
||||
constexpr static const char* ALPHABET_BASE64_URL_SAFE_AUXILIARY_CHARS = "._-";
|
||||
|
||||
/**
|
||||
* Returns size of encoding result of a string of the given size
|
||||
*/
|
||||
static v_int32 calcEncodedStringSize(v_int32 size);
|
||||
|
||||
/**
|
||||
* Returns size of decoding result. this method assumes that data passed as a param consists of standard base64 set of chars
|
||||
* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 and three configurable auxiliary chars.
|
||||
*
|
||||
* if data passed is not a base64 string then -1 is returned
|
||||
*/
|
||||
static v_int32 calcDecodedStringSize(const char* data, v_int32 size, v_int32& base64StrLength, const char* auxiliaryChars = ALPHABET_BASE64_AUXILIARY_CHARS);
|
||||
|
||||
/**
|
||||
* return (calcDecodedStringSize(data, size, auxiliaryChars) >= 0);
|
||||
*/
|
||||
static bool isBase64String(const char* data, v_int32 size, const char* auxiliaryChars = ALPHABET_BASE64_AUXILIARY_CHARS);
|
||||
|
||||
/**
|
||||
* encode data as base64 string
|
||||
*/
|
||||
static oatpp::String encode(const void* data, v_int32 size, const char* alphabet = ALPHABET_BASE64);
|
||||
|
||||
/**
|
||||
* return encode(data->getData(), data->getSize(), alphabet);
|
||||
*/
|
||||
static oatpp::String encode(const oatpp::String& data, const char* alphabet = ALPHABET_BASE64);
|
||||
|
||||
/**
|
||||
* decode() this method assumes that data passed as a param consists of standard base64 set of chars
|
||||
* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 and three configurable auxiliary chars.
|
||||
*
|
||||
* throws DecodingError(). in case invalid char found
|
||||
*/
|
||||
static oatpp::String decode(const char* data, v_int32 size, const char* auxiliaryChars = ALPHABET_BASE64_AUXILIARY_CHARS);
|
||||
|
||||
/**
|
||||
* return decode(data->getData(), data->getSize(), auxiliaryChars);
|
||||
*/
|
||||
static oatpp::String decode(const oatpp::String& data, const char* auxiliaryChars = ALPHABET_BASE64_AUXILIARY_CHARS);
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* oatpp_encoding_Base64_hpp */
|
Loading…
Reference in New Issue
Block a user