I18N_UnicodeString
[ class tree: I18N_UnicodeString ] [ index: I18N_UnicodeString ] [ all elements ]

Source for file UnicodeString.php

Documentation is available at UnicodeString.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. /**
  4. * Provides a method of storing and manipulating multibyte strings in PHP.
  5. *
  6. * PHP versions 5
  7. *
  8. * LICENSE: Copyright 2004-2006 John Downey. All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * o Redistributions of source code must retain the above copyright notice, this
  14. *   list of conditions and the following disclaimer.
  15. * o Redistributions in binary form must reproduce the above copyright notice,
  16. *   this list of conditions and the following disclaimer in the documentation
  17. *   and/or other materials provided with the distribution.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT "AS IS" AND ANY EXPRESS OR
  20. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  22. * EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  23. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  26. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  27. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  28. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * The views and conclusions contained in the software and documentation are
  31. * those of the authors and should not be interpreted as representing official
  32. * policies, either expressed or implied, of The PEAR Group.
  33. *
  34. @category  Internationalization
  35. @package   I18N_UnicodeString
  36. @author    John Downey <jdowney@gmail.com>
  37. @copyright 2004-2006 John Downey
  38. @license   http://www.freebsd.org/copyright/freebsd-license.html 2 Clause BSD License
  39. @version   CVS: $Id$
  40. @link      http://pear.php.net/packages/I18N_UnicodeString
  41. @filesource
  42. */
  43.  
  44. require_once 'I18N/UnicodeString/Exception.php';
  45.  
  46. /**
  47. * Class provides a way to use and manipulate multibyte strings in PHP
  48. *
  49. @category Internationalization
  50. @package  I18N_UnicodeString
  51. @author   John Downey <jdowney@gmail.com>
  52. @license  http://www.freebsd.org/copyright/freebsd-license.html 2 Clause BSD License
  53. @version  Release: @package_version@
  54. @link     http://pear.php.net/packages/I18N_UnicodeString
  55. @access   public
  56. */
  57. {
  58.     /**
  59.      * The internal representation of the string as an array of numbers.
  60.      * @access private
  61.      * @var    array $_unicode 
  62.      */
  63.     var $_unicode = array();
  64.  
  65.     /**
  66.      * Converts an entire array of strings to Unicode capable strings.
  67.      *
  68.      * Useful for converting a GET/POST of all its Unicode values into a
  69.      * workable and easily changed format. Takes an optional second
  70.      * parameter similer to that of {@link setString()}.
  71.      *
  72.      * @param array  $array    An array of PHP variables.
  73.      * @param string $encoding The encoding the string values are in.
  74.      *
  75.      * @return array The array with all of its string values converted to
  76.      *                I18N_Unicode objects.
  77.      * @static
  78.      * @access public
  79.      * @see    setString()
  80.      */
  81.     function convertArray($array$encoding 'HTML')
  82.     {
  83.         foreach ($array as $key => $value{
  84.             if (is_string($value)) {
  85.                 $array[$key= new I18N_UnicodeString($value$encoding);
  86.             }
  87.         }
  88.  
  89.         return $array;
  90.     }
  91.  
  92.     /**
  93.      * The constructor of the class string which can receive a new string in a
  94.      * number of formats.
  95.      *
  96.      * @param mixed  $value    A variable containing the Unicode string in one of
  97.      *                          various encodings.
  98.      * @param string $encoding The encoding that the string is in.
  99.      *
  100.      * @access public
  101.      * @see    setString()
  102.      */
  103.     function __construct($value ''$encoding 'UTF-8')
  104.     {
  105.         $this->setString($value$encoding);
  106.     }
  107.  
  108.     /**
  109.      * Set the string to a value passed in one of many encodings.
  110.      *
  111.      * You may pass the encoding as an optional second parameter which defaults
  112.      * to UTF-8 encoding. Possible encodings are:
  113.      *
  114.      * o <i>ASCII</i> - when you pass a normal 7 bit ASCII string
  115.      * o <i>UTF-8</i> - when you pass a UTF-8 encoded string
  116.      * o <i>HTML</i> - when you pass a string encoded with HTML entities, such
  117.      *   as the kind received from a GET/POST
  118.      * o <i>Unicode</i> or <i>UCS-4</i> - when passing an array of integer values representing
  119.      *   each character
  120.      *
  121.      * @param mixed  $value    A variable containing the Unicode string in one of
  122.      *                          various encodings.
  123.      * @param string $encoding The encoding that the string is in.
  124.      *
  125.      * @access public
  126.      * @return mixed Returns true on success or PEAR_Error otherwise.
  127.      */
  128.     function setString($value$encoding 'UTF-8')
  129.     {
  130.         switch(strtoupper($encoding)) {
  131.         case 'ASCII':
  132.         case 'UTF8':
  133.         case 'UTF-8':
  134.             $this->_unicode I18N_UnicodeString::utf8ToUnicode($value);
  135.             break;
  136.  
  137.         case 'HTML':
  138.             $this->_unicode $this->_stringFromHtml($value);
  139.             break;
  140.  
  141.         case 'UTF32':
  142.         case 'UTF-32':
  143.         case 'UCS4':
  144.         case 'UCS-4':
  145.         case 'UNICODE':
  146.             $this->_unicode $value;
  147.             break;
  148.  
  149.         default:
  150.             return I18N_UnicodeString::raiseError('Unrecognized encoding');
  151.         }
  152.  
  153.         if (strtolower(get_class($this->_unicode)) == 'pear_error'{
  154.             return $this->_unicode;
  155.         }
  156.  
  157.         return true;
  158.     }
  159.  
  160.     /**
  161.      * Converts a string encoded with HTML entities into our internal
  162.      * representation of an array of integers.
  163.      *
  164.      * @param string $string A string containing Unicode values encoded as HTML
  165.      *                         entities.
  166.      *
  167.      * @access private
  168.      * @return array The array of Unicode values.
  169.      */
  170.     function _stringFromHtml($string '')
  171.     {
  172.         $parts   explode('&#'$string);
  173.         $unicode = array();
  174.         foreach ($parts as $part{
  175.             $text strstr($part';');
  176.  
  177.             if (!empty($text)) {
  178.                 $value substr($part0strpos($part';'));
  179.  
  180.                 /* Suggested by Jonathan Yavner to allow HTML to also be in
  181.                    the form of &#xNNNN where NNNN is the hexidecimal of a
  182.                    Unicode character */
  183.                 if (ord($value[0]== 120{
  184.                     $unicode[intval(substr($value1)16);
  185.                 else {
  186.                     $unicode[intval($value);
  187.                 }
  188.  
  189.                 $text substr($text1);
  190.  
  191.                 for ($i = 0$max strlen($text)$i $max$i++{
  192.                     $unicode[ord($text[$i]);
  193.                 }
  194.             else {
  195.                 for ($i = 0$max strlen($part)$i $max$i++{
  196.                     $unicode[ord($part[$i]);
  197.                 }
  198.             }
  199.         }
  200.  
  201.         return $unicode;
  202.     }
  203.  
  204.     /**
  205.      * Converts a UTF-8 string into our representation of an array of integers.
  206.      *
  207.      * Method was made static by suggestion of Lukas Feiler (#7429)
  208.      *
  209.      * @param string $string A string containing Unicode values encoded in UTF-8
  210.      *
  211.      * @static
  212.      * @access public
  213.      * @return array The array of Unicode values.
  214.      */
  215.     function utf8ToUnicode($string '')
  216.     {
  217.         $unicode = array();
  218.         $values  = array();
  219.         $search  = 1;
  220.  
  221.         for ($count = 0$length strlen($string)$count $length$count++{
  222.             $value ord($string[$count]);
  223.  
  224.             if ($value < 128{
  225.                 // if the value is an ASCII char then just go ahead and add it on
  226.                 $unicode[$value;
  227.             else {
  228.                 // if not then we need to know how many more bytes make up this character
  229.                 if (count($values== 0{
  230.                     if ($value >> 5 == 6{
  231.                         $values[($value - 192<< 6;
  232.                         $search   = 2;
  233.                     elseif ($value >> 4 == 14{
  234.                         $values[($value - 224<< 12;
  235.                         $search   = 3;
  236.                     elseif ($value >> 3 == 30{
  237.                         $values[($value - 240<< 18;
  238.                         $search   = 4;
  239.                     elseif ($value >> 2 == 62{
  240.                         $values[($value - 248<< 24;
  241.                         $search   = 5;
  242.                     elseif ($value >> 1 == 126{
  243.                         $values[($value - 252<< 30;
  244.                         $search   = 6;
  245.                     else {
  246.                         return I18N_UnicodeString::raiseError('Malformed UTF-8 string');
  247.                     }
  248.                 else {
  249.                     if ($value >> 6 == 2{
  250.                         $values[$value - 128;
  251.                     else {
  252.                         return I18N_UnicodeString::raiseError('Malformed UTF-8 string');
  253.                     }
  254.  
  255.                     if (count($values== $search{
  256.                         // if we have all of our bytes then go ahead an encode it in unicode
  257.                         $value $values[0];
  258.                         for ($i = 1; $i $search$i++{
  259.                             $value += ($values[$i<< ((($search $i- 1* 6));
  260.                         }
  261.  
  262.                         $unicode[$value;
  263.  
  264.                         $values = array();
  265.                         $search = 1;
  266.                     }
  267.                 }
  268.             }
  269.         }
  270.  
  271.         return $unicode;
  272.     }
  273.  
  274.     /**
  275.      * Transforms a single unicode character represented by an integer to a UTF-8 string.
  276.      *
  277.      * Suggested by Lukas Feiler (#7429)
  278.      *
  279.      * @param integer $char A unicode character as an integer
  280.      *
  281.      * @static
  282.      * @access public
  283.      * @return string The unicode character converted to a UTF-8 string.
  284.      */
  285.     function unicodeCharToUtf8($char)
  286.     {
  287.         $string '';
  288.         if ($char < 128{
  289.             // its an ASCII char no encoding needed
  290.             $string .= chr($char);
  291.         elseif ($char < 1 << 11{
  292.             // its a 2 byte UTF-8 char
  293.             $string .= chr(192 + ($char >> 6));
  294.             $string .= chr(128 + ($char 63));
  295.         elseif ($char < 1 << 16{
  296.             // its a 3 byte UTF-8 char
  297.             $string .= chr(224 + ($char >> 12));
  298.             $string .= chr(128 + (($char >> 663));
  299.             $string .= chr(128 + ($char 63));
  300.         elseif ($char < 1 << 21{
  301.             // its a 4 byte UTF-8 char
  302.             $string .= chr(240 + ($char >> 18));
  303.             $string .= chr(128 + (($char >> 1263));
  304.             $string .= chr(128 + (($char >>  663));
  305.             $string .= chr(128 + ($char 63));
  306.         elseif ($char < 1 << 26{
  307.             // its a 5 byte UTF-8 char
  308.             $string .= chr(248 + ($char >> 24));
  309.             $string .= chr(128 + (($char >> 1863));
  310.             $string .= chr(128 + (($char >> 1263));
  311.             $string .= chr(128 + (($char >> 663));
  312.             $string .= chr(128 + ($char 63));
  313.         else {
  314.             // its a 6 byte UTF-8 char
  315.             $string .= chr(252 + ($char >> 30));
  316.             $string .= chr(128 + (($char >> 2463));
  317.             $string .= chr(128 + (($char >> 1863));
  318.             $string .= chr(128 + (($char >> 1263));
  319.             $string .= chr(128 + (($char >> 663));
  320.             $string .= chr(128 + ($char 63));
  321.         }
  322.  
  323.         return $string;
  324.     }
  325.  
  326.     /**
  327.      * Retrieves the string and returns it as a UTF-8 encoded string.
  328.      *
  329.      * @access public
  330.      * @return string A string with the Unicode values encoded in UTF-8.
  331.      */
  332.     function toUtf8String()
  333.     {
  334.         $string '';
  335.  
  336.         foreach ($this->_unicode as $char{
  337.             $string .= $this->unicodeCharToUtf8($char);
  338.         }
  339.  
  340.         return $string;
  341.     }
  342.  
  343.     /**
  344.      * Retrieves the string and returns it as a string encoded with HTML
  345.      * entities.
  346.      *
  347.      * @access public
  348.      * @return string A string with the Unicode values encoded as HTML entities.
  349.      */
  350.     function toHtmlEntitiesString()
  351.     {
  352.         $string '';
  353.  
  354.         foreach ($this->_unicode as $char{
  355.             if ($char > 127{
  356.                 $string .= '&#' $char ';';
  357.             else {
  358.                 $string .= chr($char);
  359.             }
  360.         }
  361.  
  362.         return $string;
  363.     }
  364.  
  365.     /**
  366.      * Retrieve the length of the string in characters.
  367.      *
  368.      * @access public
  369.      * @return integer The length of the string.
  370.      */
  371.     function length()
  372.     {
  373.         return count($this->_unicode);
  374.     }
  375.  
  376.     /**
  377.      * Works exactly like PHP's substr function only it works on Unicode
  378.      * strings.
  379.      *
  380.      * @param integer $begin  The beginning of the substring.
  381.      * @param integer $length The length to read. Defaults to the rest of the
  382.      *                          string.
  383.      *
  384.      * @access public
  385.      * @return I18N_UnicodeString A new I18N_UnicodeString class containing the
  386.      *                             substring or a PEAR_Error if an error is
  387.      *                             thrown.
  388.      */
  389.     function subString($begin$length = null)
  390.     {
  391.         $unicode = array();
  392.  
  393.         if (is_null($length)) {
  394.             $length $this->length($begin;
  395.         }
  396.  
  397.         if (($begin $length$this->length()) {
  398.             return I18N_UnicodeString::raiseError('Cannot read past end of string.');
  399.         }
  400.  
  401.         if ($begin $this->length()) {
  402.             return I18N_UnicodeString::raiseError('Beginning extends past end of string.');
  403.         }
  404.  
  405.         for ($i $begin$max_length ($begin $length)$i $max_length$i++{
  406.             array_push($unicode$this->_unicode[$i]);
  407.         }
  408.  
  409.         return new I18N_UnicodeString($unicode'Unicode');
  410.     }
  411.  
  412.     /**
  413.      * Works like PHP's substr_replace function.
  414.      *
  415.      * @param I18N_UnicodeString &$find    The string to replaced
  416.      * @param I18N_UnicodeString &$replace The string to replace $find with
  417.      * @param integer            $start    The position in the string to start replacing at
  418.      * @param integer            $length   The length from the starting to position to stop
  419.      *                                       replacing at
  420.      *
  421.      * @access public
  422.      * @return I18N_UnicodeString The current string with all $find replaced by
  423.      *                             $replace
  424.      * @see    stringReplace()
  425.      */
  426.     function subStringReplace($find$replace$start$length = null)
  427.     {
  428.         if (is_null($length)) {
  429.             $length $this->length($start;
  430.         }
  431.  
  432.         $begin  $this->subString(0$start);
  433.         $string $this->subString($start$length);
  434.         if (!method_exists($string'stringReplace')) {
  435.             // $string is a PEAR_Error, return it
  436.             return $string;
  437.         else {
  438.             $string $string->stringReplace($find$replace);
  439.             $after  $this->subString($start $length);
  440.  
  441.             $data array_merge($begin->_unicode$string->_unicode$after->_unicode);
  442.             return new I18N_UnicodeString($data'Unicode');
  443.         }
  444.     }
  445.  
  446.     /**
  447.      * Works like PHP's str_replace function.
  448.      *
  449.      * @param I18N_UnicodeString &$find    The string to replaced
  450.      * @param I18N_UnicodeString &$replace The string to replace $find with
  451.      *
  452.      * @access public
  453.      * @return I18N_UnicodeString The current string with all $find replaced by
  454.      *                             $replace
  455.      * @see    subStringReplace()
  456.      */
  457.     function stringReplace($find$replace)
  458.     {
  459.         $haystack    = new I18N_UnicodeString($this->_unicode'Unicode');
  460.         $return        = new I18N_UnicodeString(array()'Unicode');
  461.  
  462.         while ($haystack->strStr($find!== false{
  463.             $after      $haystack->strStr($find);
  464.             $begin      $haystack->subString(0$haystack->length($after->length());
  465.             $haystack   $after->subString($find->length());
  466.  
  467.             $return     $return->append($begin)
  468.                                  ->append($replace)
  469.                                  ->append($after->subString(0$find->length()));
  470.          }
  471.  
  472.         return $return->append($haystack);
  473.     }
  474.  
  475.     /**
  476.      * Works like PHP's strstr function by returning the string from $find on.
  477.      *
  478.      * @param I18N_UnicodeString &$find The string to found
  479.      *
  480.      * @access public
  481.      * @return I18N_UnicodeString The current string from $find on to the end
  482.      */
  483.     function strStr($find)
  484.     {
  485.         $found = false;
  486.         $after $find->_unicode;
  487.  
  488.         for ($i = 0$length $this->length()$i $length$i++{
  489.             if ($found{
  490.                 $after[$this->_unicode[$i];
  491.             else {
  492.                 if ($this->_unicode[$i== $find->_unicode[0]{
  493.                     if ($i $find->length($length{
  494.                         break;
  495.                     }
  496.  
  497.                     $found = true;
  498.                     for ($c = 1$max $find->length()$c $max$c++{
  499.                         if ($this->_unicode[++$i!= $find->_unicode[$c]{
  500.                             $found = false;
  501.                             break;
  502.                         }
  503.                     }
  504.                 }
  505.             }
  506.         }
  507.  
  508.         if ($found{
  509.             return new I18N_UnicodeString($after'Unicode');
  510.         else {
  511.             return false;
  512.         }
  513.     }
  514.  
  515.     /**
  516.      * Returns the position of a character much like PHP's strpos function.
  517.      *
  518.      * @param mixed $char A Unicode char represented as either an integer or a
  519.      *                      UTF-8 char.
  520.      *
  521.      * @access public
  522.      * @return integer The location of the character in the string.
  523.      */
  524.     function indexOf($char)
  525.     {
  526.         if (!is_int($char)) {
  527.             if (strlen($char> 1{
  528.                 $char array_shift(I18N_UnicodeString::utf8ToUnicode($char));
  529.             else {
  530.                 $char ord($char);
  531.             }
  532.         }
  533.  
  534.         for ($i = 0$length $this->length()$i $length$i++{
  535.             if ($this->_unicode[$i== $char{
  536.                 return $i;
  537.             }
  538.         }
  539.  
  540.         return -1;
  541.     }
  542.  
  543.     /**
  544.      * Returns the last position of a character much like PHP's strrpos function.
  545.      *
  546.      * @param mixed $char A Unicode char represented as either an integer or a
  547.      *                      UTF-8 char.
  548.      *
  549.      * @access public
  550.      * @return integer The last location of the character in the string.
  551.      */
  552.     function lastIndexOf($char)
  553.     {
  554.         if (!is_int($char)) {
  555.             if (strlen($char> 1{
  556.                 $char array_shift($this->utf8ToUnicode($char));
  557.             else {
  558.                 $char ord($char);
  559.             }
  560.         }
  561.  
  562.         for ($i $this->length(- 1; $i >= 0; $i--{
  563.             if ($this->_unicode[$i== $char{
  564.                 return $i;
  565.             }
  566.         }
  567.  
  568.         return -1;
  569.     }
  570.  
  571.     /**
  572.      * Determines if two Unicode strings are equal
  573.      *
  574.      * @param I18N_UnicodeString &$unicode The string to compare to.
  575.      *
  576.      * @access public
  577.      * @return boolean True if they are equal, false otherwise.
  578.      */
  579.     function equals($unicode)
  580.     {
  581.         if ($this->length(!= $unicode->length()) {
  582.             // if they arn't even the same length no need to even check
  583.             return false;
  584.         }
  585.  
  586.         return ($this->_unicode == $unicode->_unicode);
  587.     }
  588.  
  589.     /**
  590.      * Appends a given Unicode string to the end of the current one.
  591.      *
  592.      * @param I18N_UnicodeString &$unicode The string to append.
  593.      *
  594.      * @access public
  595.      * @return I18N_UnicodeString The new string created from the appension.
  596.      */
  597.     function append($unicode)
  598.     {
  599.         $data array_merge($this->_unicode$unicode->_unicode);
  600.         return new I18N_UnicodeString($data'Unicode');
  601.     }
  602.  
  603.     /**
  604.      * Used to raise a PEAR_Error.
  605.      *
  606.      * Hopefully this method is never called, but when it is it will include the
  607.      * PEAR class and return a new PEAR_Error.
  608.      *
  609.      * @param string $message The error message to raise.
  610.      *
  611.      * @static
  612.      * @access public
  613.      * @throws I18N_UnicodeString_Exception
  614.      */
  615.     function raiseError($message)
  616.     {
  617.         throw new I18N_UnicodeString_Exception($message);
  618.     }
  619. }
  620. ?>

Documentation generated on Mon, 11 Mar 2019 15:47:55 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.