├── .github └── workflows │ ├── build.ps1 │ ├── install.ps1 │ ├── package.ps1 │ ├── test.ps1 │ └── windows.yml ├── .gitignore ├── .travis.yml ├── CREDITS ├── LICENSE ├── README.API ├── config.m4 ├── config.w32 ├── package.xml ├── php_xdiff.h ├── tests ├── 001.phpt ├── 002.phpt ├── 003.phpt ├── 004.phpt ├── 005.phpt ├── 006.phpt ├── 007.phpt ├── 008.phpt ├── 009.phpt ├── 010.phpt ├── 011.phpt ├── 012.phpt ├── 013.phpt ├── 014.phpt ├── 015.phpt ├── 016.phpt ├── 017.phpt ├── 018.phpt ├── 019.phpt ├── 020.phpt ├── 021.phpt ├── 022.phpt ├── 023.phpt ├── 024.phpt ├── 025.phpt ├── 026.phpt ├── 027.phpt ├── 028.phpt ├── 029.phpt ├── 030.phpt ├── 031.phpt ├── 032.phpt ├── 033.phpt ├── 034.phpt ├── 035.phpt ├── bug81552.phpt ├── context1.patch ├── context5.patch ├── error-bpatch.phpt ├── error-patch.phpt ├── error-patch2.phpt ├── file.1 ├── file.2 ├── file.bdiff ├── file.rabdiff ├── file_test.diff ├── logo.bdiff ├── logo.rabdiff ├── lorem1.txt ├── lorem2.txt ├── merge1.h ├── merge2.h ├── merge3.h ├── merge4.h ├── php.png └── zend.png ├── xdiff.c ├── xdiff.stub.php └── xdiff_arginfo.h /.github/workflows/build.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Parameter(Mandatory)] $arch 3 | ) 4 | 5 | $ErrorActionPreference = "Stop" 6 | 7 | Set-Location .. 8 | 9 | $develdir = (Get-Item "php-devel").FullName 10 | $phpdir = (Get-Item "php").FullName 11 | $Env:PATH = "$develdir;$phpdir;$Env:PATH" 12 | 13 | Set-Location "pecl-text-xdiff" 14 | 15 | $task = New-Item "..\task.bat" -Force 16 | Add-Content $task "call phpize 2>&1" 17 | Add-Content $task "call configure --with-prefix=$phpdir --with-extra-includes=deps\include --with-extra-libs=deps\lib --enable-debug-pack --with-xdiff" 18 | Add-Content $task "nmake 2>&1" 19 | Add-Content $task "exit %errorlevel%" 20 | & "..\php-sdk\phpsdk-vc15-$arch.bat" -t $task 21 | if (-not $?) { 22 | throw "build failed with errorlevel $LastExitCode" 23 | } 24 | -------------------------------------------------------------------------------- /.github/workflows/install.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Parameter(Mandatory)] $version, 3 | [Parameter(Mandatory)] $ts, 4 | [Parameter(Mandatory)] $arch, 5 | [Parameter(Mandatory)] $libxdiff 6 | ) 7 | 8 | $ErrorActionPreference = "Stop" 9 | 10 | if ($ts -eq "ts") { 11 | $tspart = "" 12 | } else { 13 | $tspart = "-nts"; 14 | } 15 | 16 | $releases = Invoke-WebRequest "https://windows.php.net/downloads/releases/releases.json" | ConvertFrom-Json 17 | $phpversion = $releases.$version.version 18 | 19 | Set-Location .. 20 | 21 | # SDK 22 | 23 | $file = "php-sdk-2.2.0.zip" 24 | Invoke-WebRequest "https://github.com/microsoft/php-sdk-binary-tools/archive/$file" -OutFile $file 25 | Expand-Archive $file -DestinationPath . 26 | Move-Item "php-sdk-binary-tools-php-sdk-2.2.0" -Destination "php-sdk" 27 | 28 | # PHP binaries 29 | 30 | $file = "php-$phpversion$tspart-Win32-vc15-$arch.zip" 31 | Invoke-WebRequest "https://windows.php.net/downloads/releases/$file" -OutFile $file 32 | Expand-Archive $file -DestinationPath "php" 33 | 34 | # PHP devel pack 35 | 36 | $file = "php-devel-pack-$phpversion$tspart-Win32-vc15-$arch.zip" 37 | Invoke-WebRequest "https://windows.php.net/downloads/releases/$file" -OutFile $file 38 | Expand-Archive $file -DestinationPath . 39 | Move-Item "php-$phpversion-devel-vc15-$arch" -Destination "php-devel" 40 | 41 | # libxdiff 42 | 43 | $file = "libxdiff-$libxdiff-vc15-$arch.zip" 44 | Invoke-WebRequest "https://windows.php.net/downloads/pecl/deps/$file" -OutFile $file 45 | Expand-Archive $file -DestinationPath "deps" 46 | Move-Item "deps\COPYING" "deps\COPYING.LIBXDIFF" 47 | -------------------------------------------------------------------------------- /.github/workflows/package.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Parameter(Mandatory)] $ts, 3 | [Parameter(Mandatory)] $arch 4 | ) 5 | 6 | $ErrorActionPreference = "Stop" 7 | 8 | if ($arch -eq "x86") { 9 | $builddir = "." 10 | } else { 11 | $builddir = "x64" 12 | } 13 | $builddir += "\Release" 14 | if ($ts -eq "ts") { 15 | $builddir += "_TS" 16 | } 17 | 18 | $dir = New-Item "windows_package" -ItemType "directory" 19 | Copy-Item "..\deps\COPYING.LIBXDIFF" -Destination $dir 20 | Copy-Item "CREDITS" -Destination $dir 21 | Copy-Item "LICENSE" -Destination $dir 22 | Copy-Item "README.API" -Destination $dir 23 | Copy-Item "$builddir\php_xdiff.dll" -Destination $dir 24 | Copy-Item "$builddir\php_xdiff.pdb" -Destination $dir 25 | -------------------------------------------------------------------------------- /.github/workflows/test.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [Parameter(Mandatory)] $arch 3 | ) 4 | 5 | $ErrorActionPreference = "Stop" 6 | 7 | Set-Location .. 8 | 9 | $develdir = (Get-Item "php-devel").FullName 10 | $phpdir = (Get-Item "php").FullName 11 | $Env:PATH = "$develdir;$phpdir;$Env:PATH" 12 | 13 | Set-Location "pecl-text-xdiff" 14 | 15 | $task = New-Item "..\task.bat" -Force 16 | Add-Content $task 'nmake test TESTS="--show-diff tests" 2>&1' 17 | Add-Content $task "exit %errorlevel%" 18 | & "..\php-sdk\phpsdk-vc15-$arch.bat" -t $task 19 | if (-not $?) { 20 | throw "build failed with errorlevel $LastExitCode" 21 | } 22 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows build 2 | on: [push] 3 | jobs: 4 | build: 5 | strategy: 6 | matrix: 7 | version: [7.4, 7.3] 8 | ts: [nts, ts] 9 | arch: [x64, x86] 10 | runs-on: windows-2016 11 | steps: 12 | - name: Set git to use LF 13 | run: | 14 | git config --global core.autocrlf false 15 | git config --global core.eol lf 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | - name: Install 19 | run: ./.github/workflows/install.ps1 -version ${{matrix.version}} -ts ${{matrix.ts}} -arch ${{matrix.arch}} -libxdiff 0.23 20 | - name: Build 21 | run: ./.github/workflows/build.ps1 -arch ${{matrix.arch}} 22 | - name: Package 23 | run: ./.github/workflows/package.ps1 -ts ${{matrix.ts}} -arch ${{matrix.arch}} 24 | - name: Test 25 | run: ./.github/workflows/test.ps1 -arch ${{matrix.arch}} 26 | - name: Upload 27 | uses: actions/upload-artifact@v2 28 | with: 29 | name: php_xdiff-dev-${{matrix.version}}-${{matrix.ts}}-vc15-${{matrix.arch}} 30 | path: windows_package 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | *.lo 3 | *.la 4 | *.dep 5 | .libs 6 | Makefile 7 | Makefile.fragments 8 | Makefile.global 9 | Makefile.objects 10 | acinclude.m4 11 | aclocal.m4 12 | autom4te.cache/ 13 | build/ 14 | config.guess 15 | config.h 16 | config.h.in 17 | config.h.in~ 18 | config.log 19 | config.nice 20 | config.status 21 | config.sub 22 | configure 23 | configure.in 24 | configure.ac 25 | install-sh 26 | libtool 27 | ltmain.sh 28 | ltmain.sh.backup 29 | missing 30 | mkinstalldirs 31 | run-tests.php 32 | tmp-php.ini 33 | modules 34 | libxdiff* 35 | xdiff-*.tgz 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - nightly 4 | sudo: true 5 | env: 6 | - REPORT_EXIT_STATUS=1 NO_INTERACTION=1 7 | before_install: 8 | - sudo add-apt-repository ppa:curse-sds/ppa -y 9 | - sudo apt-get update -q 10 | - sudo apt-get install libxdiff-dev libxdiff0 11 | install: 12 | - phpize 13 | - EXTRA_LDFLAGS="-precious-files-regex .libs/xdiff.gcno" LDFLAGS="-lgcov" CFLAGS="-Wall -fno-strict-aliasing -coverage -O0" ./configure 14 | - make all 15 | script: 16 | - TEST_PHP_EXECUTABLE=$(which php) php -n 17 | -d open_basedir= -d output_buffering=0 -d memory_limit=-1 18 | run-tests.php -n 19 | -d extension_dir=modules -d extension=xdiff.so --show-diff 20 | tests 21 | - gcov --object-directory .libs *.c 22 | - bash <(curl -s https://codecov.io/bash) 23 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | xdiff php extension 2 | Marcin Gibula -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------- 2 | The PHP License, version 3.01 3 | Copyright (c) 1999 - 2015 The PHP Group. All rights reserved. 4 | -------------------------------------------------------------------- 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, is permitted provided that the following conditions 8 | are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | 3. The name "PHP" must not be used to endorse or promote products 19 | derived from this software without prior written permission. For 20 | written permission, please contact group@php.net. 21 | 22 | 4. Products derived from this software may not be called "PHP", nor 23 | may "PHP" appear in their name, without prior written permission 24 | from group@php.net. You may indicate that your software works in 25 | conjunction with PHP by saying "Foo for PHP" instead of calling 26 | it "PHP Foo" or "phpfoo" 27 | 28 | 5. The PHP Group may publish revised and/or new versions of the 29 | license from time to time. Each version will be given a 30 | distinguishing version number. 31 | Once covered code has been published under a particular version 32 | of the license, you may always continue to use it under the terms 33 | of that version. You may also choose to use such covered code 34 | under the terms of any subsequent version of the license 35 | published by the PHP Group. No one other than the PHP Group has 36 | the right to modify the terms applicable to covered code created 37 | under this License. 38 | 39 | 6. Redistributions of any form whatsoever must retain the following 40 | acknowledgment: 41 | "This product includes PHP software, freely available from 42 | ". 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 45 | ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 46 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP 48 | DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 49 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 50 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 53 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 55 | OF THE POSSIBILITY OF SUCH DAMAGE. 56 | 57 | -------------------------------------------------------------------- 58 | 59 | This software consists of voluntary contributions made by many 60 | individuals on behalf of the PHP Group. 61 | 62 | The PHP Group can be contacted via Email at group@php.net. 63 | 64 | For more information on the PHP Group and the PHP project, 65 | please see . 66 | 67 | PHP includes the Zend Engine, freely available at 68 | . 69 | -------------------------------------------------------------------------------- /README.API: -------------------------------------------------------------------------------- 1 | This extension requires libxdiff (http://www.xmailserver.org/xdiff-lib.html). 2 | 3 | API: 4 | 5 | * mixed xdiff_string_diff(string str1, string str2, [int context, [bool minimal]]) 6 | 7 | Makes unified diff of strings str1 and str2. 'context' indicates how many 8 | lines of context you want to include in diff result. Set 'minimal' to true if 9 | you want to minimalize size of diff (can take a long time). Returns string 10 | with result or false if an internal error happened. 11 | 12 | * bool xdiff_file_diff(string file1, string file2, string dest, [int context, [bool minimal]]) 13 | 14 | Makes unified diff of files file1 and file2 and stores result in file dest. 15 | 'context' indicates how many lines of context you want to include in diff 16 | result. Set 'minimal' to true if you want to minimalize size of diff (can take 17 | a long time). 18 | 19 | * mixed xdiff_string_diff_binary(string str1, string str2) 20 | 21 | Makes binary diff of strings str1 and str2. Returns string with result or 22 | false if an internal error happened. 23 | 24 | * bool xdiff_file_diff_binary(string file1, string file2, string dest) 25 | 26 | Makes binary diff of files file1 and file2 and stores result in file dest. 27 | Returns string with result or false if an internal error happened. 28 | 29 | * string xdiff_string_patch(string file, string patch [, int flags, [string error]]) 30 | 31 | Patches string 'file' with unified patch in 'patch' and returns a patched string. 32 | 'flags' can be one of: 33 | XDIFF_PATCH_NORMAL - normal patch (default) 34 | XDIFF_PATCH_REVERSE - reverse patch 35 | 36 | If 'error' is passed then error is stored inside this variable (it is passed by reference). 37 | 38 | * mixed xdiff_file_patch(string file, string patch, string dest [, int flags]) 39 | 40 | Patches file 'file' with unified patch in file 'patch'. 41 | 'flags' can be one of: 42 | XDIFF_PATCH_NORMAL - normal patch (default) 43 | XDIFF_PATCH_REVERSE - reverse patch 44 | 45 | Returns false if an internal error happened, string with rejected chunks of 46 | patch or true if patch was applied successfully. 47 | 48 | * string xdiff_string_patch_binary(string str, string patch) 49 | 50 | Patches string 'str' with binary patch 'patch'. 51 | Returns patched string or false if an internal error happened. 52 | 53 | * bool xdiff_file_patch_binary(string file, string patch, string dest) 54 | 55 | Patches file 'file' with binary patch in file 'patch' and stores result in file 'dest'. 56 | Returns true if file was patched successfully, false otherwise. 57 | 58 | * string xdiff_string_merge3(string str1, string str2, string str3 [, string error]) 59 | 60 | Merges strings 'str1', 'str2' and 'str3' into one. Returns merged string or 61 | false if an internal error happened. If 'error' is passed then error is 62 | stored inside this variable (it is passed by reference). 63 | 64 | * mixed xdiff_file_merge3(string file1, string file2, string file3, string dest) 65 | 66 | Merges files 'file1', 'file2' and 'file3' into one and stores result in file 67 | 'dest'. Returns true if merge was successful, string with rejected chunks if 68 | it was not or false if an internal error happened. 69 | 70 | 71 | vim:tw=78:et: 72 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl config.m4 for extension xdiff 3 | 4 | PHP_ARG_WITH(xdiff, for xdiff support, 5 | [ --with-xdiff Include xdiff support]) 6 | 7 | 8 | if test "$PHP_XDIFF" != "no"; then 9 | 10 | SEARCH_PATH="/usr/local /usr" # you might want to change this 11 | SEARCH_FOR="/include/xdiff.h" # you most likely want to change this 12 | if test -r $PHP_XDIFF/; then # path given as parameter 13 | XDIFF_DIR=$PHP_XDIFF 14 | else # search default path list 15 | AC_MSG_CHECKING([for xdiff files in default path]) 16 | for i in $SEARCH_PATH ; do 17 | if test -r $i/$SEARCH_FOR; then 18 | XDIFF_DIR=$i 19 | AC_MSG_RESULT(found in $i) 20 | fi 21 | done 22 | fi 23 | 24 | if test -z "$XDIFF_DIR"; then 25 | AC_MSG_RESULT([not found]) 26 | AC_MSG_ERROR([Please reinstall the libxdiff distribution]) 27 | fi 28 | 29 | PHP_ADD_INCLUDE($XDIFF_DIR/include) 30 | 31 | EXTRA_LIBS="-lm" 32 | AC_CHECK_LIB(dl, dlopen, [ 33 | EXTRA_LIBS="$EXTRA_LIBS -ldl" 34 | ]) 35 | 36 | LIBNAME=xdiff 37 | LIBSYMBOL=xdl_diff 38 | 39 | PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, 40 | [ 41 | PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $XDIFF_DIR/lib, XDIFF_SHARED_LIBADD) 42 | AC_DEFINE(HAVE_XDIFFLIB,1, [ libxdiff ]) 43 | ],[ 44 | AC_MSG_ERROR([wrong xdiff lib version or lib not found]) 45 | ],[ 46 | -L$XDIFF_DIR/lib $EXTRA_LIBS 47 | ]) 48 | PHP_SUBST(XDIFF_SHARED_LIBADD) 49 | 50 | dnl check for if XDL_PATCH_IGNOREBSPACE is available 51 | old_CPPFLAGS=$CPPFLAGS 52 | CPPFLAGS=-I$XDIFF_DIR/include 53 | AC_MSG_CHECKING(if XDL_PATCH_IGNOREBSPACE is defined) 54 | AC_TRY_COMPILE([ 55 | #include ],[ 56 | int i = XDL_PATCH_IGNOREBSPACE; 57 | ], AC_MSG_RESULT(yes) , AC_MSG_ERROR(your libxdiff version is too old) ) 58 | CPPFLAGS=$old_CPPFLAGS 59 | 60 | dnl check for xdl_rabdiff function 61 | PHP_CHECK_LIBRARY(xdiff,xdl_set_allocator, [ ], AC_MSG_ERROR([your libxdiff version is too old])) 62 | 63 | dnl check for xdl_rabdiff function 64 | PHP_CHECK_LIBRARY(xdiff,xdl_rabdiff, [ ], AC_MSG_ERROR([your libxdiff version is too old])) 65 | 66 | PHP_NEW_EXTENSION(xdiff, xdiff.c, $ext_shared) 67 | fi 68 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | ARG_WITH("xdiff", "libxdiff support", "no"); 5 | 6 | if (PHP_XDIFF != "no") { 7 | if (CHECK_LIB("xdiff.lib;xdiff_a.lib", "xdiff", PHP_XDIFF + ";..\\libxdiff-*") && 8 | CHECK_HEADER_ADD_INCLUDE("xdiff.h", "CFLAGS_XDIFF", PHP_XDIFF + ";..\\libxdiff-*\\xdiff")) { 9 | EXTENSION("xdiff", "xdiff.c"); 10 | } else { 11 | WARNING("did not find xdiff includes/libs"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | xdiff 7 | pecl.php.net 8 | File differences/patches. 9 | This extension creates and applies patches to both text and binary files. 10 | 11 | 12 | Marcin Gibula 13 | mg 14 | mg@iceni.pl 15 | yes 16 | 17 | 18 | Sean DuBois 19 | SeanDer 20 | sean@siobud.com 21 | yes 22 | 23 | 24 | Remi Collet 25 | remi 26 | remi@php.net 27 | yes 28 | 29 | 2022-05-24 30 | 31 | 2.1.1 32 | 2.1.0 33 | 34 | 35 | stable 36 | stable 37 | 38 | PHP License 39 | 40 | - Fixed bug #81552 xdiff_string_bpatch() and others missing (Kevin Israel) 41 | - Fixed bug #77826 xdiff_string_bpatch wrong return value on error (SATO Kentaro) 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 7.0.0 117 | 118 | 119 | 1.10 120 | 121 | 122 | 123 | xdiff 124 | 125 | 126 | 127 | 128 | 129 | 2021-05-18 130 | 131 | 2.1.0 132 | 2.1.0 133 | 134 | 135 | stable 136 | stable 137 | 138 | PHP License 139 | 140 | - PHP 8 support 141 | - Drop PHP 5 support 142 | 143 | 144 | 145 | 146 | 2.0.1 147 | 2.0 148 | 149 | 150 | stable 151 | beta 152 | 153 | 2016-05-17 154 | PHP License 155 | Update License to PHP 3.1 156 | 157 | 158 | 159 | 2.0.0 160 | 2.0 161 | 162 | 163 | stable 164 | beta 165 | 166 | 2015-11-23 167 | PHP License 168 | PHP 7 Release. 169 | 170 | 171 | 172 | 1.5.1 173 | 1.5 174 | 175 | 176 | beta 177 | beta 178 | 179 | 2009-10-18 180 | PHP License 181 | Fix for #16566. 182 | 183 | 184 | 185 | 1.5.0 186 | 1.5 187 | 188 | 189 | beta 190 | beta 191 | 192 | 2009-10-18 193 | PHP License 194 | New functions added. Memory optimizations. Better handling of out of memory situations. 195 | 196 | 197 | 198 | 1.4.1 199 | 1.4 200 | 201 | 202 | stable 203 | stable 204 | 205 | 2008-07-01 206 | PHP License 207 | Fixes for #7215, #7422 and #8227. 208 | 209 | 210 | 211 | 1.4 212 | 1.4 213 | 214 | 215 | stable 216 | stable 217 | 218 | 2005-11-14 219 | PHP License 220 | Fixed bug #5064. 221 | 222 | 223 | 224 | 1.3 225 | 1.3 226 | 227 | 228 | stable 229 | stable 230 | 231 | 2005-05-09 232 | PHP License 233 | Fix compile error. 234 | 235 | 236 | 237 | 1.2 238 | 1.2 239 | 240 | 241 | stable 242 | stable 243 | 244 | 2004-11-09 245 | PHP License 246 | Fix libxdiff 0.9 crash. Force last parameters of xdiff_string_patch and xdiff_string_merge3 to be passed by reference. 247 | 248 | 249 | 250 | 1.1 251 | 1.1 252 | 253 | 254 | stable 255 | stable 256 | 257 | 2004-03-21 258 | PHP License 259 | Fix FreeBSD build. 260 | 261 | 262 | 263 | 1.0 264 | 1.0 265 | 266 | 267 | stable 268 | stable 269 | 270 | 2004-02-09 271 | PHP License 272 | Add support to memory_limit (libxdiff >= 0.6 required). 273 | 274 | 275 | 276 | 0.3 277 | 0.3 278 | 279 | 280 | alpha 281 | alpha 282 | 283 | 2004-01-10 284 | PHP License 285 | Win32 build fixes. 286 | 287 | 288 | 289 | 0.2 290 | 0.2 291 | 292 | 293 | alpha 294 | alpha 295 | 296 | 2004-01-08 297 | PHP License 298 | Initial release. 299 | 300 | 301 | 302 | -------------------------------------------------------------------------------- /php_xdiff.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | Copyright (c) The PHP Group | 4 | +----------------------------------------------------------------------+ 5 | | This source file is subject to version 3.1 of the PHP license, | 6 | | that is bundled with this package in the file LICENSE, and is | 7 | | available at through the world-wide-web at | 8 | | http://www.php.net/license/3_1.txt. | 9 | | If you did not receive a copy of the PHP license and are unable to | 10 | | obtain it through the world-wide-web, please send a note to | 11 | | license@php.net so we can mail you a copy immediately. | 12 | +----------------------------------------------------------------------+ 13 | | Author: Marcin Gibula | 14 | +----------------------------------------------------------------------+ 15 | 16 | $Id$ 17 | */ 18 | 19 | #ifndef PHP_XDIFF_H 20 | #define PHP_XDIFF_H 21 | 22 | extern zend_module_entry xdiff_module_entry; 23 | #define phpext_xdiff_ptr &xdiff_module_entry 24 | 25 | #define PHP_XDIFF_VERSION "2.1.1" 26 | 27 | #ifdef PHP_WIN32 28 | #define PHP_XDIFF_API __declspec(dllexport) 29 | #else 30 | #define PHP_XDIFF_API 31 | #endif 32 | 33 | #ifdef ZTS 34 | #include "TSRM.h" 35 | #endif 36 | 37 | PHP_MINIT_FUNCTION(xdiff); 38 | PHP_MINFO_FUNCTION(xdiff); 39 | 40 | #endif /* PHP_XDIFF_H */ 41 | 42 | 43 | /* 44 | * Local variables: 45 | * tab-width: 4 46 | * c-basic-offset: 4 47 | * indent-tabs-mode: t 48 | * End: 49 | */ 50 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for xdiff presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 9 | --EXPECT-- 10 | xdiff extension is available 11 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_diff() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 11 | --EXPECT-- 12 | @@ -3,3 +3,3 @@ 13 | echo $a; 14 | -$b = 320; 15 | +$b = 420; 16 | echo $b; 17 | 18 | -------------------------------------------------------------------------------- /tests/003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_diff() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 11 | --EXPECT-- 12 | @@ -3,3 +3,3 @@ 13 | echo $a; 14 | -$b = 320; 15 | +$b = 420; 16 | echo $b; 17 | 18 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_diff_binary() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_diff_binary() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | int(0) 15 | -------------------------------------------------------------------------------- /tests/007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | int(0) 15 | -------------------------------------------------------------------------------- /tests/008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch_binary() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/009.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch_binary() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/010.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_merge3() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 14 | --EXPECT-- 15 | 0 16 | -------------------------------------------------------------------------------- /tests/011.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_merge3() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/012.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_rabdiff() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/013.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_rabdiff() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/014.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch_binary() with rabdiff patch 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/015.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch_binary() with rabdiff patch 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/016.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_diff_binary() with binary data 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/017.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_diff_binary() with binary data 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/018.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_rabdiff() with binary data 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/019.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_rabdiff() with binary data 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/020.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch_binary() with binary data 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/021.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch_binary() with binary data and rabdiff patch 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/022.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch_binary() with binary data 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/023.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch_binary() with binary data and rabdiff patch 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/024.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_diff() with context = 1 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 12 | --EXPECT-- 13 | 0 14 | -------------------------------------------------------------------------------- /tests/025.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_diff() with context = 5 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 12 | --EXPECT-- 13 | 0 14 | -------------------------------------------------------------------------------- /tests/026.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_diff() with context = 1 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 11 | --EXPECT-- 12 | 0 13 | -------------------------------------------------------------------------------- /tests/027.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_diff() with context = 5 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 11 | --EXPECT-- 12 | 0 13 | -------------------------------------------------------------------------------- /tests/028.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch() with context1.patch 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/029.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch() with context5.patch 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/030.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch() with context1.patch and reverse patching 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/031.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch() with context5.patch and reverse patching 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/032.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch() and context1.patch 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/033.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch() and context5.patch 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/034.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch() and context1.patch and reverse patching 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/035.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_file_patch() and context5.patch and reverse patching 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | 0 15 | -------------------------------------------------------------------------------- /tests/bug81552.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Bug #81552: xdiff_string_bpatch() and others missing 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 18 | --EXPECT-- 19 | string(44) "The quick brown fox jumps over the lazy cog." 20 | int(0) 21 | -------------------------------------------------------------------------------- /tests/context1.patch: -------------------------------------------------------------------------------- 1 | @@ -9,6 +9,2 @@ 2 | 3 | - * Aenean porta lectus ut diam. 4 | - * Vestibulum volutpat sollicitudin lorem. 5 | - * Morbi at tortor vel pede scelerisque eleifend. 6 | - 7 | * Mauris sed dolor sed est aliquam lobortis. 8 | -------------------------------------------------------------------------------- /tests/context5.patch: -------------------------------------------------------------------------------- 1 | @@ -5,14 +5,10 @@ 2 | * Curabitur a lorem ut tellus fermentum molestie. 3 | * Etiam eleifend sollicitudin neque. 4 | * Etiam quis justo in felis gravida rutrum. 5 | * Aenean ultrices diam id mi. 6 | 7 | - * Aenean porta lectus ut diam. 8 | - * Vestibulum volutpat sollicitudin lorem. 9 | - * Morbi at tortor vel pede scelerisque eleifend. 10 | - 11 | * Mauris sed dolor sed est aliquam lobortis. 12 | * Donec vestibulum nulla a augue. 13 | * Aliquam viverra sollicitudin nisl. 14 | * Nam vitae massa venenatis orci consequat fringilla. 15 | 16 | -------------------------------------------------------------------------------- /tests/error-bpatch.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_bpatch() error 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 12 | --EXPECT-- 13 | bool(false) 14 | -------------------------------------------------------------------------------- /tests/error-patch.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch() error 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 12 | --EXPECT-- 13 | bool(false) 14 | -------------------------------------------------------------------------------- /tests/error-patch2.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | xdiff_string_patch() rejection 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 13 | --EXPECT-- 14 | bool(true) 15 | bool(true) 16 | -------------------------------------------------------------------------------- /tests/file.1: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /tests/file.2: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /tests/file.bdiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-text-xdiff/21857dbe38d052ff0313e7a97086afa8a2398a12/tests/file.bdiff -------------------------------------------------------------------------------- /tests/file.rabdiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-text-xdiff/21857dbe38d052ff0313e7a97086afa8a2398a12/tests/file.rabdiff -------------------------------------------------------------------------------- /tests/file_test.diff: -------------------------------------------------------------------------------- 1 | @@ -3,3 +3,3 @@ 2 | echo $a; 3 | -$b = 320; 4 | +$b = 420; 5 | echo $b; 6 | -------------------------------------------------------------------------------- /tests/logo.bdiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-text-xdiff/21857dbe38d052ff0313e7a97086afa8a2398a12/tests/logo.bdiff -------------------------------------------------------------------------------- /tests/logo.rabdiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-text-xdiff/21857dbe38d052ff0313e7a97086afa8a2398a12/tests/logo.rabdiff -------------------------------------------------------------------------------- /tests/lorem1.txt: -------------------------------------------------------------------------------- 1 | * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 2 | * Curabitur fermentum rhoncus leo. 3 | * Phasellus pretium nibh nec neque. 4 | * In porta lectus nec ligula. 5 | * Curabitur a lorem ut tellus fermentum molestie. 6 | * Etiam eleifend sollicitudin neque. 7 | * Etiam quis justo in felis gravida rutrum. 8 | * Aenean ultrices diam id mi. 9 | 10 | * Aenean porta lectus ut diam. 11 | * Vestibulum volutpat sollicitudin lorem. 12 | * Morbi at tortor vel pede scelerisque eleifend. 13 | 14 | * Mauris sed dolor sed est aliquam lobortis. 15 | * Donec vestibulum nulla a augue. 16 | * Aliquam viverra sollicitudin nisl. 17 | * Nam vitae massa venenatis orci consequat fringilla. 18 | 19 | * Nullam sollicitudin dignissim sem. 20 | * Aenean sed tellus id felis rhoncus eleifend. 21 | * Vivamus vulputate turpis eu tortor. 22 | * Sed vulputate sollicitudin dui. 23 | * Proin porta nibh ac orci. 24 | -------------------------------------------------------------------------------- /tests/lorem2.txt: -------------------------------------------------------------------------------- 1 | * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 2 | * Curabitur fermentum rhoncus leo. 3 | * Phasellus pretium nibh nec neque. 4 | * In porta lectus nec ligula. 5 | * Curabitur a lorem ut tellus fermentum molestie. 6 | * Etiam eleifend sollicitudin neque. 7 | * Etiam quis justo in felis gravida rutrum. 8 | * Aenean ultrices diam id mi. 9 | 10 | * Mauris sed dolor sed est aliquam lobortis. 11 | * Donec vestibulum nulla a augue. 12 | * Aliquam viverra sollicitudin nisl. 13 | * Nam vitae massa venenatis orci consequat fringilla. 14 | 15 | * Nullam sollicitudin dignissim sem. 16 | * Aenean sed tellus id felis rhoncus eleifend. 17 | * Vivamus vulputate turpis eu tortor. 18 | * Sed vulputate sollicitudin dui. 19 | * Proin porta nibh ac orci. 20 | -------------------------------------------------------------------------------- /tests/merge1.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_XDIFF_H 2 | #define PHP_XDIFF_H 3 | 4 | extern zend_module_entry xdiff_module_entry; 5 | #define phpext_xdiff_ptr &diff_module_entry 6 | 7 | #ifdef PHP_WIN32 8 | #define PHP_XDIFF_API __declspec(dllexport) 9 | #else 10 | #define PHP_XDIFF_API 11 | #endif 12 | 13 | #ifdef ZTS 14 | #include "TSRM.h" 15 | #endif 16 | 17 | PHP_MINIT_FUNCTION(xdiff); 18 | PHP_MINFO_FUNCTION(xdiff); 19 | 20 | PHP_FUNCTION(xdiff_file_diff); 21 | PHP_FUNCTION(xdiff_file_diff_binary); 22 | PHP_FUNCTION(xdiff_file_patch); 23 | PHP_FUNCTION(xdiff_file_patch_binary); 24 | PHP_FUNCTION(xdiff_file_merge3); 25 | 26 | PHP_FUNCTION(xdiff_string_diff); 27 | PHP_FUNCTION(xdiff_string_diff_binary); 28 | PHP_FUNCTION(xdiff_string_patch); 29 | PHP_FUNCTION(xdiff_string_patch_binary); 30 | PHP_FUNCTION(xdiff_string_merge3); 31 | 32 | #endif /* PHP_XDIFF_H */ 33 | 34 | 35 | /* 36 | * Local variables: 37 | * tab-width: 4 38 | * c-basic-offset: 4 39 | * indent-tabs-mode: t 40 | * End: 41 | */ 42 | -------------------------------------------------------------------------------- /tests/merge2.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_XDIFF_H 2 | #define PHP_XDIFF_H 3 | 4 | #foo 5 | #define phpext_xdiff_ptr &diff_module_entry 6 | 7 | #ifdef PHP_WIN32 8 | #define PHP_XDIFF_API __declspec(dllexport) 9 | #else 10 | #define PHP_XDIFF_API 11 | #endif 12 | 13 | #ifdef ZTS 14 | #include "TSRM.h" 15 | #endif 16 | 17 | PHP_MINIT_FUNCTION(xdiff); 18 | PHP_MINFO_FUNCTION(xdiff); 19 | 20 | PHP_FUNCTION(xdiff_file_diff); 21 | PHP_FUNCTION(xdiff_file_diff_binary); 22 | PHP_FUNCTION(xdiff_file_patch); 23 | PHP_FUNCTION(xdiff_file_patch_binary); 24 | PHP_FUNCTION(xdiff_file_merge3); 25 | 26 | PHP_FUNCTION(xdiff_string_diff); 27 | PHP_FUNCTION(xdiff_string_diff_binary); 28 | PHP_FUNCTION(xdiff_string_patch); 29 | PHP_FUNCTION(xdiff_string_patch_binary); 30 | PHP_FUNCTION(xdiff_string_merge3); 31 | 32 | #endif /* PHP_XDIFF_H */ 33 | 34 | 35 | /* 36 | * Local variables: 37 | * tab-width: 4 38 | * c-basic-offset: 4 39 | * indent-tabs-mode: t 40 | * End: 41 | */ 42 | -------------------------------------------------------------------------------- /tests/merge3.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_XDIFF_H 2 | #define PHP_XDIFF_H 3 | 4 | extern zend_module_entry xdiff_module_entry; 5 | #define phpext_xdiff_ptr &diff_module_entry 6 | 7 | #ifdef PHP_WIN32 8 | #define PHP_XDIFF_API __declspec(dllexport) 9 | #else 10 | #define PHP_XDIFF_API 11 | #endif 12 | 13 | #ifdef ZTS 14 | #include "TSRM.h" 15 | #endif 16 | 17 | PHP_MINIT_FUNCTION(foo); 18 | PHP_MINFO_FUNCTION(foo); 19 | 20 | PHP_FUNCTION(xdiff_string_diff); 21 | PHP_FUNCTION(xdiff_string_diff_binary); 22 | PHP_FUNCTION(xdiff_string_patch); 23 | PHP_FUNCTION(xdiff_string_patch_binary); 24 | PHP_FUNCTION(xdiff_string_merge3); 25 | 26 | #endif /* PHP_XDIFF_H */ 27 | 28 | 29 | /* 30 | * Local variables: 31 | * tab-width: 4 32 | * c-basic-offset: 4 33 | * indent-tabs-mode: t 34 | * End: 35 | */ 36 | -------------------------------------------------------------------------------- /tests/merge4.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_XDIFF_H 2 | #define PHP_XDIFF_H 3 | 4 | #foo 5 | #define phpext_xdiff_ptr &diff_module_entry 6 | 7 | #ifdef PHP_WIN32 8 | #define PHP_XDIFF_API __declspec(dllexport) 9 | #else 10 | #define PHP_XDIFF_API 11 | #endif 12 | 13 | #ifdef ZTS 14 | #include "TSRM.h" 15 | #endif 16 | 17 | PHP_MINIT_FUNCTION(foo); 18 | PHP_MINFO_FUNCTION(foo); 19 | 20 | PHP_FUNCTION(xdiff_string_diff); 21 | PHP_FUNCTION(xdiff_string_diff_binary); 22 | PHP_FUNCTION(xdiff_string_patch); 23 | PHP_FUNCTION(xdiff_string_patch_binary); 24 | PHP_FUNCTION(xdiff_string_merge3); 25 | 26 | #endif /* PHP_XDIFF_H */ 27 | 28 | 29 | /* 30 | * Local variables: 31 | * tab-width: 4 32 | * c-basic-offset: 4 33 | * indent-tabs-mode: t 34 | * End: 35 | */ 36 | -------------------------------------------------------------------------------- /tests/php.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-text-xdiff/21857dbe38d052ff0313e7a97086afa8a2398a12/tests/php.png -------------------------------------------------------------------------------- /tests/zend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-text-xdiff/21857dbe38d052ff0313e7a97086afa8a2398a12/tests/zend.png -------------------------------------------------------------------------------- /xdiff.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | Copyright (c) The PHP Group | 4 | +----------------------------------------------------------------------+ 5 | | This source file is subject to version 3.1 of the PHP license, | 6 | | that is bundled with this package in the file LICENSE, and is | 7 | | available at through the world-wide-web at | 8 | | http://www.php.net/license/3_1.txt. | 9 | | If you did not receive a copy of the PHP license and are unable to | 10 | | obtain it through the world-wide-web, please send a note to | 11 | | license@php.net so we can mail you a copy immediately. | 12 | +----------------------------------------------------------------------+ 13 | | Author: Marcin Gibula | 14 | +----------------------------------------------------------------------+ 15 | 16 | $Id$ 17 | */ 18 | 19 | #ifdef HAVE_CONFIG_H 20 | #include "config.h" 21 | #endif 22 | 23 | #include "php.h" 24 | #include "php_ini.h" 25 | #include "ext/standard/info.h" 26 | #include "php_xdiff.h" 27 | 28 | #ifndef ZEND_ARG_INFO_WITH_DEFAULT_VALUE 29 | #define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \ 30 | ZEND_ARG_INFO(pass_by_ref, name) 31 | #endif 32 | #if PHP_VERSION_ID < 70200 33 | #undef ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX 34 | #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ 35 | static const zend_internal_arg_info name[] = { \ 36 | { (const char*)(zend_uintptr_t)(required_num_args), ( #class_name ), 0, return_reference, allow_null, 0 }, 37 | #endif 38 | 39 | #ifndef ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX 40 | #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ 41 | ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) 42 | #endif 43 | 44 | #ifndef ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE 45 | #define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \ 46 | ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) 47 | #endif 48 | 49 | #include "xdiff_arginfo.h" 50 | 51 | #ifdef PHP_WIN32 52 | /* libxdiff is compiled with /Zp1 */ 53 | # pragma pack(push, 1) 54 | #endif 55 | #include 56 | #ifdef PHP_WIN32 57 | # pragma pack(pop) 58 | #endif 59 | 60 | /* Not exported by header file */ 61 | extern char libxdiff_version[]; 62 | 63 | struct string_buffer { 64 | char *ptr; 65 | unsigned long size; 66 | }; 67 | 68 | static int load_mm_file(const char *filepath, mmfile_t *dest); 69 | static int load_into_mm_file(const char *buffer, unsigned long size, mmfile_t *dest); 70 | static int append_string(void *ptr, mmbuffer_t *buffer, int array_size); 71 | static int append_stream(void *ptr, mmbuffer_t *buffer, int array_size); 72 | static int init_string(struct string_buffer *string); 73 | static void free_string(struct string_buffer *string); 74 | 75 | static int make_diff(char *filepath1, char *filepath2, xdemitcb_t *output, int context, int minimal); 76 | static int make_diff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output, int context, int minimal); 77 | static int make_bdiff(char *filepath1, char *filepath2, xdemitcb_t *output); 78 | static int make_bdiff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output); 79 | static int make_patch(char *file_path, char *patch_path, xdemitcb_t *output, xdemitcb_t *error, int flags); 80 | static int make_patch_str(char *file, int size1, char *patch, int size2, xdemitcb_t *output, xdemitcb_t *error, int flags); 81 | static int make_bpatch(char *file_path, char *patch_path, xdemitcb_t *output); 82 | static int make_bpatch_str(char *file, int size1, char *patch, int size2, xdemitcb_t *output); 83 | static int make_merge3(char *filepath1, char *filepath2, char *filepath3, xdemitcb_t *output, xdemitcb_t *error); 84 | static int make_merge3_str(char *content1, int size1, char *content2, int size2, char *content3, int size3, xdemitcb_t *output, xdemitcb_t *error); 85 | static int make_rabdiff(char *filepath1, char *filepath2, xdemitcb_t *output); 86 | static int make_rabdiff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output); 87 | 88 | static void *xdiff_malloc(void *foo, unsigned int size) 89 | { 90 | return emalloc(size); 91 | } 92 | 93 | static void xdiff_free(void *foo, void *ptr) 94 | { 95 | if (ptr) { 96 | efree(ptr); 97 | } 98 | } 99 | 100 | static void *xdiff_realloc(void *foo, void *ptr, unsigned int nsize) 101 | { 102 | return erealloc(ptr, nsize); 103 | } 104 | 105 | static memallocator_t allocator = { NULL, xdiff_malloc, xdiff_free, xdiff_realloc }; 106 | 107 | /* {{{ xdiff_module_entry 108 | */ 109 | zend_module_entry xdiff_module_entry = { 110 | #if ZEND_MODULE_API_NO >= 20010901 111 | STANDARD_MODULE_HEADER, 112 | #endif 113 | "xdiff", 114 | ext_functions, 115 | PHP_MINIT(xdiff), 116 | NULL, 117 | NULL, 118 | NULL, 119 | PHP_MINFO(xdiff), 120 | #if ZEND_MODULE_API_NO >= 20010901 121 | PHP_XDIFF_VERSION, 122 | #endif 123 | STANDARD_MODULE_PROPERTIES 124 | }; 125 | /* }}} */ 126 | 127 | #ifdef COMPILE_DL_XDIFF 128 | ZEND_GET_MODULE(xdiff) 129 | #endif 130 | 131 | /* {{{ PHP_MINIT_FUNCTION 132 | */ 133 | PHP_MINIT_FUNCTION(xdiff) 134 | { 135 | xdl_set_allocator(&allocator); 136 | 137 | REGISTER_LONG_CONSTANT("XDIFF_PATCH_NORMAL", XDL_PATCH_NORMAL, CONST_CS | CONST_PERSISTENT); 138 | REGISTER_LONG_CONSTANT("XDIFF_PATCH_REVERSE", XDL_PATCH_REVERSE, CONST_CS | CONST_PERSISTENT); 139 | REGISTER_LONG_CONSTANT("XDIFF_PATCH_IGNORESPACE", XDL_PATCH_IGNOREBSPACE, CONST_CS | CONST_PERSISTENT); 140 | 141 | return SUCCESS; 142 | } 143 | /* }}} */ 144 | 145 | /* {{{ PHP_MINFO_FUNCTION 146 | */ 147 | PHP_MINFO_FUNCTION(xdiff) 148 | { 149 | php_info_print_table_start(); 150 | php_info_print_table_header(2, "xdiff support", "enabled"); 151 | php_info_print_table_row(2, "extension version", PHP_XDIFF_VERSION); 152 | php_info_print_table_row(2, "libxdiff version", libxdiff_version); 153 | php_info_print_table_end(); 154 | } 155 | /* }}} */ 156 | 157 | /* {{{ proto mixed xdiff_string_diff(string str1, string str2, [int context, [bool minimal]]) 158 | */ 159 | PHP_FUNCTION(xdiff_string_diff) 160 | { 161 | zend_string *str1, *str2; 162 | int retval; 163 | zend_bool minimal = 0; 164 | zend_long context = 3; 165 | xdemitcb_t output; 166 | struct string_buffer string; 167 | 168 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|lb", &str1, &str2, &context, &minimal) == FAILURE) { 169 | RETURN_FALSE; 170 | } 171 | 172 | RETVAL_FALSE; 173 | 174 | retval = init_string(&string); 175 | if (!retval) 176 | goto out; 177 | 178 | output.priv= &string; 179 | output.outf = append_string; 180 | 181 | make_diff_str(str1->val, str1->len, str2->val, str2->len, &output, context, minimal); 182 | RETVAL_STRINGL(string.ptr, string.size); 183 | free_string(&string); 184 | out: 185 | return; 186 | } 187 | /* }}} */ 188 | 189 | /* {{{ proto bool xdiff_file_diff(string file1, string file2, string dest, [int context, [bool minimal]]) 190 | */ 191 | PHP_FUNCTION(xdiff_file_diff) 192 | { 193 | zend_string *filepath1, *filepath2, *dest; 194 | int retval; 195 | zend_bool minimal = 0; 196 | zend_long context = 3; 197 | xdemitcb_t output; 198 | php_stream *output_stream; 199 | 200 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS|lb", &filepath1, &filepath2, &dest, &context, &minimal) == FAILURE) { 201 | RETURN_FALSE; 202 | } 203 | 204 | RETVAL_FALSE; 205 | 206 | output_stream = php_stream_open_wrapper(dest->val, "wb", REPORT_ERRORS, NULL); 207 | if (!output_stream) 208 | goto out; 209 | 210 | output.priv = output_stream; 211 | output.outf = append_stream; 212 | 213 | retval = make_diff(filepath1->val, filepath2->val, &output, context, minimal); 214 | if (!retval) 215 | goto out_stream_close; 216 | 217 | RETVAL_TRUE; 218 | 219 | out_stream_close: 220 | php_stream_close(output_stream); 221 | out: 222 | return; 223 | } 224 | /* }}} */ 225 | 226 | /* {{{ proto mixed xdiff_string_diff_binary(string str1, string str2) 227 | */ 228 | PHP_FUNCTION(xdiff_string_bdiff) 229 | { 230 | zend_string *str1, *str2; 231 | int retval; 232 | xdemitcb_t output; 233 | struct string_buffer string; 234 | 235 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &str1, &str2) == FAILURE) { 236 | RETURN_FALSE; 237 | } 238 | 239 | RETVAL_FALSE; 240 | 241 | retval = init_string(&string); 242 | if (!retval) 243 | goto out; 244 | 245 | output.priv= &string; 246 | output.outf = append_string; 247 | 248 | make_bdiff_str(str1->val, str1->len, str2->val, str2->len, &output); 249 | RETVAL_STRINGL(string.ptr, string.size); 250 | free_string(&string); 251 | 252 | out: 253 | return; 254 | } 255 | /* }}} */ 256 | 257 | /* {{{ proto bool xdiff_file_diff_binary(string file1, string file2, string dest) 258 | */ 259 | PHP_FUNCTION(xdiff_file_bdiff) 260 | { 261 | zend_string *filepath1, *filepath2, *result; 262 | int retval; 263 | xdemitcb_t output; 264 | php_stream *output_stream; 265 | 266 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &filepath1, &filepath2, &result) == FAILURE) { 267 | RETURN_FALSE; 268 | } 269 | 270 | RETVAL_FALSE; 271 | 272 | output_stream = php_stream_open_wrapper(result->val, "wb", REPORT_ERRORS, NULL); 273 | if (!output_stream) 274 | goto out; 275 | 276 | output.priv = output_stream; 277 | output.outf = append_stream; 278 | 279 | retval = make_bdiff(filepath1->val, filepath2->val, &output); 280 | if (!retval) 281 | goto out_stream_close; 282 | 283 | RETVAL_TRUE; 284 | 285 | out_stream_close: 286 | php_stream_close(output_stream); 287 | out: 288 | return; 289 | } 290 | /* }}} */ 291 | 292 | /* {{{ proto mixed xdiff_string_rabdiff(string str1, string str2) 293 | */ 294 | PHP_FUNCTION(xdiff_string_rabdiff) 295 | { 296 | zend_string *str1, *str2; 297 | int retval; 298 | xdemitcb_t output; 299 | struct string_buffer string; 300 | 301 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &str1, &str2) == FAILURE) { 302 | RETURN_FALSE; 303 | } 304 | 305 | RETVAL_FALSE; 306 | 307 | retval = init_string(&string); 308 | if (!retval) 309 | goto out; 310 | 311 | output.priv= &string; 312 | output.outf = append_string; 313 | 314 | make_rabdiff_str(str1->val, str1->len, str2->val, str2->len, &output); 315 | RETVAL_STRINGL(string.ptr, string.size); 316 | free_string(&string); 317 | 318 | out: 319 | return; 320 | } 321 | /* }}} */ 322 | 323 | /* {{{ proto bool xdiff_file_rabdiff(string file1, string file2, string dest) 324 | */ 325 | PHP_FUNCTION(xdiff_file_rabdiff) 326 | { 327 | zend_string *filepath1, *filepath2, *result; 328 | int retval; 329 | xdemitcb_t output; 330 | php_stream *output_stream; 331 | 332 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &filepath1, &filepath2, &result) == FAILURE) { 333 | RETURN_FALSE; 334 | } 335 | 336 | RETVAL_FALSE; 337 | 338 | output_stream = php_stream_open_wrapper(result->val, "wb", REPORT_ERRORS, NULL); 339 | if (!output_stream) 340 | goto out; 341 | 342 | output.priv = output_stream; 343 | output.outf = append_stream; 344 | 345 | retval = make_rabdiff(filepath1->val, filepath2->val, &output); 346 | if (!retval) 347 | goto out_stream_close; 348 | 349 | RETVAL_TRUE; 350 | 351 | out_stream_close: 352 | php_stream_close(output_stream); 353 | out: 354 | return; 355 | } 356 | /* }}} */ 357 | 358 | /* {{{ proto bool xdiff_file_bdiff_size(string file1, string file2, string dest) 359 | */ 360 | PHP_FUNCTION(xdiff_file_bdiff_size) 361 | { 362 | zend_string *filepath; 363 | int retval; 364 | long result; 365 | mmfile_t file; 366 | 367 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &filepath) == FAILURE) { 368 | RETURN_FALSE; 369 | } 370 | 371 | RETVAL_FALSE; 372 | 373 | retval = load_mm_file(filepath->val, &file); 374 | if (!retval) 375 | goto out; 376 | 377 | result = xdl_bdiff_tgsize(&file); 378 | if (result < 0) 379 | goto out_free_mmfile; 380 | 381 | RETVAL_LONG(result); 382 | 383 | out_free_mmfile: 384 | xdl_free_mmfile(&file); 385 | out: 386 | return; 387 | } 388 | /* }}} */ 389 | 390 | /* {{{ proto bool xdiff_string_bdiff_size(string file1, string file2, string dest) 391 | */ 392 | PHP_FUNCTION(xdiff_string_bdiff_size) 393 | { 394 | zend_string *patch; 395 | int retval; 396 | long result; 397 | mmfile_t file; 398 | 399 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &patch) == FAILURE) { 400 | RETURN_FALSE; 401 | } 402 | 403 | RETVAL_FALSE; 404 | 405 | retval = load_into_mm_file(patch->val, patch->len, &file); 406 | if (!retval) 407 | goto out; 408 | 409 | result = xdl_bdiff_tgsize(&file); 410 | if (result < 0) 411 | goto out_free_mmfile; 412 | 413 | RETVAL_LONG(result); 414 | 415 | out_free_mmfile: 416 | xdl_free_mmfile(&file); 417 | out: 418 | return; 419 | } 420 | /* }}} */ 421 | 422 | /* {{{ proto mixed xdiff_file_patch(string file, string patch, string dest [, int flags]) 423 | */ 424 | PHP_FUNCTION(xdiff_file_patch) 425 | { 426 | php_stream *output_stream; 427 | zend_string *src_path, *patch_path, *dest_path; 428 | int retval; 429 | zend_long flags = XDL_PATCH_NORMAL; /* DIFF_PATCH_NORMAL */ 430 | xdemitcb_t output, error_output; 431 | struct string_buffer error_string; 432 | 433 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS|l", &src_path, &patch_path, &dest_path, &flags) == FAILURE) { 434 | RETURN_FALSE; 435 | } 436 | 437 | RETVAL_FALSE; 438 | 439 | output_stream = php_stream_open_wrapper(dest_path->val, "wb", REPORT_ERRORS, NULL); 440 | if (!output_stream) 441 | goto out; 442 | 443 | output.outf = append_stream; 444 | output.priv = output_stream; 445 | 446 | retval = init_string(&error_string); 447 | if (!retval) 448 | goto out_stream_close; 449 | 450 | error_output.priv= &error_string; 451 | error_output.outf = append_string; 452 | 453 | retval = make_patch(src_path->val, patch_path->val, &output, &error_output, flags); 454 | if (!retval) 455 | goto out_free_string; 456 | 457 | if (error_string.size > 0) { 458 | RETVAL_STRINGL(error_string.ptr, error_string.size); 459 | } else { 460 | RETVAL_TRUE; 461 | } 462 | 463 | out_free_string: 464 | free_string(&error_string); 465 | out_stream_close: 466 | php_stream_close(output_stream); 467 | out: 468 | return; 469 | } 470 | /* }}} */ 471 | 472 | /* {{{ proto string xdiff_string_patch(string file, string patch [, int flags, [string error]]) 473 | */ 474 | PHP_FUNCTION(xdiff_string_patch) 475 | { 476 | zval *error_ref = NULL; 477 | zend_string *src, *patch; 478 | int retval; 479 | zend_long flags = XDL_PATCH_NORMAL; /* DIFF_PATCH_NORMAL */ 480 | xdemitcb_t output, error_output; 481 | struct string_buffer output_string, error_string; 482 | 483 | if (zend_parse_parameters_ex(0, ZEND_NUM_ARGS(), "SS|lz", &src, &patch, &flags, &error_ref) == FAILURE) { 484 | RETURN_FALSE; 485 | } 486 | 487 | RETVAL_FALSE; 488 | 489 | retval = init_string(&output_string); 490 | if (!retval) 491 | goto out; 492 | 493 | output.priv = &output_string; 494 | output.outf = append_string; 495 | 496 | retval = init_string(&error_string); 497 | if (!retval) 498 | goto out_free_output_string; 499 | 500 | error_output.priv= &error_string; 501 | error_output.outf = append_string; 502 | 503 | retval = make_patch_str(src->val, src->len, patch->val, patch->len, &output, &error_output, flags); 504 | if (!retval) 505 | goto out_free_error_string; 506 | 507 | if (error_string.size > 0 && error_ref) { 508 | ZVAL_DEREF(error_ref); 509 | ZVAL_STRINGL(error_ref, error_string.ptr, error_string.size); 510 | } 511 | 512 | if (output_string.size > 0) { 513 | RETVAL_STRINGL(output_string.ptr, output_string.size); 514 | } else { 515 | RETVAL_EMPTY_STRING(); 516 | } 517 | 518 | out_free_error_string: 519 | free_string(&error_string); 520 | out_free_output_string: 521 | free_string(&output_string); 522 | out: 523 | return; 524 | } 525 | /* }}} */ 526 | 527 | /* {{{ proto bool xdiff_file_patch_binary(string file, string patch, string dest) 528 | */ 529 | PHP_FUNCTION(xdiff_file_bpatch) 530 | { 531 | php_stream *output_stream; 532 | zend_string *src_path, *patch_path, *dest_path; 533 | int retval; 534 | xdemitcb_t output; 535 | 536 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &src_path, &patch_path, &dest_path) == FAILURE) { 537 | RETURN_FALSE; 538 | } 539 | 540 | RETVAL_FALSE; 541 | 542 | output_stream = php_stream_open_wrapper(dest_path->val, "wb", REPORT_ERRORS, NULL); 543 | if (!output_stream) 544 | goto out; 545 | 546 | output.outf = append_stream; 547 | output.priv = output_stream; 548 | 549 | retval = make_bpatch(src_path->val, patch_path->val, &output); 550 | php_stream_close(output_stream); 551 | 552 | if (retval == 0) 553 | RETVAL_TRUE; 554 | 555 | out: 556 | return; 557 | } 558 | /* }}} */ 559 | 560 | /* {{{ proto string xdiff_string_patch_binary(string str, string patch) 561 | */ 562 | PHP_FUNCTION(xdiff_string_bpatch) 563 | { 564 | zend_string *src, *patch; 565 | int retval; 566 | xdemitcb_t output; 567 | struct string_buffer output_string; 568 | 569 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &src, &patch) == FAILURE) { 570 | RETURN_FALSE; 571 | } 572 | 573 | RETVAL_FALSE; 574 | 575 | retval = init_string(&output_string); 576 | if (!retval) 577 | goto out; 578 | 579 | output.priv = &output_string; 580 | output.outf = append_string; 581 | 582 | retval = make_bpatch_str(src->val, src->len, patch->val, patch->len, &output); 583 | if (!retval) 584 | goto out_free_string; 585 | 586 | RETVAL_STRINGL(output_string.ptr, output_string.size); 587 | 588 | out_free_string: 589 | free_string(&output_string); 590 | out: 591 | return; 592 | } 593 | /* }}} */ 594 | 595 | /* {{{ proto mixed xdiff_file_merge3(string file1, string file2, string file3, string dest) 596 | */ 597 | PHP_FUNCTION(xdiff_file_merge3) 598 | { 599 | zend_string *file1, *file2, *file3, *dest; 600 | php_stream *output_stream; 601 | struct string_buffer string; 602 | xdemitcb_t output, error_output; 603 | int retval; 604 | 605 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSSS", &file1, &file2, &file3, &dest) == FAILURE) { 606 | RETURN_FALSE; 607 | } 608 | 609 | RETVAL_FALSE; 610 | 611 | output_stream = php_stream_open_wrapper(dest->val, "wb", REPORT_ERRORS, NULL); 612 | if (!output_stream) 613 | goto out; 614 | 615 | output.priv = output_stream; 616 | output.outf = append_stream; 617 | 618 | retval = init_string(&string); 619 | if (!retval) 620 | goto out_stream_close; 621 | 622 | error_output.priv = &string; 623 | error_output.outf = append_string; 624 | 625 | retval = make_merge3(file1->val, file2->val, file3->val, &output, &error_output); 626 | if (!retval) 627 | goto out_free_string; 628 | 629 | if (string.size > 0) { 630 | RETVAL_STRINGL(string.ptr, string.size); 631 | } else { 632 | RETVAL_TRUE; 633 | } 634 | 635 | out_free_string: 636 | free_string(&string); 637 | out_stream_close: 638 | php_stream_close(output_stream); 639 | out: 640 | return; 641 | } 642 | /* }}} */ 643 | 644 | /* {{{ proto string xdiff_string_merge3(string str1, string str2, string str3 [, string error]) 645 | */ 646 | PHP_FUNCTION(xdiff_string_merge3) 647 | { 648 | zval *error_ref = NULL; 649 | zend_string *file1, *file2, *file3; 650 | struct string_buffer output_string, error_string; 651 | xdemitcb_t output, error_output; 652 | int retval; 653 | 654 | if (zend_parse_parameters_ex(0, ZEND_NUM_ARGS(), "SSS|z", &file1, &file2, &file3, &error_ref) == FAILURE) { 655 | RETURN_FALSE; 656 | } 657 | 658 | RETVAL_FALSE; 659 | 660 | retval = init_string(&output_string); 661 | if (!retval) 662 | goto out; 663 | 664 | output.priv = &output_string; 665 | output.outf = append_string; 666 | 667 | retval = init_string(&error_string); 668 | if (!retval) 669 | goto out_free_output_string; 670 | 671 | error_output.priv = &error_string; 672 | error_output.outf = append_string; 673 | 674 | retval = make_merge3_str(file1->val, file1->len, file2->val, file2->len, file3->val, file3->len, &output, &error_output); 675 | if (!retval) 676 | goto out_free_error_string; 677 | 678 | if (error_string.size > 0 && error_ref) { 679 | ZVAL_DEREF(error_ref); 680 | ZVAL_STRINGL(error_ref, error_string.ptr, error_string.size); 681 | } 682 | 683 | if (output_string.size > 0) { 684 | RETVAL_STRINGL(output_string.ptr, output_string.size); 685 | } else { 686 | RETVAL_TRUE; 687 | } 688 | 689 | out_free_error_string: 690 | free_string(&error_string); 691 | out_free_output_string: 692 | free_string(&output_string); 693 | out: 694 | return; 695 | } 696 | /* }}} */ 697 | 698 | static int load_mm_file(const char *filepath, mmfile_t *dest) 699 | { 700 | int retval; 701 | off_t filesize; 702 | void *ptr; 703 | php_stream *src; 704 | php_stream_statbuf stat; 705 | 706 | src = php_stream_open_wrapper((char *) filepath, "rb", REPORT_ERRORS, NULL); 707 | if (!src) 708 | goto out; 709 | 710 | retval = php_stream_stat(src, &stat); 711 | if (retval < 0) 712 | goto out_stream_close; 713 | 714 | filesize = stat.sb.st_size; 715 | 716 | retval = xdl_init_mmfile(dest, filesize, XDL_MMF_ATOMIC); 717 | if (retval < 0) 718 | goto out_stream_close; 719 | 720 | ptr = xdl_mmfile_writeallocate(dest, (long) filesize); 721 | if (!ptr) 722 | goto out_free_mmfile; 723 | 724 | php_stream_read(src, ptr, filesize); 725 | php_stream_close(src); 726 | 727 | return 1; 728 | 729 | out_free_mmfile: 730 | xdl_free_mmfile(dest); 731 | out_stream_close: 732 | php_stream_close(src); 733 | out: 734 | return 0; 735 | } 736 | 737 | static int load_into_mm_file(const char *buffer, unsigned long size, mmfile_t *dest) 738 | { 739 | int retval; 740 | void *ptr; 741 | 742 | retval = xdl_init_mmfile(dest, size, XDL_MMF_ATOMIC); 743 | if (retval < 0) 744 | goto out; 745 | 746 | ptr = xdl_mmfile_writeallocate(dest, (long) size); 747 | if (!ptr) 748 | goto out_free_mmfile; 749 | 750 | memcpy(ptr, buffer, size); 751 | return 1; 752 | 753 | out_free_mmfile: 754 | xdl_free_mmfile(dest); 755 | out: 756 | return 0; 757 | } 758 | 759 | static int append_string(void *ptr, mmbuffer_t *buffer, int array_size) 760 | { 761 | struct string_buffer *string = ptr; 762 | void *new_ptr; 763 | unsigned int i; 764 | 765 | for (i = 0; i < array_size; i++) { 766 | new_ptr = erealloc(string->ptr, string->size + buffer[i].size + 1); 767 | if (!new_ptr) { 768 | efree(string->ptr); 769 | return -1; 770 | } 771 | 772 | string->ptr = new_ptr; 773 | memcpy(string->ptr + string->size, buffer[i].ptr, buffer[i].size); 774 | string->size += buffer[i].size; 775 | } 776 | if (array_size) { 777 | string->ptr[string->size] = '\0'; 778 | } 779 | 780 | return 0; 781 | } 782 | 783 | static int append_stream(void *ptr, mmbuffer_t *buffer, int array_size) 784 | { 785 | php_stream *stream = ptr; 786 | unsigned int i; 787 | 788 | for (i = 0; i < array_size; i++) { 789 | php_stream_write(stream, buffer[i].ptr, buffer[i].size); 790 | } 791 | 792 | return 1; 793 | } 794 | 795 | static int init_string(struct string_buffer *string) 796 | { 797 | string->ptr = emalloc(1); 798 | if (!string->ptr) 799 | return 0; 800 | 801 | string->size = 0; 802 | memset(string->ptr, 0, 1); 803 | 804 | return 1; 805 | } 806 | 807 | static void free_string(struct string_buffer *string) 808 | { 809 | if (string->ptr) 810 | efree(string->ptr); 811 | } 812 | 813 | static int make_diff(char *filepath1, char *filepath2, xdemitcb_t *output, int context, int minimal) 814 | { 815 | mmfile_t file1, file2; 816 | xpparam_t params; 817 | xdemitconf_t conf; 818 | int retval, result = 0; 819 | 820 | retval = load_mm_file(filepath1, &file1); 821 | if (!retval) 822 | goto out; 823 | 824 | retval = load_mm_file(filepath2, &file2); 825 | if (!retval) 826 | goto out_free_mmfile; 827 | 828 | params.flags = (minimal) ? XDF_NEED_MINIMAL : 0; 829 | conf.ctxlen = abs(context); 830 | 831 | retval = xdl_diff(&file1, &file2, ¶ms, &conf, output); 832 | if (retval < 0) 833 | goto out_free_mmfile2; 834 | 835 | result = 1; 836 | 837 | out_free_mmfile2: 838 | xdl_free_mmfile(&file2); 839 | out_free_mmfile: 840 | xdl_free_mmfile(&file1); 841 | out: 842 | return result; 843 | } 844 | 845 | static int make_diff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output, int context, int minimal) 846 | { 847 | mmfile_t file1, file2; 848 | xpparam_t params; 849 | xdemitconf_t conf; 850 | int retval, result = 0; 851 | 852 | retval = load_into_mm_file(str1, size1, &file1); 853 | if (!retval) 854 | goto out; 855 | 856 | retval = load_into_mm_file(str2, size2, &file2); 857 | if (!retval) 858 | goto out_free_mmfile; 859 | 860 | params.flags = (minimal) ? XDF_NEED_MINIMAL : 0; 861 | conf.ctxlen = abs(context); 862 | 863 | retval = xdl_diff(&file1, &file2, ¶ms, &conf, output); 864 | if (retval < 0) 865 | goto out_free_mmfile2; 866 | 867 | result = 1; 868 | 869 | out_free_mmfile2: 870 | xdl_free_mmfile(&file2); 871 | out_free_mmfile: 872 | xdl_free_mmfile(&file1); 873 | out: 874 | return result; 875 | } 876 | 877 | static int make_bdiff(char *filepath1, char *filepath2, xdemitcb_t *output) 878 | { 879 | mmfile_t file1, file2; 880 | bdiffparam_t params; 881 | int retval, result = 0; 882 | 883 | retval = load_mm_file(filepath1, &file1); 884 | if (!retval) 885 | goto out; 886 | 887 | retval = load_mm_file(filepath2, &file2); 888 | if (!retval) 889 | goto out_free_mmfile; 890 | 891 | params.bsize = 16; 892 | 893 | retval = xdl_bdiff(&file1, &file2, ¶ms, output); 894 | if (retval < 0) 895 | goto out_free_mmfile2; 896 | 897 | result = 1; 898 | 899 | out_free_mmfile2: 900 | xdl_free_mmfile(&file2); 901 | out_free_mmfile: 902 | xdl_free_mmfile(&file1); 903 | out: 904 | return result; 905 | } 906 | 907 | static int make_bdiff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output) 908 | { 909 | mmfile_t file1, file2; 910 | bdiffparam_t params; 911 | int retval, result = 0; 912 | 913 | retval = load_into_mm_file(str1, size1, &file1); 914 | if (!retval) 915 | goto out; 916 | 917 | retval = load_into_mm_file(str2, size2, &file2); 918 | if (!retval) 919 | goto out_free_mmfile; 920 | 921 | params.bsize = 16; 922 | 923 | retval = xdl_bdiff(&file1, &file2, ¶ms, output); 924 | if (retval < 0) 925 | goto out_free_mmfile2; 926 | 927 | result = 1; 928 | 929 | out_free_mmfile2: 930 | xdl_free_mmfile(&file2); 931 | out_free_mmfile: 932 | xdl_free_mmfile(&file1); 933 | out: 934 | return result; 935 | } 936 | 937 | static int make_rabdiff(char *filepath1, char *filepath2, xdemitcb_t *output) 938 | { 939 | mmfile_t file1, file2; 940 | int retval, result = 0; 941 | 942 | retval = load_mm_file(filepath1, &file1); 943 | if (!retval) 944 | goto out; 945 | 946 | retval = load_mm_file(filepath2, &file2); 947 | if (!retval) 948 | goto out_free_mmfile; 949 | 950 | retval = xdl_rabdiff(&file1, &file2, output); 951 | if (retval < 0) 952 | goto out_free_mmfile2; 953 | 954 | result = 1; 955 | 956 | out_free_mmfile2: 957 | xdl_free_mmfile(&file2); 958 | out_free_mmfile: 959 | xdl_free_mmfile(&file1); 960 | out: 961 | return result; 962 | } 963 | 964 | static int make_rabdiff_str(char *str1, int size1, char *str2, int size2, xdemitcb_t *output) 965 | { 966 | mmfile_t file1, file2; 967 | int retval, result = 0; 968 | 969 | retval = load_into_mm_file(str1, size1, &file1); 970 | if (!retval) 971 | goto out; 972 | 973 | retval = load_into_mm_file(str2, size2, &file2); 974 | if (!retval) 975 | goto out_free_mmfile; 976 | 977 | retval = xdl_rabdiff(&file1, &file2, output); 978 | if (retval < 0) 979 | goto out_free_mmfile2; 980 | 981 | result = 1; 982 | 983 | out_free_mmfile2: 984 | xdl_free_mmfile(&file2); 985 | out_free_mmfile: 986 | xdl_free_mmfile(&file1); 987 | out: 988 | return result; 989 | } 990 | 991 | static int make_patch(char *file_path, char *patch_path, xdemitcb_t *output, xdemitcb_t *error, int flags) 992 | { 993 | mmfile_t file, patch; 994 | int retval, result = 0; 995 | 996 | retval = load_mm_file(file_path, &file); 997 | if (!retval) 998 | goto out; 999 | 1000 | retval = load_mm_file(patch_path, &patch); 1001 | if (!retval) 1002 | goto out_free_mmfile; 1003 | 1004 | retval = xdl_patch(&file, &patch, flags, output, error); 1005 | if (retval < 0) 1006 | goto out_free_mmfile2; 1007 | 1008 | result = 1; 1009 | 1010 | out_free_mmfile2: 1011 | xdl_free_mmfile(&patch); 1012 | out_free_mmfile: 1013 | xdl_free_mmfile(&file); 1014 | out: 1015 | return result; 1016 | } 1017 | 1018 | static int make_patch_str(char *file, int size1, char *patch, int size2, xdemitcb_t *output, xdemitcb_t *error, int flags) 1019 | { 1020 | mmfile_t file_mm, patch_mm; 1021 | int retval, result = 0; 1022 | 1023 | retval = load_into_mm_file(file, size1, &file_mm); 1024 | if (!retval) 1025 | goto out; 1026 | 1027 | retval = load_into_mm_file(patch, size2, &patch_mm); 1028 | if (!retval) 1029 | goto out_free_mmfile; 1030 | 1031 | retval = xdl_patch(&file_mm, &patch_mm, flags, output, error); 1032 | if (retval < 0) 1033 | goto out_free_mmfile2; 1034 | 1035 | result = 1; 1036 | 1037 | out_free_mmfile2: 1038 | xdl_free_mmfile(&patch_mm); 1039 | out_free_mmfile: 1040 | xdl_free_mmfile(&file_mm); 1041 | out: 1042 | return result; 1043 | } 1044 | 1045 | static int make_bpatch(char *file_path, char *patch_path, xdemitcb_t *output) 1046 | { 1047 | mmfile_t file_mm, patch_mm; 1048 | int retval, result = 0; 1049 | 1050 | retval = load_mm_file(file_path, &file_mm); 1051 | if (!retval) 1052 | goto out; 1053 | 1054 | retval = load_mm_file(patch_path, &patch_mm); 1055 | if (!retval) 1056 | goto out_free_mmfile; 1057 | 1058 | retval = xdl_bpatch(&file_mm, &patch_mm, output); 1059 | if (retval < 0) 1060 | goto out_free_mmfile2; 1061 | 1062 | result = 1; 1063 | 1064 | out_free_mmfile2: 1065 | xdl_free_mmfile(&patch_mm); 1066 | out_free_mmfile: 1067 | xdl_free_mmfile(&file_mm); 1068 | out: 1069 | return result; 1070 | } 1071 | 1072 | static int make_bpatch_str(char *file, int size1, char *patch, int size2, xdemitcb_t *output) 1073 | { 1074 | mmfile_t file_mm, patch_mm; 1075 | int retval, result = 0; 1076 | 1077 | retval = load_into_mm_file(file, size1, &file_mm); 1078 | if (!retval) 1079 | goto out; 1080 | 1081 | retval = load_into_mm_file(patch, size2, &patch_mm); 1082 | if (!retval) 1083 | goto out_free_mmfile; 1084 | 1085 | retval = xdl_bpatch(&file_mm, &patch_mm, output); 1086 | if (retval < 0) 1087 | goto out_free_mmfile2; 1088 | 1089 | result = 1; 1090 | 1091 | out_free_mmfile2: 1092 | xdl_free_mmfile(&patch_mm); 1093 | out_free_mmfile: 1094 | xdl_free_mmfile(&file_mm); 1095 | out: 1096 | return result; 1097 | } 1098 | 1099 | static int make_merge3(char *filepath1, char *filepath2, char *filepath3, xdemitcb_t *output, xdemitcb_t *error) 1100 | { 1101 | mmfile_t file1, file2, file3; 1102 | int retval, result = 0; 1103 | 1104 | retval = load_mm_file(filepath1, &file1); 1105 | if (!retval) 1106 | goto out; 1107 | 1108 | retval = load_mm_file(filepath2, &file2); 1109 | if (!retval) 1110 | goto out_free_mmfile; 1111 | 1112 | retval = load_mm_file(filepath3, &file3); 1113 | if (!retval) 1114 | goto out_free_mmfile2; 1115 | 1116 | retval = xdl_merge3(&file1, &file2, &file3, output, error); 1117 | if (retval < 0) 1118 | goto out_free_mmfile3; 1119 | 1120 | result = 1; 1121 | 1122 | out_free_mmfile3: 1123 | xdl_free_mmfile(&file3); 1124 | out_free_mmfile2: 1125 | xdl_free_mmfile(&file2); 1126 | out_free_mmfile: 1127 | xdl_free_mmfile(&file1); 1128 | out: 1129 | return result; 1130 | } 1131 | 1132 | static int make_merge3_str(char *content1, int size1, char *content2, int size2, char *content3, int size3, xdemitcb_t *output, xdemitcb_t *error) 1133 | { 1134 | mmfile_t file1, file2, file3; 1135 | int retval, result = 0; 1136 | 1137 | retval = load_into_mm_file(content1, size1, &file1); 1138 | if (!retval) 1139 | goto out; 1140 | 1141 | retval = load_into_mm_file(content2, size2, &file2); 1142 | if (!retval) 1143 | goto out_free_mmfile; 1144 | 1145 | retval = load_into_mm_file(content3, size3, &file3); 1146 | if (!retval) 1147 | goto out_free_mmfile2; 1148 | 1149 | retval = xdl_merge3(&file1, &file2, &file3, output, error); 1150 | if (retval < 0) 1151 | goto out_free_mmfile3; 1152 | 1153 | result = 1; 1154 | 1155 | out_free_mmfile3: 1156 | xdl_free_mmfile(&file3); 1157 | out_free_mmfile2: 1158 | xdl_free_mmfile(&file2); 1159 | out_free_mmfile: 1160 | xdl_free_mmfile(&file1); 1161 | out: 1162 | return result; 1163 | } 1164 | 1165 | /* 1166 | * Local variables: 1167 | * tab-width: 4 1168 | * c-basic-offset: 4 1169 | * End: 1170 | * vim600: noet sw=4 ts=4 fdm=marker 1171 | * vim<600: noet sw=4 ts=4 1172 | */ 1173 | -------------------------------------------------------------------------------- /xdiff.stub.php: -------------------------------------------------------------------------------- 1 |