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

Source for file I18N_UnicodeString.php

Documentation is available at I18N_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 4 and 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. @filesource
  41. */
  42.  
  43. /**
  44. * Class provides a way to use and manipulate multibyte strings in PHP
  45. *
  46. @package I18N_UnicodeString
  47. @author  John Downey <jdowney@gmail.com>
  48. @access  public
  49. @version Release: @package_version@
  50. */
  51. {
  52.     /**
  53.     * The internal representation of the string as an array of numbers.
  54.     * @access private
  55.     * @var    array $_unicode 
  56.     */
  57.     var $_unicode = array();
  58.     
  59.     /**
  60.     * Converts an entire array of strings to Unicode capable strings.
  61.     *
  62.     * Useful for converting a GET/POST of all its Unicode values into a
  63.     * workable and easily changed format. Takes an optional second
  64.     * parameter similer to that of {@link setString()}.
  65.     *
  66.     * @static
  67.     * @access public
  68.     * @param  array $array An array of PHP variables.
  69.     * @param  string $encoding The encoding the string values are in.
  70.     * @return array The array with all of its string values converted to
  71.     *                I18N_Unicode objects.
  72.     * @see    setString()
  73.     */
  74.     function convertArray($array$encoding 'HTML'{
  75.         foreach($array as $key => $value{
  76.             if (is_string($value)) {
  77.                 $array[$key= new I18N_UnicodeString($value$encoding);
  78.             }
  79.         }
  80.         
  81.         return $array;
  82.     }
  83.     
  84.     /**
  85.     * The constructor of the class string which can receive a new string in a
  86.     * number of formats.
  87.     *
  88.     * @access public
  89.     * @param  mixed $value A variable containing the Unicode string in one of
  90.     *                       various encodings.
  91.     * @param  string $encoding The encoding that the string is in.
  92.     * @see    setString()
  93.     */
  94.     function I18N_UnicodeString($value ''$encoding 'UTF-8'{
  95.         $this->setString($value$encoding);
  96.     }
  97.     
  98.     /**
  99.     * Set the string to a value passed in one of many encodings.
  100.     *
  101.     * You may pass the encoding as an optional second parameter which defaults
  102.     * to UTF-8 encoding. Possible encodings are:
  103.     * 
  104.     * o <i>ASCII</i> - when you pass a normal 7 bit ASCII string
  105.     * o <i>UTF-8</i> - when you pass a UTF-8 encoded string
  106.     * o <i>HTML</i> - when you pass a string encoded with HTML entities, such
  107.     *   as the kind received from a GET/POST
  108.     * o <i>Unicode</i> or <i>UCS-4</i> - when passing an array of integer values representing
  109.     *   each character
  110.     *
  111.     * @access public
  112.     * @param  mixed $value A variable containing the Unicode string in one of
  113.     *                       various encodings.
  114.     * @param  string $encoding The encoding that the string is in.
  115.     * @return mixed Returns true on success or PEAR_Error otherwise.
  116.     */
  117.     function setString($value$encoding 'UTF-8'{
  118.            switch(strtoupper($encoding)) {
  119.             case 'ASCII':
  120.             case 'UTF8':
  121.             case 'UTF-8':
  122.                 $this->_unicode = self::utf8ToUnicode($value);
  123.                 break;
  124.  
  125.             case 'HTML':
  126.                 $this->_unicode $this->_stringFromHtml($value);
  127.                 break;
  128.  
  129.             case 'UTF32':
  130.             case 'UTF-32':
  131.             case 'UCS4':
  132.             case 'UCS-4':
  133.             case 'UNICODE':
  134.                 $this->_unicode $value;
  135.                 break;
  136.  
  137.             default:
  138.                 return self::raiseError('Unrecognized encoding');
  139.         }
  140.         
  141.         if (strtolower(get_class($this->_unicode)) == 'pear_error'{
  142.             return $this->_unicode;
  143.         }
  144.         
  145.         return true;
  146.     }
  147.     
  148.     /**
  149.     * Converts a string encoded with HTML entities into our internal
  150.     * representation of an array of integers.
  151.     *
  152.     * @access private
  153.     * @param  string $string A string containing Unicode values encoded as HTML
  154.     *                         entities.
  155.     * @return array The array of Unicode values.
  156.     */
  157.     function _stringFromHtml($string ''{
  158.         $parts   explode('&#'$string);
  159.         $unicode = array();
  160.         foreach($parts as $part{
  161.             $text strstr($part';');
  162.             
  163.             if (!empty($text)) {
  164.                 $value substr($part0strpos($part';'));
  165.  
  166.                 /* Suggested by Jonathan Yavner to allow HTML to also be in
  167.                    the form of &#xNNNN where NNNN is the hexidecimal of a
  168.                    Unicode character */
  169.                 if (ord($value[0]== 120{
  170.                     $unicode[intval(substr($value1)16);
  171.                 else {
  172.                     $unicode[intval($value);
  173.                 }
  174.  
  175.                 $text substr($text1);
  176.  
  177.                 for($i = 0$max strlen($text)$i $max$i++{
  178.                     $unicode[ord($text[$i]);
  179.                 }
  180.             else {
  181.                 for($i = 0$max strlen($part)$i $max$i++{
  182.                     $unicode[ord($part[$i]);
  183.                 }
  184.             }
  185.         }
  186.  
  187.         return $unicode;
  188.     }
  189.     
  190.     /**
  191.     * Converts a UTF-8 string into our representation of an array of integers.
  192.     *
  193.     * Method was made static by suggestion of Lukas Feiler (#7429)
  194.     *
  195.     * @static
  196.     * @access public
  197.     * @param  string $string A string containing Unicode values encoded in UTF-8
  198.     * @return array The array of Unicode values.
  199.     */
  200.     function utf8ToUnicode($string ''{
  201.         $unicode = array();
  202.         $values  = array();
  203.         $search  = 1;
  204.         
  205.         for($count = 0$length strlen($string)$count $length$count++{
  206.             $value ord($string[$count]);
  207.  
  208.             if ($value < 128{
  209.                 // if the value is an ASCII char then just go ahead and add it on
  210.                 $unicode[$value;
  211.             else {
  212.                 // if not then we need to know how many more bytes make up this character
  213.                 if (count($values== 0{
  214.                     if ($value >> 5 == 6{
  215.                         $values[($value - 192<< 6;
  216.                         $search   = 2;
  217.                     elseif ($value >> 4 == 14{
  218.                         $values[($value - 224<< 12;
  219.                         $search   = 3;
  220.                     elseif ($value >> 3 == 30{
  221.                         $values[($value - 240<< 18;
  222.                         $search   = 4;
  223.                     elseif ($value >> 2 == 62{
  224.                         $values[($value - 248<< 24;
  225.                         $search   = 5;
  226.                     elseif ($value >> 1 == 126{
  227.                         $values[($value - 252<< 30;
  228.                         $search   = 6;
  229.                     else {
  230.                         return self::raiseError('Malformed UTF-8 string');
  231.                     }
  232.                 else {
  233.                     if ($value >> 6 == 2{
  234.                         $values[$value - 128;
  235.                     else {
  236.                         return self::raiseError('Malformed UTF-8 string');
  237.                     }
  238.  
  239.                     if (count($values== $search{
  240.                         // if we have all of our bytes then go ahead an encode it in unicode
  241.                         $value $values[0];
  242.                         for($i = 1; $i $search$i++{
  243.                             $value += ($values[$i<< ((($search $i- 1* 6));
  244.                         }
  245.                         
  246.                         $unicode[$value;
  247.  
  248.                         $values = array();
  249.                         $search = 1;
  250.                     }
  251.                 }
  252.             }
  253.         }
  254.         
  255.         return $unicode;
  256.     }
  257.  
  258.     /**
  259.      * Transforms a single unicode character represented by an integer to a UTF-8 string.
  260.      *
  261.      * Suggested by Lukas Feiler (#7429)
  262.      *
  263.      * @static
  264.      * @access public
  265.      * @param  integer $int A unicode character as an integer
  266.      * @return string The unicode character converted to a UTF-8 string.
  267.      */
  268.     function unicodeCharToUtf8($char{
  269.         $string '';
  270.         if ($char < 128{
  271.             // its an ASCII char no encoding needed
  272.             $string .= chr($char);
  273.         elseif ($char < 1 << 11{
  274.             // its a 2 byte UTF-8 char
  275.             $string .= chr(192 + ($char >> 6));
  276.             $string .= chr(128 + ($char 63));
  277.         elseif ($char < 1 << 16{
  278.             // its a 3 byte UTF-8 char
  279.             $string .= chr(224 + ($char >> 12));
  280.             $string .= chr(128 + (($char >> 663));
  281.             $string .= chr(128 + ($char 63));
  282.         elseif ($char < 1 << 21{
  283.             // its a 4 byte UTF-8 char
  284.             $string .= chr(240 + ($char >> 18));
  285.             $string .= chr(128 + (($char >> 1263));
  286.             $string .= chr(128 + (($char >>  663));
  287.             $string .= chr(128 + ($char 63));
  288.         elseif ($char < 1 << 26{
  289.             // its a 5 byte UTF-8 char
  290.             $string .= chr(248 + ($char >> 24));
  291.             $string .= chr(128 + (($char >> 1863));
  292.             $string .= chr(128 + (($char >> 1263));
  293.             $string .= chr(128 + (($char >> 663));
  294.             $string .= chr(128 + ($char 63));
  295.         else {
  296.             // its a 6 byte UTF-8 char
  297.             $string .= chr(252 + ($char >> 30));
  298.             $string .= chr(128 + (($char >> 2463));
  299.             $string .= chr(128 + (($char >> 1863));
  300.             $string .= chr(128 + (($char >> 1263));
  301.             $string .= chr(128 + (($char >> 663));
  302.             $string .= chr(128 + ($char 63));
  303.         }
  304.  
  305.         return $string;
  306.     }
  307.     
  308.     /**
  309.     * Retrieves the string and returns it as a UTF-8 encoded string.
  310.     *
  311.     * @access public
  312.     * @return string A string with the Unicode values encoded in UTF-8.
  313.     */
  314.     function toUtf8String({
  315.         $string '';
  316.  
  317.         foreach($this->_unicode as $char{
  318.             $string .= $this->unicodeCharToUtf8($char);
  319.         }
  320.  
  321.         return $string;
  322.     }
  323.     
  324.     /**
  325.     * Retrieves the string and returns it as a string encoded with HTML
  326.     * entities.
  327.     *
  328.     * @access public
  329.     * @return string A string with the Unicode values encoded as HTML entities.
  330.     */
  331.     function toHtmlEntitiesString({
  332.         $string '';
  333.  
  334.         foreach($this->_unicode as $char{
  335.             if ($char > 127{
  336.                 $string .= '&#' $char ';';
  337.             else {
  338.                 $string .= chr($char);
  339.             }
  340.         }
  341.  
  342.         return $string;
  343.     }
  344.     
  345.     /**
  346.     * Retrieve the length of the string in characters.
  347.     *
  348.     * @access public
  349.     * @return integer The length of the string.
  350.     */
  351.     function length({
  352.         return count($this->_unicode);
  353.     }
  354.     
  355.     /**
  356.     * Works exactly like PHP's substr function only it works on Unicode
  357.     * strings.
  358.     *
  359.     * @access public
  360.     * @param  integer $begin The beginning of the substring.
  361.     * @param  integer $length The length to read. Defaults to the rest of the
  362.     *                          string.
  363.     * @return I18N_UnicodeString A new I18N_UnicodeString class containing the
  364.     *                             substring or a PEAR_Error if an error is
  365.     *                             thrown.
  366.     */
  367.     function subString($begin$length = null{
  368.         $unicode = array();
  369.         
  370.         if (is_null($length)) {
  371.             $length $this->length($begin;
  372.         }
  373.         
  374.         if (($begin $length$this->length()) {
  375.             return self::raiseError('Cannot read past end of string.');        
  376.         }
  377.         
  378.         if ($begin $this->length()) {
  379.             return self::raiseError('Beginning extends past end of string.');
  380.         }
  381.         
  382.         for($i $begin$max_length ($begin $length)$i $max_length$i++{
  383.             array_push($unicode$this->_unicode[$i]);
  384.         }
  385.  
  386.         return new I18N_UnicodeString($unicode'Unicode');
  387.     }
  388.     
  389.     /**
  390.     * Works like PHP's substr_replace function.
  391.     *
  392.     * @access public
  393.     * @param  I18N_UnicodeString $find The string to replaced
  394.     * @param  I18N_UnicodeString $replace The string to replace $find with
  395.     * @param  integer $start The position in the string to start replacing at
  396.     * @param  integer $length The length from the starting to position to stop
  397.     *                          replacing at
  398.     * @return I18N_UnicodeString The current string with all $find replaced by
  399.     *                             $replace
  400.     * @see    stringReplace()
  401.     */
  402.     function subStringReplace(&$find&$replace$start$length = null{
  403.         if (is_null($length)) {
  404.             $length $this->length($start;
  405.         }
  406.         
  407.         $begin  $this->subString(0$start);
  408.         $string $this->subString($start$length);
  409.         if (!method_exists($string'stringReplace')) {
  410.             // $string is a PEAR_Error, return it
  411.             return $string;
  412.         else {
  413.             $string $string->stringReplace($find$replace);
  414.             $after  $this->subString($start $length);
  415.             
  416.             return new I18N_UnicodeString(array_merge($begin->_unicode$string->_unicode$after->_unicode)'Unicode');
  417.         }
  418.     }
  419.     
  420.     /**
  421.     * Works like PHP's str_replace function.
  422.     *
  423.     * @access public
  424.     * @param  I18N_UnicodeString $find The string to replaced
  425.     * @param  I18N_UnicodeString $replace The string to replace $find with
  426.     * @return I18N_UnicodeString The current string with all $find replaced by
  427.     *                             $replace
  428.     * @see    subStringReplace()
  429.     */
  430.     function stringReplace(&$find&$replace{
  431.         $return = new I18N_UnicodeString($this->_unicode'Unicode');
  432.         
  433.         while($return->strStr($find!== false{
  434.             $after $return->strStr($find);
  435.             $begin $return->subString(0$return->length($after->length());
  436.             $after $after->subString($find->length());
  437.             
  438.             $return = new I18N_UnicodeString(array_merge($begin->_unicode$replace->_unicode$after->_unicode)'Unicode');
  439.         }
  440.         
  441.         return $return;
  442.     }
  443.     
  444.     /**
  445.     * Works like PHP's strstr function by returning the string from $find on.
  446.     *
  447.     * @access public
  448.     * @param  I18N_UnicodeString $find The string to found
  449.     * @return I18N_UnicodeString The current string from $find on to the end
  450.     */
  451.     function strStr(&$find{
  452.         $found = false;
  453.         $after $find->_unicode;
  454.         
  455.         for($i = 0$length $this->length()$i $length$i++{
  456.             if ($found{
  457.                 $after[$this->_unicode[$i];
  458.             else {
  459.                 if ($this->_unicode[$i== $find->_unicode[0]{
  460.                     if ($i $find->length($length{
  461.                         break;
  462.                     }
  463.                     
  464.                     $found = true;
  465.                     for($c = 1$max $find->length()$c $max$c++{
  466.                         if ($this->_unicode[++$i!= $find->_unicode[$c]{
  467.                             $found = false;
  468.                             break;
  469.                         }
  470.                     }
  471.                 }
  472.             }
  473.         }
  474.         
  475.         if ($found{
  476.             return new I18N_UnicodeString($after'Unicode');
  477.         else {
  478.             return false;
  479.         }
  480.     }
  481.  
  482.     /**
  483.     * Returns the position of a character much like PHP's strpos function.
  484.     *
  485.     * @access public
  486.     * @param  mixed $char A Unicode char represented as either an integer or a
  487.     *                      UTF-8 char.
  488.     * @return integer The location of the character in the string.
  489.     */
  490.     function indexOf($char{
  491.         if (!is_int($char)) {
  492.             if (strlen($char> 1{
  493.                 $char array_shift(self::utf8ToUnicode($char));
  494.             else {
  495.                 $char ord($char);
  496.             }
  497.         }
  498.         
  499.         for($i = 0$length $this->length()$i $length$i++{
  500.             if ($this->_unicode[$i== $char{
  501.                 return $i;
  502.             }
  503.         }
  504.         
  505.         return -1;
  506.     }
  507.     
  508.     /**
  509.     * Returns the last position of a character much like PHP's strrpos function.
  510.     *
  511.     * @access public
  512.     * @param  mixed $char A Unicode char represented as either an integer or a
  513.     *                      UTF-8 char.
  514.     * @return integer The last location of the character in the string.
  515.     */
  516.     function lastIndexOf($char{
  517.         if (!is_int($char)) {
  518.             if (strlen($char> 1{
  519.                 $char array_shift($this->utf8ToUnicode($char));
  520.             else {
  521.                 $char ord($char);
  522.             }
  523.         }
  524.         
  525.         for($i $this->length(- 1; $i >= 0; $i--{
  526.             if ($this->_unicode[$i== $char{
  527.                 return $i;
  528.             }
  529.         }
  530.         
  531.         return -1;    
  532.     }
  533.     
  534.     /**
  535.     * Determines if two Unicode strings are equal
  536.     *
  537.     * @access public
  538.     * @param  I18N_UnicodeString $unicode The string to compare to.
  539.     * @return boolean True if they are equal, false otherwise.
  540.     */
  541.     function equals(&$unicode{
  542.         if ($this->length(!= $unicode->length()) {
  543.             // if they arn't even the same length no need to even check
  544.             return false;
  545.         }
  546.         
  547.         return ($this->_unicode == $unicode->_unicode);
  548.     }
  549.     
  550.     /**
  551.     * Appends a given Unicode string to the end of the current one.
  552.     *
  553.     * @access public
  554.     * @param  I18N_UnicodeString $unicode The string to append.
  555.     * @return I18N_UnicodeString The new string created from the appension.
  556.     */
  557.     function append(&$unicode{
  558.         return new I18N_UnicodeString(array_merge($this->_unicode$unicode->_unicode)'Unicode');
  559.     }
  560.     
  561.     /**
  562.     * Used to raise a PEAR_Error.
  563.     *
  564.     * Hopefully this method is never called, but when it is it will include the
  565.     * PEAR class and return a new PEAR_Error.
  566.     *
  567.     * @static
  568.     * @access public
  569.     * @param string $message The error message to raise.
  570.     * @return PEAR_Error A PEAR error message.
  571.     */
  572.     function raiseError($message{
  573.         include_once('PEAR.php');
  574.     
  575.         return PEAR::raiseError($message);
  576.     }
  577. }
  578. ?>

Documentation generated on Mon, 11 Mar 2019 14:39:30 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.