web/wp-includes/Text/Diff.php
author ymh
Fri, 12 Mar 2010 13:29:04 +0000
changeset 1 0d28b7c10758
permissions -rw-r--r--
First commit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
0d28b7c10758 First commit
ymh
parents:
diff changeset
     1
<?php
0d28b7c10758 First commit
ymh
parents:
diff changeset
     2
/**
0d28b7c10758 First commit
ymh
parents:
diff changeset
     3
 * General API for generating and formatting diffs - the differences between
0d28b7c10758 First commit
ymh
parents:
diff changeset
     4
 * two sequences of strings.
0d28b7c10758 First commit
ymh
parents:
diff changeset
     5
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
     6
 * The original PHP version of this code was written by Geoffrey T. Dairiki
0d28b7c10758 First commit
ymh
parents:
diff changeset
     7
 * <dairiki@dairiki.org>, and is used/adapted with his permission.
0d28b7c10758 First commit
ymh
parents:
diff changeset
     8
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
     9
 * $Horde: framework/Text_Diff/Diff.php,v 1.26 2008/01/04 10:07:49 jan Exp $
0d28b7c10758 First commit
ymh
parents:
diff changeset
    10
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
    11
 * Copyright 2004 Geoffrey T. Dairiki <dairiki@dairiki.org>
0d28b7c10758 First commit
ymh
parents:
diff changeset
    12
 * Copyright 2004-2008 The Horde Project (http://www.horde.org/)
0d28b7c10758 First commit
ymh
parents:
diff changeset
    13
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
    14
 * See the enclosed file COPYING for license information (LGPL). If you did
0d28b7c10758 First commit
ymh
parents:
diff changeset
    15
 * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    16
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
    17
 * @package Text_Diff
0d28b7c10758 First commit
ymh
parents:
diff changeset
    18
 * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
0d28b7c10758 First commit
ymh
parents:
diff changeset
    19
 */
0d28b7c10758 First commit
ymh
parents:
diff changeset
    20
