diff -r 000000000000 -r 4eba9c11703f web/Zend/Measure/Number.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/Zend/Measure/Number.php Mon Dec 13 18:29:26 2010 +0100 @@ -0,0 +1,420 @@ + array(2, '⑵'), + 'TERNARY' => array(3, '⑶'), + 'QUATERNARY' => array(4, '⑷'), + 'QUINARY' => array(5, '⑸'), + 'SENARY' => array(6, '⑹'), + 'SEPTENARY' => array(7, '⑺'), + 'OCTAL' => array(8, '⑻'), + 'NONARY' => array(9, '⑼'), + 'DECIMAL' => array(10, '⑽'), + 'DUODECIMAL' => array(12, '⑿'), + 'HEXADECIMAL' => array(16, '⒃'), + 'ROMAN' => array(99, ''), + 'STANDARD' => 'DECIMAL' + ); + + /** + * Definition of all roman signs + * + * @var array $_roman + */ + private static $_roman = array( + 'I' => 1, + 'A' => 4, + 'V' => 5, + 'B' => 9, + 'X' => 10, + 'E' => 40, + 'L' => 50, + 'F' => 90, + 'C' => 100, + 'G' => 400, + 'D' => 500, + 'H' => 900, + 'M' => 1000, + 'J' => 4000, + 'P' => 5000, + 'K' => 9000, + 'Q' => 10000, + 'N' => 40000, + 'R' => 50000, + 'W' => 90000, + 'S' => 100000, + 'Y' => 400000, + 'T' => 500000, + 'Z' => 900000, + 'U' => 1000000 + ); + + /** + * Convertion table for roman signs + * + * @var array $_romanconvert + */ + private static $_romanconvert = array( + '/_V/' => '/P/', + '/_X/' => '/Q/', + '/_L/' => '/R/', + '/_C/' => '/S/', + '/_D/' => '/T/', + '/_M/' => '/U/', + '/IV/' => '/A/', + '/IX/' => '/B/', + '/XL/' => '/E/', + '/XC/' => '/F/', + '/CD/' => '/G/', + '/CM/' => '/H/', + '/M_V/'=> '/J/', + '/MQ/' => '/K/', + '/QR/' => '/N/', + '/QS/' => '/W/', + '/ST/' => '/Y/', + '/SU/' => '/Z/' + ); + + /** + * Zend_Measure_Abstract is an abstract class for the different measurement types + * + * @param integer $value Value + * @param string $type (Optional) A Zend_Measure_Number Type + * @param string|Zend_Locale $locale (Optional) A Zend_Locale + * @throws Zend_Measure_Exception When language is unknown + * @throws Zend_Measure_Exception When type is unknown + */ + public function __construct($value, $type, $locale = null) + { + if (($type !== null) and (Zend_Locale::isLocale($type, null, false))) { + $locale = $type; + $type = null; + } + + if ($locale === null) { + $locale = new Zend_Locale(); + } + + if (!Zend_Locale::isLocale($locale, true, false)) { + if (!Zend_Locale::isLocale($locale, true, false)) { + require_once 'Zend/Measure/Exception.php'; + throw new Zend_Measure_Exception("Language (" . (string) $locale . ") is unknown"); + } + + $locale = new Zend_Locale($locale); + } + + $this->_locale = (string) $locale; + + if ($type === null) { + $type = $this->_units['STANDARD']; + } + + if (isset($this->_units[$type]) === false) { + require_once 'Zend/Measure/Exception.php'; + throw new Zend_Measure_Exception("Type ($type) is unknown"); + } + + $this->setValue($value, $type, $this->_locale); + } + + /** + * Set a new value + * + * @param integer $value Value + * @param string $type (Optional) A Zend_Measure_Number Type + * @param string|Zend_Locale $locale (Optional) A Zend_Locale Type + * @throws Zend_Measure_Exception + */ + public function setValue($value, $type = null, $locale = null) + { + if (empty($locale)) { + $locale = $this->_locale; + } + + if (empty($this->_units[$type])) { + require_once 'Zend/Measure/Exception.php'; + throw new Zend_Measure_Exception('unknown type of number:' . $type); + } + + switch($type) { + case 'BINARY': + preg_match('/[01]+/', $value, $ergebnis); + $value = $ergebnis[0]; + break; + + case 'TERNARY': + preg_match('/[012]+/', $value, $ergebnis); + $value = $ergebnis[0]; + break; + + case 'QUATERNARY': + preg_match('/[0123]+/', $value, $ergebnis); + $value = $ergebnis[0]; + break; + + case 'QUINARY': + preg_match('/[01234]+/', $value, $ergebnis); + $value = $ergebnis[0]; + break; + + case 'SENARY': + preg_match('/[012345]+/', $value, $ergebnis); + $value = $ergebnis[0]; + break; + + case 'SEPTENARY': + preg_match('/[0123456]+/', $value, $ergebnis); + $value = $ergebnis[0]; + break; + + case 'OCTAL': + preg_match('/[01234567]+/', $value, $ergebnis); + $value = $ergebnis[0]; + break; + + case 'NONARY': + preg_match('/[012345678]+/', $value, $ergebnis); + $value = $ergebnis[0]; + break; + + case 'DUODECIMAL': + preg_match('/[0123456789AB]+/', strtoupper($value), $ergebnis); + $value = $ergebnis[0]; + break; + + case 'HEXADECIMAL': + preg_match('/[0123456789ABCDEF]+/', strtoupper($value), $ergebnis); + $value = $ergebnis[0]; + break; + + case 'ROMAN': + preg_match('/[IVXLCDM_]+/', strtoupper($value), $ergebnis); + $value = $ergebnis[0]; + break; + + default: + try { + $value = Zend_Locale_Format::getInteger($value, array('locale' => $locale)); + } catch (Exception $e) { + require_once 'Zend/Measure/Exception.php'; + throw new Zend_Measure_Exception($e->getMessage(), $e->getCode(), $e); + } + if (call_user_func(Zend_Locale_Math::$comp, $value, 0) < 0) { + $value = call_user_func(Zend_Locale_Math::$sqrt, call_user_func(Zend_Locale_Math::$pow, $value, 2)); + } + break; + } + + $this->_value = $value; + $this->_type = $type; + } + + /** + * Convert input to decimal value string + * + * @param integer $input Input string + * @param string $type Type from which to convert to decimal + * @return string + */ + private function _toDecimal($input, $type) + { + $value = ''; + // Convert base xx values + if ($this->_units[$type][0] <= 16) { + $split = str_split($input); + $length = strlen($input); + for ($x = 0; $x < $length; ++$x) { + $split[$x] = hexdec($split[$x]); + $value = call_user_func(Zend_Locale_Math::$add, $value, + call_user_func(Zend_Locale_Math::$mul, $split[$x], + call_user_func(Zend_Locale_Math::$pow, $this->_units[$type][0], ($length - $x - 1)))); + } + } + + // Convert roman numbers + if ($type === 'ROMAN') { + $input = strtoupper($input); + $input = preg_replace(array_keys(self::$_romanconvert), array_values(self::$_romanconvert), $input); + + $split = preg_split('//', strrev($input), -1, PREG_SPLIT_NO_EMPTY); + + for ($x =0; $x < sizeof($split); $x++) { + if ($split[$x] == '/') { + continue; + } + + $num = self::$_roman[$split[$x]]; + if (($x > 0 and ($split[$x-1] != '/') and ($num < self::$_roman[$split[$x-1]]))) { + $num -= $num; + } + + $value += $num; + } + + str_replace('/', '', $value); + } + + return $value; + } + + /** + * Convert input to type value string + * + * @param integer $value Input string + * @param string $type Type to convert to + * @return string + * @throws Zend_Measure_Exception When more than 200 digits are calculated + */ + private function _fromDecimal($value, $type) + { + $tempvalue = $value; + if ($this->_units[$type][0] <= 16) { + $newvalue = ''; + $count = 200; + $base = $this->_units[$type][0]; + + while (call_user_func(Zend_Locale_Math::$comp, $value, 0, 25) <> 0) { + $target = call_user_func(Zend_Locale_Math::$mod, $value, $base); + + $newvalue = strtoupper(dechex($target)) . $newvalue; + + $value = call_user_func(Zend_Locale_Math::$sub, $value, $target, 0); + $value = call_user_func(Zend_Locale_Math::$div, $value, $base, 0); + + --$count; + if ($count === 0) { + require_once 'Zend/Measure/Exception.php'; + throw new Zend_Measure_Exception("Your value '$tempvalue' cannot be processed because it extends 200 digits"); + } + } + + if ($newvalue === '') { + $newvalue = '0'; + } + } + + if ($type === 'ROMAN') { + $i = 0; + $newvalue = ''; + $romanval = array_values(array_reverse(self::$_roman)); + $romankey = array_keys(array_reverse(self::$_roman)); + $count = 200; + while (call_user_func(Zend_Locale_Math::$comp, $value, 0, 25) <> 0) { + while ($value >= $romanval[$i]) { + $value -= $romanval[$i]; + $newvalue .= $romankey[$i]; + + if ($value < 1) { + break; + } + + --$count; + if ($count === 0) { + require_once 'Zend/Measure/Exception.php'; + throw new Zend_Measure_Exception("Your value '$tempvalue' cannot be processed because it extends 200 digits"); + } + } + + $i++; + } + + $newvalue = str_replace('/', '', preg_replace(array_values(self::$_romanconvert), array_keys(self::$_romanconvert), $newvalue)); + } + + return $newvalue; + } + + /** + * Set a new type, and convert the value + * + * @param string $type New type to set + * @throws Zend_Measure_Exception When a unknown type is given + * @return void + */ + public function setType($type) + { + if (empty($this->_units[$type]) === true) { + require_once 'Zend/Measure/Exception.php'; + throw new Zend_Measure_Exception('Unknown type of number:' . $type); + } + + $value = $this->_toDecimal($this->getValue(-1), $this->getType(-1)); + $value = $this->_fromDecimal($value, $type); + + $this->_value = $value; + $this->_type = $type; + } + + /** + * Alias function for setType returning the converted unit + * Default is 0 as this class only handles numbers without precision + * + * @param string $type Type to convert to + * @param integer $round (Optional) Precision to add, will always be 0 + * @return string + */ + public function convertTo($type, $round = 0, $locale = null) + { + $this->setType($type); + return $this->toString($round, $locale); + } +}