1<?php
2
3/**
4 * FINE granularity DIFF
5 *
6 * Computes a set of instructions to convert the content of
7 * one string into another.
8 *
9 * Originally created by Raymond Hill (https://github.com/gorhill/PHP-FineDiff), brought up
10 * to date by Cog Powered (https://github.com/cogpowered/FineDiff).
11 *
12 * @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
13 * @copyright Copyright 2013 (c) Robert Crowe (http://cogpowered.com)
14 * @link https://github.com/cogpowered/FineDiff
15 * @version 0.0.1
16 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
17 */
18
19namespace cogpowered\FineDiff\Render;
20
21use cogpowered\FineDiff\Parser\OpcodesInterface;
22use InvalidArgumentException;
23
24abstract class Renderer implements RendererInterface
25{
26    /**
27     * Covert text based on the provided opcodes.
28     *
29     * @param string                                              $from_text
30     * @param string|\cogpowered\FineDiff\Parser\OpcodesInterface $opcodes
31     *
32     * @return string
33     */
34    public function process($from_text, $opcodes)
35    {
36        // Validate opcodes
37        if (!is_string($opcodes) && !($opcodes instanceof OpcodesInterface)) {
38            throw new InvalidArgumentException('Invalid opcodes type');
39        } else {
40            $opcodes = ($opcodes instanceof OpcodesInterface) ? $opcodes->generate() : $opcodes;
41        }
42
43        // Holds the generated string that is returned
44        $output = '';
45
46        $opcodes_len    = strlen($opcodes);
47        $from_offset    = 0;
48        $opcodes_offset = 0;
49
50        while ($opcodes_offset < $opcodes_len) {
51
52            $opcode = substr($opcodes, $opcodes_offset, 1);
53            $opcodes_offset++;
54            $n = intval(substr($opcodes, $opcodes_offset));
55
56            if ($n) {
57                $opcodes_offset += strlen(strval($n));
58            } else {
59                $n = 1;
60            }
61
62            if ($opcode === 'c') {
63                // copy n characters from source
64                $data = $this->callback('c', $from_text, $from_offset, $n);
65                $from_offset += $n;
66            } else if ($opcode === 'd') {
67                // delete n characters from source
68                $data = $this->callback('d', $from_text, $from_offset, $n);
69                $from_offset += $n;
70            } else /* if ( $opcode === 'i' ) */ {
71                // insert n characters from opcodes
72                $data = $this->callback('i', $opcodes, $opcodes_offset + 1, $n);
73                $opcodes_offset += 1 + $n;
74            }
75
76            $output .= $data;
77        }
78
79        return $output;
80    }
81}