class Text_Diff {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    21
0d28b7c10758 First commit
ymh
parents:
diff changeset
    22
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
    23
     * Array of changes.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    24
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
    25
     * @var array
0d28b7c10758 First commit
ymh
parents:
diff changeset
    26
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
    27
    var $_edits;
0d28b7c10758 First commit
ymh
parents:
diff changeset
    28
0d28b7c10758 First commit
ymh
parents:
diff changeset
    29
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
    30
     * Computes diffs between sequences of strings.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    31
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
    32
     * @param string $engine     Name of the diffing engine to use.  'auto'
0d28b7c10758 First commit
ymh
parents:
diff changeset
    33
     *                           will automatically select the best.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    34
     * @param array $params      Parameters to pass to the diffing engine.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    35
     *                           Normally an array of two arrays, each
0d28b7c10758 First commit
ymh
parents:
diff changeset
    36
     *                           containing the lines from a file.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    37
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
    38
    function Text_Diff($engine, $params)
0d28b7c10758 First commit
ymh
parents:
diff changeset
    39
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    40
        // Backward compatibility workaround.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    41
        if (!is_string($engine)) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    42
            $params = array($engine, $params);
0d28b7c10758 First commit
ymh
parents:
diff changeset
    43
            $engine = 'auto';
0d28b7c10758 First commit
ymh
parents:
diff changeset
    44
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
    45
0d28b7c10758 First commit
ymh
parents:
diff changeset
    46
        if ($engine == 'auto') {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    47
            $engine = extension_loaded('xdiff') ? 'xdiff' : 'native';
0d28b7c10758 First commit
ymh
parents:
diff changeset
    48
        } else {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    49
            $engine = basename($engine);
0d28b7c10758 First commit
ymh
parents:
diff changeset
    50
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
    51
0d28b7c10758 First commit
ymh
parents:
diff changeset
    52
        // WP #7391
0d28b7c10758 First commit
ymh
parents:
diff changeset
    53
        require_once dirname(__FILE__).'/Diff/Engine/' . $engine . '.php';
0d28b7c10758 First commit
ymh
parents:
diff changeset
    54
        $class = 'Text_Diff_Engine_' . $engine;
0d28b7c10758 First commit
ymh
parents:
diff changeset
    55
        $diff_engine = new $class();
0d28b7c10758 First commit
ymh
parents:
diff changeset
    56
0d28b7c10758 First commit
ymh
parents:
diff changeset
    57
        $this->_edits = call_user_func_array(array($diff_engine, 'diff'), $params);
0d28b7c10758 First commit
ymh
parents:
diff changeset
    58
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
    59
0d28b7c10758 First commit
ymh
parents:
diff changeset
    60
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
    61
     * Returns the array of differences.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    62
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
    63
    function getDiff()
0d28b7c10758 First commit
ymh
parents:
diff changeset
    64
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    65
        return $this->_edits;
0d28b7c10758 First commit
ymh
parents:
diff changeset
    66
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
    67
0d28b7c10758 First commit
ymh
parents:
diff changeset
    68
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
    69
     * Computes a reversed diff.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    70
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
    71
     * Example:
0d28b7c10758 First commit
ymh
parents:
diff changeset
    72
     * <code>
0d28b7c10758 First commit
ymh
parents:
diff changeset
    73
     * $diff = new Text_Diff($lines1, $lines2);
0d28b7c10758 First commit
ymh
parents:
diff changeset
    74
     * $rev = $diff->reverse();
0d28b7c10758 First commit
ymh
parents:
diff changeset
    75
     * </code>
0d28b7c10758 First commit
ymh
parents:
diff changeset
    76
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
    77
     * @return Text_Diff  A Diff object representing the inverse of the
0d28b7c10758 First commit
ymh
parents:
diff changeset
    78
     *                    original diff.  Note that we purposely don't return a
0d28b7c10758 First commit
ymh
parents:
diff changeset
    79
     *                    reference here, since this essentially is a clone()
0d28b7c10758 First commit
ymh
parents:
diff changeset
    80
     *                    method.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    81
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
    82
    function reverse()
0d28b7c10758 First commit
ymh
parents:
diff changeset
    83
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    84
        if (version_compare(zend_version(), '2', '>')) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    85
            $rev = clone($this);
0d28b7c10758 First commit
ymh
parents:
diff changeset
    86
        } else {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    87
            $rev = $this;
0d28b7c10758 First commit
ymh
parents:
diff changeset
    88
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
    89
        $rev->_edits = array();
0d28b7c10758 First commit
ymh
parents:
diff changeset
    90
        foreach ($this->_edits as $edit) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
    91
            $rev->_edits[] = $edit->reverse();
0d28b7c10758 First commit
ymh
parents:
diff changeset
    92
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
    93
        return $rev;
0d28b7c10758 First commit
ymh
parents:
diff changeset
    94
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
    95
0d28b7c10758 First commit
ymh
parents:
diff changeset
    96
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
    97
     * Checks for an empty diff.
0d28b7c10758 First commit
ymh
parents:
diff changeset
    98
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
    99
     * @return boolean  True if two sequences were identical.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   100
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   101
    function isEmpty()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   102
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   103
        foreach ($this->_edits as $edit) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   104
            if (!is_a($edit, 'Text_Diff_Op_copy')) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   105
                return false;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   106
            }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   107
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   108
        return true;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   109
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   110
0d28b7c10758 First commit
ymh
parents:
diff changeset
   111
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   112
     * Computes the length of the Longest Common Subsequence (LCS).
0d28b7c10758 First commit
ymh
parents:
diff changeset
   113
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   114
     * This is mostly for diagnostic purposes.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   115
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   116
     * @return integer  The length of the LCS.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   117
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   118
    function lcs()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   119
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   120
        $lcs = 0;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   121
        foreach ($this->_edits as $edit) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   122
            if (is_a($edit, 'Text_Diff_Op_copy')) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   123
                $lcs += count($edit->orig);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   124
            }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   125
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   126
        return $lcs;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   127
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   128
0d28b7c10758 First commit
ymh
parents:
diff changeset
   129
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   130
     * Gets the original set of lines.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   131
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   132
     * This reconstructs the $from_lines parameter passed to the constructor.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   133
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   134
     * @return array  The original sequence of strings.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   135
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   136
    function getOriginal()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   137
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   138
        $lines = array();
