Make WordPress Core


Ignore:
Timestamp:
11/12/2009 04:05:43 PM (15 years ago)
Author:
ryan
Message:

pomo performance improvements. Props nbachiyski. fixes #10165

File:
1 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;
Note: See TracChangeset for help on using the changeset viewer.