0

During my research I've found these information but it seems like they are not really matching to my problem.


So I'd like to implement a custom Base64 to BaseN encoding and decoding using C++.

I should be able to convert a (Base64)-string like "IloveC0mpil3rs" to a custom Base (e.g Base4) string like e.g "10230102010301" and back again.

Additional I should be able to use a custom charset (alphabet) for the base values like the default one probably is "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".

So I should be able to use a shuffled one like e.g this (kind of encoding :) ): "J87opBEyWwDQdNAYujzshP3LOx1T0XK2e+ZrvFnticbCS64a9/Il5GmgVkqUfRMH".

I thought about translating the convertBase-function below from javascript into C++ but I'm obviously a beginner and got big problems, so I got stuck right there because my code is not working as expected and I can not find the error:

string encoded = convertBase("Test", 64, 4); // gets 313032130131000
cout << encoded << endl;

string decoded = convertBase(encoded, 4, 64); // error
cout << decoded << endl;

C++ code: (not working)

std::string convertBase(string value, int from_base, int to_base) {
    string range = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/";
    string  from_range = range.substr(0, from_base),
            to_range = range.substr(0, to_base);

    int dec_value = 0;
    int index = 0;
    string reversed(value.rbegin(), value.rend());
    for(std::string::iterator it = reversed.begin(); it != reversed.end(); ++it) {
        index++;
        char digit = *it;
        if (!range.find(digit)) return "error";
        dec_value += from_range.find(digit) * pow(from_base, index);
    }
    string new_value = "";
    while (dec_value > 0) {
        new_value = to_range[dec_value % to_base] + new_value;
        dec_value = (dec_value - (dec_value % to_base)) / to_base;
    }
    return new_value;
}

javascript code: (working)

function convertBase(value, from_base, to_base) {
  var range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'.split('');
  var from_range = range.slice(0, from_base);
  var to_range = range.slice(0, to_base);
  
  var dec_value = value.split('').reverse().reduce(function (carry, digit, index) {
    if (from_range.indexOf(digit) === -1) throw new Error('Invalid digit `'+digit+'` for base '+from_base+'.');
    return carry += from_range.indexOf(digit) * (Math.pow(from_base, index));
  }, 0);
  
  var new_value = '';
  while (dec_value > 0) {
    new_value = to_range[dec_value % to_base] + new_value;
    dec_value = (dec_value - (dec_value % to_base)) / to_base;
  }
  return new_value || '0';
}

let encoded = convertBase("Test", 64, 4)
console.log(encoded);

let decoded = convertBase(encoded, 4, 64)
console.log(decoded);

Any help how to fix my code would be very appreciated!

  • Suggestion: If you're using C++11 or better, use a range-based for loop. – user202729 Mar 30 '18 at 14:08
  • [Related](https://stackoverflow.com/questions/29127192/stdstringfind-not-working-as-expected-in-c). – user202729 Mar 30 '18 at 14:10
  • This code doesn't work in JS either, at least not if your base64-string is longer than 8-9 chars. Do you understand how this code works? Even with a base2 input string you have a limit of 53 ones and zeroes, after that it will produce false results. – Thomas Mar 30 '18 at 14:10
  • [Related](https://stackoverflow.com/questions/4299605/problem-with-stdstringfind). – user202729 Mar 30 '18 at 14:11
  • because in JS `var dec_value` is a float with 53bits of precision, and in c++ `int dec_value` has merely 16 bits of data untill it breaks. That's about 2.6 chars of base64 input string. Plus c++ is more likely to throw errors when the value you want to store in a variable is bigger than that the type can contain, ... How do you store `n*pow(from_base, index)` for index 3 in a 16 bit integer? That's why I asked wether you understand how the code works? – Thomas Mar 30 '18 at 14:20
  • @Thomas 32 bits on typical computers. – user202729 Mar 30 '18 at 14:21
  • @tempi I feel that asking others to "share some code" is extremely unnice on [so]. Just my opinion. – user202729 Mar 30 '18 at 14:22
  • @user202729: the original had 64 characters. After the edit, it has 66. – Scott Sauyet Mar 30 '18 at 14:47
  • base64 is a standard, not a notation on how to write number in base64. In fact `0` is encoded with `A` in base64. – Giacomo Catenazzi Mar 30 '18 at 15:21
  • so you should avoid to write "Base64" in the text. It would just create confusion (and you are using the same symbols as Base64, but in a different order, it is also a future cause of problems. – Giacomo Catenazzi Mar 30 '18 at 15:24
  • Wonder that no one is capable of finding my mistake. That's too bad! : / –  Mar 30 '18 at 18:09
  • Your mistake is pointed out in a "related" link above. It's your fault not to read it. – user202729 Apr 01 '18 at 02:13

0 Answers0