2016-10-29 10 views
0

このjavascript base64エンコードルーチンをC++で書き直そうとしています(非標準のbase64であり、デコード文字列の先頭に。があることに注意してください)。ここで C++でのBase64エンコード関数のビットシフト

は、JSスクリプトの例です - https://jsfiddle.net/km53844e/1/

そしてここで、C++のスクリプトの例である - http://www.tutorialspoint.com/compile_cpp11_online.php?PID=0Bw_CjBb95KQMZ0d5UHc0enhRbXM

私は下に掲載しているjavascriptのbase64のクラス。

JSスクリプトでは、CcnKをCMlaKAに正しく変換します。しかし、C++スクリプトでは、これをCMlaKrに間違って変換します(理由はわかりませんが、JSスクリプトの追加NaNステートメントと何か関係があるでしょうか)。

また、NULL終了文字列C++スクリプトで?私はこれを削除した場合、私はまだ正しくないCMlaKsを得ることに気づく。

私は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++コード:

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コード:

var Base64 = { 
     _keyStr: ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=", 

    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); 
    } 

}; 
+0

65値の場合はどのようにして64ですか?そのbase65じゃない? –

+0

Well base65 then。 –

+0

'isNaN(chr2)'チェックは、対応する位置が入力シーケンスの外にあったことを意味します。これは、入力シーケンスの長さが3の倍数でない場合に発生します。あなたのC++コードは、そのケースを適切に処理しません。 – Leon

答えて

1

ので、)JavaScriptのISNAN(に比べて、C++のコードを見ていたときには、次のようにしなければならない:

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 
} 

しかし、主な問題は、ということですisnan()関数はC++の 浮動小数点値専用であり、 JavaScriptと同じ意味を持ちません。次のいずれかによって

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; 
    } 

:予期しない値を防止する

1-未満の3つのバイトが左代わりisnan()関数は、base64_encode()の以下の部分を交換することを使用しての

入力バッファで0x00に強制します。また、すべての次のループの前に(for(j=0;j<3;j++) char_array_3[j]=0x00;)。

2- 2バイト入力バッファif (i == 2)からロードされたときのみ1バイト入力バッファif (i == 1)からロードされたときに、出力バッファの 最後の項目は、64

-3-に設定されています出力バッファの 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 
    } 

JavaScriptに比較C++でbase64_encode()関数の最後のエラーは、中間項目の出力バッファ計算であります。代わりに、これらの次の割り当ての :

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; 

は、以下のものを使用する:

1- char_array_4[1](= ENC2 JSで)を計算するとき、JSのエントリ char_array_3[0](= CHR1を)とchar_array_3[1](= JS内のchr2)は逆です。

2-(JSで= ENC3)、エントリが char_array_3[1](JSで= ChR2をchar_array_4[2]を算出し、char_array_3[2](= CHR 3 JSで)が逆になっています。これらの補正後の

// 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; 

、条件ブロックif (i)は無用であり、除去されなければなりません。

+0

こんにちはJ.ピカード。私はあなたが示唆したように、C++オンラインコンパイラで見ることができるように試みましたが、うまくいきません。以前と同じ結果が得られます。 –

+0

@Ke。私はあなたの追加されたソースコードを確認した後、私の答えを更新しました。 –

+0

はい、これは正解です。問題はchar_array_4が作成された場所(isnanステートメントではありません)にあります。しかし、なぜisnanがjavascriptのバージョンで必要とされているのかよく分かりません。それは基本的にbase65なのでこれは?スクリプトに65文字(最初は。を含む)があるので、 –

関連する問題