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 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 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 Unicode 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.     * @access public
  67.     * @static
  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_Unicode($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 $this->_stringFromUtf8($value);
  123.                 break;
  124.  
  125.             case 'HTML':
  126.                 $this->_unicode $this->_stringFromHtml($value);
  127.                 break;
  128.  
  129.             case 'UCS4':
  130.             case 'UCS-4':
  131.             case 'UNICODE':
  132.                 $this->_unicode $value;
  133.                 break;
  134.  
  135.             default:
  136.                 return $this->raiseError('Unrecognized encoding');
  137.         }
  138.         
  139.         if (strtolower(get_class($this->_unicode)) == 'pear_error'{
  140.             return $this->_unicode;
  141.         }
  142.         
  143.         return true;
  144.     }
  145.     
  146.     /**
  147.     * Converts a string encoded with HTML entities into our internal
  148.     * representation of an array of integers.
  149.     *
  150.     * @access private
  151.     * @param  string $string A string containing Unicode values encoded as HTML
  152.     *                         entities.
  153.     * @return array The array of Unicode values.
  154.     */
  155.     function _stringFromHtml($string ''{
  156.         $parts   explode('&#'$string);
  157.         $unicode = array();
  158.         foreach($parts as $part{
  159.             $text strstr($part';');
  160.             
  161.             if (!empty($text)) {
  162.                 $value substr($part0strpos($part';'));
  163.                 $unicode[intval($value);
  164.  
  165.                 $text substr($text1);
  166.  
  167.                 for($i = 0$max strlen($text)$i $max$i++{
  168.                     $unicode[ord($text[$i]);
  169.                 }
  170.             else {
  171.                 for($i = 0$max strlen($part)$i $max$i++{
  172.                     $unicode[ord($part[$i]);
  173.                 }
  174.             }
  175.         }
  176.  
  177.         return $unicode;
  178.     }
  179.     
  180.     /**
  181.     * Converts a UTF-8 string into our internal representation of an array of
  182.     * integers.
  183.     *
  184.     * @access private
  185.     * @param  string $string A string containing Unicode values encoded in UTF-8
  186.     * @return array The array of Unicode values.
  187.     */
  188.     function _stringFromUtf8($string ''{
  189.         $unicode = array();
  190.         $values  = array();
  191.         $search  = 1;
  192.         
  193.         for($count = 0$length strlen($string)$count $length$count++{
  194.             $value ord($string[$count]);
  195.  
  196.             if ($value < 128{
  197.                 // if the value is an ASCII char then just go ahead and add it on
  198.                 $unicode[$value;
  199.             else {
  200.                 // if not then we need to know how many more bytes make up this character
  201.                 if (count($values== 0{
  202.                     if ($value >> 5 == 6{
  203.                         $values[($value - 192<< 6;
  204.                         $search   = 2;
  205.                     elseif ($value >> 4 == 14{
  206.                         $values[($value - 224<< 12;
  207.                         $search   = 3;
  208.                     elseif ($value >> 3 == 30{
  209.                         $values[($value - 240<< 18;
  210.                         $search   = 4;
  211.                     elseif ($value >> 2 == 62{
  212.                         $values[($value - 248<< 24;
  213.                         $search   = 5;
  214.                     elseif ($value >> 1 == 126{
  215.                         $values[($value - 252<< 30;
  216.                         $search   = 6;
  217.                     else {
  218.                         return $this->raiseError('Malformed UTF-8 string');
  219.                     }
  220.                 else {
  221.                     if ($value >> 6 == 2{
  222.                         $values[$value - 128;
  223.                     else {
  224.                         return $this->raiseError('Malformed UTF-8 string');
  225.                     }
  226.  
  227.                     if (count($values== $search{
  228.                         // if we have all of our bytes then go ahead an encode it in unicode
  229.                         $value $values[0];
  230.                         for($i = 1; $i $search$i++{
  231.                             $value += ($values[$i<< ((($search $i- 1* 6));
  232.                         }
  233.                         
  234.                         $unicode[$value;
  235.  
  236.                         $values = array();
  237.                         $search = 1;
  238.                     }
  239.                 }
  240.             }
  241.         }
  242.         
  243.         return $unicode;
  244.     }
  245.     
  246.     /**
  247.     * Retrieves the string and returns it as a UTF-8 encoded string.
  248.     *
  249.     * @access public
  250.     * @return string A string with the Unicode values encoded in UTF-8.
  251.     */
  252.     function toUtf8String({
  253.         $string '';
  254.  
  255.         foreach($this->_unicode as $char{
  256.             if ($char < 128{
  257.                 // its an ASCII char no encoding needed
  258.                 $string .= chr($char);
  259.             elseif ($char < 1 << 11{
  260.                 // its a 2 byte UTF-8 char
  261.                 $string .= chr(192 + ($char >> 6));
  262.                 $string .= chr(128 + ($char 63));
  263.             elseif ($char < 1 << 16{
  264.                 // its a 3 byte UTF-8 char
  265.                 $string .= chr(224 + ($char >> 12));
  266.                 $string .= chr(128 + (($char >> 663));
  267.                 $string .= chr(128 + ($char 63));
  268.             elseif ($char < 1 << 21{
  269.                 // its a 4 byte UTF-8 char
  270.                 $string .= chr(240 + ($char >> 18));
  271.                 $string .= chr(128 + (($char >> 1263));
  272.                 $string .= chr(128 + (($char >>  663));
  273.                 $string .= chr(128 + ($char 63));
  274.             elseif ($char < 1 << 26{
  275.                 // its a 5 byte UTF-8 char
  276.                 $string .= chr(248 + ($char >> 24));
  277.                 $string .= chr(128 + (($char >> 1863));
  278.                 $string .= chr(128 + (($char >> 1263));
  279.                 $string .= chr(128 + (($char >> 663));
  280.                 $string .= chr(128 + ($char 63));
  281.             else {
  282.                 // its a 6 byte UTF-8 char
  283.                 $string .= chr(252 + ($char >> 30));
  284.                 $string .= chr(128 + (($char >> 2463));
  285.                 $string .= chr(128 + (($char >> 1863));
  286.                 $string .= chr(128 + (($char >> 1263));
  287.                 $string .= chr(128 + (($char >> 663));
  288.                 $string .= chr(128 + ($char 63));
  289.             }
  290.         }
  291.  
  292.         return $string;
  293.     }
  294.     
  295.     /**
  296.     * Retrieves the string and returns it as a string encoded with HTML
  297.     * entities.
  298.     *
  299.     * @access public
  300.     * @return string A string with the Unicode values encoded as HTML entities.
  301.     */
  302.     function toHtmlEntitiesString({
  303.         $string '';
  304.  
  305.         foreach($this->_unicode as $char{
  306.             if ($char > 127{
  307.                 $string .= '&#' $char ';';
  308.             else {
  309.                 $string .= chr($char);
  310.             }
  311.         }
  312.  
  313.         return $string;
  314.     }
  315.     
  316.     /**
  317.     * Retrieve the length of the string in characters.
  318.     *
  319.     * @access public
  320.     * @return integer The length of the string.
  321.     */
  322.     function length({
  323.         return count($this->_unicode);
  324.     }
  325.     
  326.     /**
  327.     * Works exactly like PHP's substr function only it works on Unicode
  328.     * strings.
  329.     *
  330.     * @access public
  331.     * @param  integer $begin The beginning of the substring.
  332.     * @param  integer $length The length to read. Defaults to the rest of the
  333.     *                          string.
  334.     * @return I18N_UnicodeString A new I18N_UnicodeString class containing the
  335.     *                             substring or a PEAR_Error if an error is
  336.     *                             thrown.
  337.     */
  338.     function subString($begin$length = null{
  339.         $unicode = array();
  340.         
  341.         if (is_null($length)) {
  342.             $length $this->length($begin;
  343.         }
  344.         
  345.         if (($begin $length$this->length()) {
  346.             return $this->raiseError('Cannot read past end of string.');        
  347.         }
  348.         
  349.         if ($begin $this->length()) {
  350.             return $this->raiseError('Beginning extends past end of string.');
  351.         }
  352.         
  353.         for($i $begin$max_length ($begin $length)$i $max_length$i++{
  354.             array_push($unicode$this->_unicode[$i]);
  355.         }
  356.  
  357.         return new I18N_UnicodeString($unicode'Unicode');
  358.     }
  359.     
  360.     /**
  361.     * Works like PHP's substr_replace function.
  362.     *
  363.     * @access public
  364.     * @param  I18N_UnicodeString $find The string to replaced
  365.     * @param  I18N_UnicodeString $replace The string to replace $find with
  366.     * @param  integer $start The position in the string to start replacing at
  367.     * @param  integer $length The length from the starting to position to stop
  368.     *                          replacing at
  369.     * @return I18N_UnicodeString The current string with all $find replaced by
  370.     *                             $replace
  371.     * @see    stringReplace()
  372.     */
  373.     function subStringReplace(&$find&$replace$start$length = null{
  374.         if (is_null($length)) {
  375.             $length $this->length($start;
  376.         }
  377.         
  378.         $begin  $this->subString(0$start);
  379.         $string $this->subString($start$length);
  380.         $string $string->stringReplace($find$replace);
  381.         $after  $this->subString($start $length);
  382.         
  383.         return new I18N_UnicodeString(array_merge($begin->_unicode$string->_unicode$after->_unicode)'Unicode');
  384.     }
  385.     
  386.     /**
  387.     * Works like PHP's str_replace function.
  388.     *
  389.     * @access public
  390.     * @param  I18N_UnicodeString $find The string to replaced
  391.     * @param  I18N_UnicodeString $replace The string to replace $find with
  392.     * @return I18N_UnicodeString The current string with all $find replaced by
  393.     *                             $replace
  394.     * @see    subStringReplace()
  395.     */
  396.     function stringReplace(&$find&$replace{
  397.         $return = new I18N_UnicodeString($this->_unicode'Unicode');
  398.         
  399.         while($return->strStr($find!== false{
  400.             $after $return->strStr($find);
  401.             $begin $return->subString(0$return->length($after->length());
  402.             $after $after->subString($find->length());
  403.             
  404.             $return = new I18N_UnicodeString(array_merge($begin->_unicode$replace->_unicode$after->_unicode)'Unicode');
  405.         }
  406.         
  407.         return $return;
  408.     }
  409.     
  410.     /**
  411.     * Works like PHP's strstr function by returning the string from $find on.
  412.     *
  413.     * @access public
  414.     * @param  I18N_UnicodeString $find The string to found
  415.     * @return I18N_UnicodeString The current string from $find on to the end
  416.     */
  417.     function strStr(&$find{
  418.         $found = false;
  419.         $after $find->_unicode;
  420.         
  421.         for($i = 0$length $this->length()$i $length$i++{
  422.             if ($found{
  423.                 $after[$this->_unicode[$i];
  424.             else {
  425.                 if ($this->_unicode[$i== $find->_unicode[0]{
  426.                     if ($i $find->length($length{
  427.                         break;
  428.                     }
  429.                     
  430.                     for($c = 1$max $find->length()$c $max$c++{
  431.                         $found = true;
  432.  
  433.                         if ($this->_unicode[++$i!= $find->_unicode[$c]{
  434.                             $found = false;
  435.                             break;
  436.                         }
  437.                     }
  438.                 }
  439.             }
  440.         }
  441.         
  442.         if ($found{
  443.             return new I18N_UnicodeString($after'Unicode');
  444.         else {
  445.             return false;
  446.         }
  447.     }
  448.  
  449.     /**
  450.     * Returns the position of a character much like PHP's strpos function.
  451.     *
  452.     * @access public
  453.     * @param  mixed $char A Unicode char represented as either an integer or a
  454.     *                      UTF-8 char.
  455.     * @return integer The location of the character in the string.
  456.     */
  457.     function indexOf($char{
  458.         if (!is_int($char)) {
  459.             if (strlen($char> 1{
  460.                 $char array_shift($this->_stringFromUtf8($char));
  461.             else {
  462.                 $char ord($char);
  463.             }
  464.         }
  465.         
  466.         for($i = 0$length $this->length()$i $length$i++{
  467.             if ($this->_unicode[$i== $char{
  468.                 return $i;
  469.             }
  470.         }
  471.         
  472.         return -1;
  473.     }
  474.     
  475.     /**
  476.     * Returns the last position of a character much like PHP's strrpos function.
  477.     *
  478.     * @access public
  479.     * @param  mixed $char A Unicode char represented as either an integer or a
  480.     *                      UTF-8 char.
  481.     * @return integer The last location of the character in the string.
  482.     */
  483.     function lastIndexOf($char{
  484.         if (!is_int($char)) {
  485.             if (strlen($char> 1{
  486.                 $char array_shift($this->_stringFromUtf8($char));
  487.             else {
  488.                 $char ord($char);
  489.             }
  490.         }
  491.         
  492.         for($i $this->length(- 1; $i >= 0; $i--{
  493.             if ($this->_unicode[$i== $char{
  494.                 return $i;
  495.             }
  496.         }
  497.         
  498.         return -1;    
  499.     }
  500.     
  501.     /**
  502.     * Determines if two Unicode strings are equal
  503.     *
  504.     * @access public
  505.     * @param  I18N_UnicodeString $unicode The string to compare to.
  506.     * @return boolean True if they are equal, false otherwise.
  507.     */
  508.     function equals(&$unicode{
  509.         if ($this->length(!= $unicode->length()) {
  510.             // if they arn't even the same length no need to even check
  511.             return false;
  512.         }
  513.         
  514.         return ($this->_unicode == $unicode->_unicode);
  515.     }
  516.     
  517.     /**
  518.     * Appends a given Unicode string to the end of the current one.
  519.     *
  520.     * @access public
  521.     * @param  I18N_UnicodeString $unicode The string to append.
  522.     * @return I18N_UnicodeString The new string created from the appension.
  523.     */
  524.     function append(&$unicode{
  525.         return new I18N_UnicodeString(array_merge($this->_unicode$unicode->_unicode)'Unicode');
  526.     }
  527.     
  528.     /**
  529.     * Used to raise a PEAR_Error.
  530.     *
  531.     * Hopefully this method is never called, but when it is it will include the
  532.     * PEAR class and return a new PEAR_Error.
  533.     *
  534.     * @param string $message The error message to raise.
  535.     * @return PEAR_Error A PEAR error message.
  536.     */
  537.     function raiseError($message{
  538.         include_once('PEAR.php');
  539.     
  540.         return PEAR::raiseError($message);
  541.     }
  542. }
  543. ?>

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