0d28b7c10758 First commit
ymh
parents:
diff changeset
   139
        foreach ($this->_edits as $edit) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   140
            if ($edit->orig) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   141
                array_splice($lines, count($lines), 0, $edit->orig);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   142
            }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   143
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   144
        return $lines;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   145
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   146
0d28b7c10758 First commit
ymh
parents:
diff changeset
   147
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   148
     * Gets the final set of lines.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   149
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   150
     * This reconstructs the $to_lines parameter passed to the constructor.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   151
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   152
     * @return array  The sequence of strings.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   153
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   154
    function getFinal()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   155
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   156
        $lines = array();
0d28b7c10758 First commit
ymh
parents:
diff changeset
   157
        foreach ($this->_edits as $edit) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   158
            if ($edit->final) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   159
                array_splice($lines, count($lines), 0, $edit->final);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   160
            }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   161
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   162
        return $lines;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   163
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   164
0d28b7c10758 First commit
ymh
parents:
diff changeset
   165
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   166
     * Removes trailing newlines from a line of text. This is meant to be used
0d28b7c10758 First commit
ymh
parents:
diff changeset
   167
     * with array_walk().
0d28b7c10758 First commit
ymh
parents:
diff changeset
   168
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   169
     * @param string $line  The line to trim.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   170
     * @param integer $key  The index of the line in the array. Not used.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   171
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   172
    function trimNewlines(&$line, $key)
0d28b7c10758 First commit
ymh
parents:
diff changeset
   173
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   174
        $line = str_replace(array("\n", "\r"), '', $line);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   175
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   176
0d28b7c10758 First commit
ymh
parents:
diff changeset
   177
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   178
     * Determines the location of the system temporary directory.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   179
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   180
     * @static
0d28b7c10758 First commit
ymh
parents:
diff changeset
   181
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   182
     * @access protected
0d28b7c10758 First commit
ymh
parents:
diff changeset
   183
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   184
     * @return string  A directory name which can be used for temp files.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   185
     *                 Returns false if one could not be found.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   186
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   187
    function _getTempDir()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   188
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   189
        $tmp_locations = array('/tmp', '/var/tmp', 'c:\WUTemp', 'c:\temp',
0d28b7c10758 First commit
ymh
parents:
diff changeset
   190
                               'c:\windows\temp', 'c:\winnt\temp');
0d28b7c10758 First commit
ymh
parents:
diff changeset
   191
0d28b7c10758 First commit
ymh
parents:
diff changeset
   192
        /* Try PHP's upload_tmp_dir directive. */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   193
        $tmp = ini_get('upload_tmp_dir');
0d28b7c10758 First commit
ymh
parents:
diff changeset
   194
0d28b7c10758 First commit
ymh
parents:
diff changeset
   195
        /* Otherwise, try to determine the TMPDIR environment variable. */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   196
        if (!strlen($tmp)) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   197
            $tmp = getenv('TMPDIR');
0d28b7c10758 First commit
ymh
parents:
diff changeset
   198
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   199
0d28b7c10758 First commit
ymh
parents:
diff changeset
   200
        /* If we still cannot determine a value, then cycle through a list of
0d28b7c10758 First commit
ymh
parents:
diff changeset
   201
         * preset possibilities. */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   202
        while (!strlen($tmp) && count($tmp_locations)) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   203
            $tmp_check = array_shift($tmp_locations);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   204
            if (@is_dir($tmp_check)) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   205
                $tmp = $tmp_check;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   206
            }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   207
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   208
0d28b7c10758 First commit
ymh
parents:
diff changeset
   209
        /* If it is still empty, we have failed, so return false; otherwise
0d28b7c10758 First commit
ymh
parents:
diff changeset
   210
         * return the directory determined. */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   211
        return strlen($tmp) ? $tmp : false;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   212
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   213
0d28b7c10758 First commit
ymh
parents:
diff changeset
   214
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   215
     * Checks a diff for validity.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   216
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   217
     * This is here only for debugging purposes.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   218
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   219
    function _check($from_lines, $to_lines)
