<?php
/**
* @class Integer
* @author Julien Garand (Go On Web)
*
* Can encode and decode integers to/from a string, using a custom alphabet
*/
class Integer
{
// Default alphabet for a "normal" base 62 encoding
static protected $alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
static protected $base = 62;
/**
* Define your custom alphabet here
*/
static public function setAlphabet( $alphabet )
{
// only strings are allowed
if ( !is_string($alphabet) )
{
throw new Exception('Given alphabet is not a string !');
}
self::$base = strlen( $alphabet ); // Our base will be the length of the given alphabet
// We check if alphabet doesn't have doubled characters
if ( strlen( count_chars( $alphabet, 3 ) ) != self::$base )
{
throw new Exception('The following alphabet has doubled characters : '.$alphabet);
}
self::$alphabet = $alphabet; // store it
}
/**
* Basic accessors
*/
static public function getAlphabet() { return self::$alphabet; }
static public function getBase() { return self::$base; }
/**
* Encode an integer according to the defined alphabet
*
* @param integer : Unsigned integer to be encoded
* @return string (or false if failed)
*/
static public function encode( $integer )
{
$integer = (int)$integer; // Be sure to have an integer
// We only accept unsigned integers
if ( $integer < 0 )
{
return false; // or throw new Exception( "($integer) is less than 0 and cannot be converted" );
}
$string = ''; // our encoded integer
// while we have to encode
while( $integer )
{
$pos = $integer % self::$base; // get the rest of euclidian division...
$string .= self::$alphabet[ $pos ]; // thats the position of the char in alphabet
$integer = ( $integer - $pos ) / self::$base; // and divide integer (minus just encoded char) by the base
}
return strrev( $string ); // As we started by the unit of our base ( $base ^ 0 ), we have to reverse the string
}
/**
* Decode a string to an integer according to the defined alphabet
*
* @param string : String to be decoded
* @return integer (or false if failed)
*/
static public function decode( $string )
{
$string = (string)$string; // be sure to have a string;
// check if our string only have chars that are in the alphabet
if ( strcspn( $string, self::$alphabet ) )
{
return false; // or throw new Exception( "($string) is not a string or contains characters that are not in alphabet" );
}
$integer = 0; // our integer to find
$unit = 1; // we start by $base^0
// foreach chars, starting at the end
for( $i = strlen( $string ) -1; $i >= 0; $i -- )
{
$pos = strpos( self::$alphabet, $string[$i] ); // we find it's position in alphabet
$integer += $pos * $unit; // its our number to add, multiplied by the current unit
$unit = $unit * self::$base; // and go to next unit in our base
}
return $integer;
}
}