Fast base64 / uuencoding encodage/decodage

Soyez le premier à donner votre avis sur cette source.

Vue 10 468 fois - Téléchargée 676 fois

Description

Classes C++ permettant de coder/décoder rapidement et simplement une string en/depuis Base64/Uuencoding.

Source / Exemple :


/////////////////////BASE64.HPP/////////////////////
#ifndef __ENCODING_BASE64_HPP__
#define __ENCODING_BASE64_HPP__

#include <iostream>

/// Base64 alphabet
static const std::string b64table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

class Base64
{
private :
  /// Filling character
  static const char fillchar = '=';
  
  // The masks
  static const uint32_t mask1 = 0xFC000000;
  static const uint32_t mask2 = 0x03F00000;
  static const uint32_t mask3 = 0x000FC000;
  static const uint32_t mask4 = 0x00003F00;

  typedef union
  {
    uint32_t l   ;
    char     c[4];
  }un32;
  
public:
  static std::string encode(const std::string & data);
  static std::string decode(const std::string & data);
}; 
  
#endif
////////////////////////////////////////////////////

/////////////////////BASE64.CPP/////////////////////

#include <base64.hpp>

using namespace std;

string Base64::encode(const std::string & data)
{
  const size_t trail = data.size()%3;
  size_t sz          = data.size()/3*4;
  sz += (trail != 0) ? 4 : 0;
  
  un32 b64; 

  string out;
  out.resize(sz); 

  size_t i = 0, k = 0;
  
  while(i < data.size()-trail)
    {
      b64.c[3] = data[i++];
      b64.c[2] = data[i++];
      b64.c[1] = data[i++];
       
      out[k++] = b64table[static_cast <int> ((b64.l & mask1) >> 26)];
      out[k++] = b64table[static_cast <int> ((b64.l & mask2) >> 20)];
      out[k++] = b64table[static_cast <int> ((b64.l & mask3) >> 14)];
      out[k++] = b64table[static_cast <int> ((b64.l & mask4) >>  8)];
    }

  b64.l = 0;
  
  switch(trail)
    {
    case 1:
      b64.c[3] = data[i++];
      out[k++] = b64table[static_cast <int> ((b64.l & mask1) >> 26)];
      out[k++] = b64table[static_cast <int> ((b64.l & mask2) >> 20)];
      out[k++] = fillchar;
      out[k++] = fillchar; 
      break;

    case 2:
      b64.c[3] = data[i++];
      b64.c[2] = data[i++];
      out[k++] = b64table[static_cast <int> ((b64.l & mask1) >> 26)];
      out[k++] = b64table[static_cast <int> ((b64.l & mask2) >> 20)];
      out[k++] = b64table[static_cast <int> ((b64.l & mask3) >> 14)];
      out[k++] = fillchar;
      break;
    }
  
  return out;
}

string Base64::decode(const std::string & data)
{
  // Number of trailing '='
  const size_t trail = (data[data.size()-1] == fillchar) ? ((data[data.size()-2] == fillchar) ? 2 : 1 ) : 0;
  // Number of char to decode
  const size_t szin  = (trail == 0) ? data.size() : data.size()-4;
  // Output string size
  const size_t szout = szin/4*3+ ((trail == 0)? 0 : ((trail == 1) ? 3 : 2)); 

  un32 b64; 

  string out;
  out.resize(szout); 

  size_t i = 0, k = 0;

  while(i < szin)
    {
      b64.l  = 0; 
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<  26;
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<  20;
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<  14;
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<   8;

      out[k++] = b64.c[3];
      out[k++] = b64.c[2];
      out[k++] = b64.c[1];
    }

  b64.l = 0;
  
  switch(trail)
    {
    case 1:
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<  26;
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<  20;
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<  14;
      
      out[k++] =  b64.c[3];
      out[k++] =  b64.c[2];
      break;

    case 2:
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<  26;
      b64.l += (static_cast < uint32_t > (b64table.find_first_of(data[i++])) ) <<  20;
      
      out[k++] = b64.c[3];
      break;
    }
  
  return out;
}

////////////////////////////////////////////////////

Conclusion :


Ici pour le Base64, le Uuencoding est dans le zip mais le principe reste le même.

Codes Sources

A voir également

Ajouter un commentaire Commentaire
jphippie2 Messages postés 2 Date d'inscription dimanche 11 avril 2004 Statut Membre Dernière intervention 7 octobre 2008
7 oct. 2008 à 14:36
Merci pour ce code que je trouve joliment écrit.

Il fonctionne bien à deux petits bugs près:
base64.cpp Ligne 100 : dans le decodeur base 64, remplacer la ligne:
const size_t szout szin/4*3+ ((trail 0)? 0 : ((trail == 1) ? 3 : 2));
par la ligne:
const size_t szout szin/4*3+ ((trail 0)? 0 : ((trail == 1) ? 2 : 1));
Sinon, un caractère supplémentaire non initialisé est ajouté au buffer.

uuencoding.cpp Ligne 6 : remplacer
#define SPtoBACKQ(x) (x == 32) ? 96 : x
par:
#define SPtoBACKQ(x) (x)
En effet, le fait de remplacer systématiquement les blancs par des accents graves n'est pas une bonne idée car le même caractère est utilisé pour le padding en fin de ligne.
Par exemple la chaîne "LA CONSTITUTION Française " est codée avec deux accents graves à la fin plutôt que espace+accent grave. Lors du décodage on obtient une chaîne trop courte d'un caractère!

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.