[英]Bitwise shifting for Base64 encode function in C++
I'm trying to rewrite this javascript base64 encode routine in C++ (please note that it is non standard base64, and has a . at the beginning of the decode string). 我正在尝试用C ++重写此javascript base64编码例程(请注意,它是非标准的base64,并且在解码字符串的开头有一个。)。
Here is an example of the JS script - https://jsfiddle.net/km53844e/1/ 这是JS脚本的示例-https: //jsfiddle.net/km53844e/1/
The javascript base64 class I have posted beneath. 我在下面发布了javascript base64类。
In the JS script it correctly converts CcnK to CMlaKA . 在JS脚本中,它将CcnK正确转换为CMlaKA。 However, in the C++ script, it incorrectly converts this to CMlaKr (not sure why, could it be something to do with the additional NaN statements in the JS script? 但是,在C ++脚本中,它错误地将其转换为CMlaKr(不知道为什么,这可能与JS脚本中的其他NaN语句有关吗?
Or could it possibly be to do with the null terminated string in the C++ script? 还是可能与C ++脚本中以null结尾的字符串有关? I notice that if I remove this I get CMlaKs which is still not correct. 我注意到,如果删除此选项,我会得到仍然不正确的CMlaK。
I've tried adding the following to deal with the isnans but its not working. 我尝试添加以下内容来处理isnans,但它不起作用。
if (isnan(char_array_4[1])) {
char_array_4[2] = char_array_4[1] = 64;
} else if (isnan(char_array_4[2])) {
char_array_4[3] = 64;
}
C++ Code: C ++代码:
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = char_array_3[0] & 0x3f;
char_array_4[1] = ((char_array_3[0] & 0x0f) << 2) + ((char_array_3[1] & 0xc0) >> 6);
char_array_4[2] = ((char_array_3[1] & 0x03) << 4) + ((char_array_3[2] & 0xf0) >> 4);
char_array_4[3] = (char_array_3[2] & 0xfc) >> 2;
if (isnan(char_array_4[1])) {
char_array_4[2] = char_array_4[1] = 64;
} else if (isnan(char_array_4[2])) {
char_array_4[3] = 64;
}
for(i = 0; (i < 4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = char_array_3[0] & 0x3f;
char_array_4[1] = ((char_array_3[0] & 0x0f) << 2) + ((char_array_3[1] & 0xc0) >> 6);
char_array_4[2] = ((char_array_3[1] & 0x03) << 4) + ((char_array_3[2] & 0xf0) >> 4);
char_array_4[3] = (char_array_3[2] & 0xfc) >> 2;
if (isnan(char_array_4[1])) {
char_array_4[2] = char_array_4[1] = 64;
} else if (isnan(char_array_4[2])) {
char_array_4[3] = 64;
}
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
JS Code: JS代码:
var Base64 = {
_keyStr: ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=",
encode : function (input) {
var output = [],
chr1, chr2, chr3, enc1, enc2, enc3, enc4,
i = 0;
while (i < input.length) {
chr1 = input[i++];
chr2 = input[i++];
chr3 = input[i++];
enc1 = chr1 & 0x3f;
enc2 = (chr1 >> 6) | ((chr2 & 0xf) << 2);
enc3 = (chr2 >> 4) | ((chr3 & 0x3) << 4);
enc4 = chr3 >> 2;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output.push([this._keyStr.charAt(enc1),
this._keyStr.charAt(enc2),
this._keyStr.charAt(enc3),
this._keyStr.charAt(enc4)].join(''));
}
return output.join('');
},
decodeAsArray: function (b) {
var d = this.decode(b),
a = [],
c;
//alert("decoded base64:" + d);
for (c = 0; c < d.length; c++) {
a[c] = d.charCodeAt(c)
}
//alert("returning a");
return a
},
decode: function( input ) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
do {
enc1 = this._keyStr.indexOf(input.charAt(i++)) ;
enc2 = this._keyStr.indexOf(input.charAt(i++)) ;
enc3 = this._keyStr.indexOf(input.charAt(i++)) ;
enc4 = this._keyStr.indexOf(input.charAt(i++)) ;
chr1 = (enc1 | ((enc2 & 3) << 6));
chr2 = (enc2 >> 2) | ((enc3 & 0x0F) << 4);
chr3 = (enc3 >> 4) | (enc4 << 2);
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return (output);
}
};
So, when looking at your c++ code compared to the JavaScript the isnan() shall be as follow: 因此,当您将c ++代码与JavaScript进行比较时,isnan()应该如下所示:
if (isnan(char_array_3[1])) { // char_array_3[1] = chr2
char_array_4[2] = char_array_4[1] = 64; // char_array_4[2] = enc3 & char_array_4[1] = enc2
} else if (isnan(char_array_3[2])) { // char_array_3[2] = chr3
char_array_4[3] = 64; // char_array_4[3] = enc2
}
But the main problem is that the
isnan()
function is only dedicated to floating-point value in C++ and doesn't have the same meaning as in JavaScript. 但是主要的问题是isnan()
函数仅专用于C ++中的浮点值,并且与JavaScript中的含义不同。
Instead of using that isnan()
function, replace the following part of base64_encode()
: 代替使用那个isnan()
函数,替换base64_encode()
的以下部分:
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
...
if (isnan(char_array_4[1])) {
char_array_4[2] = char_array_4[1] = 64;
} else if (isnan(char_array_4[2])) {
char_array_4[3] = 64;
}
...
for(i = 0; (i < 4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
By the following one: 通过以下之一:
1- to prevent unexpected value when less than 3 bytes left in the input buffer, force them to 0x00. 1-为防止在输入缓冲区中剩余少于3个字节时出现意外值,请将其强制为0x00。 Also before every next loop (
for(j=0;j<3;j++) char_array_3[j]=0x00;
). 同样在每个下一个循环之前(for(j=0;j<3;j++) char_array_3[j]=0x00;
)。2- when 2 bytes have been loaded from the input buffer
if (i == 2)
, the last item of the output buffer is set to 64. 2-if (i == 2)
从输入缓冲区中加载了2个字节,则输出缓冲区的最后一项设置为64。3- when only 1 byte has been loaded from the input buffer
if (i == 1)
, the 2 last items of output buffer are set to 64. 3-if (i == 1)
仅从输入缓冲区加载了1个字节,则输出缓冲区的最后2个项目将设置为64。
for(j=0;j<3;j++) char_array_3[j]=0x00; // initialize input array
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if ((i == 3) || (in_len == 0)) { // encode when 3 bytes or end of buffer
...
if (i == 1) { // instead of (isnan(char_array_4[1]))
// both char_array_3[1] and char_array_3[2] are not defined
char_array_4[3] = char_array_4[2] = 64;
} else if (i == 2) { // instead of (isnan(char_array_4[2]))
// char_array_3[2] is not defined
char_array_4[3] = 64;
}
...
for(i = 0; (i < 4) ; i++)
ret += base64_chars[char_array_4[i]];
i = 0;
for(j=0;j<3;j++) char_array_3[j]=0x00; // initialize input array
}
The last error in the base64_encode()
function in C++ compare to the JavaScript are in the output buffer computation for the intermediate items. 与JavaScript相比,C ++中base64_encode()
函数的最后一个错误在中间项的输出缓冲区计算中。 Instead of those following assignments: 代替以下任务:
char_array_4[0] = char_array_3[0] & 0x3f;
char_array_4[1] = ((char_array_3[0] & 0x0f) << 2) + ((char_array_3[1] & 0xc0) >> 6); // NOK
char_array_4[2] = ((char_array_3[1] & 0x03) << 4) + ((char_array_3[2] & 0xf0) >> 4); // NOK
char_array_4[3] = (char_array_3[2] & 0xfc) >> 2;
Use the following ones: 使用以下内容:
1- When calculating
char_array_4[1]
(= enc2 in JS), the entrieschar_array_3[0]
(= chr1 in JS) andchar_array_3[1]
(= chr2 in JS) are reversed. 1-当计算char_array_4[1]
(在JS中为enc2 )时,将对char_array_3[0]
(在JS中为chr1 )和char_array_3[1]
(在JS中的chr2 )进行反转。2- When calculating
char_array_4[2]
(= enc3 in JS), the entrieschar_array_3[1]
(= chr2 in JS) andchar_array_3[2]
(= chr3 in JS) are reversed. 2-计算char_array_4[2]
(在JS中为enc3 )时,将对char_array_3[1]
(在JS中为chr2 )和char_array_3[2]
(在JS中的chr3 )进行反转。
// JS => enc1 = chr1 & 0x3f;
char_array_4[0] = (char_array_3[0] & 0x3f); // OK
// JS => enc2 = (chr1 >> 6) | ((chr2 & 0xf) << 2);
char_array_4[1] = ((char_array_3[0] & 0xc0) >> 6) + ((char_array_3[1] & 0x0f) << 2); // OK
// JS => enc3 = (chr2 >> 4) | ((chr3 & 0x3) << 4);
char_array_4[2] = ((char_array_3[1] & 0xf0) >> 4) + ((char_array_3[2] & 0x03) << 4); // OK
// JS => enc4 = chr3 >> 2;
char_array_4[3] = (char_array_3[2] & 0xfc) >> 2;
After those corrections, the conditional block
if (i)
is useless and shall be removed. 进行这些更正后,if (i)
条件块if (i)
无效,则应将其删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.