WordPress.org

Make WordPress Core

Changeset 12174


Ignore:
Timestamp:
11/12/09 16:05:43 (6 years ago)
Author:
ryan
Message:

pomo performance improvements. Props nbachiyski. fixes #10165

Location:
trunk/wp-includes/pomo
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/pomo/mo.php

    r12079 r12174  
    33 * Class for working with MO files 
    44 * 
    5  * @version $Id: mo.php 221 2009-09-07 21:08:21Z nbachiyski $ 
     5 * @version $Id: mo.php 293 2009-11-12 15:43:50Z nbachiyski $ 
    66 * @package pomo 
    77 * @subpackage mo 
     
    2222     */ 
    2323    function import_from_file($filename) { 
    24         $reader = new POMO_CachedIntFileReader($filename); 
    25         if (isset($reader->error)) { 
    26             return false; 
    27         } 
     24        $reader = new POMO_FileReader($filename); 
     25        if (!$reader->is_resource()) 
     26            return false; 
    2827        return $this->import_from_reader($reader); 
    2928    } 
     
    114113 
    115114    function import_from_reader($reader) { 
    116         $reader->setEndian('little'); 
    117         $endian = MO::get_byteorder($reader->readint32()); 
    118         if (false === $endian) { 
    119             return false; 
    120         } 
    121         $reader->setEndian($endian); 
    122  
    123         $revision = $reader->readint32(); 
    124         $total = $reader->readint32(); 
    125         // get addresses of array of lenghts and offsets for original string and translations 
    126         $originals_lenghts_addr = $reader->readint32(); 
    127         $translations_lenghts_addr = $reader->readint32(); 
    128  
     115        $endian_string = MO::get_byteorder($reader->readint32()); 
     116        if (false === $endian_string) { 
     117            return false; 
     118        } 
     119        $reader->setEndian($endian_string); 
     120 
     121        $endian = ('big' == $endian_string)? 'N' : 'V'; 
     122 
     123        $header = $reader->read(24); 
     124        if ($reader->strlen($header) != 24) 
     125            return false; 
     126 
     127        // parse header 
     128        $header = unpack("{$endian}revision/{$endian}total/{$endian}originals_lenghts_addr/{$endian}translations_lenghts_addr/{$endian}hash_length/{$endian}hash_addr", $header); 
     129        if (!is_array($header)) 
     130            return false; 
     131 
     132        extract( $header ); 
     133 
     134        // support revision 0 of MO format specs, only 
     135        if ($revision != 0) 
     136            return false; 
     137 
     138        // seek to data blocks 
    129139        $reader->seekto($originals_lenghts_addr); 
    130         $originals_lenghts = $reader->readint32array($total * 2); // each of  
    131         $reader->seekto($translations_lenghts_addr); 
    132         $translations_lenghts = $reader->readint32array($total * 2); 
    133  
    134         $length = create_function('$i', 'return $i * 2 + 1;'); 
    135         $offset = create_function('$i', 'return $i * 2 + 2;'); 
    136  
    137         for ($i = 0; $i < $total; ++$i) { 
    138             $reader->seekto($originals_lenghts[$offset($i)]); 
    139             $original = $reader->read($originals_lenghts[$length($i)]); 
    140             $reader->seekto($translations_lenghts[$offset($i)]); 
    141             $translation = $reader->read($translations_lenghts[$length($i)]); 
    142             if ('' == $original) { 
     140 
     141        // read originals' indices 
     142        $originals_lengths_length = $translations_lenghts_addr - $originals_lenghts_addr; 
     143        if ( $originals_lengths_length != $total * 8 ) 
     144            return false; 
     145 
     146        $originals = $reader->read($originals_lengths_length); 
     147        if ( $reader->strlen( $originals ) != $originals_lengths_length ) 
     148            return false; 
     149 
     150        // read translations' indices 
     151        $translations_lenghts_length = $hash_addr - $translations_lenghts_addr; 
     152        if ( $translations_lenghts_length != $total * 8 ) 
     153            return false; 
     154 
     155        $translations = $reader->read($translations_lenghts_length); 
     156        if ( $reader->strlen( $translations ) != $translations_lenghts_length ) 
     157            return false; 
     158 
     159        // transform raw data into set of indices 
     160        $originals    = $reader->str_split( $originals, 8 ); 
     161        $translations = $reader->str_split( $translations, 8 ); 
     162 
     163        // skip hash table 
     164        $strings_addr = $hash_addr + $hash_length * 4; 
     165 
     166        $reader->seekto($strings_addr); 
     167 
     168        $strings = $reader->read_all(); 
     169        $reader->close(); 
     170 
     171        for ( $i = 0; $i < $total; $i++ ) { 
     172            $o = unpack( "{$endian}length/{$endian}pos", $originals[$i] ); 
     173            $t = unpack( "{$endian}length/{$endian}pos", $translations[$i] ); 
     174            if ( !$o || !$t ) return false; 
     175 
     176            // adjust offset due to reading strings to separate space before 
     177            $o['pos'] -= $strings_addr; 
     178            $t['pos'] -= $strings_addr; 
     179 
     180            $original    = $reader->substr( $strings, $o['pos'], $o['length'] ); 
     181            $translation = $reader->substr( $strings, $t['pos'], $t['length'] ); 
     182 
     183            if ('' === $original) { 
    143184                $this->set_headers($this->make_headers($translation)); 
    144185            } else { 
    145                 $this->add_entry($this->make_entry($original, $translation)); 
     186                $entry = &$this->make_entry($original, $translation); 
     187                $this->entries[$entry->key()] = &$entry; 
    146188            } 
    147189        } 
     
    150192 
    151193    /** 
     194     * Build a Translation_Entry from original string and translation strings, 
     195     * found in a MO file 
     196     *  
    152197     * @static 
     198     * @param string $original original string to translate from MO file. Might contain 
     199     *  0x04 as context separator or 0x00 as singular/plural separator 
     200     * @param string $translation translation string from MO file. Might contain 
     201     *  0x00 as a plural translations separator 
    153202     */ 
    154203    function &make_entry($original, $translation) { 
    155         $args = array(); 
     204        $entry = & new Translation_Entry(); 
    156205        // look for context 
    157206        $parts = explode(chr(4), $original); 
    158207        if (isset($parts[1])) { 
    159208            $original = $parts[1]; 
    160             $args['context'] = $parts[0]; 
     209            $entry->context = $parts[0]; 
    161210        } 
    162211        // look for plural original 
    163212        $parts = explode(chr(0), $original); 
    164         $args['singular'] = $parts[0]; 
     213        $entry->singular = $parts[0]; 
    165214        if (isset($parts[1])) { 
    166             $args['plural'] = $parts[1]; 
     215            $entry->is_plural = true; 
     216            $entry->plural = $parts[1]; 
    167217        } 
    168218        // plural translations are also separated by \0 
    169         $args['translations'] = explode(chr(0), $translation); 
    170         $entry = & new Translation_Entry($args); 
     219        $entry->translations = explode(chr(0), $translation); 
    171220        return $entry; 
    172221    } 
     
    179228        return $this->_nplurals; 
    180229    } 
    181  
    182  
    183230} 
    184231endif; 
  • trunk/wp-includes/pomo/streams.php

    r12079 r12174  
    44 * Based on the classes from Danilo Segan <danilo@kvota.net> 
    55 * 
    6  * @version $Id: streams.php 223 2009-09-07 21:20:13Z nbachiyski $ 
     6 * @version $Id: streams.php 293 2009-11-12 15:43:50Z nbachiyski $ 
    77 * @package pomo 
    88 * @subpackage streams 
    99 */ 
    1010 
    11  
    12 if ( !class_exists( 'POMO_StringReader' ) ): 
    13 /** 
    14  * Provides file-like methods for manipulating a string instead 
    15  * of a physical file. 
    16  */ 
    17 class POMO_StringReader { 
    18   var $_pos; 
    19   var $_str; 
    20  
    21     function POMO_StringReader($str = '') { 
    22         $this->_str = $str; 
     11if ( !class_exists( 'POMO_Reader' ) ): 
     12class POMO_Reader { 
     13     
     14    var $endian = 'little'; 
     15    var $_post = ''; 
     16     
     17    function POMO_Reader() { 
     18        $this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); 
    2319        $this->_pos = 0; 
    24         $this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); 
    25     } 
    26  
    27     function _substr($string, $start, $length) { 
    28         if ($this->is_overloaded) { 
    29             return mb_substr($string,$start,$length,'ascii'); 
    30         } else { 
    31             return substr($string,$start,$length); 
    32         } 
    33     } 
    34      
    35     function _strlen($string) { 
    36         if ($this->is_overloaded) { 
    37             return mb_strlen($string,'ascii'); 
    38         } else { 
    39             return strlen($string); 
    40         } 
    41     } 
    42  
    43     function read($bytes) { 
    44         $data = $this->_substr($this->_str, $this->_pos, $bytes); 
    45         $this->_pos += $bytes; 
    46         if ($this->_strlen($this->_str) < $this->_pos) $this->_pos = $this->_strlen($this->_str); 
    47         return $data; 
    48     } 
    49  
    50     function seekto($pos) { 
    51         $this->_pos = $pos; 
    52         if ($this->_strlen($this->_str) < $this->_pos) $this->_pos = $this->_strlen($this->_str); 
    53         return $this->_pos; 
    54     } 
    55  
    56     function pos() { 
    57         return $this->_pos; 
    58     } 
    59  
    60     function length() { 
    61         return $this->_strlen($this->_str); 
    62     } 
    63  
    64 } 
    65 endif; 
    66  
    67 if ( !class_exists( 'POMO_CachedFileReader' ) ): 
    68 /** 
    69  * Reads the contents of the file in the beginning. 
    70  */ 
    71 class POMO_CachedFileReader extends POMO_StringReader { 
    72     function POMO_CachedFileReader($filename) { 
    73         parent::POMO_StringReader(); 
    74         $this->_str = file_get_contents($filename); 
    75         if (false === $this->_str) 
    76             return false; 
    77         $this->_pos = 0; 
    78     } 
    79 } 
    80 endif; 
    81  
    82 if ( !class_exists( 'POMO_CachedIntFileReader' ) ): 
    83 /** 
    84  * Allows reading integers from a file. 
    85  */ 
    86 class POMO_CachedIntFileReader extends POMO_CachedFileReader { 
    87  
    88     var $endian = 'little'; 
    89  
    90     /** 
    91      * Opens a file and caches it. 
    92      * 
    93      * @param $filename string name of the file to be opened 
    94      * @param $endian string endianness of the words in the file, allowed 
    95      *  values are 'little' or 'big'. Default value is 'little' 
    96      */ 
    97     function POMO_CachedIntFileReader($filename, $endian = 'little') { 
    98         $this->endian = $endian; 
    99         parent::POMO_CachedFileReader($filename); 
    100     } 
    101  
     20    } 
     21     
    10222    /** 
    10323     * Sets the endianness of the file. 
     
    11737    function readint32() { 
    11838        $bytes = $this->read(4); 
    119         if (4 != $this->_strlen($bytes)) 
     39        if (4 != $this->strlen($bytes)) 
    12040            return false; 
    12141        $endian_letter = ('big' == $this->endian)? 'N' : 'V'; 
     
    13353    function readint32array($count) { 
    13454        $bytes = $this->read(4 * $count); 
    135         if (4*$count != $this->_strlen($bytes)) 
     55        if (4*$count != $this->strlen($bytes)) 
    13656            return false; 
    13757        $endian_letter = ('big' == $this->endian)? 'N' : 'V'; 
    13858        return unpack($endian_letter.$count, $bytes); 
    13959    } 
    140 } 
    141 endif; 
     60     
     61     
     62    function substr($string, $start, $length) { 
     63        if ($this->is_overloaded) { 
     64            return mb_substr($string, $start, $length, 'ascii'); 
     65        } else { 
     66            return substr($string, $start, $length); 
     67        } 
     68    } 
     69     
     70    function strlen($string) { 
     71        if ($this->is_overloaded) { 
     72            return mb_strlen($string, 'ascii'); 
     73        } else { 
     74            return strlen($string); 
     75        } 
     76    } 
     77     
     78    function str_split($string, $chunk_size) { 
     79        if (!function_exists('str_split')) { 
     80            $length = $this->strlen($string); 
     81            $out = array(); 
     82            for ($i = 0; $i < $length; $i += $chunk_size) 
     83                $out[] = $this->substr($string, $i, $chunk_size); 
     84            return $out; 
     85        } else { 
     86            return str_split( $string, $chunk_size ); 
     87        } 
     88    } 
     89     
     90         
     91    function pos() { 
     92        return $this->_pos; 
     93    } 
     94 
     95    function is_resource() { 
     96        return true; 
     97    } 
     98     
     99    function close() { 
     100        return true; 
     101    } 
     102} 
     103endif; 
     104 
     105if ( !class_exists( 'POMO_FileReader' ) ): 
     106class POMO_FileReader extends POMO_Reader { 
     107    function POMO_FileReader($filename) { 
     108        parent::POMO_Reader(); 
     109        $this->_f = fopen($filename, 'r'); 
     110    } 
     111     
     112    function read($bytes) { 
     113        return fread($this->_f, $bytes); 
     114    } 
     115     
     116    function seekto($pos) { 
     117        if ( -1 == fseek($this->_f, $pos, SEEK_SET)) { 
     118            return false; 
     119        } 
     120        $this->_pos = $pos; 
     121        return true; 
     122    } 
     123     
     124    function is_resource() { 
     125        return is_resource($this->_f); 
     126    } 
     127     
     128    function feof() { 
     129        return feof($this->_f); 
     130    } 
     131     
     132    function close() { 
     133        return fclose($this->_f); 
     134    } 
     135     
     136    function read_all() { 
     137        $all = ''; 
     138        while ( !$this->feof() ) 
     139            $all .= $this->read(4096); 
     140        return $all; 
     141    } 
     142} 
     143endif; 
     144 
     145if ( !class_exists( 'POMO_StringReader' ) ): 
     146/** 
     147 * Provides file-like methods for manipulating a string instead 
     148 * of a physical file. 
     149 */ 
     150class POMO_StringReader extends POMO_Reader { 
     151     
     152    var $_str = ''; 
     153     
     154    function POMO_StringReader($str = '') { 
     155        parent::POMO_Reader(); 
     156        $this->_str = $str; 
     157        $this->_pos = 0; 
     158    } 
     159 
     160 
     161    function read($bytes) { 
     162        $data = $this->substr($this->_str, $this->_pos, $bytes); 
     163        $this->_pos += $bytes; 
     164        if ($this->strlen($this->_str) < $this->_pos) $this->_pos = $this->strlen($this->_str); 
     165        return $data; 
     166    } 
     167 
     168    function seekto($pos) { 
     169        $this->_pos = $pos; 
     170        if ($this->strlen($this->_str) < $this->_pos) $this->_pos = $this->strlen($this->_str); 
     171        return $this->_pos; 
     172    } 
     173 
     174    function length() { 
     175        return $this->strlen($this->_str); 
     176    } 
     177 
     178    function read_all() { 
     179        return $this->substr($this->_str, $this->_pos, $this->strlen($this->_str)); 
     180    } 
     181     
     182} 
     183endif; 
     184 
     185if ( !class_exists( 'POMO_CachedFileReader' ) ): 
     186/** 
     187 * Reads the contents of the file in the beginning. 
     188 */ 
     189class POMO_CachedFileReader extends POMO_StringReader { 
     190    function POMO_CachedFileReader($filename) { 
     191        parent::POMO_StringReader(); 
     192        $this->_str = file_get_contents($filename); 
     193        if (false === $this->_str) 
     194            return false; 
     195        $this->_pos = 0; 
     196    } 
     197} 
     198endif; 
     199 
     200if ( !class_exists( 'POMO_CachedIntFileReader' ) ): 
     201/** 
     202 * Reads the contents of the file in the beginning. 
     203 */ 
     204class POMO_CachedIntFileReader extends POMO_CachedFileReader { 
     205    function POMO_CachedIntFileReader($filename) { 
     206        parent::POMO_CachedFileReader($filename); 
     207    } 
     208} 
     209endif; 
Note: See TracChangeset for help on using the changeset viewer.