0d28b7c10758 First commit
ymh
parents:
diff changeset
   220
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   221
        if (serialize($from_lines) != serialize($this->getOriginal())) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   222
            trigger_error("Reconstructed original doesn't match", E_USER_ERROR);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   223
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   224
        if (serialize($to_lines) != serialize($this->getFinal())) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   225
            trigger_error("Reconstructed final doesn't match", E_USER_ERROR);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   226
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   227
0d28b7c10758 First commit
ymh
parents:
diff changeset
   228
        $rev = $this->reverse();
0d28b7c10758 First commit
ymh
parents:
diff changeset
   229
        if (serialize($to_lines) != serialize($rev->getOriginal())) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   230
            trigger_error("Reversed original doesn't match", E_USER_ERROR);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   231
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   232
        if (serialize($from_lines) != serialize($rev->getFinal())) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   233
            trigger_error("Reversed final doesn't match", E_USER_ERROR);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   234
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   235
0d28b7c10758 First commit
ymh
parents:
diff changeset
   236
        $prevtype = null;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   237
        foreach ($this->_edits as $edit) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   238
            if ($prevtype == get_class($edit)) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   239
                trigger_error("Edit sequence is non-optimal", E_USER_ERROR);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   240
            }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   241
            $prevtype = get_class($edit);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   242
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   243
0d28b7c10758 First commit
ymh
parents:
diff changeset
   244
        return true;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   245
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   246
0d28b7c10758 First commit
ymh
parents:
diff changeset
   247
}
0d28b7c10758 First commit
ymh
parents:
diff changeset
   248
0d28b7c10758 First commit
ymh
parents:
diff changeset
   249
/**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   250
 * @package Text_Diff
0d28b7c10758 First commit
ymh
parents:
diff changeset
   251
 * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
0d28b7c10758 First commit
ymh
parents:
diff changeset
   252
 */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   253
class Text_MappedDiff extends Text_Diff {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   254
0d28b7c10758 First commit
ymh
parents:
diff changeset
   255
    /**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   256
     * Computes a diff between sequences of strings.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   257
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   258
     * This can be used to compute things like case-insensitve diffs, or diffs
0d28b7c10758 First commit
ymh
parents:
diff changeset
   259
     * which ignore changes in white-space.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   260
     *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   261
     * @param array $from_lines         An array of strings.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   262
     * @param array $to_lines           An array of strings.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   263
     * @param array $mapped_from_lines  This array should have the same size
0d28b7c10758 First commit
ymh
parents:
diff changeset
   264
     *                                  number of elements as $from_lines.  The
0d28b7c10758 First commit
ymh
parents:
diff changeset
   265
     *                                  elements in $mapped_from_lines and
0d28b7c10758 First commit
ymh
parents:
diff changeset
   266
     *                                  $mapped_to_lines are what is actually
0d28b7c10758 First commit
ymh
parents:
diff changeset
   267
     *                                  compared when computing the diff.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   268
     * @param array $mapped_to_lines    This array should have the same number
0d28b7c10758 First commit
ymh
parents:
diff changeset
   269
     *                                  of elements as $to_lines.
0d28b7c10758 First commit
ymh
parents:
diff changeset
   270
     */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   271
    function Text_MappedDiff($from_lines, $to_lines,
0d28b7c10758 First commit
ymh
parents:
diff changeset
   272
                             $mapped_from_lines, $mapped_to_lines)
0d28b7c10758 First commit
ymh
parents:
diff changeset
   273
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   274
        assert(count($from_lines) == count($mapped_from_lines));
0d28b7c10758 First commit
ymh
parents:
diff changeset
   275
        assert(count($to_lines) == count($mapped_to_lines));
0d28b7c10758 First commit
ymh
parents:
diff changeset
   276
0d28b7c10758 First commit
ymh
parents:
diff changeset
   277
        parent::Text_Diff($mapped_from_lines, $mapped_to_lines);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   278
0d28b7c10758 First commit
ymh
parents:
diff changeset
   279
        $xi = $yi = 0;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   280
        for ($i = 0; $i < count($this->_edits); $i++) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   281
            $orig = &$this->_edits[$i]->orig;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   282
            if (is_array($orig)) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   283
                $orig = array_slice($from_lines, $xi, count($orig));
0d28b7c10758 First commit
ymh
parents:
diff changeset
   284
                $xi += count($orig);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   285
            }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   286
