text: /**
   * base64url.cpp
   *
   * Copyright (c) 2021 Yuriy Lisovskiy
   */
  
  #include "./base64url.h"
  
  // STL Libraries.
  #include <vector>
  
  
  __CRYPTO_BEGIN__
  const char base64_url_alphabet[] = {
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
      'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
      'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
  };
  
  std::string base64url_encode(const std::string& raw_data)
  {
  	std::string out;
  	int val = 0, val_b = -6;
  	size_t len = raw_data.length();
  	unsigned int i = 0;
  	for (i = 0; i < len; i++)
  	{
  		unsigned char c = raw_data[i];
  		val = (val << 8) + c;
  		val_b += 8;
  		while (val_b >= 0)
  		{
  			out.push_back(base64_url_alphabet[(val >> val_b) & 0x3F]);
  			val_b -= 6;
  		}
  	}
  
  	if (val_b > -6)
  	{
  		out.push_back(base64_url_alphabet[((val << 8) >> (val_b + 8)) & 0x3F]);
  	}
  
  	return out;
  }
  
  static const int B64index[256] = { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62, 63, 62, 62, 63, 52, 53, 54, 55,
  	56, 57, 58, 59, 60, 61,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,
  	7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,
  	0,  0,  0, 63,  0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
  };
  
  std::string base64url_decode(const std::string& data)
  {
  	auto len = data.size();
      auto* p = (const unsigned char*)data.data();
      int pad = len > 0 && (len % 4 || p[len - 1] == '=');
      const size_t L = ((len + 3) / 4 - pad) * 4;
      std::string str(L / 4 * 3 + pad, '\0');
  
      for (size_t i = 0, j = 0; i < L; i += 4)
      {
          int n = B64index[p[i]] << 18 | B64index[p[i + 1]] << 12 | B64index[p[i + 2]] << 6 | B64index[p[i + 3]];
          str[j++] = n >> 16;
          str[j++] = n >> 8 & 0xFF;
          str[j++] = n & 0xFF;
      }
  
      if (pad)
      {
          int n = B64index[p[L]] << 18 | B64index[p[L + 1]] << 12;
          str[str.size() - 1] = n >> 16;
  
          if (len > L + 2 && p[L + 2] != '=')
          {
              n |= B64index[p[L + 2]] << 6;
              str.push_back(n >> 8 & 0xFF);
          }
      }
  
      return str;
  }
  
  __CRYPTO_END__
  