--- /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 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Measure
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Number.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * Implement needed classes
+ */
+require_once 'Zend/Measure/Abstract.php';
+require_once 'Zend/Locale.php';
+
+/**
+ * Class for handling number conversions
+ *
+ * This class can only handle numbers without precision
+ *
+ * @category Zend
+ * @package Zend_Measure
+ * @subpackage Zend_Measure_Number
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Measure_Number extends Zend_Measure_Abstract
+{
+ const STANDARD = 'DECIMAL';
+
+ const BINARY = 'BINARY';
+ const TERNARY = 'TERNARY';
+ const QUATERNARY = 'QUATERNARY';
+ const QUINARY = 'QUINARY';
+ const SENARY = 'SENARY';
+ const SEPTENARY = 'SEPTENARY';
+ const OCTAL = 'OCTAL';
+ const NONARY = 'NONARY';
+ const DECIMAL = 'DECIMAL';
+ const DUODECIMAL = 'DUODECIMAL';
+ const HEXADECIMAL = 'HEXADECIMAL';
+ const ROMAN = 'ROMAN';
+
+ /**
+ * Calculations for all number units
+ *
+ * @var array
+ */
+ protected $_units = array(
+ 'BINARY' => 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);
+ }
+}