0d28b7c10758 First commit
ymh
parents:
diff changeset
   287
            $final = &$this->_edits[$i]->final;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   288
            if (is_array($final)) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   289
                $final = array_slice($to_lines, $yi, count($final));
0d28b7c10758 First commit
ymh
parents:
diff changeset
   290
                $yi += count($final);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   291
            }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   292
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   293
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   294
0d28b7c10758 First commit
ymh
parents:
diff changeset
   295
}
0d28b7c10758 First commit
ymh
parents:
diff changeset
   296
0d28b7c10758 First commit
ymh
parents:
diff changeset
   297
/**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   298
 * @package Text_Diff
0d28b7c10758 First commit
ymh
parents:
diff changeset
   299
 * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
0d28b7c10758 First commit
ymh
parents:
diff changeset
   300
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   301
 * @access private
0d28b7c10758 First commit
ymh
parents:
diff changeset
   302
 */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   303
class Text_Diff_Op {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   304
0d28b7c10758 First commit
ymh
parents:
diff changeset
   305
    var $orig;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   306
    var $final;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   307
0d28b7c10758 First commit
ymh
parents:
diff changeset
   308
    function &reverse()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   309
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   310
        trigger_error('Abstract method', E_USER_ERROR);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   311
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   312
0d28b7c10758 First commit
ymh
parents:
diff changeset
   313
    function norig()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   314
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   315
        return $this->orig ? count($this->orig) : 0;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   316
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   317
0d28b7c10758 First commit
ymh
parents:
diff changeset
   318
    function nfinal()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   319
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   320
        return $this->final ? count($this->final) : 0;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   321
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   322
0d28b7c10758 First commit
ymh
parents:
diff changeset
   323
}
0d28b7c10758 First commit
ymh
parents:
diff changeset
   324
0d28b7c10758 First commit
ymh
parents:
diff changeset
   325
/**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   326
 * @package Text_Diff
0d28b7c10758 First commit
ymh
parents:
diff changeset
   327
 * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
0d28b7c10758 First commit
ymh
parents:
diff changeset
   328
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   329
 * @access private
0d28b7c10758 First commit
ymh
parents:
diff changeset
   330
 */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   331
class Text_Diff_Op_copy extends Text_Diff_Op {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   332
0d28b7c10758 First commit
ymh
parents:
diff changeset
   333
    function Text_Diff_Op_copy($orig, $final = false)
0d28b7c10758 First commit
ymh
parents:
diff changeset
   334
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   335
        if (!is_array($final)) {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   336
            $final = $orig;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   337
        }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   338
        $this->orig = $orig;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   339
        $this->final = $final;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   340
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   341
0d28b7c10758 First commit
ymh
parents:
diff changeset
   342
    function &reverse()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   343
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   344
        $reverse = &new Text_Diff_Op_copy($this->final, $this->orig);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   345
        return $reverse;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   346
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   347
0d28b7c10758 First commit
ymh
parents:
diff changeset
   348
}
0d28b7c10758 First commit
ymh
parents:
diff changeset
   349
