Report abuse

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