]> CyberLeo.Net >> Repos - Github/YOURLS.git/blob - includes/functions-baseconvert.php
Initial commit (importing from http://svn.planetozh.com/ozhin)
[Github/YOURLS.git] / includes / functions-baseconvert.php
1 <?php\r
2 /*\r
3  * PHP Number Base Conversion Functions\r
4  * Version 1.0 - February 2004\r
5  * Version 2.0 - January 2005 - converted to using bcmath\r
6  * Version 2.1 - September 2005 - added decimal point conversion ability\r
7  * (c) 2004,2005 Paul Gregg <pgregg@pgregg.com>\r
8  * http://www.pgregg.com\r
9  *\r
10  * Function: Arbitrary Number Base conversion from base 2 - 62\r
11  * This file should be included by other php scripts\r
12  * For normal base 2 - 36 conversion use the built in base_convert function\r
13  *\r
14  * Open Source Code:     If you use this code on your site for public\r
15  * access (i.e. on the Internet) then you must attribute the author and\r
16  * source web site: http://www.pgregg.com/projects/\r
17  * You must also make this original source code available for download\r
18  * unmodified or provide a link to the source.  Additionally you must provide\r
19  * the source to any modified or translated versions or derivatives.\r
20  *\r
21  */\r
22  \r
23 /* Ozh' note: this script:\r
24  * - allows handling large integers on 32bits machines, which base_convert() does not\r
25  * - allows encoding upt to base 64 (base_convert() is limited to 36)\r
26  * - needs PHP extension BCCOMP (http://www.php.net/bccomp)\r
27  */\r
28  \r
29 function yourls_dec2base($iNum, $iBase, $iScale=0) { // cope with base 2..62\r
30         $LDEBUG = FALSE;\r
31         $sChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\r
32         $sResult = ''; // Store the result\r
33 \r
34         // special case for Base64 encoding\r
35         if ($iBase == 64)\r
36          $sChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\r
37 \r
38         $sNum = is_integer($iNum) ? "$iNum" : (string)$iNum;\r
39         $iBase = yourls_intval($iBase); // incase it is a string or some weird decimal\r
40 \r
41         // Check to see if we are an integer or real number\r
42         if (strpos($sNum, '.') !== FALSE) {\r
43                 list ($sNum, $sReal) = explode('.', $sNum, 2);\r
44                 $sReal = '0.' . $sReal;\r
45         } else\r
46                 $sReal = '0';\r
47 \r
48         while (bccomp($sNum, 0, $iScale) != 0) { // still data to process\r
49                 $sRem = bcmod($sNum, $iBase); // calc the remainder\r
50                 $sNum = bcdiv( bcsub($sNum, $sRem, $iScale), $iBase, $iScale );\r
51                 $sResult = $sChars[$sRem] . $sResult;\r
52         }\r
53         if ($sReal != '0') {\r
54                 $sResult .= '.';\r
55                 $fraciScale = $iScale;\r
56                 while($fraciScale-- && bccomp($sReal, 0, $iScale) != 0) { // still data to process\r
57                         if ($LDEBUG) print "<br> -> $sReal * $iBase = ";\r
58                         $sReal = bcmul($sReal, $iBase, $iScale); // multiple the float part with the base\r
59                         if ($LDEBUG) print "$sReal      => ";\r
60                         $sFrac = 0;\r
61                         if (bccomp($sReal ,1, $iScale) > -1)\r
62                                 list($sFrac, $dummy) = explode('.', $sReal, 2); // get the yourls_intval\r
63                         if ($LDEBUG) print "$sFrac\n";\r
64                         $sResult .= $sChars[$sFrac];\r
65                         $sReal = bcsub($sReal, $sFrac, $iScale);\r
66                 }\r
67         }\r
68 \r
69         return $sResult;\r
70 }\r
71 \r
72 \r
73 function yourls_base2dec($sNum, $iBase=0, $iScale=0) {\r
74         $sChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\r
75         $sResult = '';\r
76 \r
77         $iBase = yourls_intval($iBase); // incase it is a string or some weird decimal\r
78 \r
79         // special case for Base64 encoding\r
80         if ($iBase == 64)\r
81          $sChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\r
82 \r
83         // clean up the input string if it uses particular input formats\r
84         switch ($iBase) {\r
85                 case 16: // remove 0x from start of string\r
86                         if (strtolower(substr($sNum, 0, 2)) == '0x') $sNum = substr($sNum, 2);\r
87                         break;\r
88                 case 8: // remove the 0 from the start if it exists - not really required\r
89                         if (strpos($sNum, '0')===0) $sNum = substr($sNum, 1);\r
90                         break;\r
91                 case 2: // remove an 0b from the start if it exists\r
92                         if (strtolower(substr($sNum, 0, 2)) == '0b') $sNum = substr($sNum, 2);\r
93                         break;\r
94                 case 64: // remove padding chars: =\r
95                         $sNum = str_replace('=', '', $sNum);\r
96                         break;\r
97                 default: // Look for numbers in the format base#number,\r
98                                                  // if so split it up and use the base from it\r
99                         if (strpos($sNum, '#') !== false) {\r
100                                 list ($sBase, $sNum) = explode('#', $sNum, 2);\r
101                                 $iBase = yourls_intval($sBase); // take the new base\r
102                         }\r
103                         if ($iBase == 0) {\r
104                                 print("yourls_base2dec called without a base value and not in base#number format");\r
105                                 return '';\r
106                         }\r
107                         break;\r
108         }\r
109 \r
110         // Convert string to upper case since base36 or less is case insensitive\r
111         if ($iBase < 37) $sNum = strtoupper($sNum);\r
112 \r
113         // Check to see if we are an integer or real number\r
114         if (strpos($sNum, '.') !== FALSE) {\r
115                 list ($sNum, $sReal) = explode('.', $sNum, 2);\r
116                 $sReal = '0.' . $sReal;\r
117         } else\r
118                 $sReal = '0';\r
119 \r
120 \r
121         // By now we know we have a correct base and number\r
122         $iLen = strlen($sNum);\r
123         \r
124         // Now loop through each digit in the number\r
125         for ($i=$iLen-1; $i>=0; $i--) {\r
126                 $sChar = $sNum[$i]; // extract the last char from the number\r
127                 $iValue = strpos($sChars, $sChar); // get the decimal value\r
128                 if ($iValue > $iBase) {\r
129                         print("yourls_base2dec: $sNum is not a valid base $iBase number");\r
130                         return '';\r
131                 }\r
132                 // Now convert the value+position to decimal\r
133                 $sResult = bcadd($sResult, bcmul( $iValue, bcpow($iBase, ($iLen-$i-1))) );\r
134         }\r
135 \r
136         // Now append the real part\r
137         if (strcmp($sReal, '0') != 0) {\r
138                 $sReal = substr($sReal, 2); // Chop off the '0.' characters\r
139                 $iLen = strlen($sReal);\r
140                 for ($i=0; $i<$iLen; $i++) {\r
141                         $sChar = $sReal[$i]; // extract the first, second, third, etc char\r
142                         $iValue = strpos($sChars, $sChar); // get the decimal value\r
143                         if ($iValue > $iBase) {\r
144                                 print("yourls_base2dec: $sNum is not a valid base $iBase number");\r
145                                 return '';\r
146                         }\r
147                         $sResult = bcadd($sResult, bcdiv($iValue, bcpow($iBase, ($i+1)), $iScale), $iScale);\r
148                 }\r
149         }\r
150 \r
151         return $sResult;\r
152 }\r
153                 \r
154 function yourls_base2base($iNum, $iBase, $oBase, $iScale=0) {\r
155         if (!function_exists('bccomp'))\r
156                 return base_convert($iNum, $iBase, $oBase);\r
157 \r
158         if ($iBase != 10) $oNum = yourls_base2dec($iNum, $iBase, $iScale);\r
159                 else $oNum = $iNum;\r
160         $oNum = yourls_dec2base($oNum, $oBase, $iScale);\r
161                 return $oNum;\r
162 }\r
163 \r