0d28b7c10758 First commit
ymh
parents:
diff changeset
   350
/**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   351
 * @package Text_Diff
0d28b7c10758 First commit
ymh
parents:
diff changeset
   352
 * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
0d28b7c10758 First commit
ymh
parents:
diff changeset
   353
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   354
 * @access private
0d28b7c10758 First commit
ymh
parents:
diff changeset
   355
 */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   356
class Text_Diff_Op_delete extends Text_Diff_Op {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   357
0d28b7c10758 First commit
ymh
parents:
diff changeset
   358
    function Text_Diff_Op_delete($lines)
0d28b7c10758 First commit
ymh
parents:
diff changeset
   359
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   360
        $this->orig = $lines;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   361
        $this->final = false;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   362
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   363
0d28b7c10758 First commit
ymh
parents:
diff changeset
   364
    function &reverse()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   365
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   366
        $reverse = &new Text_Diff_Op_add($this->orig);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   367
        return $reverse;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   368
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   369
0d28b7c10758 First commit
ymh
parents:
diff changeset
   370
}
0d28b7c10758 First commit
ymh
parents:
diff changeset
   371
0d28b7c10758 First commit
ymh
parents:
diff changeset
   372
/**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   373
 * @package Text_Diff
0d28b7c10758 First commit
ymh
parents:
diff changeset
   374
 * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
0d28b7c10758 First commit
ymh
parents:
diff changeset
   375
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   376
 * @access private
0d28b7c10758 First commit
ymh
parents:
diff changeset
   377
 */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   378
class Text_Diff_Op_add extends Text_Diff_Op {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   379
0d28b7c10758 First commit
ymh
parents:
diff changeset
   380
    function Text_Diff_Op_add($lines)
0d28b7c10758 First commit
ymh
parents:
diff changeset
   381
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   382
        $this->final = $lines;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   383
        $this->orig = false;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   384
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   385
0d28b7c10758 First commit
ymh
parents:
diff changeset
   386
    function &reverse()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   387
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   388
        $reverse = &new Text_Diff_Op_delete($this->final);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   389
        return $reverse;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   390
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   391
0d28b7c10758 First commit
ymh
parents:
diff changeset
   392
}
0d28b7c10758 First commit
ymh
parents:
diff changeset
   393
0d28b7c10758 First commit
ymh
parents:
diff changeset
   394
/**
0d28b7c10758 First commit
ymh
parents:
diff changeset
   395
 * @package Text_Diff
0d28b7c10758 First commit
ymh
parents:
diff changeset
   396
 * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
0d28b7c10758 First commit
ymh
parents:
diff changeset
   397
 *
0d28b7c10758 First commit
ymh
parents:
diff changeset
   398
 * @access private
0d28b7c10758 First commit
ymh
parents:
diff changeset
   399
 */
0d28b7c10758 First commit
ymh
parents:
diff changeset
   400
class Text_Diff_Op_change extends Text_Diff_Op {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   401
0d28b7c10758 First commit
ymh
parents:
diff changeset
   402
    function Text_Diff_Op_change($orig, $final)
0d28b7c10758 First commit
ymh
parents:
diff changeset
   403
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   404
        $this->orig = $orig;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   405
        $this->final = $final;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   406
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   407
0d28b7c10758 First commit
ymh
parents:
diff changeset
   408
    function &reverse()
0d28b7c10758 First commit
ymh
parents:
diff changeset
   409
    {
0d28b7c10758 First commit
ymh
parents:
diff changeset
   410
        $reverse = &new Text_Diff_Op_change($this->final, $this->orig);
0d28b7c10758 First commit
ymh
parents:
diff changeset
   411
        return $reverse;
0d28b7c10758 First commit
ymh
parents:
diff changeset
   412
    }
0d28b7c10758 First commit
ymh
parents:
diff changeset
   413
0d28b7c10758 First commit
ymh
parents:
diff changeset
   414
}