├── AUTHORS ├── CMakeLists.txt ├── COPYING ├── ChangeLog ├── README ├── config.h.in ├── man ├── xdiff-lib.html ├── xdiff.3 ├── xdiff.html ├── xdiff.pdf └── xdiff.txt ├── test ├── xdiff_test.c ├── xregression.c ├── xtestutils.c └── xtestutils.h ├── tools └── xrabin.c └── xdiff ├── xadler32.c ├── xadler32.h ├── xalloc.c ├── xbdiff.c ├── xbdiff.h ├── xbpatchi.c ├── xdiff.h ├── xdiffi.c ├── xdiffi.h ├── xemit.c ├── xemit.h ├── xinclude.h ├── xmacros.h ├── xmerge3.c ├── xmissing.c ├── xmissing.h ├── xpatchi.c ├── xprepare.c ├── xprepare.h ├── xrabdiff.c ├── xrabply.c ├── xtypes.h ├── xutils.c ├── xutils.h └── xversion.c /AUTHORS: -------------------------------------------------------------------------------- 1 | Davide Libenzi 2 | 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.2) 2 | 3 | # Project definition 4 | 5 | PROJECT(LibXDiff) 6 | 7 | # Package name and version 8 | 9 | SET(PACKAGE_NAME xdiff) 10 | 11 | SET(PACKAGE_MAJOR_VERSION 0) 12 | SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.23") 13 | 14 | # Some options to customise the build 15 | 16 | OPTION(ENABLE_TESTS "Enable the tests to be built" OFF) 17 | OPTION(ENABLE_TOOLS "Enable the tools to be built" OFF) 18 | 19 | # Check for some include files and functions 20 | 21 | INCLUDE(CheckIncludeFiles) 22 | INCLUDE(CheckFunctionExists) 23 | 24 | CHECK_INCLUDE_FILES(limits.h HAVE_LIMITS_H) 25 | CHECK_FUNCTION_EXISTS(memchr HAVE_MEMCHR) 26 | CHECK_FUNCTION_EXISTS(memcmp HAVE_MEMCMP) 27 | CHECK_FUNCTION_EXISTS(memcpy HAVE_MEMCPY) 28 | CHECK_FUNCTION_EXISTS(memset HAVE_MEMSET) 29 | CHECK_INCLUDE_FILES(stdio.h HAVE_STDIO_H) 30 | CHECK_INCLUDE_FILES(stdlib.h HAVE_STDLIB_H) 31 | CHECK_INCLUDE_FILES(string.h HAVE_STRING_H) 32 | CHECK_FUNCTION_EXISTS(strlen HAVE_STRLEN) 33 | CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) 34 | 35 | # Configure LibXDiff 36 | 37 | CONFIGURE_FILE(config.h.in config.h) 38 | 39 | ADD_DEFINITIONS(-DHAVE_CONFIG_H) 40 | 41 | INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}) 42 | 43 | # Build LibXDiff 44 | 45 | IF(WIN32) 46 | ADD_DEFINITIONS(-DLIBXDIFF_DLL_EXPORT) 47 | ENDIF() 48 | 49 | ADD_LIBRARY(${PACKAGE_NAME} SHARED 50 | xdiff/xadler32.c 51 | xdiff/xalloc.c 52 | xdiff/xbdiff.c 53 | xdiff/xbpatchi.c 54 | xdiff/xdiffi.c 55 | xdiff/xemit.c 56 | xdiff/xmerge3.c 57 | xdiff/xmissing.c 58 | xdiff/xpatchi.c 59 | xdiff/xprepare.c 60 | xdiff/xrabdiff.c 61 | xdiff/xrabply.c 62 | xdiff/xutils.c 63 | xdiff/xversion.c 64 | ) 65 | 66 | SET_TARGET_PROPERTIES(${PACKAGE_NAME} PROPERTIES VERSION ${PACKAGE_VERSION}) 67 | SET_TARGET_PROPERTIES(${PACKAGE_NAME} PROPERTIES SOVERSION ${PACKAGE_MAJOR_VERSION}) 68 | 69 | # Install LibXDiff 70 | 71 | INSTALL(TARGETS ${PACKAGE_NAME} 72 | RUNTIME DESTINATION bin 73 | LIBRARY DESTINATION lib 74 | ARCHIVE DESTINATION lib) 75 | 76 | INSTALL(FILES xdiff/xdiff.h 77 | DESTINATION include) 78 | 79 | # Set the RPATH information on Linux and macOS 80 | 81 | IF(ENABLE_TESTS OR ENABLE_TOOLS) 82 | IF(APPLE) 83 | SET(CMAKE_INSTALL_RPATH "@executable_path/../lib") 84 | ELSEIF(NOT WIN32) 85 | SET(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") 86 | ENDIF() 87 | ENDIF() 88 | 89 | # Build the tests, if requested 90 | 91 | IF(ENABLE_TESTS) 92 | INCLUDE_DIRECTORIES(xdiff) 93 | 94 | ADD_EXECUTABLE(xdiff_test 95 | test/xdiff_test.c 96 | test/xtestutils.c 97 | ) 98 | 99 | TARGET_LINK_LIBRARIES(xdiff_test ${PACKAGE_NAME}) 100 | 101 | ADD_EXECUTABLE(xregression 102 | test/xregression.c 103 | test/xtestutils.c 104 | ) 105 | 106 | TARGET_LINK_LIBRARIES(xregression ${PACKAGE_NAME}) 107 | 108 | INSTALL(TARGETS xregression 109 | RUNTIME DESTINATION bin) 110 | ENDIF() 111 | 112 | # Build the tools, if requested 113 | 114 | IF(ENABLE_TOOLS) 115 | ADD_EXECUTABLE(xrabin 116 | tools/xrabin.c 117 | ) 118 | 119 | INSTALL(TARGETS xrabin 120 | RUNTIME DESTINATION bin) 121 | ENDIF() 122 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | 504 | 505 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2 | * Sun, Mar 26 2006 - Davide Libenzi 3 | 4 | Fixed the missing end of line problem for text diff and patch. 5 | 6 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | LibXDiff 0.23 (http://www.xmailserver.org/xdiff-lib.html) 2 | 3 | The LibXDiff library implements basic and yet complete functionalities to create 4 | file differences/patches to both binary and text files. The library uses memory 5 | files as file abstraction to achieve both performance and portability. For 6 | binary files, LibXDiff implements both (with some modification) the algorithm 7 | described in File System Support for Delta Compression by Joshua P. MacDonald, 8 | and the algorithm described in Fingerprinting By Random Polynomials by Michael 9 | O. Rabin. While for text files it follows directives described in An O(ND) 10 | Difference Algorithm and Its Variations by Eugene W. Myers. Memory files used by 11 | the library are basically a collection of buffers that store the file content. 12 | There are two different requirements for memory files when passed to diff/patch 13 | functions. Text files for diff/patch functions require that a single line do not 14 | have to spawn across two different memory file blocks. Binary diff/patch 15 | functions require memory files to be compact. A compact memory files is a file 16 | whose content is stored inside a single block. Functionalities inside the 17 | library are available to satisfy these rules. Using the XDL_MMF_ATOMIC memory 18 | file flag it is possible to make writes to not split the written record across 19 | different blocks, while the functions xdl_mmfile_iscompact() , 20 | xdl_mmfile_compact() and xdl_mmfile_writeallocate() are usefull to test if the 21 | file is compact and to create a compacted version of the file itself. The text 22 | file differential output uses the raw unified output format, by omitting the 23 | file header since the result is always relative to a single compare operation 24 | (between two files). The output format of the binary patch file is proprietary 25 | (and binary) and it is basically a collection of copy and insert commands, like 26 | described inside the MacDonald paper. The library is compatible with almost 27 | every Unix implementation (configure script) and it is also compatible with 28 | Windows through custom (nmake) make files. Examples are available inside the 29 | test subdirectory of the distribution tarball that show how to use the library. 30 | Also, inside the same subdirectory, a regression test in available that tests 31 | the library with random data by requiring a diff followed by a patch and 32 | comparing results. Regression tests ran successfully for days on my Linux, 33 | Solaris, FreeBSD and Windows boxes, and this makes me believe that the library 34 | itself is completely ready for production (despite the version number). 35 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.in by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #cmakedefine HAVE_LIMITS_H 1 5 | 6 | /* Define to 1 if you have the `memchr' function. */ 7 | #cmakedefine HAVE_MEMCHR 1 8 | 9 | /* Define to 1 if you have the `memcmp' function. */ 10 | #cmakedefine HAVE_MEMCMP 1 11 | 12 | /* Define to 1 if you have the `memcpy' function. */ 13 | #cmakedefine HAVE_MEMCPY 1 14 | 15 | /* Define to 1 if you have the `memset' function. */ 16 | #cmakedefine HAVE_MEMSET 1 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #cmakedefine HAVE_STDIO_H 1 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #cmakedefine HAVE_STDLIB_H 1 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #cmakedefine HAVE_STRING_H 1 26 | 27 | /* Define to 1 if you have the `strlen' function. */ 28 | #cmakedefine HAVE_STRLEN 1 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #cmakedefine HAVE_UNISTD_H 1 32 | 33 | /* Define to the version of this package. */ 34 | #cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@" 35 | -------------------------------------------------------------------------------- /man/xdiff-lib.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | LibXDiff Home Page 9 | 10 | 11 |

LibXDiff
12 |

13 |

 
14 | The LibXDiff library implements basic and yet complete 15 | functionalities to create file differences/patches to both binary and 16 | text files. The library uses memory files as file abstraction to 17 | achieve 18 | both performance and portability. For binary files, LibXDiff 19 | implements both (with some modification) the algorithm described in File 20 | System Support for Delta Compression by Joshua P. MacDonald, 21 | and the algorithm described in Fingerprinting 22 | By Random Polynomials by Michael 23 | O. Rabin. While for text files it follows directives described 24 | in An O(ND) 25 | Difference Algorithm and Its Variations by Eugene W. Myers. 26 | Memory files used by the library are basically a collection of buffers 27 | that store the file content. There are two different requirements for 28 | memory files when passed to diff/patch functions. Text files for 29 | diff/patch functions require that a single line do not have to spawn 30 | across two different memory file blocks. Binary diff/patch functions 31 | require memory files to be compact. A compact memory files is a file 32 | whose content is stored inside a single block. Functionalities inside 33 | the library are available to satisfy these rules. Using the XDL_MMF_ATOMIC 34 | memory file flag it is possible to make writes to not split the written 35 | record across different blocks, while the functions xdl_mmfile_iscompact() 36 | , xdl_mmfile_compact() and xdl_mmfile_writeallocate() 37 | are usefull to test if the file is compact and to create a compacted 38 | version of the file itself. The text file differential output uses the 39 | raw unified output format, by omitting the file header since the result 40 | is always relative to a single compare operation (between two files). 41 | The output format of the binary patch file is proprietary (and binary) 42 | and it is basically a collection of copy and insert commands, like 43 | described inside the MacDonald paper. The library is compatible with 44 | almost every Unix implementation (configure script) and it is also 45 | compatible with Windows through custom (nmake) make files. Examples are 46 | available inside the test 47 | subdirectory of the distribution tarball that show how to use the 48 | library. Also, inside the same subdirectory, a regression test in 49 | available that tests the library with random data by requiring a diff 50 | followed by a patch and comparing results. Regression tests ran 51 | successfully for days on my Linux, Solaris, FreeBSD and Windows boxes, 52 | and this makes me believe that the library itself is completely ready 53 | for production (despite the version number).
54 |

55 |


56 |

57 |

Documentation
58 |

59 |

60 | The LibXDiff library man page 61 | is available : HTML   TXT    PDF
63 |

64 |
65 |
66 |

License 67 | and Software

68 |

LibXDiff  70 | is made available through the GNU LGPL license 72 | together with the complete sources. Please read carefully the license before 74 | using 75 | the software. The latest library package is available here :

76 |

Version 78 | 0.23

79 |


80 |

81 |

Links And Docs
82 |

83 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /man/xdiff.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opencor/libxdiff/a858a2d5ee76616e01ecc078059f31777eac641e/man/xdiff.pdf -------------------------------------------------------------------------------- /test/xdiff_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "xdiff.h" 31 | #include "xtestutils.h" 32 | 33 | 34 | 35 | 36 | 37 | static int xdlt_outf(void *priv, mmbuffer_t *mb, int nbuf) { 38 | int i; 39 | 40 | for (i = 0; i < nbuf; i++) 41 | if (!fwrite(mb[i].ptr, mb[i].size, 1, (FILE *) priv)) 42 | return -1; 43 | 44 | return 0; 45 | } 46 | 47 | 48 | void usage(char const *prg) { 49 | 50 | fprintf(stderr, 51 | "use: %s --diff [-C N] from-file to-file\n" 52 | " %s --patch orig-file patch-file\n" 53 | " %s --bdiff [-B N] from-file to-file\n" 54 | " %s --rabdiff from-file to-file\n" 55 | " %s --bpatch orig-file patch-file\n", 56 | prg, prg, prg, prg, prg); 57 | } 58 | 59 | 60 | static void *wrap_malloc(void *priv, unsigned int size) { 61 | 62 | return malloc(size); 63 | } 64 | 65 | 66 | static void wrap_free(void *priv, void *ptr) { 67 | 68 | free(ptr); 69 | } 70 | 71 | 72 | static void *wrap_realloc(void *priv, void *ptr, unsigned int size) { 73 | 74 | return realloc(ptr, size); 75 | } 76 | 77 | 78 | int main(int argc, char *argv[]) { 79 | int i = 1, ctxlen = 3, bsize = 16, do_diff, do_patch, do_bdiff, do_bpatch, do_rabdiff; 80 | memallocator_t malt; 81 | mmfile_t mf1, mf2; 82 | xpparam_t xpp; 83 | xdemitconf_t xecfg; 84 | bdiffparam_t bdp; 85 | xdemitcb_t ecb, rjecb; 86 | 87 | if (argc < 4) { 88 | usage(argv[0]); 89 | return 1; 90 | } 91 | malt.priv = NULL; 92 | malt.malloc = wrap_malloc; 93 | malt.free = wrap_free; 94 | malt.realloc = wrap_realloc; 95 | xdl_set_allocator(&malt); 96 | 97 | do_diff = do_patch = do_bdiff = do_bpatch = do_rabdiff = 0; 98 | if (!strcmp(argv[i], "--diff")) { 99 | i++; 100 | do_diff = 1; 101 | for (; i < argc; i++) { 102 | if (strcmp(argv[i], "-C") == 0) { 103 | if (++i < argc) 104 | ctxlen = atoi(argv[i]); 105 | } else 106 | break; 107 | } 108 | } else if (!strcmp(argv[i], "--patch")) { 109 | i++; 110 | do_patch = 1; 111 | } else if (!strcmp(argv[i], "--bdiff")) { 112 | i++; 113 | do_bdiff = 1; 114 | for (; i < argc; i++) { 115 | if (strcmp(argv[i], "-B") == 0) { 116 | if (++i < argc) 117 | bsize = atoi(argv[i]); 118 | } else 119 | break; 120 | } 121 | } else if (!strcmp(argv[i], "--rabdiff")) { 122 | i++; 123 | do_rabdiff = 1; 124 | } else if (!strcmp(argv[i], "--bpatch")) { 125 | i++; 126 | do_bpatch = 1; 127 | } else { 128 | usage(argv[0]); 129 | return 1; 130 | } 131 | if (argc - i < 2) { 132 | usage(argv[0]); 133 | return 1; 134 | } 135 | 136 | xpp.flags = 0; 137 | xecfg.ctxlen = ctxlen; 138 | bdp.bsize = bsize; 139 | if (xdlt_load_mmfile(argv[i], &mf1, do_bdiff || do_bpatch) < 0) { 140 | 141 | return 2; 142 | } 143 | if (xdlt_load_mmfile(argv[i + 1], &mf2, do_bdiff || do_bpatch) < 0) { 144 | 145 | xdl_free_mmfile(&mf1); 146 | return 2; 147 | } 148 | if (do_diff) { 149 | ecb.priv = stdout; 150 | ecb.outf = xdlt_outf; 151 | 152 | if (xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb) < 0) { 153 | 154 | xdl_free_mmfile(&mf2); 155 | xdl_free_mmfile(&mf1); 156 | return 3; 157 | } 158 | } else if (do_bdiff) { 159 | ecb.priv = stdout; 160 | ecb.outf = xdlt_outf; 161 | if (xdl_bdiff(&mf1, &mf2, &bdp, &ecb) < 0) { 162 | 163 | xdl_free_mmfile(&mf2); 164 | xdl_free_mmfile(&mf1); 165 | return 4; 166 | } 167 | } else if (do_rabdiff) { 168 | ecb.priv = stdout; 169 | ecb.outf = xdlt_outf; 170 | if (xdl_rabdiff(&mf1, &mf2, &ecb) < 0) { 171 | 172 | xdl_free_mmfile(&mf2); 173 | xdl_free_mmfile(&mf1); 174 | return 4; 175 | } 176 | } else if (do_bpatch) { 177 | ecb.priv = stdout; 178 | ecb.outf = xdlt_outf; 179 | if (xdl_bpatch(&mf1, &mf2, &ecb) < 0) { 180 | 181 | xdl_free_mmfile(&mf2); 182 | xdl_free_mmfile(&mf1); 183 | return 5; 184 | } 185 | } else if (do_patch) { 186 | ecb.priv = stdout; 187 | ecb.outf = xdlt_outf; 188 | rjecb.priv = stderr; 189 | rjecb.outf = xdlt_outf; 190 | if (xdl_patch(&mf1, &mf2, XDL_PATCH_NORMAL, &ecb, &rjecb) < 0) { 191 | 192 | xdl_free_mmfile(&mf2); 193 | xdl_free_mmfile(&mf1); 194 | return 6; 195 | } 196 | } 197 | xdl_free_mmfile(&mf2); 198 | xdl_free_mmfile(&mf1); 199 | 200 | return 0; 201 | } 202 | 203 | -------------------------------------------------------------------------------- /test/xregression.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "xdiff.h" 30 | #include "xtestutils.h" 31 | 32 | 33 | 34 | static void *wrap_malloc(void *priv, unsigned int size) { 35 | 36 | return malloc(size); 37 | } 38 | 39 | 40 | static void wrap_free(void *priv, void *ptr) { 41 | 42 | free(ptr); 43 | } 44 | 45 | 46 | static void *wrap_realloc(void *priv, void *ptr, unsigned int size) { 47 | 48 | return realloc(ptr, size); 49 | } 50 | 51 | 52 | int main(int argc, char *argv[]) { 53 | int i, chmax = 64; 54 | long size = 1024 * 100; 55 | double rmod = 0.1; 56 | xpparam_t xpp; 57 | xdemitconf_t xecfg; 58 | bdiffparam_t bdp; 59 | memallocator_t malt; 60 | 61 | malt.priv = NULL; 62 | malt.malloc = wrap_malloc; 63 | malt.free = wrap_free; 64 | malt.realloc = wrap_realloc; 65 | xdl_set_allocator(&malt); 66 | 67 | xpp.flags = 0; 68 | xecfg.ctxlen = 3; 69 | bdp.bsize = 16; 70 | 71 | for (i = 1; i < argc; i++) { 72 | if (!strcmp(argv[i], "--size")) { 73 | if (++i < argc) 74 | size = atol(argv[i]); 75 | } else if (!strcmp(argv[i], "--rmod")) { 76 | if (++i < argc) 77 | rmod = atof(argv[i]); 78 | } else if (!strcmp(argv[i], "--ctxlen")) { 79 | if (++i < argc) 80 | xecfg.ctxlen = atol(argv[i]); 81 | } else if (!strcmp(argv[i], "--chmax")) { 82 | if (++i < argc) 83 | chmax = atoi(argv[i]); 84 | } 85 | } 86 | 87 | srand(time(NULL)); 88 | for (i = 0;; i++) { 89 | fprintf(stderr, "Running TEXT test : %d ... ", i); 90 | if (xdlt_auto_regress(&xpp, &xecfg, size, rmod, chmax) < 0) { 91 | 92 | fprintf(stderr, "FAIL\n"); 93 | break; 94 | } else { 95 | 96 | fprintf(stderr, "OK\n"); 97 | } 98 | 99 | fprintf(stderr, "Running BIN test : %d ... ", i); 100 | if (xdlt_auto_binregress(&bdp, size, rmod, chmax) < 0) { 101 | 102 | fprintf(stderr, "FAIL\n"); 103 | break; 104 | } else { 105 | 106 | fprintf(stderr, "OK\n"); 107 | } 108 | 109 | fprintf(stderr, "Running RBIN test : %d ... ", i); 110 | if (xdlt_auto_rabinregress(size, rmod, chmax) < 0) { 111 | 112 | fprintf(stderr, "FAIL\n"); 113 | break; 114 | } else { 115 | 116 | fprintf(stderr, "OK\n"); 117 | } 118 | 119 | fprintf(stderr, "Running MBIN test : %d ... ", i); 120 | if (xdlt_auto_mbinregress(&bdp, size, rmod, chmax, 32) != 0) { 121 | 122 | fprintf(stderr, "FAIL\n"); 123 | break; 124 | } else { 125 | 126 | fprintf(stderr, "OK\n"); 127 | } 128 | } 129 | 130 | return 0; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /test/xtestutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #if defined(WIN32) || defined(_WIN32) 32 | 33 | #include 34 | 35 | #define write _write 36 | #define read _read 37 | #define lseek _lseek 38 | #define close _close 39 | #define O_CREAT _O_CREAT 40 | #define O_WRONLY _O_WRONLY 41 | #define O_RDONLY _O_RDONLY 42 | #define off_t long 43 | #define size_t int 44 | 45 | #else /* #if defined(WIN32) || defined(_WIN32) */ 46 | 47 | #include 48 | 49 | #endif /* #if defined(WIN32) || defined(_WIN32) */ 50 | 51 | #include "xmacros.h" 52 | #include "xdiff.h" 53 | #include "xtestutils.h" 54 | 55 | 56 | 57 | #define XDLT_STD_BLKSIZE (1024 * 8) 58 | #define XDLT_MAX_LINE_SIZE 80 59 | 60 | 61 | 62 | 63 | static int xdlt_mmfile_outf(void *priv, mmbuffer_t *mb, int nbuf); 64 | 65 | 66 | 67 | 68 | 69 | int xdlt_dump_mmfile(char const *fname, mmfile_t *mmf) { 70 | int fd; 71 | long size; 72 | char *blk; 73 | 74 | if ((fd = open(fname, O_CREAT | O_WRONLY, 0644)) == -1) { 75 | perror(fname); 76 | return -1; 77 | } 78 | 79 | if ((blk = (char *) xdl_mmfile_first(mmf, &size)) != NULL) { 80 | do { 81 | if (write(fd, blk, (size_t) size) != (size_t) size) { 82 | perror(fname); 83 | close(fd); 84 | return -1; 85 | } 86 | } while ((blk = (char *) xdl_mmfile_next(mmf, &size)) != NULL); 87 | } 88 | 89 | close(fd); 90 | 91 | return 0; 92 | } 93 | 94 | 95 | int xdlt_load_mmfile(char const *fname, mmfile_t *mf, int binmode) { 96 | char cc; 97 | int fd; 98 | long size; 99 | char *blk; 100 | 101 | if (xdl_init_mmfile(mf, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 102 | 103 | return -1; 104 | } 105 | if ((fd = open(fname, O_RDONLY)) == -1) { 106 | perror(fname); 107 | xdl_free_mmfile(mf); 108 | return -1; 109 | } 110 | size = lseek(fd, 0, SEEK_END); 111 | lseek(fd, 0, SEEK_SET); 112 | if (!(blk = (char *) xdl_mmfile_writeallocate(mf, size))) { 113 | xdl_free_mmfile(mf); 114 | close(fd); 115 | return -1; 116 | } 117 | if (read(fd, blk, (size_t) size) != (size_t) size) { 118 | perror(fname); 119 | xdl_free_mmfile(mf); 120 | close(fd); 121 | return -1; 122 | } 123 | close(fd); 124 | 125 | return 0; 126 | } 127 | 128 | 129 | static int xdlt_mmfile_outf(void *priv, mmbuffer_t *mb, int nbuf) { 130 | mmfile_t *mmf = priv; 131 | 132 | if (xdl_writem_mmfile(mmf, mb, nbuf) < 0) { 133 | 134 | return -1; 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | 141 | int xdlt_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 142 | xdemitconf_t const *xecfg, mmfile_t *mfp) { 143 | xdemitcb_t ecb; 144 | 145 | if (xdl_init_mmfile(mfp, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 146 | 147 | return -1; 148 | } 149 | ecb.priv = mfp; 150 | ecb.outf = xdlt_mmfile_outf; 151 | if (xdl_diff(mf1, mf2, xpp, xecfg, &ecb) < 0) { 152 | 153 | xdl_free_mmfile(mfp); 154 | return -1; 155 | } 156 | 157 | return 0; 158 | } 159 | 160 | 161 | int xdlt_do_patch(mmfile_t *mfo, mmfile_t *mfp, int mode, mmfile_t *mfr) { 162 | xdemitcb_t ecb, rjecb; 163 | mmfile_t mmfrj; 164 | 165 | if (xdl_init_mmfile(mfr, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 166 | 167 | return -1; 168 | } 169 | if (xdl_init_mmfile(&mmfrj, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 170 | 171 | xdl_free_mmfile(mfr); 172 | return -1; 173 | } 174 | ecb.priv = mfr; 175 | ecb.outf = xdlt_mmfile_outf; 176 | rjecb.priv = &mmfrj; 177 | rjecb.outf = xdlt_mmfile_outf; 178 | if (xdl_patch(mfo, mfp, mode, &ecb, &rjecb) < 0) { 179 | 180 | xdl_free_mmfile(&mmfrj); 181 | xdl_free_mmfile(mfr); 182 | return -1; 183 | } 184 | 185 | if (mmfrj.fsize > 0) { 186 | 187 | #if 1 188 | xdlt_dump_mmfile("xregr.orig", mfo); 189 | xdlt_dump_mmfile("xregr.patch", mfp); 190 | xdlt_dump_mmfile("xregr.rej", &mmfrj); 191 | #endif 192 | 193 | xdl_free_mmfile(&mmfrj); 194 | xdl_free_mmfile(mfr); 195 | return -1; 196 | } 197 | xdl_free_mmfile(&mmfrj); 198 | 199 | return 0; 200 | } 201 | 202 | 203 | int xdlt_do_regress(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 204 | xdemitconf_t const *xecfg) { 205 | mmfile_t mfp, mfr; 206 | 207 | if (xdlt_do_diff(mf1, mf2, xpp, xecfg, &mfp) < 0) { 208 | 209 | return -1; 210 | } 211 | if (xdlt_do_patch(mf1, &mfp, XDL_PATCH_NORMAL, &mfr) < 0) { 212 | 213 | xdl_free_mmfile(&mfp); 214 | return -1; 215 | } 216 | if (xdl_mmfile_cmp(&mfr, mf2)) { 217 | 218 | xdl_free_mmfile(&mfr); 219 | xdl_free_mmfile(&mfp); 220 | return -1; 221 | } 222 | xdl_free_mmfile(&mfr); 223 | if (xdlt_do_patch(mf2, &mfp, XDL_PATCH_REVERSE, &mfr) < 0) { 224 | 225 | xdl_free_mmfile(&mfp); 226 | return -1; 227 | } 228 | if (xdl_mmfile_cmp(&mfr, mf1)) { 229 | 230 | xdl_free_mmfile(&mfr); 231 | xdl_free_mmfile(&mfp); 232 | return -1; 233 | } 234 | xdl_free_mmfile(&mfr); 235 | xdl_free_mmfile(&mfp); 236 | 237 | return 0; 238 | } 239 | 240 | 241 | long xdlt_gen_line(char *buf, long msize) { 242 | long i, size; 243 | static const char ab[] = 244 | "zxcvbnmlkjhgfdsaqwertyuiop" 245 | "ZXCVBNMLKJHGFDSAQWERTYUIOP" 246 | "0123456789 "; 247 | static const int absize = sizeof(ab) - 1; 248 | 249 | if (msize > 0) 250 | size = rand() % (msize - 1); 251 | else 252 | size = -msize - 1; 253 | for (i = 0; i < size; i++) 254 | buf[i] = ab[rand() % absize]; 255 | buf[i] = '\n'; 256 | return size + 1; 257 | } 258 | 259 | 260 | int xdlt_create_file(mmfile_t *mf, long size) { 261 | long lnsize, csize; 262 | char *data; 263 | 264 | if (xdl_init_mmfile(mf, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 265 | 266 | return -1; 267 | } 268 | if (!(data = xdl_mmfile_writeallocate(mf, size))) { 269 | 270 | xdl_free_mmfile(mf); 271 | return -1; 272 | } 273 | for (csize = 0; size - csize > XDLT_MAX_LINE_SIZE;) { 274 | lnsize = xdlt_gen_line(data, XDLT_MAX_LINE_SIZE); 275 | data += lnsize; 276 | csize += lnsize; 277 | } 278 | if (csize < size) 279 | xdlt_gen_line(data, -(size - csize)); 280 | 281 | return 0; 282 | } 283 | 284 | 285 | int xdlt_change_file(mmfile_t *mfo, mmfile_t *mfr, double rmod, 286 | int chmax) { 287 | long skipln, lnsize, bsize; 288 | char const *blk, *cur, *top, *eol; 289 | char lnbuf[XDLT_MAX_LINE_SIZE + 1]; 290 | 291 | if (xdl_init_mmfile(mfr, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 292 | 293 | return -1; 294 | } 295 | if ((blk = xdl_mmfile_first(mfo, &bsize)) != NULL) { 296 | for (cur = blk, top = blk + bsize, skipln = 0;;) { 297 | if (cur >= top) { 298 | if ((blk = xdl_mmfile_next(mfo, &bsize)) == NULL) 299 | break; 300 | cur = blk; 301 | top = blk + bsize; 302 | } 303 | if (!(eol = memchr(cur, '\n', top - cur))) 304 | eol = top; 305 | if (!skipln) { 306 | if (DBL_RAND() < rmod) { 307 | skipln = rand() % chmax; 308 | if (rand() & 1) { 309 | for (; skipln > 0; skipln--) { 310 | lnsize = xdlt_gen_line(lnbuf, XDLT_MAX_LINE_SIZE); 311 | if (xdl_write_mmfile(mfr, lnbuf, lnsize) != lnsize) { 312 | 313 | xdl_free_mmfile(mfr); 314 | return -1; 315 | } 316 | } 317 | } 318 | } else { 319 | lnsize = (eol - cur) + 1; 320 | if (xdl_write_mmfile(mfr, cur, lnsize) != lnsize) { 321 | 322 | xdl_free_mmfile(mfr); 323 | return -1; 324 | } 325 | } 326 | } else 327 | skipln--; 328 | 329 | cur = eol + 1; 330 | } 331 | } 332 | 333 | return 0; 334 | } 335 | 336 | 337 | int xdlt_auto_regress(xpparam_t const *xpp, xdemitconf_t const *xecfg, long size, 338 | double rmod, int chmax) { 339 | mmfile_t mf1, mf2; 340 | 341 | if (xdlt_create_file(&mf1, size) < 0) { 342 | 343 | return -1; 344 | } 345 | if (xdlt_change_file(&mf1, &mf2, rmod, chmax) < 0) { 346 | 347 | xdl_free_mmfile(&mf1); 348 | return -1; 349 | } 350 | if (xdlt_do_regress(&mf1, &mf2, xpp, xecfg) < 0) { 351 | 352 | xdl_free_mmfile(&mf2); 353 | xdl_free_mmfile(&mf1); 354 | return -1; 355 | } 356 | xdl_free_mmfile(&mf2); 357 | xdl_free_mmfile(&mf1); 358 | 359 | return 0; 360 | } 361 | 362 | 363 | int xdlt_do_bindiff(mmfile_t *mf1, mmfile_t *mf2, bdiffparam_t const *bdp, mmfile_t *mfp) { 364 | xdemitcb_t ecb; 365 | 366 | if (xdl_init_mmfile(mfp, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 367 | 368 | return -1; 369 | } 370 | ecb.priv = mfp; 371 | ecb.outf = xdlt_mmfile_outf; 372 | if (xdl_bdiff(mf1, mf2, bdp, &ecb) < 0) { 373 | 374 | xdl_free_mmfile(mfp); 375 | return -1; 376 | } 377 | 378 | return 0; 379 | } 380 | 381 | 382 | int xdlt_do_rabdiff(mmfile_t *mf1, mmfile_t *mf2, mmfile_t *mfp) { 383 | xdemitcb_t ecb; 384 | 385 | if (xdl_init_mmfile(mfp, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 386 | 387 | return -1; 388 | } 389 | ecb.priv = mfp; 390 | ecb.outf = xdlt_mmfile_outf; 391 | if (xdl_rabdiff(mf1, mf2, &ecb) < 0) { 392 | 393 | xdl_free_mmfile(mfp); 394 | return -1; 395 | } 396 | 397 | return 0; 398 | } 399 | 400 | 401 | int xdlt_do_binpatch(mmfile_t *mf, mmfile_t *mfp, mmfile_t *mfr) { 402 | xdemitcb_t ecb; 403 | 404 | if (xdl_init_mmfile(mfr, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 405 | 406 | return -1; 407 | } 408 | ecb.priv = mfr; 409 | ecb.outf = xdlt_mmfile_outf; 410 | if (xdl_bpatch(mf, mfp, &ecb) < 0) { 411 | 412 | xdl_free_mmfile(mfr); 413 | return -1; 414 | } 415 | 416 | return 0; 417 | } 418 | 419 | 420 | int xdlt_do_binregress(mmfile_t *mf1, mmfile_t *mf2, bdiffparam_t const *bdp) { 421 | mmfile_t mfp, mfr; 422 | 423 | if (xdlt_do_bindiff(mf1, mf2, bdp, &mfp) < 0) { 424 | 425 | return -1; 426 | } 427 | if (xdlt_do_binpatch(mf1, &mfp, &mfr) < 0) { 428 | 429 | xdl_free_mmfile(&mfp); 430 | return -1; 431 | } 432 | if (xdl_mmfile_cmp(&mfr, mf2)) { 433 | 434 | xdl_free_mmfile(&mfr); 435 | xdl_free_mmfile(&mfp); 436 | return -1; 437 | } 438 | xdl_free_mmfile(&mfr); 439 | xdl_free_mmfile(&mfp); 440 | 441 | return 0; 442 | } 443 | 444 | 445 | int xdlt_do_rabinregress(mmfile_t *mf1, mmfile_t *mf2) { 446 | mmfile_t mfp, mfr; 447 | 448 | if (xdlt_do_rabdiff(mf1, mf2, &mfp) < 0) { 449 | 450 | return -1; 451 | } 452 | if (xdlt_do_binpatch(mf1, &mfp, &mfr) < 0) { 453 | 454 | xdl_free_mmfile(&mfp); 455 | return -1; 456 | } 457 | if (xdl_mmfile_cmp(&mfr, mf2)) { 458 | 459 | xdl_free_mmfile(&mfr); 460 | xdl_free_mmfile(&mfp); 461 | return -1; 462 | } 463 | xdl_free_mmfile(&mfr); 464 | xdl_free_mmfile(&mfp); 465 | 466 | return 0; 467 | } 468 | 469 | 470 | int xdlt_auto_binregress(bdiffparam_t const *bdp, long size, 471 | double rmod, int chmax) { 472 | mmfile_t mf1, mf2, mf2c; 473 | 474 | if (xdlt_create_file(&mf1, size) < 0) { 475 | 476 | return -1; 477 | } 478 | if (xdlt_change_file(&mf1, &mf2, rmod, chmax) < 0) { 479 | 480 | xdl_free_mmfile(&mf1); 481 | return -1; 482 | } 483 | if (xdl_mmfile_compact(&mf2, &mf2c, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 484 | 485 | xdl_free_mmfile(&mf2); 486 | xdl_free_mmfile(&mf1); 487 | return -1; 488 | } 489 | xdl_free_mmfile(&mf2); 490 | if (xdlt_do_binregress(&mf1, &mf2c, bdp) < 0) { 491 | 492 | xdl_free_mmfile(&mf2c); 493 | xdl_free_mmfile(&mf1); 494 | return -1; 495 | } 496 | xdl_free_mmfile(&mf2c); 497 | xdl_free_mmfile(&mf1); 498 | 499 | return 0; 500 | } 501 | 502 | 503 | int xdlt_auto_rabinregress(long size, double rmod, int chmax) { 504 | mmfile_t mf1, mf2, mf2c; 505 | 506 | if (xdlt_create_file(&mf1, size) < 0) { 507 | 508 | return -1; 509 | } 510 | if (xdlt_change_file(&mf1, &mf2, rmod, chmax) < 0) { 511 | 512 | xdl_free_mmfile(&mf1); 513 | return -1; 514 | } 515 | if (xdl_mmfile_compact(&mf2, &mf2c, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 516 | 517 | xdl_free_mmfile(&mf2); 518 | xdl_free_mmfile(&mf1); 519 | return -1; 520 | } 521 | xdl_free_mmfile(&mf2); 522 | if (xdlt_do_rabinregress(&mf1, &mf2c) < 0) { 523 | 524 | xdl_free_mmfile(&mf2c); 525 | xdl_free_mmfile(&mf1); 526 | return -1; 527 | } 528 | xdl_free_mmfile(&mf2c); 529 | xdl_free_mmfile(&mf1); 530 | 531 | return 0; 532 | } 533 | 534 | 535 | int xdlt_auto_mbinregress(bdiffparam_t const *bdp, long size, 536 | double rmod, int chmax, int n) { 537 | int i, res; 538 | mmbuffer_t *mbb; 539 | mmfile_t *mf, *mfc, *mfx; 540 | mmfile_t mfn, mff, mfd, mfb; 541 | xdemitcb_t ecb; 542 | 543 | if ((mbb = (mmbuffer_t *) xdl_malloc((n + 2) * sizeof(mmbuffer_t))) == NULL) { 544 | 545 | return -1; 546 | } 547 | if ((mf = mfc = (mmfile_t *) xdl_malloc((n + 2) * sizeof(mmfile_t))) == NULL) { 548 | 549 | xdl_free(mbb); 550 | return -1; 551 | } 552 | if (xdlt_create_file(mfc, size) < 0) { 553 | 554 | xdl_free(mf); 555 | xdl_free(mbb); 556 | return -1; 557 | } 558 | mbb[0].ptr = (char *) xdl_mmfile_first(mfc, &mbb[0].size); 559 | mfc++; 560 | mfx = mf; 561 | for (i = 0; i < n; i++) { 562 | if (xdlt_change_file(mfx, &mfn, rmod, chmax) < 0) { 563 | 564 | if (mfx != mf) xdl_free_mmfile(mfx); 565 | for (; i >= 0; i--) 566 | xdl_free_mmfile(mf + i); 567 | xdl_free(mf); 568 | xdl_free(mbb); 569 | return -1; 570 | } 571 | if (xdl_mmfile_compact(&mfn, &mff, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 572 | 573 | xdl_free_mmfile(&mfn); 574 | if (mfx != mf) xdl_free_mmfile(mfx); 575 | for (; i >= 0; i--) 576 | xdl_free_mmfile(mf + i); 577 | xdl_free(mf); 578 | xdl_free(mbb); 579 | return -1; 580 | } 581 | xdl_free_mmfile(&mfn); 582 | if (xdlt_do_bindiff(mfx, &mff, bdp, &mfd) < 0) { 583 | 584 | xdl_free_mmfile(&mff); 585 | if (mfx != mf) xdl_free_mmfile(mfx); 586 | for (; i >= 0; i--) 587 | xdl_free_mmfile(mf + i); 588 | xdl_free(mf); 589 | xdl_free(mbb); 590 | return -1; 591 | } 592 | if (mfx != mf) xdl_free_mmfile(mfx); 593 | mfx = &mfb; 594 | *mfx = mff; 595 | if (xdl_mmfile_compact(&mfd, mfc, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 596 | 597 | xdl_free_mmfile(&mfd); 598 | xdl_free_mmfile(mfx); 599 | for (; i >= 0; i--) 600 | xdl_free_mmfile(mf + i); 601 | xdl_free(mf); 602 | xdl_free(mbb); 603 | return -1; 604 | } 605 | mbb[i + 1].ptr = (char *) xdl_mmfile_first(mfc, &mbb[i + 1].size); 606 | mfc++; 607 | xdl_free_mmfile(&mfd); 608 | } 609 | if (xdl_init_mmfile(mfc, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 610 | 611 | xdl_free_mmfile(mfx); 612 | for (i = n; i >= 0; i--) 613 | xdl_free_mmfile(mf + i); 614 | xdl_free(mf); 615 | xdl_free(mbb); 616 | return -1; 617 | } 618 | ecb.priv = mfc; 619 | ecb.outf = xdlt_mmfile_outf; 620 | if ((res = xdl_bpatch_multi(&mbb[0], &mbb[1], n, &ecb)) == 0) 621 | res = xdl_mmfile_cmp(mfx, mfc); 622 | 623 | xdl_free_mmfile(mfx); 624 | for (i = n + 1; i >= 0; i--) 625 | xdl_free_mmfile(mf + i); 626 | xdl_free(mf); 627 | xdl_free(mbb); 628 | 629 | return res; 630 | } 631 | 632 | -------------------------------------------------------------------------------- /test/xtestutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XTESTUTILS_H) 24 | #define XTESTUTILS_H 25 | 26 | 27 | 28 | #define DBL_RAND() (((double) rand()) / (1.0 + (double) RAND_MAX)) 29 | 30 | 31 | 32 | int xdlt_dump_mmfile(char const *fname, mmfile_t *mmf); 33 | int xdlt_load_mmfile(char const *fname, mmfile_t *mf, int binmode); 34 | int xdlt_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 35 | xdemitconf_t const *xecfg, mmfile_t *mfp); 36 | int xdlt_do_patch(mmfile_t *mfo, mmfile_t *mfp, int mode, mmfile_t *mfr); 37 | int xdlt_do_regress(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 38 | xdemitconf_t const *xecfg); 39 | long xdlt_gen_line(char *buf, long msize); 40 | int xdlt_create_file(mmfile_t *mf, long size); 41 | int xdlt_change_file(mmfile_t *mfo, mmfile_t *mfr, double rmod, int chmax); 42 | int xdlt_auto_regress(xpparam_t const *xpp, xdemitconf_t const *xecfg, long size, 43 | double rmod, int chmax); 44 | int xdlt_do_bindiff(mmfile_t *mf1, mmfile_t *mf2, bdiffparam_t const *bdp, mmfile_t *mfp); 45 | int xdlt_do_rabdiff(mmfile_t *mf1, mmfile_t *mf2, mmfile_t *mfp); 46 | int xdlt_do_binpatch(mmfile_t *mf, mmfile_t *mfp, mmfile_t *mfr); 47 | int xdlt_do_binregress(mmfile_t *mf1, mmfile_t *mf2, bdiffparam_t const *bdp); 48 | int xdlt_do_rabinregress(mmfile_t *mf1, mmfile_t *mf2); 49 | int xdlt_auto_binregress(bdiffparam_t const *bdp, long size, 50 | double rmod, int chmax); 51 | int xdlt_auto_rabinregress(long size, double rmod, int chmax); 52 | int xdlt_auto_mbinregress(bdiffparam_t const *bdp, long size, 53 | double rmod, int chmax, int n); 54 | 55 | 56 | #endif /* #if !defined(XTESTUTILS_H) */ 57 | 58 | -------------------------------------------------------------------------------- /tools/xrabin.c: -------------------------------------------------------------------------------- 1 | /* 2 | * xrabin by Davide Libenzi (Rabin's polynomial generator) 3 | * Copyright (C) 2006 Davide Libenzi 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | * 22 | * Hints, ideas and code for the implementation came from: 23 | * 24 | * Rabin's original paper: http://www.xmailserver.org/rabin.pdf 25 | * Chan & Lu's paper: http://www.xmailserver.org/rabin_impl.pdf 26 | * Broder's paper: http://www.xmailserver.org/rabin_apps.pdf 27 | * LBFS source code: http://www.fs.net/sfswww/lbfs/ 28 | * Geert Bosch's post: http://marc.theaimsgroup.com/?l=git&m=114565424620771&w=2 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | 39 | #if defined(WIN32) 40 | #define strtoll _strtoi64 41 | #endif 42 | 43 | 44 | #if !defined(XRAB_WORD_TYPE) 45 | #if defined(WIN32) 46 | #define XRAB_WORD_TYPE __int64 47 | 48 | #else /* #if defined(WIN32) */ 49 | #define XRAB_WORD_TYPE long long 50 | 51 | #endif /* #if defined(WIN32) */ 52 | #endif /* #if !defined(XRAB_WORD_TYPE) */ 53 | 54 | #if !defined(XRAB_WORD_PFMT) 55 | #if defined(WIN32) 56 | #define XRAB_WORD_PFMT "0x%I64x" 57 | 58 | #else /* #if defined(WIN32) */ 59 | #define XRAB_WORD_PFMT "0x%llx" 60 | 61 | #endif /* #if defined(WIN32) */ 62 | #endif /* #if !defined(XRAB_WORD_PFMT) */ 63 | 64 | #define XPLYW_BITS (sizeof(xply_word) * 8) 65 | #define XPLYW_MSB ((xply_word) 1 << (sizeof(xply_word) * 8 - 1)) 66 | 67 | 68 | 69 | typedef unsigned XRAB_WORD_TYPE xply_word; 70 | 71 | 72 | 73 | 74 | static int xrab_isprime(int n) { 75 | 76 | if (n > 3) { 77 | if (n & 1) { 78 | int i, hn = n / 2; 79 | 80 | for (i = 3; i < hn; i += 2) 81 | if (!(n % i)) 82 | return 0; 83 | } else 84 | return 0; 85 | } 86 | 87 | return 1; 88 | } 89 | 90 | static int xrab_fls(xply_word v) { 91 | int r, s; 92 | xply_word mask = ~(((xply_word) 1 << (XPLYW_BITS / 2)) - 1); 93 | 94 | if (v == 0) 95 | return 0; 96 | for (r = XPLYW_BITS, s = r / 2; s != 0;) { 97 | if ((v & mask) == 0) { 98 | v <<= s; 99 | r -= s; 100 | } 101 | s /= 2; 102 | mask <<= s; 103 | } 104 | 105 | return r; 106 | } 107 | 108 | static xply_word xrab_polymod(xply_word nh, xply_word nl, xply_word d) { 109 | int i, k = xrab_fls(d) - 1; 110 | 111 | d <<= (XPLYW_BITS - 1) - k; 112 | if (nh) { 113 | if (nh & XPLYW_MSB) 114 | nh ^= d; 115 | for (i = XPLYW_BITS - 2; i >= 0; i--) 116 | if (nh & ((xply_word) 1) << i) { 117 | nh ^= d >> (XPLYW_BITS - 1) - i; 118 | nl ^= d << i + 1; 119 | } 120 | } 121 | for (i = XPLYW_BITS - 1; i >= k; i--) 122 | if (nl & ((xply_word) 1 << i)) 123 | nl ^= d >> (XPLYW_BITS - 1) - i; 124 | 125 | return nl; 126 | } 127 | 128 | static xply_word xrab_polygcd(xply_word x, xply_word y) { 129 | 130 | for (;;) { 131 | if (!y) 132 | return x; 133 | x = xrab_polymod(0, x, y); 134 | if (!x) 135 | return y; 136 | y = xrab_polymod(0, y, x); 137 | } 138 | } 139 | 140 | static void xrab_polymult(xply_word *php, xply_word *plp, xply_word x, 141 | xply_word y) { 142 | int i; 143 | xply_word ph = 0, pl = 0; 144 | 145 | if (x & 1) 146 | pl = y; 147 | for (i = 1; i < XPLYW_BITS; i++) 148 | if (x & (((xply_word) 1) << i)) { 149 | ph ^= y >> (XPLYW_BITS - i); 150 | pl ^= y << i; 151 | } 152 | if (php) 153 | *php = ph; 154 | if (plp) 155 | *plp = pl; 156 | } 157 | 158 | static xply_word xrab_polymmult(xply_word x, xply_word y, xply_word d) { 159 | xply_word h, l; 160 | 161 | xrab_polymult(&h, &l, x, y); 162 | 163 | return xrab_polymod(h, l, d); 164 | } 165 | 166 | static int xrab_polyirreducible(xply_word f) { 167 | xply_word u = 2; 168 | int i, m = (xrab_fls(f) - 1) >> 1; 169 | 170 | for (i = 0; i < m; i++) { 171 | u = xrab_polymmult(u, u, f); 172 | if (xrab_polygcd(f, u ^ 2) != 1) 173 | return 0; 174 | } 175 | 176 | return 1; 177 | } 178 | 179 | static void xrab_rndgen(xply_word *f) { 180 | unsigned int i; 181 | xply_word g; 182 | 183 | for (i = 0, g = 0; i < sizeof(xply_word); i++) 184 | g ^= (g << 11) + (unsigned int) rand() + (g >> 7); 185 | *f = g; 186 | } 187 | 188 | static int xrab_polygen(int degree, xply_word *ply) { 189 | xply_word msb, mask, f; 190 | 191 | if (degree <= 0 || degree >= XPLYW_BITS) 192 | return -1; 193 | msb = ((xply_word) 1) << degree; 194 | mask = msb - 1; 195 | srand(time(NULL)); 196 | do { 197 | xrab_rndgen(&f); 198 | f = (f & mask) | msb; 199 | } while (!xrab_polyirreducible(f)); 200 | *ply = f; 201 | 202 | return 0; 203 | } 204 | 205 | static int xarb_calc_tu(xply_word poly, int size, xply_word *t, xply_word *u) { 206 | int j, xshift, shift; 207 | xply_word t1, ssh; 208 | 209 | xshift = xrab_fls(poly) - 1; 210 | shift = xshift - 8; 211 | if (shift < 0) 212 | return -1; 213 | t1 = xrab_polymod(0, ((xply_word) 1) << xshift, poly); 214 | for (j = 0; j < 256; j++) 215 | t[j] = xrab_polymmult(j, t1, poly) | ((xply_word) j << xshift); 216 | for (j = 1, ssh = 1; j < size; j++) 217 | ssh = (ssh << 8) ^ t[ssh >> shift]; 218 | for (j = 0; j < 256; j++) 219 | u[j] = xrab_polymmult(j, ssh, poly); 220 | 221 | return 0; 222 | } 223 | 224 | int main(int ac, char **av) { 225 | int i, size = 20, degree = 0, shift; 226 | xply_word ply = 0, t[256], u[256]; 227 | 228 | for (i = 1; i < ac; i++) { 229 | if (strcmp(av[i], "-s") == 0) { 230 | if (++i < ac) 231 | size = atol(av[i]); 232 | } else if (strcmp(av[i], "-p") == 0) { 233 | if (++i < ac) 234 | ply = (xply_word) strtoll(av[i], NULL, 16); 235 | } else if (strcmp(av[i], "-d") == 0) { 236 | if (++i < ac) 237 | degree = atol(av[i]); 238 | } 239 | } 240 | if (degree && (degree < 8 || degree >= XPLYW_BITS)) { 241 | fprintf(stderr, "degree (%d) out of bound for the poly word size (8..%u)\n", 242 | degree, XPLYW_BITS); 243 | return 1; 244 | } 245 | if (degree == 0) 246 | for (degree = XPLYW_BITS - 1; !xrab_isprime(degree); degree--); 247 | if (ply == 0 && xrab_polygen(degree, &ply) < 0) 248 | return 2; 249 | shift = (xrab_fls(ply) - 1) - 8; 250 | fprintf(stderr, "found poly = " XRAB_WORD_PFMT " (shift %d)\n", 251 | ply, shift); 252 | if (xarb_calc_tu(ply, size, t, u) < 0) 253 | return 3; 254 | 255 | fprintf(stdout, "#if defined(XRABPLY_TYPE%d)\n\n", XPLYW_BITS); 256 | fprintf(stdout, "#if !defined(XV%d)\n", XPLYW_BITS); 257 | fprintf(stdout, "#define XV%d(v) ((xply_word) v ## ULL)\n", XPLYW_BITS); 258 | fprintf(stdout, "#endif\n\n"); 259 | fprintf(stdout, "#define XRAB_ROOTPOLY XV%d(" XRAB_WORD_PFMT ")\n\n", 260 | XPLYW_BITS, ply); 261 | fprintf(stdout, "#define XRAB_SHIFT %d\n", shift); 262 | fprintf(stdout, "#define XRAB_WNDSIZE %d\n\n", size); 263 | fprintf(stdout, "typedef unsigned XRABPLY_TYPE%d xply_word;\n\n", XPLYW_BITS); 264 | fprintf(stdout, "static const xply_word T[256] = {\n"); 265 | for (i = 0; i < 256; i++) { 266 | if (i) { 267 | fputs(",", stdout); 268 | if (i % 4 == 0) 269 | fputs("\n\t", stdout); 270 | else 271 | fputs(" ", stdout); 272 | } else 273 | fputs("\t", stdout); 274 | fprintf(stdout, "XV%d(" XRAB_WORD_PFMT ")", XPLYW_BITS, t[i]); 275 | } 276 | fprintf(stdout, "\n};\n\n"); 277 | 278 | fprintf(stdout, "static const xply_word U[256] = {\n"); 279 | for (i = 0; i < 256; i++) { 280 | if (i) { 281 | fputs(",", stdout); 282 | if (i % 4 == 0) 283 | fputs("\n\t", stdout); 284 | else 285 | fputs(" ", stdout); 286 | } else 287 | fputs("\t", stdout); 288 | fprintf(stdout, "XV%d(" XRAB_WORD_PFMT ")", XPLYW_BITS, u[i]); 289 | } 290 | fprintf(stdout, "\n};\n\n"); 291 | 292 | fprintf(stdout, "#endif /* if defined(XRABPLY_TYPE%d) */\n\n", XPLYW_BITS); 293 | 294 | return 0; 295 | } 296 | 297 | -------------------------------------------------------------------------------- /xdiff/xadler32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | 27 | /* largest prime smaller than 65536 */ 28 | #define BASE 65521L 29 | 30 | /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ 31 | #define NMAX 5552 32 | 33 | 34 | #define DO1(buf, i) { s1 += buf[i]; s2 += s1; } 35 | #define DO2(buf, i) DO1(buf, i); DO1(buf, i + 1); 36 | #define DO4(buf, i) DO2(buf, i); DO2(buf, i + 2); 37 | #define DO8(buf, i) DO4(buf, i); DO4(buf, i + 4); 38 | #define DO16(buf) DO8(buf, 0); DO8(buf, 8); 39 | 40 | 41 | 42 | unsigned long xdl_adler32(unsigned long adler, unsigned char const *buf, 43 | unsigned int len) { 44 | int k; 45 | unsigned long s1 = adler & 0xffff; 46 | unsigned long s2 = (adler >> 16) & 0xffff; 47 | 48 | if (!buf) 49 | return 1; 50 | 51 | while (len > 0) { 52 | k = len < NMAX ? len :NMAX; 53 | len -= k; 54 | while (k >= 16) { 55 | DO16(buf); 56 | buf += 16; 57 | k -= 16; 58 | } 59 | if (k != 0) 60 | do { 61 | s1 += *buf++; 62 | s2 += s1; 63 | } while (--k); 64 | s1 %= BASE; 65 | s2 %= BASE; 66 | } 67 | 68 | return (s2 << 16) | s1; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /xdiff/xadler32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XADLER32_H) 24 | #define XADLER32_H 25 | 26 | 27 | 28 | unsigned long xdl_adler32(unsigned long adler, unsigned char const *buf, 29 | unsigned int len); 30 | 31 | 32 | 33 | #endif /* #if !defined(XADLER32_H) */ 34 | 35 | -------------------------------------------------------------------------------- /xdiff/xalloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | 27 | static memallocator_t xmalt = {NULL, NULL, NULL}; 28 | 29 | 30 | 31 | int xdl_set_allocator(memallocator_t const *malt) { 32 | xmalt = *malt; 33 | return 0; 34 | } 35 | 36 | 37 | void *xdl_malloc(unsigned int size) { 38 | return xmalt.malloc ? xmalt.malloc(xmalt.priv, size): NULL; 39 | } 40 | 41 | 42 | void xdl_free(void *ptr) { 43 | if (xmalt.free) 44 | xmalt.free(xmalt.priv, ptr); 45 | } 46 | 47 | 48 | void *xdl_realloc(void *ptr, unsigned int size) { 49 | return xmalt.realloc ? xmalt.realloc(xmalt.priv, ptr, size): NULL; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /xdiff/xbdiff.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | typedef struct s_bdrecord { 27 | struct s_bdrecord *next; 28 | unsigned long fp; 29 | char const *ptr; 30 | } bdrecord_t; 31 | 32 | typedef struct s_bdfile { 33 | char const *data, *top; 34 | chastore_t cha; 35 | unsigned int fphbits; 36 | bdrecord_t **fphash; 37 | } bdfile_t; 38 | 39 | 40 | 41 | static int xdl_prepare_bdfile(mmbuffer_t *mmb, long fpbsize, bdfile_t *bdf) { 42 | unsigned int fphbits; 43 | long i, size, hsize; 44 | char const *base, *data, *top; 45 | bdrecord_t *brec; 46 | bdrecord_t **fphash; 47 | 48 | fphbits = xdl_hashbits((unsigned int) (mmb->size / fpbsize) + 1); 49 | hsize = 1 << fphbits; 50 | if (!(fphash = (bdrecord_t **) xdl_malloc(hsize * sizeof(bdrecord_t *)))) { 51 | 52 | return -1; 53 | } 54 | for (i = 0; i < hsize; i++) 55 | fphash[i] = NULL; 56 | 57 | if (xdl_cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1) < 0) { 58 | 59 | xdl_free(fphash); 60 | return -1; 61 | } 62 | 63 | if (!(size = mmb->size)) { 64 | bdf->data = bdf->top = NULL; 65 | } else { 66 | bdf->data = data = base = mmb->ptr; 67 | bdf->top = top = mmb->ptr + mmb->size; 68 | 69 | if ((data += (size / fpbsize) * fpbsize) == top) 70 | data -= fpbsize; 71 | 72 | for (; data >= base; data -= fpbsize) { 73 | if (!(brec = (bdrecord_t *) xdl_cha_alloc(&bdf->cha))) { 74 | 75 | xdl_cha_free(&bdf->cha); 76 | xdl_free(fphash); 77 | return -1; 78 | } 79 | 80 | brec->fp = xdl_adler32(0, (unsigned char const *) data, 81 | XDL_MIN(fpbsize, (long) (top - data))); 82 | brec->ptr = data; 83 | 84 | i = (long) XDL_HASHLONG(brec->fp, fphbits); 85 | brec->next = fphash[i]; 86 | fphash[i] = brec; 87 | } 88 | } 89 | 90 | bdf->fphbits = fphbits; 91 | bdf->fphash = fphash; 92 | 93 | return 0; 94 | } 95 | 96 | 97 | static void xdl_free_bdfile(bdfile_t *bdf) { 98 | 99 | xdl_free(bdf->fphash); 100 | xdl_cha_free(&bdf->cha); 101 | } 102 | 103 | 104 | unsigned long xdl_mmb_adler32(mmbuffer_t *mmb) { 105 | 106 | return mmb->size ? xdl_adler32(0, (unsigned char const *) mmb->ptr, mmb->size): 0; 107 | } 108 | 109 | 110 | unsigned long xdl_mmf_adler32(mmfile_t *mmf) { 111 | unsigned long fp = 0; 112 | long size; 113 | char const *blk; 114 | 115 | if ((blk = (char const *) xdl_mmfile_first(mmf, &size)) != NULL) { 116 | do { 117 | fp = xdl_adler32(fp, (unsigned char const *) blk, size); 118 | } while ((blk = (char const *) xdl_mmfile_next(mmf, &size)) != NULL); 119 | } 120 | return fp; 121 | } 122 | 123 | 124 | int xdl_bdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, bdiffparam_t const *bdp, xdemitcb_t *ecb) { 125 | long i, rsize, size, bsize, csize, msize, moff; 126 | unsigned long fp; 127 | char const *blk, *base, *data, *top, *ptr1, *ptr2; 128 | bdrecord_t *brec; 129 | bdfile_t bdf; 130 | mmbuffer_t mb[2]; 131 | unsigned char cpybuf[32]; 132 | 133 | if ((bsize = bdp->bsize) < XDL_MIN_BLKSIZE) 134 | bsize = XDL_MIN_BLKSIZE; 135 | if (xdl_prepare_bdfile(mmb1, bsize, &bdf) < 0) { 136 | 137 | return -1; 138 | } 139 | 140 | /* 141 | * Prepare and emit the binary patch file header. It will be used 142 | * to verify that that file being patched matches in size and fingerprint 143 | * the one that generated the patch. 144 | */ 145 | fp = xdl_mmb_adler32(mmb1); 146 | size = mmb1->size; 147 | XDL_LE32_PUT(cpybuf, fp); 148 | XDL_LE32_PUT(cpybuf + 4, size); 149 | 150 | mb[0].ptr = (char *) cpybuf; 151 | mb[0].size = 4 + 4; 152 | 153 | if (ecb->outf(ecb->priv, mb, 1) < 0) { 154 | 155 | xdl_free_bdfile(&bdf); 156 | return -1; 157 | } 158 | 159 | if ((blk = (char const *) mmb2->ptr) != NULL) { 160 | size = mmb2->size; 161 | for (base = data = blk, top = data + size; data < top;) { 162 | rsize = XDL_MIN(bsize, (long) (top - data)); 163 | fp = xdl_adler32(0, (unsigned char const *) data, rsize); 164 | 165 | i = (long) XDL_HASHLONG(fp, bdf.fphbits); 166 | for (msize = 0, brec = bdf.fphash[i]; brec; brec = brec->next) 167 | if (brec->fp == fp) { 168 | csize = XDL_MIN((long) (top - data), (long) (bdf.top - brec->ptr)); 169 | for (ptr1 = brec->ptr, ptr2 = data; csize && *ptr1 == *ptr2; 170 | csize--, ptr1++, ptr2++); 171 | 172 | if ((csize = (long) (ptr1 - brec->ptr)) > msize) { 173 | moff = (long) (brec->ptr - bdf.data); 174 | msize = csize; 175 | } 176 | } 177 | 178 | if (msize < XDL_COPYOP_SIZE) { 179 | data++; 180 | } else { 181 | if (data > base) { 182 | i = (long) (data - base); 183 | if (i > 255) { 184 | cpybuf[0] = XDL_BDOP_INSB; 185 | XDL_LE32_PUT(cpybuf + 1, i); 186 | 187 | mb[0].ptr = (char *) cpybuf; 188 | mb[0].size = XDL_INSBOP_SIZE; 189 | } else { 190 | cpybuf[0] = XDL_BDOP_INS; 191 | cpybuf[1] = (unsigned char) i; 192 | 193 | mb[0].ptr = (char *) cpybuf; 194 | mb[0].size = 2; 195 | } 196 | mb[1].ptr = (char *) base; 197 | mb[1].size = i; 198 | 199 | if (ecb->outf(ecb->priv, mb, 2) < 0) { 200 | 201 | xdl_free_bdfile(&bdf); 202 | return -1; 203 | } 204 | } 205 | 206 | data += msize; 207 | 208 | cpybuf[0] = XDL_BDOP_CPY; 209 | XDL_LE32_PUT(cpybuf + 1, moff); 210 | XDL_LE32_PUT(cpybuf + 5, msize); 211 | 212 | mb[0].ptr = (char *) cpybuf; 213 | mb[0].size = XDL_COPYOP_SIZE; 214 | 215 | if (ecb->outf(ecb->priv, mb, 1) < 0) { 216 | 217 | xdl_free_bdfile(&bdf); 218 | return -1; 219 | } 220 | base = data; 221 | } 222 | } 223 | if (data > base) { 224 | i = (long) (data - base); 225 | if (i > 255) { 226 | cpybuf[0] = XDL_BDOP_INSB; 227 | XDL_LE32_PUT(cpybuf + 1, i); 228 | 229 | mb[0].ptr = (char *) cpybuf; 230 | mb[0].size = XDL_INSBOP_SIZE; 231 | } else { 232 | cpybuf[0] = XDL_BDOP_INS; 233 | cpybuf[1] = (unsigned char) i; 234 | 235 | mb[0].ptr = (char *) cpybuf; 236 | mb[0].size = 2; 237 | } 238 | mb[1].ptr = (char *) base; 239 | mb[1].size = i; 240 | 241 | if (ecb->outf(ecb->priv, mb, 2) < 0) { 242 | 243 | xdl_free_bdfile(&bdf); 244 | return -1; 245 | } 246 | } 247 | } 248 | 249 | xdl_free_bdfile(&bdf); 250 | 251 | return 0; 252 | } 253 | 254 | 255 | int xdl_bdiff(mmfile_t *mmf1, mmfile_t *mmf2, bdiffparam_t const *bdp, xdemitcb_t *ecb) { 256 | mmbuffer_t mmb1, mmb2; 257 | 258 | if (!xdl_mmfile_iscompact(mmf1) || !xdl_mmfile_iscompact(mmf2)) { 259 | 260 | return -1; 261 | } 262 | 263 | if ((mmb1.ptr = (char *) xdl_mmfile_first(mmf1, &mmb1.size)) == NULL) 264 | mmb1.size = 0; 265 | if ((mmb2.ptr = (char *) xdl_mmfile_first(mmf2, &mmb2.size)) == NULL) 266 | mmb2.size = 0; 267 | 268 | return xdl_bdiff_mb(&mmb1, &mmb2, bdp, ecb); 269 | } 270 | 271 | 272 | long xdl_bdiff_tgsize(mmfile_t *mmfp) { 273 | long tgsize = 0, size, off, csize; 274 | char const *blk; 275 | unsigned char const *data, *top; 276 | 277 | if ((blk = (char const *) xdl_mmfile_first(mmfp, &size)) == NULL || 278 | size < XDL_BPATCH_HDR_SIZE) { 279 | 280 | return -1; 281 | } 282 | blk += XDL_BPATCH_HDR_SIZE; 283 | size -= XDL_BPATCH_HDR_SIZE; 284 | 285 | do { 286 | for (data = (unsigned char const *) blk, top = data + size; 287 | data < top;) { 288 | if (*data == XDL_BDOP_INS) { 289 | data++; 290 | csize = (long) *data++; 291 | tgsize += csize; 292 | data += csize; 293 | } else if (*data == XDL_BDOP_INSB) { 294 | data++; 295 | XDL_LE32_GET(data, csize); 296 | data += 4; 297 | tgsize += csize; 298 | data += csize; 299 | } else if (*data == XDL_BDOP_CPY) { 300 | data++; 301 | XDL_LE32_GET(data, off); 302 | data += 4; 303 | XDL_LE32_GET(data, csize); 304 | data += 4; 305 | tgsize += csize; 306 | } else { 307 | 308 | return -1; 309 | } 310 | } 311 | } while ((blk = (char const *) xdl_mmfile_next(mmfp, &size)) != NULL); 312 | 313 | return tgsize; 314 | } 315 | 316 | -------------------------------------------------------------------------------- /xdiff/xbdiff.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XBDIFF_H) 24 | #define XBDIFF_H 25 | 26 | 27 | #define XDL_BPATCH_HDR_SIZE (4 + 4) 28 | #define XDL_MIN_BLKSIZE 16 29 | #define XDL_INSBOP_SIZE (1 + 4) 30 | #define XDL_COPYOP_SIZE (1 + 4 + 4) 31 | 32 | 33 | 34 | unsigned long xdl_mmb_adler32(mmbuffer_t *mmb); 35 | unsigned long xdl_mmf_adler32(mmfile_t *mmf); 36 | 37 | 38 | 39 | #endif /* #if !defined(XBDIFF_H) */ 40 | 41 | -------------------------------------------------------------------------------- /xdiff/xbpatchi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | #define XDL_MOBF_MINALLOC 128 27 | 28 | 29 | typedef struct s_mmoffbuffer { 30 | long off, size; 31 | char *ptr; 32 | } mmoffbuffer_t; 33 | 34 | 35 | 36 | static int xdl_copy_range(mmfile_t *mmf, long off, long size, xdemitcb_t *ecb) { 37 | if (xdl_seek_mmfile(mmf, off) < 0) { 38 | 39 | return -1; 40 | } 41 | if (xdl_copy_mmfile(mmf, size, ecb) != size) { 42 | 43 | return -1; 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | 50 | int xdl_bpatch(mmfile_t *mmf, mmfile_t *mmfp, xdemitcb_t *ecb) { 51 | long size, off, csize, osize; 52 | unsigned long fp, ofp; 53 | char const *blk; 54 | unsigned char const *data, *top; 55 | mmbuffer_t mb; 56 | 57 | if ((blk = (char const *) xdl_mmfile_first(mmfp, &size)) == NULL || 58 | size < XDL_BPATCH_HDR_SIZE) { 59 | 60 | return -1; 61 | } 62 | ofp = xdl_mmf_adler32(mmf); 63 | osize = xdl_mmfile_size(mmf); 64 | XDL_LE32_GET(blk, fp); 65 | XDL_LE32_GET(blk + 4, csize); 66 | if (fp != ofp || csize != osize) { 67 | 68 | return -1; 69 | } 70 | 71 | blk += XDL_BPATCH_HDR_SIZE; 72 | size -= XDL_BPATCH_HDR_SIZE; 73 | 74 | do { 75 | for (data = (unsigned char const *) blk, top = data + size; 76 | data < top;) { 77 | if (*data == XDL_BDOP_INS) { 78 | data++; 79 | 80 | mb.size = (long) *data++; 81 | mb.ptr = (char *) data; 82 | data += mb.size; 83 | 84 | if (ecb->outf(ecb->priv, &mb, 1) < 0) { 85 | 86 | return -1; 87 | } 88 | } else if (*data == XDL_BDOP_INSB) { 89 | data++; 90 | XDL_LE32_GET(data, csize); 91 | data += 4; 92 | 93 | mb.size = csize; 94 | mb.ptr = (char *) data; 95 | data += mb.size; 96 | 97 | if (ecb->outf(ecb->priv, &mb, 1) < 0) { 98 | 99 | return -1; 100 | } 101 | } else if (*data == XDL_BDOP_CPY) { 102 | data++; 103 | XDL_LE32_GET(data, off); 104 | data += 4; 105 | XDL_LE32_GET(data, csize); 106 | data += 4; 107 | 108 | if (xdl_copy_range(mmf, off, csize, ecb) < 0) { 109 | 110 | return -1; 111 | } 112 | } else { 113 | 114 | return -1; 115 | } 116 | } 117 | } while ((blk = (char const *) xdl_mmfile_next(mmfp, &size)) != NULL); 118 | 119 | return 0; 120 | } 121 | 122 | 123 | static unsigned long xdl_mmob_adler32(mmoffbuffer_t *obf, int n) { 124 | unsigned long ha; 125 | 126 | for (ha = 0; n > 0; n--, obf++) 127 | ha = xdl_adler32(ha, (unsigned char const *) obf->ptr, obf->size); 128 | 129 | return ha; 130 | } 131 | 132 | 133 | static long xdl_mmob_size(mmoffbuffer_t *obf, int n) { 134 | 135 | return n > 0 ? obf[n - 1].off + obf[n - 1].size: 0; 136 | } 137 | 138 | 139 | static mmoffbuffer_t *xdl_mmob_new(mmoffbuffer_t **probf, int *pnobf, int *paobf) { 140 | int aobf; 141 | mmoffbuffer_t *cobf, *rrobf; 142 | 143 | if (*pnobf >= *paobf) { 144 | aobf = 2 * (*paobf) + 1; 145 | if ((rrobf = (mmoffbuffer_t *) 146 | xdl_realloc(*probf, aobf * sizeof(mmoffbuffer_t))) == NULL) { 147 | 148 | return NULL; 149 | } 150 | *probf = rrobf; 151 | *paobf = aobf; 152 | } 153 | cobf = (*probf) + (*pnobf); 154 | (*pnobf)++; 155 | 156 | return cobf; 157 | } 158 | 159 | 160 | static int xdl_mmob_find_cntr(mmoffbuffer_t *obf, int n, long off) { 161 | int i, lo, hi; 162 | 163 | for (lo = -1, hi = n; hi - lo > 1;) { 164 | i = (hi + lo) / 2; 165 | if (off < obf[i].off) 166 | hi = i; 167 | else 168 | lo = i; 169 | } 170 | 171 | return (lo >= 0 && off >= obf[lo].off && off < obf[lo].off + obf[lo].size) ? lo: -1; 172 | } 173 | 174 | 175 | static int xdl_bmerge(mmoffbuffer_t *obf, int n, mmbuffer_t *mbfp, mmoffbuffer_t **probf, 176 | int *pnobf) { 177 | int i, aobf, nobf; 178 | long ooff, off, csize; 179 | unsigned long fp, ofp; 180 | unsigned char const *data, *top; 181 | mmoffbuffer_t *robf, *cobf; 182 | 183 | if (mbfp->size < XDL_BPATCH_HDR_SIZE) { 184 | 185 | return -1; 186 | } 187 | data = (unsigned char const *) mbfp->ptr; 188 | top = data + mbfp->size; 189 | 190 | ofp = xdl_mmob_adler32(obf, n); 191 | XDL_LE32_GET(data, fp); 192 | data += 4; 193 | XDL_LE32_GET(data, csize); 194 | data += 4; 195 | if (fp != ofp || csize != xdl_mmob_size(obf, n)) { 196 | 197 | return -1; 198 | } 199 | aobf = XDL_MOBF_MINALLOC; 200 | nobf = 0; 201 | if ((robf = (mmoffbuffer_t *) xdl_malloc(aobf * sizeof(mmoffbuffer_t))) == NULL) { 202 | 203 | return -1; 204 | } 205 | 206 | for (ooff = 0; data < top;) { 207 | if (*data == XDL_BDOP_INS) { 208 | data++; 209 | 210 | if ((cobf = xdl_mmob_new(&robf, &nobf, &aobf)) == NULL) { 211 | 212 | xdl_free(robf); 213 | return -1; 214 | } 215 | cobf->off = ooff; 216 | cobf->size = (long) *data++; 217 | cobf->ptr = (char *) data; 218 | 219 | data += cobf->size; 220 | ooff += cobf->size; 221 | } else if (*data == XDL_BDOP_INSB) { 222 | data++; 223 | XDL_LE32_GET(data, csize); 224 | data += 4; 225 | 226 | if ((cobf = xdl_mmob_new(&robf, &nobf, &aobf)) == NULL) { 227 | 228 | xdl_free(robf); 229 | return -1; 230 | } 231 | cobf->off = ooff; 232 | cobf->size = csize; 233 | cobf->ptr = (char *) data; 234 | 235 | data += cobf->size; 236 | ooff += cobf->size; 237 | } else if (*data == XDL_BDOP_CPY) { 238 | data++; 239 | XDL_LE32_GET(data, off); 240 | data += 4; 241 | XDL_LE32_GET(data, csize); 242 | data += 4; 243 | 244 | if ((i = xdl_mmob_find_cntr(obf, n, off)) < 0) { 245 | 246 | xdl_free(robf); 247 | return -1; 248 | } 249 | off -= obf[i].off; 250 | for (; i < n && csize > 0; i++, off = 0) { 251 | if ((cobf = xdl_mmob_new(&robf, &nobf, &aobf)) == NULL) { 252 | 253 | xdl_free(robf); 254 | return -1; 255 | } 256 | cobf->off = ooff; 257 | cobf->size = XDL_MIN(csize, obf[i].size - off); 258 | cobf->ptr = obf[i].ptr + off; 259 | 260 | ooff += cobf->size; 261 | csize -= cobf->size; 262 | } 263 | if (csize > 0) { 264 | 265 | xdl_free(robf); 266 | return -1; 267 | } 268 | } else { 269 | 270 | xdl_free(robf); 271 | return -1; 272 | } 273 | } 274 | *probf = robf; 275 | *pnobf = nobf; 276 | 277 | return 0; 278 | } 279 | 280 | 281 | static int xdl_bmerge_synt(mmoffbuffer_t *obf, int n, xdemitcb_t *ecb) { 282 | int i; 283 | mmbuffer_t *mb; 284 | 285 | if ((mb = (mmbuffer_t *) xdl_malloc(n * sizeof(mmbuffer_t))) == NULL) { 286 | 287 | return -1; 288 | } 289 | for (i = 0; i < n; i++) { 290 | mb[i].ptr = obf[i].ptr; 291 | mb[i].size = obf[i].size; 292 | } 293 | if (ecb->outf(ecb->priv, mb, n) < 0) { 294 | 295 | xdl_free(mb); 296 | return -1; 297 | } 298 | xdl_free(mb); 299 | 300 | return 0; 301 | } 302 | 303 | 304 | int xdl_bpatch_multi(mmbuffer_t *base, mmbuffer_t *mbpch, int n, xdemitcb_t *ecb) { 305 | int i, nobf, fnobf; 306 | mmoffbuffer_t *obf, *fobf; 307 | 308 | nobf = 1; 309 | if ((obf = (mmoffbuffer_t *) xdl_malloc(nobf * sizeof(mmoffbuffer_t))) == NULL) { 310 | 311 | return -1; 312 | } 313 | obf->off = 0; 314 | obf->ptr = base->ptr; 315 | obf->size = base->size; 316 | for (i = 0; i < n; i++) { 317 | if (xdl_bmerge(obf, nobf, &mbpch[i], &fobf, &fnobf) < 0) { 318 | 319 | xdl_free(obf); 320 | return -1; 321 | } 322 | xdl_free(obf); 323 | 324 | obf = fobf; 325 | nobf = fnobf; 326 | } 327 | if (xdl_bmerge_synt(obf, nobf, ecb) < 0) { 328 | 329 | xdl_free(obf); 330 | return -1; 331 | } 332 | xdl_free(obf); 333 | 334 | return 0; 335 | } 336 | 337 | -------------------------------------------------------------------------------- /xdiff/xdiff.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XDIFF_H) 24 | #define XDIFF_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif /* #ifdef __cplusplus */ 29 | 30 | #ifdef _WIN32 31 | #ifdef LIBXDIFF_DLL_EXPORT 32 | #define LIBXDIFF_EXPORT __declspec(dllexport) 33 | #else 34 | #define LIBXDIFF_EXPORT __declspec(dllimport) 35 | #endif 36 | #else 37 | #define LIBXDIFF_EXPORT 38 | #endif 39 | 40 | #define XDF_NEED_MINIMAL (1 << 1) 41 | 42 | #define XDL_PATCH_NORMAL '-' 43 | #define XDL_PATCH_REVERSE '+' 44 | #define XDL_PATCH_MODEMASK ((1 << 8) - 1) 45 | #define XDL_PATCH_IGNOREBSPACE (1 << 8) 46 | 47 | #define XDL_MMB_READONLY (1 << 0) 48 | 49 | #define XDL_MMF_ATOMIC (1 << 0) 50 | 51 | #define XDL_BDOP_INS 1 52 | #define XDL_BDOP_CPY 2 53 | #define XDL_BDOP_INSB 3 54 | 55 | 56 | 57 | LIBXDIFF_EXPORT typedef struct s_memallocator { 58 | void *priv; 59 | void *(*malloc)(void *, unsigned int); 60 | void (*free)(void *, void *); 61 | void *(*realloc)(void *, void *, unsigned int); 62 | } memallocator_t; 63 | 64 | LIBXDIFF_EXPORT typedef struct s_mmblock { 65 | struct s_mmblock *next; 66 | unsigned long flags; 67 | long size, bsize; 68 | char *ptr; 69 | } mmblock_t; 70 | 71 | LIBXDIFF_EXPORT typedef struct s_mmfile { 72 | unsigned long flags; 73 | mmblock_t *head, *tail; 74 | long bsize, fsize, rpos; 75 | mmblock_t *rcur, *wcur; 76 | } mmfile_t; 77 | 78 | LIBXDIFF_EXPORT typedef struct s_mmbuffer { 79 | char *ptr; 80 | long size; 81 | } mmbuffer_t; 82 | 83 | LIBXDIFF_EXPORT typedef struct s_xpparam { 84 | unsigned long flags; 85 | } xpparam_t; 86 | 87 | LIBXDIFF_EXPORT typedef struct s_xdemitcb { 88 | void *priv; 89 | int (*outf)(void *, mmbuffer_t *, int); 90 | } xdemitcb_t; 91 | 92 | LIBXDIFF_EXPORT typedef struct s_xdemitconf { 93 | long ctxlen; 94 | } xdemitconf_t; 95 | 96 | LIBXDIFF_EXPORT typedef struct s_bdiffparam { 97 | long bsize; 98 | } bdiffparam_t; 99 | 100 | 101 | LIBXDIFF_EXPORT int xdl_set_allocator(memallocator_t const *malt); 102 | LIBXDIFF_EXPORT void *xdl_malloc(unsigned int size); 103 | LIBXDIFF_EXPORT void xdl_free(void *ptr); 104 | LIBXDIFF_EXPORT void *xdl_realloc(void *ptr, unsigned int size); 105 | 106 | LIBXDIFF_EXPORT int xdl_init_mmfile(mmfile_t *mmf, long bsize, unsigned long flags); 107 | LIBXDIFF_EXPORT void xdl_free_mmfile(mmfile_t *mmf); 108 | LIBXDIFF_EXPORT int xdl_mmfile_iscompact(mmfile_t *mmf); 109 | LIBXDIFF_EXPORT int xdl_seek_mmfile(mmfile_t *mmf, long off); 110 | LIBXDIFF_EXPORT long xdl_read_mmfile(mmfile_t *mmf, void *data, long size); 111 | LIBXDIFF_EXPORT long xdl_write_mmfile(mmfile_t *mmf, void const *data, long size); 112 | LIBXDIFF_EXPORT long xdl_writem_mmfile(mmfile_t *mmf, mmbuffer_t *mb, int nbuf); 113 | LIBXDIFF_EXPORT void *xdl_mmfile_writeallocate(mmfile_t *mmf, long size); 114 | LIBXDIFF_EXPORT long xdl_mmfile_ptradd(mmfile_t *mmf, char *ptr, long size, unsigned long flags); 115 | LIBXDIFF_EXPORT long xdl_copy_mmfile(mmfile_t *mmf, long size, xdemitcb_t *ecb); 116 | LIBXDIFF_EXPORT void *xdl_mmfile_first(mmfile_t *mmf, long *size); 117 | LIBXDIFF_EXPORT void *xdl_mmfile_next(mmfile_t *mmf, long *size); 118 | LIBXDIFF_EXPORT long xdl_mmfile_size(mmfile_t *mmf); 119 | LIBXDIFF_EXPORT int xdl_mmfile_cmp(mmfile_t *mmf1, mmfile_t *mmf2); 120 | LIBXDIFF_EXPORT int xdl_mmfile_compact(mmfile_t *mmfo, mmfile_t *mmfc, long bsize, unsigned long flags); 121 | 122 | LIBXDIFF_EXPORT int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 123 | xdemitconf_t const *xecfg, xdemitcb_t *ecb); 124 | LIBXDIFF_EXPORT int xdl_patch(mmfile_t *mf, mmfile_t *mfp, int mode, xdemitcb_t *ecb, 125 | xdemitcb_t *rjecb); 126 | 127 | LIBXDIFF_EXPORT int xdl_merge3(mmfile_t *mmfo, mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb, 128 | xdemitcb_t *rjecb); 129 | 130 | LIBXDIFF_EXPORT int xdl_bdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, bdiffparam_t const *bdp, xdemitcb_t *ecb); 131 | LIBXDIFF_EXPORT int xdl_bdiff(mmfile_t *mmf1, mmfile_t *mmf2, bdiffparam_t const *bdp, xdemitcb_t *ecb); 132 | LIBXDIFF_EXPORT int xdl_rabdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, xdemitcb_t *ecb); 133 | LIBXDIFF_EXPORT int xdl_rabdiff(mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb); 134 | LIBXDIFF_EXPORT long xdl_bdiff_tgsize(mmfile_t *mmfp); 135 | LIBXDIFF_EXPORT int xdl_bpatch(mmfile_t *mmf, mmfile_t *mmfp, xdemitcb_t *ecb); 136 | LIBXDIFF_EXPORT int xdl_bpatch_multi(mmbuffer_t *base, mmbuffer_t *mbpch, int n, xdemitcb_t *ecb); 137 | 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif /* #ifdef __cplusplus */ 142 | 143 | #endif /* #if !defined(XDIFF_H) */ 144 | 145 | -------------------------------------------------------------------------------- /xdiff/xdiffi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | 27 | #define XDL_MAX_COST_MIN 256 28 | #define XDL_HEUR_MIN_COST 256 29 | #define XDL_LINE_MAX (long)((1UL << (8 * sizeof(long) - 1)) - 1) 30 | #define XDL_SNAKE_CNT 20 31 | #define XDL_K_HEUR 4 32 | 33 | 34 | 35 | typedef struct s_xdpsplit { 36 | long i1, i2; 37 | int min_lo, min_hi; 38 | } xdpsplit_t; 39 | 40 | 41 | 42 | /* 43 | * See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers. 44 | * Basically considers a "box" (off1, off2, lim1, lim2) and scan from both 45 | * the forward diagonal starting from (off1, off2) and the backward diagonal 46 | * starting from (lim1, lim2). If the K values on the same diagonal crosses 47 | * returns the furthest point of reach. We might end up having to expensive 48 | * cases using this algorithm is full, so a little bit of heuristic is needed 49 | * to cut the search and to return a suboptimal point. 50 | */ 51 | static long xdl_split(unsigned long const *ha1, long off1, long lim1, 52 | unsigned long const *ha2, long off2, long lim2, 53 | long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl, 54 | xdalgoenv_t *xenv) { 55 | long dmin = off1 - lim2, dmax = lim1 - off2; 56 | long fmid = off1 - off2, bmid = lim1 - lim2; 57 | long odd = (fmid - bmid) & 1; 58 | long fmin = fmid, fmax = fmid; 59 | long bmin = bmid, bmax = bmid; 60 | long ec, d, i1, i2, prev1, best, dd, v, k; 61 | 62 | /* 63 | * Set initial diagonal values for both forward and backward path. 64 | */ 65 | kvdf[fmid] = off1; 66 | kvdb[bmid] = lim1; 67 | 68 | for (ec = 1;; ec++) { 69 | int got_snake = 0; 70 | 71 | /* 72 | * We need to extent the diagonal "domain" by one. If the next 73 | * values exits the box boundaries we need to change it in the 74 | * opposite direction because (max - min) must be a power of two. 75 | * Also we initialize the extenal K value to -1 so that we can 76 | * avoid extra conditions check inside the core loop. 77 | */ 78 | if (fmin > dmin) 79 | kvdf[--fmin - 1] = -1; 80 | else 81 | ++fmin; 82 | if (fmax < dmax) 83 | kvdf[++fmax + 1] = -1; 84 | else 85 | --fmax; 86 | 87 | for (d = fmax; d >= fmin; d -= 2) { 88 | if (kvdf[d - 1] >= kvdf[d + 1]) 89 | i1 = kvdf[d - 1] + 1; 90 | else 91 | i1 = kvdf[d + 1]; 92 | prev1 = i1; 93 | i2 = i1 - d; 94 | for (; i1 < lim1 && i2 < lim2 && ha1[i1] == ha2[i2]; i1++, i2++); 95 | if (i1 - prev1 > xenv->snake_cnt) 96 | got_snake = 1; 97 | kvdf[d] = i1; 98 | if (odd && bmin <= d && d <= bmax && kvdb[d] <= i1) { 99 | spl->i1 = i1; 100 | spl->i2 = i2; 101 | spl->min_lo = spl->min_hi = 1; 102 | return ec; 103 | } 104 | } 105 | 106 | /* 107 | * We need to extent the diagonal "domain" by one. If the next 108 | * values exits the box boundaries we need to change it in the 109 | * opposite direction because (max - min) must be a power of two. 110 | * Also we initialize the extenal K value to -1 so that we can 111 | * avoid extra conditions check inside the core loop. 112 | */ 113 | if (bmin > dmin) 114 | kvdb[--bmin - 1] = XDL_LINE_MAX; 115 | else 116 | ++bmin; 117 | if (bmax < dmax) 118 | kvdb[++bmax + 1] = XDL_LINE_MAX; 119 | else 120 | --bmax; 121 | 122 | for (d = bmax; d >= bmin; d -= 2) { 123 | if (kvdb[d - 1] < kvdb[d + 1]) 124 | i1 = kvdb[d - 1]; 125 | else 126 | i1 = kvdb[d + 1] - 1; 127 | prev1 = i1; 128 | i2 = i1 - d; 129 | for (; i1 > off1 && i2 > off2 && ha1[i1 - 1] == ha2[i2 - 1]; i1--, i2--); 130 | if (prev1 - i1 > xenv->snake_cnt) 131 | got_snake = 1; 132 | kvdb[d] = i1; 133 | if (!odd && fmin <= d && d <= fmax && i1 <= kvdf[d]) { 134 | spl->i1 = i1; 135 | spl->i2 = i2; 136 | spl->min_lo = spl->min_hi = 1; 137 | return ec; 138 | } 139 | } 140 | 141 | if (need_min) 142 | continue; 143 | 144 | /* 145 | * If the edit cost is above the heuristic trigger and if 146 | * we got a good snake, we sample current diagonals to see 147 | * if some of the, have reached an "interesting" path. Our 148 | * measure is a function of the distance from the diagonal 149 | * corner (i1 + i2) penalized with the distance from the 150 | * mid diagonal itself. If this value is above the current 151 | * edit cost times a magic factor (XDL_K_HEUR) we consider 152 | * it interesting. 153 | */ 154 | if (got_snake && ec > xenv->heur_min) { 155 | for (best = 0, d = fmax; d >= fmin; d -= 2) { 156 | dd = d > fmid ? d - fmid: fmid - d; 157 | i1 = kvdf[d]; 158 | i2 = i1 - d; 159 | v = (i1 - off1) + (i2 - off2) - dd; 160 | 161 | if (v > XDL_K_HEUR * ec && v > best && 162 | off1 + xenv->snake_cnt <= i1 && i1 < lim1 && 163 | off2 + xenv->snake_cnt <= i2 && i2 < lim2) { 164 | for (k = 1; ha1[i1 - k] == ha2[i2 - k]; k++) 165 | if (k == xenv->snake_cnt) { 166 | best = v; 167 | spl->i1 = i1; 168 | spl->i2 = i2; 169 | break; 170 | } 171 | } 172 | } 173 | if (best > 0) { 174 | spl->min_lo = 1; 175 | spl->min_hi = 0; 176 | return ec; 177 | } 178 | 179 | for (best = 0, d = bmax; d >= bmin; d -= 2) { 180 | dd = d > bmid ? d - bmid: bmid - d; 181 | i1 = kvdb[d]; 182 | i2 = i1 - d; 183 | v = (lim1 - i1) + (lim2 - i2) - dd; 184 | 185 | if (v > XDL_K_HEUR * ec && v > best && 186 | off1 < i1 && i1 <= lim1 - xenv->snake_cnt && 187 | off2 < i2 && i2 <= lim2 - xenv->snake_cnt) { 188 | for (k = 0; ha1[i1 + k] == ha2[i2 + k]; k++) 189 | if (k == xenv->snake_cnt - 1) { 190 | best = v; 191 | spl->i1 = i1; 192 | spl->i2 = i2; 193 | break; 194 | } 195 | } 196 | } 197 | if (best > 0) { 198 | spl->min_lo = 0; 199 | spl->min_hi = 1; 200 | return ec; 201 | } 202 | } 203 | 204 | /* 205 | * Enough is enough. We spent too much time here and now we collect 206 | * the furthest reaching path using the (i1 + i2) measure. 207 | */ 208 | if (ec >= xenv->mxcost) { 209 | long fbest, fbest1, bbest, bbest1; 210 | 211 | fbest = -1; 212 | for (d = fmax; d >= fmin; d -= 2) { 213 | i1 = XDL_MIN(kvdf[d], lim1); 214 | i2 = i1 - d; 215 | if (lim2 < i2) 216 | i1 = lim2 + d, i2 = lim2; 217 | if (fbest < i1 + i2) { 218 | fbest = i1 + i2; 219 | fbest1 = i1; 220 | } 221 | } 222 | 223 | bbest = XDL_LINE_MAX; 224 | for (d = bmax; d >= bmin; d -= 2) { 225 | i1 = XDL_MAX(off1, kvdb[d]); 226 | i2 = i1 - d; 227 | if (i2 < off2) 228 | i1 = off2 + d, i2 = off2; 229 | if (i1 + i2 < bbest) { 230 | bbest = i1 + i2; 231 | bbest1 = i1; 232 | } 233 | } 234 | 235 | if ((lim1 + lim2) - bbest < fbest - (off1 + off2)) { 236 | spl->i1 = fbest1; 237 | spl->i2 = fbest - fbest1; 238 | spl->min_lo = 1; 239 | spl->min_hi = 0; 240 | } else { 241 | spl->i1 = bbest1; 242 | spl->i2 = bbest - bbest1; 243 | spl->min_lo = 0; 244 | spl->min_hi = 1; 245 | } 246 | return ec; 247 | } 248 | } 249 | 250 | return -1; 251 | } 252 | 253 | 254 | /* 255 | * Rule: "Divide et Impera". Recursively split the box in sub-boxes by calling 256 | * the box splitting function. Note that the real job (marking changed lines) 257 | * is done in the two boundary reaching checks. 258 | */ 259 | int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1, 260 | diffdata_t *dd2, long off2, long lim2, 261 | long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv) { 262 | unsigned long const *ha1 = dd1->ha, *ha2 = dd2->ha; 263 | 264 | /* 265 | * Shrink the box by walking through each diagonal snake (SW and NE). 266 | */ 267 | for (; off1 < lim1 && off2 < lim2 && ha1[off1] == ha2[off2]; off1++, off2++); 268 | for (; off1 < lim1 && off2 < lim2 && ha1[lim1 - 1] == ha2[lim2 - 1]; lim1--, lim2--); 269 | 270 | /* 271 | * If one dimension is empty, then all records on the other one must 272 | * be obviously changed. 273 | */ 274 | if (off1 == lim1) { 275 | char *rchg2 = dd2->rchg; 276 | long *rindex2 = dd2->rindex; 277 | 278 | for (; off2 < lim2; off2++) 279 | rchg2[rindex2[off2]] = 1; 280 | } else if (off2 == lim2) { 281 | char *rchg1 = dd1->rchg; 282 | long *rindex1 = dd1->rindex; 283 | 284 | for (; off1 < lim1; off1++) 285 | rchg1[rindex1[off1]] = 1; 286 | } else { 287 | long ec; 288 | xdpsplit_t spl; 289 | 290 | /* 291 | * Divide ... 292 | */ 293 | if ((ec = xdl_split(ha1, off1, lim1, ha2, off2, lim2, kvdf, kvdb, 294 | need_min, &spl, xenv)) < 0) { 295 | 296 | return -1; 297 | } 298 | 299 | /* 300 | * ... et Impera. 301 | */ 302 | if (xdl_recs_cmp(dd1, off1, spl.i1, dd2, off2, spl.i2, 303 | kvdf, kvdb, spl.min_lo, xenv) < 0 || 304 | xdl_recs_cmp(dd1, spl.i1, lim1, dd2, spl.i2, lim2, 305 | kvdf, kvdb, spl.min_hi, xenv) < 0) { 306 | 307 | return -1; 308 | } 309 | } 310 | 311 | return 0; 312 | } 313 | 314 | 315 | int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 316 | xdfenv_t *xe) { 317 | long ndiags; 318 | long *kvd, *kvdf, *kvdb; 319 | xdalgoenv_t xenv; 320 | diffdata_t dd1, dd2; 321 | 322 | if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) { 323 | 324 | return -1; 325 | } 326 | 327 | /* 328 | * Allocate and setup K vectors to be used by the differential algorithm. 329 | * One is to store the forward path and one to store the backward path. 330 | */ 331 | ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3; 332 | if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) { 333 | 334 | xdl_free_env(xe); 335 | return -1; 336 | } 337 | kvdf = kvd; 338 | kvdb = kvdf + ndiags; 339 | kvdf += xe->xdf2.nreff + 1; 340 | kvdb += xe->xdf2.nreff + 1; 341 | 342 | xenv.mxcost = xdl_bogosqrt(ndiags); 343 | if (xenv.mxcost < XDL_MAX_COST_MIN) 344 | xenv.mxcost = XDL_MAX_COST_MIN; 345 | xenv.snake_cnt = XDL_SNAKE_CNT; 346 | xenv.heur_min = XDL_HEUR_MIN_COST; 347 | 348 | dd1.nrec = xe->xdf1.nreff; 349 | dd1.ha = xe->xdf1.ha; 350 | dd1.rchg = xe->xdf1.rchg; 351 | dd1.rindex = xe->xdf1.rindex; 352 | dd2.nrec = xe->xdf2.nreff; 353 | dd2.ha = xe->xdf2.ha; 354 | dd2.rchg = xe->xdf2.rchg; 355 | dd2.rindex = xe->xdf2.rindex; 356 | 357 | if (xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec, 358 | kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0, &xenv) < 0) { 359 | 360 | xdl_free(kvd); 361 | xdl_free_env(xe); 362 | return -1; 363 | } 364 | 365 | xdl_free(kvd); 366 | 367 | return 0; 368 | } 369 | 370 | 371 | static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2) { 372 | xdchange_t *xch; 373 | 374 | if (!(xch = (xdchange_t *) xdl_malloc(sizeof(xdchange_t)))) 375 | return NULL; 376 | 377 | xch->next = xscr; 378 | xch->i1 = i1; 379 | xch->i2 = i2; 380 | xch->chg1 = chg1; 381 | xch->chg2 = chg2; 382 | 383 | return xch; 384 | } 385 | 386 | 387 | static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) { 388 | long ix, ixo, ixs, ixref, grpsiz, nrec = xdf->nrec; 389 | char *rchg = xdf->rchg, *rchgo = xdfo->rchg; 390 | xrecord_t **recs = xdf->recs; 391 | 392 | /* 393 | * This is the same of what GNU diff does. Move back and forward 394 | * change groups for a consistent and pretty diff output. This also 395 | * helps in finding joineable change groups and reduce the diff size. 396 | */ 397 | for (ix = ixo = 0;;) { 398 | /* 399 | * Find the first changed line in the to-be-compacted file. 400 | * We need to keep track of both indexes, so if we find a 401 | * changed lines group on the other file, while scanning the 402 | * to-be-compacted file, we need to skip it properly. Note 403 | * that loops that are testing for changed lines on rchg* do 404 | * not need index bounding since the array is prepared with 405 | * a zero at position -1 and N. 406 | */ 407 | for (; ix < nrec && !rchg[ix]; ix++) 408 | while (rchgo[ixo++]); 409 | if (ix == nrec) 410 | break; 411 | 412 | /* 413 | * Record the start of a changed-group in the to-be-compacted file 414 | * and find the end of it, on both to-be-compacted and other file 415 | * indexes (ix and ixo). 416 | */ 417 | ixs = ix; 418 | for (ix++; rchg[ix]; ix++); 419 | for (; rchgo[ixo]; ixo++); 420 | 421 | do { 422 | grpsiz = ix - ixs; 423 | 424 | /* 425 | * If the line before the current change group, is equal to 426 | * the last line of the current change group, shift backward 427 | * the group. 428 | */ 429 | while (ixs > 0 && recs[ixs - 1]->ha == recs[ix - 1]->ha && 430 | XDL_RECMATCH(recs[ixs - 1], recs[ix - 1])) { 431 | rchg[--ixs] = 1; 432 | rchg[--ix] = 0; 433 | 434 | /* 435 | * This change might have joined two change groups, 436 | * so we try to take this scenario in account by moving 437 | * the start index accordingly (and so the other-file 438 | * end-of-group index). 439 | */ 440 | for (; rchg[ixs - 1]; ixs--); 441 | while (rchgo[--ixo]); 442 | } 443 | 444 | /* 445 | * Record the end-of-group position in case we are matched 446 | * with a group of changes in the other file (that is, the 447 | * change record before the enf-of-group index in the other 448 | * file is set). 449 | */ 450 | ixref = rchgo[ixo - 1] ? ix: nrec; 451 | 452 | /* 453 | * If the first line of the current change group, is equal to 454 | * the line next of the current change group, shift forward 455 | * the group. 456 | */ 457 | while (ix < nrec && recs[ixs]->ha == recs[ix]->ha && 458 | XDL_RECMATCH(recs[ixs], recs[ix])) { 459 | rchg[ixs++] = 0; 460 | rchg[ix++] = 1; 461 | 462 | /* 463 | * This change might have joined two change groups, 464 | * so we try to take this scenario in account by moving 465 | * the start index accordingly (and so the other-file 466 | * end-of-group index). Keep tracking the reference 467 | * index in case we are shifting together with a 468 | * corresponding group of changes in the other file. 469 | */ 470 | for (; rchg[ix]; ix++); 471 | while (rchgo[++ixo]) 472 | ixref = ix; 473 | } 474 | } while (grpsiz != ix - ixs); 475 | 476 | /* 477 | * Try to move back the possibly merged group of changes, to match 478 | * the recorded postion in the other file. 479 | */ 480 | while (ixref < ix) { 481 | rchg[--ixs] = 1; 482 | rchg[--ix] = 0; 483 | while (rchgo[--ixo]); 484 | } 485 | } 486 | 487 | return 0; 488 | } 489 | 490 | 491 | int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr) { 492 | xdchange_t *cscr = NULL, *xch; 493 | char *rchg1 = xe->xdf1.rchg, *rchg2 = xe->xdf2.rchg; 494 | long i1, i2, l1, l2; 495 | 496 | /* 497 | * Trivial. Collects "groups" of changes and creates an edit script. 498 | */ 499 | for (i1 = xe->xdf1.nrec, i2 = xe->xdf2.nrec; i1 >= 0 || i2 >= 0; i1--, i2--) 500 | if (rchg1[i1 - 1] || rchg2[i2 - 1]) { 501 | for (l1 = i1; rchg1[i1 - 1]; i1--); 502 | for (l2 = i2; rchg2[i2 - 1]; i2--); 503 | 504 | if (!(xch = xdl_add_change(cscr, i1, i2, l1 - i1, l2 - i2))) { 505 | xdl_free_script(cscr); 506 | return -1; 507 | } 508 | cscr = xch; 509 | } 510 | 511 | *xscr = cscr; 512 | 513 | return 0; 514 | } 515 | 516 | 517 | void xdl_free_script(xdchange_t *xscr) { 518 | xdchange_t *xch; 519 | 520 | while ((xch = xscr) != NULL) { 521 | xscr = xscr->next; 522 | xdl_free(xch); 523 | } 524 | } 525 | 526 | 527 | int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 528 | xdemitconf_t const *xecfg, xdemitcb_t *ecb) { 529 | xdchange_t *xscr; 530 | xdfenv_t xe; 531 | 532 | if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) { 533 | 534 | return -1; 535 | } 536 | if (xdl_change_compact(&xe.xdf1, &xe.xdf2) < 0 || 537 | xdl_change_compact(&xe.xdf2, &xe.xdf1) < 0 || 538 | xdl_build_script(&xe, &xscr) < 0) { 539 | 540 | xdl_free_env(&xe); 541 | return -1; 542 | } 543 | if (xscr) { 544 | if (xdl_emit_diff(&xe, xscr, ecb, xecfg) < 0) { 545 | 546 | xdl_free_script(xscr); 547 | xdl_free_env(&xe); 548 | return -1; 549 | } 550 | xdl_free_script(xscr); 551 | } 552 | xdl_free_env(&xe); 553 | 554 | return 0; 555 | } 556 | 557 | -------------------------------------------------------------------------------- /xdiff/xdiffi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XDIFFI_H) 24 | #define XDIFFI_H 25 | 26 | 27 | typedef struct s_diffdata { 28 | long nrec; 29 | unsigned long const *ha; 30 | long *rindex; 31 | char *rchg; 32 | } diffdata_t; 33 | 34 | typedef struct s_xdalgoenv { 35 | long mxcost; 36 | long snake_cnt; 37 | long heur_min; 38 | } xdalgoenv_t; 39 | 40 | typedef struct s_xdchange { 41 | struct s_xdchange *next; 42 | long i1, i2; 43 | long chg1, chg2; 44 | } xdchange_t; 45 | 46 | 47 | 48 | int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1, 49 | diffdata_t *dd2, long off2, long lim2, 50 | long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv); 51 | int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 52 | xdfenv_t *xe); 53 | int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr); 54 | void xdl_free_script(xdchange_t *xscr); 55 | int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, 56 | xdemitconf_t const *xecfg); 57 | 58 | 59 | #endif /* #if !defined(XDIFFI_H) */ 60 | 61 | -------------------------------------------------------------------------------- /xdiff/xemit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) { 27 | 28 | *rec = xdf->recs[ri]->ptr; 29 | 30 | return xdf->recs[ri]->size; 31 | } 32 | 33 | 34 | static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) { 35 | long size, psize = strlen(pre); 36 | char const *rec; 37 | 38 | size = xdl_get_rec(xdf, ri, &rec); 39 | if (xdl_emit_diffrec(rec, size, pre, psize, ecb) < 0) { 40 | 41 | return -1; 42 | } 43 | 44 | return 0; 45 | } 46 | 47 | 48 | /* 49 | * Starting at the passed change atom, find the latest change atom to be included 50 | * inside the differential hunk according to the specified configuration. 51 | */ 52 | static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { 53 | xdchange_t *xch, *xchp; 54 | 55 | for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next) 56 | if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen) 57 | break; 58 | 59 | return xchp; 60 | } 61 | 62 | 63 | int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, 64 | xdemitconf_t const *xecfg) { 65 | long s1, s2, e1, e2, lctx; 66 | xdchange_t *xch, *xche; 67 | 68 | for (xch = xche = xscr; xch; xch = xche->next) { 69 | xche = xdl_get_hunk(xch, xecfg); 70 | 71 | s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); 72 | s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); 73 | 74 | lctx = xecfg->ctxlen; 75 | lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1)); 76 | lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2)); 77 | 78 | e1 = xche->i1 + xche->chg1 + lctx; 79 | e2 = xche->i2 + xche->chg2 + lctx; 80 | 81 | /* 82 | * Emit current hunk header. 83 | */ 84 | if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, ecb) < 0) 85 | return -1; 86 | 87 | /* 88 | * Emit pre-context. 89 | */ 90 | for (; s1 < xch->i1; s1++) 91 | if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0) 92 | return -1; 93 | 94 | for (s1 = xch->i1, s2 = xch->i2;; xch = xch->next) { 95 | /* 96 | * Merge previous with current change atom. 97 | */ 98 | for (; s1 < xch->i1 && s2 < xch->i2; s1++, s2++) 99 | if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0) 100 | return -1; 101 | 102 | /* 103 | * Removes lines from the first file. 104 | */ 105 | for (s1 = xch->i1; s1 < xch->i1 + xch->chg1; s1++) 106 | if (xdl_emit_record(&xe->xdf1, s1, "-", ecb) < 0) 107 | return -1; 108 | 109 | /* 110 | * Adds lines from the second file. 111 | */ 112 | for (s2 = xch->i2; s2 < xch->i2 + xch->chg2; s2++) 113 | if (xdl_emit_record(&xe->xdf2, s2, "+", ecb) < 0) 114 | return -1; 115 | 116 | if (xch == xche) 117 | break; 118 | s1 = xch->i1 + xch->chg1; 119 | s2 = xch->i2 + xch->chg2; 120 | } 121 | 122 | /* 123 | * Emit post-context. 124 | */ 125 | for (s1 = xche->i1 + xche->chg1; s1 < e1; s1++) 126 | if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0) 127 | return -1; 128 | } 129 | 130 | return 0; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /xdiff/xemit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XEMIT_H) 24 | #define XEMIT_H 25 | 26 | 27 | 28 | int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, 29 | xdemitconf_t const *xecfg); 30 | 31 | 32 | 33 | #endif /* #if !defined(XEMIT_H) */ 34 | 35 | -------------------------------------------------------------------------------- /xdiff/xinclude.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XINCLUDE_H) 24 | #define XINCLUDE_H 25 | 26 | 27 | #if defined(HAVE_WINCONFIG_H) 28 | #include "winconfig.h" 29 | #endif /* #if defined(HAVE_CONFIG_H) */ 30 | 31 | #if defined(HAVE_CONFIG_H) 32 | #include "config.h" 33 | #endif /* #if defined(HAVE_CONFIG_H) */ 34 | 35 | #if defined(HAVE_STDIO_H) 36 | #include 37 | #endif /* #if defined(HAVE_STDIO_H) */ 38 | 39 | #if defined(HAVE_STDLIB_H) 40 | #include 41 | #endif /* #if defined(HAVE_STDLIB_H) */ 42 | 43 | #if defined(HAVE_UNISTD_H) 44 | #include 45 | #endif /* #if defined(HAVE_UNISTD_H) */ 46 | 47 | #if defined(HAVE_STRING_H) 48 | #include 49 | #endif /* #if defined(HAVE_STRING_H) */ 50 | 51 | #if defined(HAVE_LIMITS_H) 52 | #include 53 | #endif /* #if defined(HAVE_LIMITS_H) */ 54 | 55 | 56 | 57 | #include "xmacros.h" 58 | #include "xmissing.h" 59 | #include "xdiff.h" 60 | #include "xtypes.h" 61 | #include "xutils.h" 62 | #include "xadler32.h" 63 | #include "xprepare.h" 64 | #include "xdiffi.h" 65 | #include "xemit.h" 66 | #include "xbdiff.h" 67 | 68 | 69 | 70 | #endif /* #if !defined(XINCLUDE_H) */ 71 | 72 | -------------------------------------------------------------------------------- /xdiff/xmacros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XMACROS_H) 24 | #define XMACROS_H 25 | 26 | 27 | #define XDL_MIN(a, b) ((a) < (b) ? (a): (b)) 28 | #define XDL_MAX(a, b) ((a) > (b) ? (a): (b)) 29 | #define XDL_ABS(v) ((v) >= 0 ? (v): -(v)) 30 | #define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9') 31 | #define XDL_ADDBITS(v, b) ((v) + ((v) >> (b))) 32 | #define XDL_MASKBITS(b) ((1UL << (b)) - 1) 33 | #define XDL_HASHLONG(v, b) (XDL_ADDBITS((unsigned long) (v), b) & XDL_MASKBITS(b)) 34 | #define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0) 35 | #define XDL_RECMATCH(r1, r2) ((r1)->size == (r2)->size && memcmp((r1)->ptr, (r2)->ptr, (r1)->size) == 0) 36 | #define XDL_LE32_PUT(p, v) do { \ 37 | unsigned char *__p = (unsigned char *) (p); \ 38 | *__p++ = (unsigned char) (v); \ 39 | *__p++ = (unsigned char) ((v) >> 8); \ 40 | *__p++ = (unsigned char) ((v) >> 16); \ 41 | *__p = (unsigned char) ((v) >> 24); \ 42 | } while (0) 43 | #define XDL_LE32_GET(p, v) do { \ 44 | unsigned char const *__p = (unsigned char const *) (p); \ 45 | (v) = (unsigned long) __p[0] | ((unsigned long) __p[1]) << 8 | \ 46 | ((unsigned long) __p[2]) << 16 | ((unsigned long) __p[3]) << 24; \ 47 | } while (0) 48 | 49 | 50 | #endif /* #if !defined(XMACROS_H) */ 51 | 52 | -------------------------------------------------------------------------------- /xdiff/xmerge3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | #define XDL_MERGE3_BLKSIZE (1024 * 8) 27 | #define XDL_MERGE3_CTXLEN 3 28 | 29 | 30 | 31 | int xdl_merge3(mmfile_t *mmfo, mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb, 32 | xdemitcb_t *rjecb) { 33 | xpparam_t xpp; 34 | xdemitconf_t xecfg; 35 | xdemitcb_t xecb; 36 | mmfile_t mmfp; 37 | 38 | if (xdl_init_mmfile(&mmfp, XDL_MERGE3_BLKSIZE, XDL_MMF_ATOMIC) < 0) { 39 | 40 | return -1; 41 | } 42 | 43 | xpp.flags = 0; 44 | 45 | xecfg.ctxlen = XDL_MERGE3_CTXLEN; 46 | 47 | xecb.priv = &mmfp; 48 | xecb.outf = xdl_mmfile_outf; 49 | 50 | if (xdl_diff(mmfo, mmf2, &xpp, &xecfg, &xecb) < 0) { 51 | 52 | xdl_free_mmfile(&mmfp); 53 | return -1; 54 | } 55 | 56 | if (xdl_patch(mmf1, &mmfp, XDL_PATCH_NORMAL, ecb, rjecb) < 0) { 57 | 58 | xdl_free_mmfile(&mmfp); 59 | return -1; 60 | } 61 | 62 | xdl_free_mmfile(&mmfp); 63 | 64 | return 0; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /xdiff/xmissing.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | 27 | #if !defined(HAVE_MEMCHR) 28 | 29 | void *memchr(void const *p, int c, long n) { 30 | char const *pc = p; 31 | 32 | for (; n; n--, pc++) 33 | if (*pc == (char) c) 34 | return pc; 35 | return NULL; 36 | } 37 | 38 | #endif /* #if !defined(HAVE_MEMCHR) */ 39 | 40 | 41 | #if !defined(HAVE_MEMCMP) 42 | 43 | int memcmp(void const *p1, void const *p2, long n) { 44 | char const *pc1 = p1, *pc2 = p2; 45 | 46 | for (; n; n--, pc1++, pc2++) 47 | if (*pc1 != *pc2) 48 | return *pc1 - *pc2; 49 | return 0; 50 | } 51 | 52 | #endif /* #if !defined(HAVE_MEMCMP) */ 53 | 54 | 55 | #if !defined(HAVE_MEMCPY) 56 | 57 | void *memcpy(void *d, void const *s, long n) { 58 | char *dc = d; 59 | char const *sc = s; 60 | 61 | for (; n; n--, dc++, sc++) 62 | *dc = *sc; 63 | return d; 64 | } 65 | 66 | #endif /* #if !defined(HAVE_MEMCPY) */ 67 | 68 | 69 | #if !defined(HAVE_MEMSET) 70 | 71 | void *memset(void *d, int c, long n) { 72 | char *dc = d; 73 | 74 | for (; n; n--, dc++) 75 | *dc = (char) c; 76 | return d; 77 | } 78 | 79 | #endif /* #if !defined(HAVE_MEMSET) */ 80 | 81 | 82 | #if !defined(HAVE_STRLEN) 83 | 84 | long strlen(char const *s) { 85 | char const *tmp; 86 | 87 | for (tmp = s; *s; s++); 88 | return (long) (s - tmp); 89 | } 90 | 91 | #endif /* #if !defined(HAVE_STRLEN) */ 92 | 93 | -------------------------------------------------------------------------------- /xdiff/xmissing.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XMISSING_H) 24 | #define XMISSING_H 25 | 26 | 27 | #if !defined(CHAR_BIT) 28 | #define CHAR_BIT 8 29 | #endif /* #if !defined(CHAR_BIT) */ 30 | 31 | 32 | 33 | #if !defined(HAVE_MEMCHR) 34 | void *memchr(void const *p, int c, long n); 35 | #endif /* #if !defined(HAVE_MEMCHR) */ 36 | 37 | #if !defined(HAVE_MEMCMP) 38 | int memcmp(void const *p1, void const *p2, long n); 39 | #endif /* #if !defined(HAVE_MEMCMP) */ 40 | 41 | #if !defined(HAVE_MEMCPY) 42 | void *memcpy(void *d, void const *s, long n); 43 | #endif /* #if !defined(HAVE_MEMCPY) */ 44 | 45 | #if !defined(HAVE_MEMSET) 46 | void *memset(void *d, int c, long n); 47 | #endif /* #if !defined(HAVE_MEMSET) */ 48 | 49 | #if !defined(HAVE_STRLEN) 50 | long strlen(char const *s); 51 | #endif /* #if !defined(HAVE_STRLEN) */ 52 | 53 | 54 | 55 | #endif /* #if !defined(XMISSING_H) */ 56 | 57 | -------------------------------------------------------------------------------- /xdiff/xpatchi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | 27 | #define XDL_MAX_FUZZ 3 28 | #define XDL_MIN_SYNCLINES 4 29 | 30 | 31 | 32 | typedef struct s_recinfo { 33 | char const *ptr; 34 | long size; 35 | } recinfo_t; 36 | 37 | typedef struct s_recfile { 38 | mmfile_t *mf; 39 | long nrec; 40 | recinfo_t *recs; 41 | } recfile_t; 42 | 43 | typedef struct s_hunkinfo { 44 | long s1, s2; 45 | long c1, c2; 46 | long cmn, radd, rdel, pctx, sctx; 47 | } hunkinfo_t; 48 | 49 | typedef struct s_patchstats { 50 | long adds, dels; 51 | } patchstats_t; 52 | 53 | typedef struct s_patch { 54 | recfile_t rf; 55 | hunkinfo_t hi; 56 | long hkrec; 57 | long hklen; 58 | long flags; 59 | patchstats_t ps; 60 | int fuzzies; 61 | } patch_t; 62 | 63 | 64 | 65 | 66 | static int xdl_load_hunk_info(char const *line, long size, hunkinfo_t *hki); 67 | static int xdl_init_recfile(mmfile_t *mf, int ispatch, recfile_t *rf); 68 | static void xdl_free_recfile(recfile_t *rf); 69 | static char const *xdl_recfile_get(recfile_t *rf, long irec, long *size); 70 | static int xdl_init_patch(mmfile_t *mf, long flags, patch_t *pch); 71 | static void xdl_free_patch(patch_t *pch); 72 | static int xdl_load_hunk(patch_t *pch, long hkrec); 73 | static int xdl_first_hunk(patch_t *pch); 74 | static int xdl_next_hunk(patch_t *pch); 75 | static int xdl_line_match(patch_t *pch, const char *s, long ns, char const *m, long nm); 76 | static int xdl_hunk_match(recfile_t *rf, long irec, patch_t *pch, int mode, int fuzz); 77 | static int xdl_find_hunk(recfile_t *rf, long ibase, patch_t *pch, int mode, 78 | int fuzz, long *hkpos, int *exact); 79 | static int xdl_emit_rfile_line(recfile_t *rf, long line, xdemitcb_t *ecb); 80 | static int xdl_flush_section(recfile_t *rf, long start, long top, xdemitcb_t *ecb); 81 | static int xdl_apply_hunk(recfile_t *rf, long hkpos, patch_t *pch, int mode, 82 | long *ibase, xdemitcb_t *ecb); 83 | static int xdl_reject_hunk(recfile_t *rf, patch_t *pch, int mode, 84 | xdemitcb_t *rjecb); 85 | static int xdl_process_hunk(recfile_t *rff, patch_t *pch, long *ibase, int mode, 86 | xdemitcb_t *ecb, xdemitcb_t *rjecb); 87 | 88 | 89 | 90 | 91 | static int xdl_load_hunk_info(char const *line, long size, hunkinfo_t *hki) { 92 | char const *next; 93 | 94 | /* 95 | * The diff header format should be: 96 | * 97 | * @@ -OP,OC +NP,NC @@ 98 | * 99 | * Unfortunately some software avoid to emit OP or/and NP in case 100 | * of not existing old or new file (it should be mitted as zero). 101 | * We need to handle both syntaxes. 102 | */ 103 | if (memcmp(line, "@@ -", 4)) 104 | return -1; 105 | line += 4; 106 | size -= 4; 107 | 108 | if (!size || !XDL_ISDIGIT(*line)) 109 | return -1; 110 | hki->s1 = xdl_atol(line, &next); 111 | size -= next - line; 112 | line = next; 113 | if (!size) 114 | return -1; 115 | if (*line == ',') { 116 | size--, line++; 117 | if (!size || !XDL_ISDIGIT(*line)) 118 | return -1; 119 | hki->c1 = xdl_atol(line, &next); 120 | size -= next - line; 121 | line = next; 122 | if (!size || *line != ' ') 123 | return -1; 124 | size--, line++; 125 | } else if (*line == ' ') { 126 | size--, line++; 127 | hki->c1 = hki->s1; 128 | hki->s1 = 0; 129 | } else 130 | return -1; 131 | 132 | if (!size || *line != '+') 133 | return -1; 134 | size--, line++; 135 | if (!size || !XDL_ISDIGIT(*line)) 136 | return -1; 137 | hki->s2 = xdl_atol(line, &next); 138 | size -= next - line; 139 | line = next; 140 | if (!size) 141 | return -1; 142 | if (*line == ',') { 143 | size--, line++; 144 | if (!size || !XDL_ISDIGIT(*line)) 145 | return -1; 146 | hki->c2 = xdl_atol(line, &next); 147 | size -= next - line; 148 | line = next; 149 | if (!size || *line != ' ') 150 | return -1; 151 | size--, line++; 152 | } else if (*line == ' ') { 153 | size--, line++; 154 | hki->c2 = hki->s2; 155 | hki->s2 = 0; 156 | } else 157 | return -1; 158 | if (size < 2 || memcmp(line, "@@", 2) != 0) 159 | return -1; 160 | 161 | /* 162 | * We start from zero, so decrement by one unless it's the special position 163 | * '0' inside the unified diff (new or deleted file). 164 | */ 165 | if (hki->s1 > 0 && hki->c1 > 0) 166 | hki->s1--; 167 | if (hki->s2 > 0 && hki->c2 > 0) 168 | hki->s2--; 169 | 170 | return 0; 171 | } 172 | 173 | 174 | static int xdl_init_recfile(mmfile_t *mf, int ispatch, recfile_t *rf) { 175 | long narec, nrec, bsize; 176 | recinfo_t *recs, *rrecs; 177 | char const *blk, *cur, *top, *eol; 178 | 179 | narec = xdl_guess_lines(mf); 180 | if (!(recs = (recinfo_t *) xdl_malloc(narec * sizeof(recinfo_t)))) { 181 | 182 | return -1; 183 | } 184 | nrec = 0; 185 | if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) { 186 | for (top = blk + bsize;;) { 187 | if (cur >= top) { 188 | if (!(cur = blk = xdl_mmfile_next(mf, &bsize))) 189 | break; 190 | top = blk + bsize; 191 | } 192 | if (nrec >= narec) { 193 | narec *= 2; 194 | if (!(rrecs = (recinfo_t *) 195 | xdl_realloc(recs, narec * sizeof(recinfo_t)))) { 196 | 197 | xdl_free(recs); 198 | return -1; 199 | } 200 | recs = rrecs; 201 | } 202 | recs[nrec].ptr = cur; 203 | if (!(eol = memchr(cur, '\n', top - cur))) 204 | eol = top - 1; 205 | recs[nrec].size = (long) (eol - cur) + 1; 206 | if (ispatch && *cur == '\\' && nrec > 0 && recs[nrec - 1].size > 0 && 207 | recs[nrec - 1].ptr[recs[nrec - 1].size - 1] == '\n') 208 | recs[nrec - 1].size--; 209 | else 210 | nrec++; 211 | cur = eol + 1; 212 | } 213 | } 214 | rf->mf = mf; 215 | rf->nrec = nrec; 216 | rf->recs = recs; 217 | 218 | return 0; 219 | } 220 | 221 | 222 | static void xdl_free_recfile(recfile_t *rf) { 223 | 224 | xdl_free(rf->recs); 225 | } 226 | 227 | 228 | static char const *xdl_recfile_get(recfile_t *rf, long irec, long *size) { 229 | 230 | if (irec < 0 || irec >= rf->nrec) 231 | return NULL; 232 | *size = rf->recs[irec].size; 233 | 234 | return rf->recs[irec].ptr; 235 | } 236 | 237 | 238 | static int xdl_init_patch(mmfile_t *mf, long flags, patch_t *pch) { 239 | 240 | if (xdl_init_recfile(mf, 1, &pch->rf) < 0) { 241 | 242 | return -1; 243 | } 244 | pch->hkrec = 0; 245 | pch->hklen = 0; 246 | pch->flags = flags; 247 | pch->ps.adds = pch->ps.dels = 0; 248 | pch->fuzzies = 0; 249 | 250 | return 0; 251 | } 252 | 253 | 254 | static void xdl_free_patch(patch_t *pch) { 255 | 256 | xdl_free_recfile(&pch->rf); 257 | } 258 | 259 | 260 | static int xdl_load_hunk(patch_t *pch, long hkrec) { 261 | long size, i, nb; 262 | char const *line; 263 | 264 | for (;; hkrec++) { 265 | pch->hkrec = hkrec; 266 | if (!(line = xdl_recfile_get(&pch->rf, pch->hkrec, &size))) 267 | return 0; 268 | if (*line == '@') 269 | break; 270 | } 271 | if (xdl_load_hunk_info(line, size, &pch->hi) < 0) { 272 | 273 | return -1; 274 | } 275 | pch->hi.cmn = pch->hi.radd = pch->hi.rdel = pch->hi.pctx = pch->hi.sctx = 0; 276 | for (i = pch->hkrec + 1, nb = 0; 277 | (line = xdl_recfile_get(&pch->rf, i, &size)) != NULL; i++) { 278 | if (*line == '@' || *line == '\n') 279 | break; 280 | if (*line == ' ') { 281 | nb++; 282 | pch->hi.cmn++; 283 | } else if (*line == '+') { 284 | if (pch->hi.radd + pch->hi.rdel == 0) 285 | pch->hi.pctx = nb; 286 | nb = 0; 287 | pch->hi.radd++; 288 | } else if (*line == '-') { 289 | if (pch->hi.radd + pch->hi.rdel == 0) 290 | pch->hi.pctx = nb; 291 | nb = 0; 292 | pch->hi.rdel++; 293 | } else { 294 | 295 | return -1; 296 | } 297 | } 298 | pch->hi.sctx = nb; 299 | if (pch->hi.cmn + pch->hi.radd != pch->hi.c2 || 300 | pch->hi.cmn + pch->hi.rdel != pch->hi.c1) { 301 | 302 | return -1; 303 | } 304 | pch->hklen = i - pch->hkrec - 1; 305 | 306 | return 1; 307 | } 308 | 309 | 310 | static int xdl_first_hunk(patch_t *pch) { 311 | 312 | return xdl_load_hunk(pch, 0); 313 | } 314 | 315 | 316 | static int xdl_next_hunk(patch_t *pch) { 317 | 318 | return xdl_load_hunk(pch, pch->hkrec + pch->hklen + 1); 319 | } 320 | 321 | 322 | static int xdl_line_match(patch_t *pch, const char *s, long ns, char const *m, long nm) { 323 | 324 | for (; ns > 0 && (s[ns - 1] == '\r' || s[ns - 1] == '\n'); ns--); 325 | for (; nm > 0 && (m[nm - 1] == '\r' || m[nm - 1] == '\n'); nm--); 326 | if (pch->flags & XDL_PATCH_IGNOREBSPACE) { 327 | for (; ns > 0 && (*s == ' ' || *s == '\t'); ns--, s++); 328 | for (; ns > 0 && (s[ns - 1] == ' ' || s[ns - 1] == '\t'); ns--); 329 | for (; nm > 0 && (*m == ' ' || *m == '\t'); nm--, m++); 330 | for (; nm > 0 && (m[nm - 1] == ' ' || m[nm - 1] == '\t'); nm--); 331 | } 332 | 333 | return ns == nm && memcmp(s, m, ns) == 0; 334 | } 335 | 336 | 337 | static int xdl_hunk_match(recfile_t *rf, long irec, patch_t *pch, int mode, int fuzz) { 338 | long i, j, z, fsize, psize, ptop, pfuzz, sfuzz, misses; 339 | char const *fline, *pline; 340 | 341 | /* 342 | * Limit fuzz to not be greater than the prefix and suffix context. 343 | */ 344 | pfuzz = fuzz < pch->hi.pctx ? fuzz: pch->hi.pctx; 345 | sfuzz = fuzz < pch->hi.sctx ? fuzz: pch->hi.sctx; 346 | 347 | /* 348 | * First loop through the prefix fuzz area. In this loop we simply 349 | * note mismatching lines. We allow missing lines here, that is, 350 | * some prefix context lines are missing. 351 | */ 352 | for (z = pfuzz, misses = 0, i = irec, j = pch->hkrec + 1, 353 | ptop = pch->hkrec + 1 + pch->hklen - sfuzz; 354 | z > 0 && i < rf->nrec && j < ptop; i++, j++, z--) { 355 | if (!(pline = xdl_recfile_get(&pch->rf, j, &psize))) 356 | return 0; 357 | if (!(fline = xdl_recfile_get(rf, i, &fsize)) || 358 | !xdl_line_match(pch, fline, fsize, pline + 1, psize - 1)) 359 | misses++; 360 | } 361 | if (misses > fuzz) 362 | return 0; 363 | 364 | /* 365 | * Strict match loop. 366 | */ 367 | for (; i < rf->nrec && j < ptop; i++, j++) { 368 | for (; j < ptop; j++) { 369 | if (!(pline = xdl_recfile_get(&pch->rf, j, &psize))) 370 | return 0; 371 | if (*pline == ' ' || *pline == mode) 372 | break; 373 | } 374 | if (j == ptop) 375 | break; 376 | if (!(fline = xdl_recfile_get(rf, i, &fsize)) || 377 | !xdl_line_match(pch, fline, fsize, pline + 1, psize - 1)) 378 | return 0; 379 | } 380 | for (; j < ptop; j++) 381 | if (!(pline = xdl_recfile_get(&pch->rf, j, &psize)) || 382 | *pline == ' ' || *pline == mode) 383 | return 0; 384 | 385 | /* 386 | * Finally loop through the suffix fuzz area. In this loop we simply 387 | * note mismatching lines. We allow missing lines here, that is, 388 | * some suffix context lines are missing. 389 | */ 390 | for (z = sfuzz; z > 0 && i < rf->nrec; i++, j++, z--) { 391 | if (!(pline = xdl_recfile_get(&pch->rf, j, &psize))) 392 | return 0; 393 | if (!(fline = xdl_recfile_get(rf, i, &fsize)) || 394 | !xdl_line_match(pch, fline, fsize, pline + 1, psize - 1)) 395 | misses++; 396 | } 397 | 398 | return misses <= fuzz; 399 | } 400 | 401 | 402 | static int xdl_find_hunk(recfile_t *rf, long ibase, patch_t *pch, int mode, 403 | int fuzz, long *hkpos, int *exact) { 404 | long hpos, hlen, i, j; 405 | long pos[2]; 406 | 407 | hpos = mode == '-' ? pch->hi.s1: pch->hi.s2; 408 | hlen = mode == '-' ? pch->hi.cmn + pch->hi.rdel: pch->hi.cmn + pch->hi.radd; 409 | if (xdl_hunk_match(rf, hpos, pch, mode, fuzz)) { 410 | *hkpos = hpos; 411 | *exact = 1; 412 | return 1; 413 | } 414 | for (i = 1;; i++) { 415 | /* 416 | * We allow a negative starting hunk position, up to the 417 | * number of prefix context lines. 418 | */ 419 | j = 0; 420 | if (hpos - i >= ibase - pch->hi.pctx) 421 | pos[j++] = hpos - i; 422 | if (hpos + i + hlen <= rf->nrec) 423 | pos[j++] = hpos + i; 424 | if (!j) 425 | break; 426 | for (j--; j >= 0; j--) 427 | if (xdl_hunk_match(rf, pos[j], pch, mode, fuzz)) { 428 | *hkpos = pos[j]; 429 | *exact = 0; 430 | return 1; 431 | } 432 | } 433 | 434 | return 0; 435 | } 436 | 437 | 438 | static int xdl_emit_rfile_line(recfile_t *rf, long line, xdemitcb_t *ecb) { 439 | mmbuffer_t mb; 440 | 441 | if (!(mb.ptr = (char *) xdl_recfile_get(rf, line, &mb.size)) || 442 | ecb->outf(ecb->priv, &mb, 1) < 0) { 443 | 444 | return -1; 445 | } 446 | 447 | return 0; 448 | } 449 | 450 | 451 | static int xdl_flush_section(recfile_t *rf, long start, long top, xdemitcb_t *ecb) { 452 | long i; 453 | 454 | for (i = start; i <= top; i++) { 455 | if (xdl_emit_rfile_line(rf, i, ecb) < 0) { 456 | 457 | return -1; 458 | } 459 | } 460 | 461 | return 0; 462 | } 463 | 464 | 465 | static int xdl_apply_hunk(recfile_t *rf, long hkpos, patch_t *pch, int mode, 466 | long *ibase, xdemitcb_t *ecb) { 467 | long j, psize, ptop; 468 | char const *pline; 469 | mmbuffer_t mb; 470 | 471 | /* 472 | * The hunk starting position (hkpos) can be negative, up to the number 473 | * of prefix context lines. Since this function only emit the core of 474 | * the hunk (the remaining lines are flushed by xdl_flush_section() calls) 475 | * we need to normalize it by adding the number of prefix context lines. 476 | * The normalized value of the starting position is then greater/equal 477 | * to zero. 478 | */ 479 | hkpos += pch->hi.pctx; 480 | if (xdl_flush_section(rf, *ibase, hkpos - 1, ecb) < 0) { 481 | 482 | return -1; 483 | } 484 | *ibase = hkpos; 485 | for (j = pch->hkrec + 1 + pch->hi.pctx, 486 | ptop = pch->hkrec + 1 + pch->hklen - pch->hi.sctx; j < ptop; j++) { 487 | if (!(pline = xdl_recfile_get(&pch->rf, j, &psize))) { 488 | 489 | return -1; 490 | } 491 | if (*pline == ' ') { 492 | if (xdl_emit_rfile_line(rf, *ibase, ecb) < 0) { 493 | 494 | return -1; 495 | } 496 | (*ibase)++; 497 | } else if (*pline != mode) { 498 | mb.ptr = (char *) pline + 1; 499 | mb.size = psize - 1; 500 | if (ecb->outf(ecb->priv, &mb, 1) < 0) { 501 | 502 | return -1; 503 | } 504 | pch->ps.adds++; 505 | } else { 506 | (*ibase)++; 507 | pch->ps.dels++; 508 | } 509 | } 510 | 511 | return 0; 512 | } 513 | 514 | 515 | static int xdl_reject_hunk(recfile_t *rf, patch_t *pch, int mode, 516 | xdemitcb_t *rjecb) { 517 | long i, size, s1, s2, c1, c2; 518 | char const *line, *pre; 519 | mmbuffer_t mb; 520 | 521 | if (mode == '-') { 522 | s1 = pch->hi.s1; 523 | s2 = pch->hi.s2; 524 | c1 = pch->hi.c1; 525 | c2 = pch->hi.c2; 526 | } else { 527 | s1 = pch->hi.s2; 528 | s2 = pch->hi.s1; 529 | c1 = pch->hi.c2; 530 | c2 = pch->hi.c1; 531 | } 532 | s1 += pch->ps.adds - pch->ps.dels; 533 | if (xdl_emit_hunk_hdr(s1 + 1, c1, s2 + 1, c2, rjecb) < 0) { 534 | 535 | return -1; 536 | } 537 | for (i = pch->hkrec + 1; 538 | (line = xdl_recfile_get(&pch->rf, i, &size)) != NULL; i++) { 539 | if (*line == '@' || *line == '\n') 540 | break; 541 | if (mode == '-' || *line == ' ') { 542 | mb.ptr = (char *) line; 543 | mb.size = size; 544 | if (rjecb->outf(rjecb->priv, &mb, 1) < 0) { 545 | 546 | return -1; 547 | } 548 | } else { 549 | pre = *line == '+' ? "-": "+"; 550 | if (xdl_emit_diffrec(line + 1, size - 1, pre, strlen(pre), 551 | rjecb) < 0) { 552 | 553 | return -1; 554 | } 555 | } 556 | } 557 | 558 | return 0; 559 | } 560 | 561 | 562 | static int xdl_process_hunk(recfile_t *rff, patch_t *pch, long *ibase, int mode, 563 | xdemitcb_t *ecb, xdemitcb_t *rjecb) { 564 | int fuzz, exact, hlen, maxfuzz; 565 | long hkpos; 566 | 567 | hlen = mode == '-' ? pch->hi.cmn + pch->hi.rdel: pch->hi.cmn + pch->hi.radd; 568 | maxfuzz = XDL_MAX_FUZZ; 569 | if (hlen - maxfuzz < XDL_MIN_SYNCLINES) 570 | maxfuzz = hlen - XDL_MIN_SYNCLINES; 571 | if (maxfuzz < 0) 572 | maxfuzz = 0; 573 | for (fuzz = 0; fuzz <= maxfuzz; fuzz++) { 574 | if (xdl_find_hunk(rff, *ibase, pch, mode, fuzz, 575 | &hkpos, &exact)) { 576 | if (xdl_apply_hunk(rff, hkpos, pch, mode, 577 | ibase, ecb) < 0) { 578 | 579 | return -1; 580 | } 581 | if (!exact || fuzz) 582 | pch->fuzzies++; 583 | 584 | return 0; 585 | } 586 | } 587 | if (xdl_reject_hunk(rff, pch, mode, rjecb) < 0) { 588 | 589 | return -1; 590 | } 591 | 592 | return 0; 593 | } 594 | 595 | 596 | int xdl_patch(mmfile_t *mf, mmfile_t *mfp, int mode, xdemitcb_t *ecb, 597 | xdemitcb_t *rjecb) { 598 | int hkres, exact; 599 | long hkpos, ibase; 600 | recfile_t rff; 601 | patch_t pch; 602 | 603 | if (xdl_init_recfile(mf, 0, &rff) < 0) { 604 | 605 | return -1; 606 | } 607 | if (xdl_init_patch(mfp, mode & ~XDL_PATCH_MODEMASK, &pch) < 0) { 608 | 609 | xdl_free_recfile(&rff); 610 | return -1; 611 | } 612 | mode &= XDL_PATCH_MODEMASK; 613 | ibase = 0; 614 | if ((hkres = xdl_first_hunk(&pch)) > 0) { 615 | do { 616 | if (xdl_process_hunk(&rff, &pch, &ibase, mode, 617 | ecb, rjecb) < 0) { 618 | xdl_free_patch(&pch); 619 | xdl_free_recfile(&rff); 620 | return -1; 621 | } 622 | } while ((hkres = xdl_next_hunk(&pch)) > 0); 623 | } 624 | if (hkres < 0) { 625 | 626 | xdl_free_patch(&pch); 627 | xdl_free_recfile(&rff); 628 | return -1; 629 | } 630 | if (xdl_flush_section(&rff, ibase, rff.nrec - 1, ecb) < 0) { 631 | 632 | xdl_free_patch(&pch); 633 | xdl_free_recfile(&rff); 634 | return -1; 635 | } 636 | xdl_free_patch(&pch); 637 | xdl_free_recfile(&rff); 638 | 639 | return pch.fuzzies; 640 | } 641 | 642 | -------------------------------------------------------------------------------- /xdiff/xprepare.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | #define XDL_KPDIS_RUN 4 27 | #define XDL_MAX_EQLIMIT 1024 28 | #define XDL_SIMSCAN_WINDOWN 100 29 | 30 | 31 | typedef struct s_xdlclass { 32 | struct s_xdlclass *next; 33 | unsigned long ha; 34 | char const *line; 35 | long size; 36 | long idx; 37 | } xdlclass_t; 38 | 39 | typedef struct s_xdlclassifier { 40 | unsigned int hbits; 41 | long hsize; 42 | xdlclass_t **rchash; 43 | chastore_t ncha; 44 | long count; 45 | } xdlclassifier_t; 46 | 47 | 48 | 49 | static int xdl_init_classifier(xdlclassifier_t *cf, long size) { 50 | long i; 51 | 52 | cf->hbits = xdl_hashbits((unsigned int) size); 53 | cf->hsize = 1 << cf->hbits; 54 | 55 | if (xdl_cha_init(&cf->ncha, sizeof(xdlclass_t), size / 4 + 1) < 0) { 56 | 57 | return -1; 58 | } 59 | if (!(cf->rchash = (xdlclass_t **) xdl_malloc(cf->hsize * sizeof(xdlclass_t *)))) { 60 | 61 | xdl_cha_free(&cf->ncha); 62 | return -1; 63 | } 64 | for (i = 0; i < cf->hsize; i++) 65 | cf->rchash[i] = NULL; 66 | 67 | cf->count = 0; 68 | 69 | return 0; 70 | } 71 | 72 | 73 | static void xdl_free_classifier(xdlclassifier_t *cf) { 74 | xdl_free(cf->rchash); 75 | xdl_cha_free(&cf->ncha); 76 | } 77 | 78 | 79 | static int xdl_classify_record(xdlclassifier_t *cf, xrecord_t **rhash, unsigned int hbits, 80 | xrecord_t *rec) { 81 | long hi; 82 | char const *line; 83 | xdlclass_t *rcrec; 84 | 85 | line = rec->ptr; 86 | hi = (long) XDL_HASHLONG(rec->ha, cf->hbits); 87 | for (rcrec = cf->rchash[hi]; rcrec; rcrec = rcrec->next) 88 | if (rcrec->ha == rec->ha && rcrec->size == rec->size && 89 | !memcmp(line, rcrec->line, rec->size)) 90 | break; 91 | 92 | if (!rcrec) { 93 | if (!(rcrec = xdl_cha_alloc(&cf->ncha))) { 94 | 95 | return -1; 96 | } 97 | rcrec->idx = cf->count++; 98 | rcrec->line = line; 99 | rcrec->size = rec->size; 100 | rcrec->ha = rec->ha; 101 | rcrec->next = cf->rchash[hi]; 102 | cf->rchash[hi] = rcrec; 103 | } 104 | 105 | rec->ha = (unsigned long) rcrec->idx; 106 | 107 | hi = (long) XDL_HASHLONG(rec->ha, hbits); 108 | rec->next = rhash[hi]; 109 | rhash[hi] = rec; 110 | 111 | return 0; 112 | } 113 | 114 | 115 | static int xdl_prepare_ctx(mmfile_t *mf, long narec, xpparam_t const *xpp, 116 | xdlclassifier_t *cf, xdfile_t *xdf) { 117 | unsigned int hbits; 118 | long i, nrec, hsize, bsize; 119 | unsigned long hav; 120 | char const *blk, *cur, *top, *prev; 121 | xrecord_t *crec; 122 | xrecord_t **recs, **rrecs; 123 | xrecord_t **rhash; 124 | unsigned long *ha; 125 | char *rchg; 126 | long *rindex; 127 | 128 | if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0) { 129 | 130 | return -1; 131 | } 132 | if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *)))) { 133 | 134 | xdl_cha_free(&xdf->rcha); 135 | return -1; 136 | } 137 | 138 | hbits = xdl_hashbits((unsigned int) narec); 139 | hsize = 1 << hbits; 140 | if (!(rhash = (xrecord_t **) xdl_malloc(hsize * sizeof(xrecord_t *)))) { 141 | 142 | xdl_free(recs); 143 | xdl_cha_free(&xdf->rcha); 144 | return -1; 145 | } 146 | for (i = 0; i < hsize; i++) 147 | rhash[i] = NULL; 148 | 149 | nrec = 0; 150 | if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) { 151 | for (top = blk + bsize;;) { 152 | if (cur >= top) { 153 | if (!(cur = blk = xdl_mmfile_next(mf, &bsize))) 154 | break; 155 | top = blk + bsize; 156 | } 157 | prev = cur; 158 | hav = xdl_hash_record(&cur, top); 159 | if (nrec >= narec) { 160 | narec *= 2; 161 | if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *)))) { 162 | 163 | xdl_free(rhash); 164 | xdl_free(recs); 165 | xdl_cha_free(&xdf->rcha); 166 | return -1; 167 | } 168 | recs = rrecs; 169 | } 170 | if (!(crec = xdl_cha_alloc(&xdf->rcha))) { 171 | 172 | xdl_free(rhash); 173 | xdl_free(recs); 174 | xdl_cha_free(&xdf->rcha); 175 | return -1; 176 | } 177 | crec->ptr = prev; 178 | crec->size = (long) (cur - prev); 179 | crec->ha = hav; 180 | recs[nrec++] = crec; 181 | 182 | if (xdl_classify_record(cf, rhash, hbits, crec) < 0) { 183 | 184 | xdl_free(rhash); 185 | xdl_free(recs); 186 | xdl_cha_free(&xdf->rcha); 187 | return -1; 188 | } 189 | } 190 | } 191 | 192 | if (!(rchg = (char *) xdl_malloc(nrec + 2))) { 193 | 194 | xdl_free(rhash); 195 | xdl_free(recs); 196 | xdl_cha_free(&xdf->rcha); 197 | return -1; 198 | } 199 | memset(rchg, 0, nrec + 2); 200 | 201 | if (!(rindex = (long *) xdl_malloc((nrec + 1) * sizeof(long)))) { 202 | 203 | xdl_free(rchg); 204 | xdl_free(rhash); 205 | xdl_free(recs); 206 | xdl_cha_free(&xdf->rcha); 207 | return -1; 208 | } 209 | if (!(ha = (unsigned long *) xdl_malloc((nrec + 1) * sizeof(unsigned long)))) { 210 | 211 | xdl_free(rindex); 212 | xdl_free(rchg); 213 | xdl_free(rhash); 214 | xdl_free(recs); 215 | xdl_cha_free(&xdf->rcha); 216 | return -1; 217 | } 218 | 219 | xdf->nrec = nrec; 220 | xdf->recs = recs; 221 | xdf->hbits = hbits; 222 | xdf->rhash = rhash; 223 | xdf->rchg = rchg + 1; 224 | xdf->rindex = rindex; 225 | xdf->nreff = 0; 226 | xdf->ha = ha; 227 | xdf->dstart = 0; 228 | xdf->dend = nrec - 1; 229 | 230 | return 0; 231 | } 232 | 233 | 234 | static void xdl_free_ctx(xdfile_t *xdf) { 235 | xdl_free(xdf->rhash); 236 | xdl_free(xdf->rindex); 237 | xdl_free(xdf->rchg - 1); 238 | xdl_free(xdf->ha); 239 | xdl_free(xdf->recs); 240 | xdl_cha_free(&xdf->rcha); 241 | } 242 | 243 | 244 | static int xdl_clean_mmatch(char const *dis, long i, long s, long e) { 245 | long r, rdis0, rpdis0, rdis1, rpdis1; 246 | 247 | /* 248 | * Limits the window the is examined during the similar-lines 249 | * scan. The loops below stops when dis[i - r] == 1 (line that 250 | * has no match), but there are corner cases where the loop 251 | * proceed all the way to the extremities by causing huge 252 | * performance penalties in case of big files. 253 | */ 254 | if (i - s > XDL_SIMSCAN_WINDOWN) 255 | s = i - XDL_SIMSCAN_WINDOWN; 256 | if (e - i > XDL_SIMSCAN_WINDOWN) 257 | e = i + XDL_SIMSCAN_WINDOWN; 258 | 259 | /* 260 | * Scans the lines before 'i' to find a run of lines that either 261 | * have no match (dis[j] == 0) or have multiple matches (dis[j] > 1). 262 | * Note that we always call this function with dis[i] > 1, so the 263 | * current line (i) is already a multimatch line. 264 | */ 265 | for (r = 1, rdis0 = 0, rpdis0 = 1; (i - r) >= s; r++) { 266 | if (!dis[i - r]) 267 | rdis0++; 268 | else if (dis[i - r] == 2) 269 | rpdis0++; 270 | else 271 | break; 272 | } 273 | /* 274 | * If the run before the line 'i' found only multimatch lines, we 275 | * return 0 and hence we don't make the current line (i) discarded. 276 | * We want to discard multimatch lines only when they appear in the 277 | * middle of runs with nomatch lines (dis[j] == 0). 278 | */ 279 | if (rdis0 == 0) 280 | return 0; 281 | for (r = 1, rdis1 = 0, rpdis1 = 1; (i + r) <= e; r++) { 282 | if (!dis[i + r]) 283 | rdis1++; 284 | else if (dis[i + r] == 2) 285 | rpdis1++; 286 | else 287 | break; 288 | } 289 | /* 290 | * If the run after the line 'i' found only multimatch lines, we 291 | * return 0 and hence we don't make the current line (i) discarded. 292 | */ 293 | if (rdis1 == 0) 294 | return 0; 295 | rdis1 += rdis0; 296 | rpdis1 += rpdis0; 297 | 298 | return rpdis1 * XDL_KPDIS_RUN < (rpdis1 + rdis1); 299 | } 300 | 301 | 302 | /* 303 | * Try to reduce the problem complexity, discard records that have no 304 | * matches on the other file. Also, lines that have multiple matches 305 | * might be potentially discarded if they happear in a run of discardable. 306 | */ 307 | static int xdl_cleanup_records(xdfile_t *xdf1, xdfile_t *xdf2) { 308 | long i, nm, rhi, nreff, mlim; 309 | unsigned long hav; 310 | xrecord_t **recs; 311 | xrecord_t *rec; 312 | char *dis, *dis1, *dis2; 313 | 314 | if (!(dis = (char *) xdl_malloc(xdf1->nrec + xdf2->nrec + 2))) { 315 | 316 | return -1; 317 | } 318 | memset(dis, 0, xdf1->nrec + xdf2->nrec + 2); 319 | dis1 = dis; 320 | dis2 = dis1 + xdf1->nrec + 1; 321 | 322 | if ((mlim = xdl_bogosqrt(xdf1->nrec)) > XDL_MAX_EQLIMIT) 323 | mlim = XDL_MAX_EQLIMIT; 324 | for (i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; i <= xdf1->dend; i++, recs++) { 325 | hav = (*recs)->ha; 326 | rhi = (long) XDL_HASHLONG(hav, xdf2->hbits); 327 | for (nm = 0, rec = xdf2->rhash[rhi]; rec; rec = rec->next) 328 | if (rec->ha == hav && ++nm == mlim) 329 | break; 330 | dis1[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1; 331 | } 332 | 333 | if ((mlim = xdl_bogosqrt(xdf2->nrec)) > XDL_MAX_EQLIMIT) 334 | mlim = XDL_MAX_EQLIMIT; 335 | for (i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; i <= xdf2->dend; i++, recs++) { 336 | hav = (*recs)->ha; 337 | rhi = (long) XDL_HASHLONG(hav, xdf1->hbits); 338 | for (nm = 0, rec = xdf1->rhash[rhi]; rec; rec = rec->next) 339 | if (rec->ha == hav && ++nm == mlim) 340 | break; 341 | dis2[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1; 342 | } 343 | 344 | for (nreff = 0, i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; 345 | i <= xdf1->dend; i++, recs++) { 346 | if (dis1[i] == 1 || 347 | (dis1[i] == 2 && !xdl_clean_mmatch(dis1, i, xdf1->dstart, xdf1->dend))) { 348 | xdf1->rindex[nreff] = i; 349 | xdf1->ha[nreff] = (*recs)->ha; 350 | nreff++; 351 | } else 352 | xdf1->rchg[i] = 1; 353 | } 354 | xdf1->nreff = nreff; 355 | 356 | for (nreff = 0, i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; 357 | i <= xdf2->dend; i++, recs++) { 358 | if (dis2[i] == 1 || 359 | (dis2[i] == 2 && !xdl_clean_mmatch(dis2, i, xdf2->dstart, xdf2->dend))) { 360 | xdf2->rindex[nreff] = i; 361 | xdf2->ha[nreff] = (*recs)->ha; 362 | nreff++; 363 | } else 364 | xdf2->rchg[i] = 1; 365 | } 366 | xdf2->nreff = nreff; 367 | 368 | xdl_free(dis); 369 | 370 | return 0; 371 | } 372 | 373 | 374 | /* 375 | * Early trim initial and terminal matching records. 376 | */ 377 | static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2) { 378 | long i, lim; 379 | xrecord_t **recs1, **recs2; 380 | 381 | recs1 = xdf1->recs; 382 | recs2 = xdf2->recs; 383 | for (i = 0, lim = XDL_MIN(xdf1->nrec, xdf2->nrec); i < lim; 384 | i++, recs1++, recs2++) 385 | if ((*recs1)->ha != (*recs2)->ha) 386 | break; 387 | 388 | xdf1->dstart = xdf2->dstart = i; 389 | 390 | recs1 = xdf1->recs + xdf1->nrec - 1; 391 | recs2 = xdf2->recs + xdf2->nrec - 1; 392 | for (lim -= i, i = 0; i < lim; i++, recs1--, recs2--) 393 | if ((*recs1)->ha != (*recs2)->ha) 394 | break; 395 | 396 | xdf1->dend = xdf1->nrec - i - 1; 397 | xdf2->dend = xdf2->nrec - i - 1; 398 | 399 | return 0; 400 | } 401 | 402 | 403 | static int xdl_optimize_ctxs(xdfile_t *xdf1, xdfile_t *xdf2) { 404 | if (xdl_trim_ends(xdf1, xdf2) < 0 || 405 | xdl_cleanup_records(xdf1, xdf2) < 0) { 406 | 407 | return -1; 408 | } 409 | 410 | return 0; 411 | } 412 | 413 | 414 | int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 415 | xdfenv_t *xe) { 416 | long enl1, enl2; 417 | xdlclassifier_t cf; 418 | 419 | enl1 = xdl_guess_lines(mf1) + 1; 420 | enl2 = xdl_guess_lines(mf2) + 1; 421 | 422 | if (xdl_init_classifier(&cf, enl1 + enl2 + 1) < 0) { 423 | 424 | return -1; 425 | } 426 | 427 | if (xdl_prepare_ctx(mf1, enl1, xpp, &cf, &xe->xdf1) < 0) { 428 | 429 | xdl_free_classifier(&cf); 430 | return -1; 431 | } 432 | if (xdl_prepare_ctx(mf2, enl2, xpp, &cf, &xe->xdf2) < 0) { 433 | 434 | xdl_free_ctx(&xe->xdf1); 435 | xdl_free_classifier(&cf); 436 | return -1; 437 | } 438 | 439 | xdl_free_classifier(&cf); 440 | 441 | if (xdl_optimize_ctxs(&xe->xdf1, &xe->xdf2) < 0) { 442 | 443 | xdl_free_ctx(&xe->xdf2); 444 | xdl_free_ctx(&xe->xdf1); 445 | return -1; 446 | } 447 | 448 | return 0; 449 | } 450 | 451 | 452 | void xdl_free_env(xdfenv_t *xe) { 453 | xdl_free_ctx(&xe->xdf2); 454 | xdl_free_ctx(&xe->xdf1); 455 | } 456 | 457 | -------------------------------------------------------------------------------- /xdiff/xprepare.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XPREPARE_H) 24 | #define XPREPARE_H 25 | 26 | 27 | 28 | int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, 29 | xdfenv_t *xe); 30 | void xdl_free_env(xdfenv_t *xe); 31 | 32 | 33 | 34 | #endif /* #if !defined(XPREPARE_H) */ 35 | 36 | -------------------------------------------------------------------------------- /xdiff/xrabdiff.c: -------------------------------------------------------------------------------- 1 | /* 2 | * xrabdiff by Davide Libenzi (Rabin's polynomial fingerprint based delta generator) 3 | * Copyright (C) 2006 Davide Libenzi 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | * 22 | * Hints, ideas and code for the implementation came from: 23 | * 24 | * Rabin's original paper: http://www.xmailserver.org/rabin.pdf 25 | * Chan & Lu's paper: http://www.xmailserver.org/rabin_impl.pdf 26 | * Broder's paper: http://www.xmailserver.org/rabin_apps.pdf 27 | * LBFS source code: http://www.fs.net/sfswww/lbfs/ 28 | * Geert Bosch's post: http://marc.theaimsgroup.com/?l=git&m=114565424620771&w=2 29 | * 30 | */ 31 | 32 | #include "xinclude.h" 33 | 34 | 35 | #if !defined(XRABPLY_TYPE32) && !defined(XRABPLY_TYPE64) 36 | #define XRABPLY_TYPE64 long long 37 | #define XV64(v) ((xply_word) v ## ULL) 38 | #endif 39 | 40 | #include "xrabply.c" 41 | 42 | 43 | 44 | #define XRAB_SLIDE(v, c) do { \ 45 | if (++wpos == XRAB_WNDSIZE) wpos = 0; \ 46 | v ^= U[wbuf[wpos]]; \ 47 | wbuf[wpos] = (c); \ 48 | v = ((v << 8) | (c)) ^ T[v >> XRAB_SHIFT]; \ 49 | } while (0) 50 | 51 | 52 | #define XRAB_MINCPYSIZE 12 53 | #define XRAB_WBITS (sizeof(xply_word) * 8) 54 | 55 | 56 | 57 | typedef struct s_xrabctx { 58 | long idxsize; 59 | long *idx; 60 | unsigned char const *data; 61 | long size; 62 | } xrabctx_t; 63 | 64 | typedef struct s_xrabcpyi { 65 | long src; 66 | long tgt; 67 | long len; 68 | } xrabcpyi_t; 69 | 70 | typedef struct s_xrabcpyi_arena { 71 | long cnt, size; 72 | xrabcpyi_t *acpy; 73 | } xrabcpyi_arena_t; 74 | 75 | 76 | 77 | static void xrab_init_cpyarena(xrabcpyi_arena_t *aca) { 78 | aca->cnt = aca->size = 0; 79 | aca->acpy = NULL; 80 | } 81 | 82 | 83 | static void xrab_free_cpyarena(xrabcpyi_arena_t *aca) { 84 | xdl_free(aca->acpy); 85 | } 86 | 87 | 88 | static int xrab_add_cpy(xrabcpyi_arena_t *aca, xrabcpyi_t const *rcpy) { 89 | long size; 90 | xrabcpyi_t *acpy; 91 | 92 | if (aca->cnt >= aca->size) { 93 | size = 2 * aca->size + 1024; 94 | if ((acpy = (xrabcpyi_t *) 95 | xdl_realloc(aca->acpy, size * sizeof(xrabcpyi_t))) == NULL) 96 | return -1; 97 | aca->acpy = acpy; 98 | aca->size = size; 99 | } 100 | aca->acpy[aca->cnt++] = *rcpy; 101 | 102 | return 0; 103 | } 104 | 105 | 106 | static long xrab_cmnseq(unsigned char const *data, long start, long size) { 107 | unsigned char ch = data[start]; 108 | unsigned char const *ptr, *top; 109 | 110 | for (ptr = data + start + 1, top = data + size; ptr < top && ch == *ptr; ptr++); 111 | 112 | return (long) (ptr - (data + start + 1)); 113 | } 114 | 115 | 116 | static int xrab_build_ctx(unsigned char const *data, long size, xrabctx_t *ctx) { 117 | long i, isize, idxsize, seq, wpos = 0; 118 | xply_word fp = 0, mask; 119 | unsigned char ch; 120 | unsigned char const *ptr, *eot; 121 | long *idx; 122 | unsigned char wbuf[XRAB_WNDSIZE]; 123 | long maxoffs[256]; 124 | long maxseq[256]; 125 | xply_word maxfp[256]; 126 | 127 | memset(wbuf, 0, sizeof(wbuf)); 128 | memset(maxseq, 0, sizeof(maxseq)); 129 | isize = 2 * (size / XRAB_WNDSIZE); 130 | for (idxsize = 1; idxsize < isize; idxsize <<= 1); 131 | mask = (xply_word) (idxsize - 1); 132 | if ((idx = (long *) xdl_malloc(idxsize * sizeof(long))) == NULL) 133 | return -1; 134 | memset(idx, 0, idxsize * sizeof(long)); 135 | for (i = 0; i + XRAB_WNDSIZE < size; i += XRAB_WNDSIZE) { 136 | /* 137 | * Generate a brand new hash for the current window. Here we could 138 | * try to perform pseudo-loop unroll by 4 blocks if necessary, and 139 | * if we force XRAB_WNDSIZE to be a multiple of 4, we could reduce 140 | * the branch occurence inside XRAB_SLIDE by a factor of 4. 141 | */ 142 | for (ptr = data + i, eot = ptr + XRAB_WNDSIZE; ptr < eot; ptr++) 143 | XRAB_SLIDE(fp, *ptr); 144 | 145 | /* 146 | * Try to scan for single value scans, and store them in the 147 | * array according to the longest one. Before we do a fast check 148 | * to avoid calling xrab_cmnseq() when not necessary. 149 | */ 150 | if ((ch = data[i]) == data[i + XRAB_WNDSIZE - 1] && 151 | (seq = xrab_cmnseq(data, i, size)) > XRAB_WNDSIZE && 152 | seq > maxseq[ch]) { 153 | maxseq[ch] = seq; 154 | maxfp[ch] = fp; 155 | maxoffs[ch] = i + XRAB_WNDSIZE; 156 | seq = (seq / XRAB_WNDSIZE) * XRAB_WNDSIZE; 157 | i += seq - XRAB_WNDSIZE; 158 | } else 159 | idx[fp & mask] = i + XRAB_WNDSIZE; 160 | } 161 | 162 | /* 163 | * Restore back the logest sequences by overwriting target hash buckets. 164 | */ 165 | for (i = 0; i < 256; i++) 166 | if (maxseq[i]) 167 | idx[maxfp[i] & mask] = maxoffs[i]; 168 | ctx->idxsize = idxsize; 169 | ctx->idx = idx; 170 | ctx->data = data; 171 | ctx->size = size; 172 | 173 | return 0; 174 | } 175 | 176 | 177 | static void xrab_free_ctx(xrabctx_t *ctx) { 178 | 179 | xdl_free(ctx->idx); 180 | } 181 | 182 | 183 | static int xrab_diff(unsigned char const *data, long size, xrabctx_t *ctx, 184 | xrabcpyi_arena_t *aca) { 185 | long i, offs, ssize, src, tgt, esrc, etgt, wpos = 0; 186 | xply_word fp = 0, mask; 187 | long const *idx; 188 | unsigned char const *sdata; 189 | xrabcpyi_t rcpy; 190 | unsigned char wbuf[XRAB_WNDSIZE]; 191 | 192 | xrab_init_cpyarena(aca); 193 | memset(wbuf, 0, sizeof(wbuf)); 194 | for (i = 0; i < XRAB_WNDSIZE - 1 && i < size; i++) 195 | XRAB_SLIDE(fp, data[i]); 196 | idx = ctx->idx; 197 | sdata = ctx->data; 198 | ssize = ctx->size; 199 | mask = (xply_word) (ctx->idxsize - 1); 200 | while (i < size) { 201 | unsigned char ch = data[i++]; 202 | 203 | XRAB_SLIDE(fp, ch); 204 | offs = idx[fp & mask]; 205 | 206 | /* 207 | * Fast check here to probabilistically reduce false positives 208 | * that would trigger the slow path below. 209 | */ 210 | if (offs == 0 || ch != sdata[offs - 1]) 211 | continue; 212 | 213 | /* 214 | * Stretch the match both sides as far as possible. 215 | */ 216 | src = offs - 1; 217 | tgt = i - 1; 218 | for (; tgt > 0 && src > 0 && data[tgt - 1] == sdata[src - 1]; 219 | tgt--, src--); 220 | esrc = offs; 221 | etgt = i; 222 | for (; etgt < size && esrc < ssize && data[etgt] == sdata[esrc]; 223 | etgt++, esrc++); 224 | 225 | /* 226 | * Avoid considering copies smaller than the XRAB_MINCPYSIZE 227 | * threshold. 228 | */ 229 | if (etgt - tgt >= XRAB_MINCPYSIZE) { 230 | rcpy.src = src; 231 | rcpy.tgt = tgt; 232 | rcpy.len = etgt - tgt; 233 | if (xrab_add_cpy(aca, &rcpy) < 0) { 234 | xrab_free_cpyarena(aca); 235 | return -1; 236 | } 237 | 238 | /* 239 | * Fill up the new window and exit with 'i' properly set on exit. 240 | */ 241 | for (i = etgt - XRAB_WNDSIZE; i < etgt; i++) 242 | XRAB_SLIDE(fp, data[i]); 243 | } 244 | } 245 | 246 | return 0; 247 | } 248 | 249 | 250 | static int xrab_tune_cpyarena(unsigned char const *data, long size, xrabctx_t *ctx, 251 | xrabcpyi_arena_t *aca) { 252 | long i, cpos; 253 | xrabcpyi_t *rcpy; 254 | 255 | for (cpos = size, i = aca->cnt - 1; i >= 0; i--) { 256 | rcpy = aca->acpy + i; 257 | if (rcpy->tgt >= cpos) 258 | rcpy->len = 0; 259 | else if (rcpy->tgt + rcpy->len > cpos) { 260 | if ((rcpy->len = cpos - rcpy->tgt) >= XRAB_MINCPYSIZE) 261 | cpos = rcpy->tgt; 262 | else 263 | rcpy->len = 0; 264 | } else 265 | cpos = rcpy->tgt; 266 | } 267 | 268 | return 0; 269 | } 270 | 271 | 272 | int xdl_rabdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, xdemitcb_t *ecb) { 273 | long i, cpos, size; 274 | unsigned long fp; 275 | xrabcpyi_t *rcpy; 276 | xrabctx_t ctx; 277 | xrabcpyi_arena_t aca; 278 | mmbuffer_t mb[2]; 279 | unsigned char cpybuf[32]; 280 | 281 | fp = xdl_mmb_adler32(mmb1); 282 | if (xrab_build_ctx((unsigned char const *) mmb1->ptr, mmb1->size, 283 | &ctx) < 0) 284 | return -1; 285 | if (xrab_diff((unsigned char const *) mmb2->ptr, mmb2->size, &ctx, 286 | &aca) < 0) { 287 | xrab_free_ctx(&ctx); 288 | return -1; 289 | } 290 | xrab_tune_cpyarena((unsigned char const *) mmb2->ptr, mmb2->size, &ctx, 291 | &aca); 292 | xrab_free_ctx(&ctx); 293 | 294 | /* 295 | * Prepare and emit the binary patch file header. It will be used 296 | * to verify that that file being patched matches in size and fingerprint 297 | * the one that generated the patch. 298 | */ 299 | size = mmb1->size; 300 | XDL_LE32_PUT(cpybuf, fp); 301 | XDL_LE32_PUT(cpybuf + 4, size); 302 | 303 | mb[0].ptr = (char *) cpybuf; 304 | mb[0].size = 4 + 4; 305 | if (ecb->outf(ecb->priv, mb, 1) < 0) { 306 | xrab_free_cpyarena(&aca); 307 | return -1; 308 | } 309 | for (cpos = 0, i = 0; i < aca.cnt; i++) { 310 | rcpy = aca.acpy + i; 311 | if (rcpy->len == 0) 312 | continue; 313 | if (cpos < rcpy->tgt) { 314 | size = rcpy->tgt - cpos; 315 | if (size > 255) { 316 | cpybuf[0] = XDL_BDOP_INSB; 317 | XDL_LE32_PUT(cpybuf + 1, size); 318 | mb[0].ptr = (char *) cpybuf; 319 | mb[0].size = XDL_INSBOP_SIZE; 320 | } else { 321 | cpybuf[0] = XDL_BDOP_INS; 322 | cpybuf[1] = (unsigned char) size; 323 | mb[0].ptr = (char *) cpybuf; 324 | mb[0].size = 2; 325 | } 326 | mb[1].ptr = mmb2->ptr + cpos; 327 | mb[1].size = size; 328 | if (ecb->outf(ecb->priv, mb, 2) < 0) { 329 | xrab_free_cpyarena(&aca); 330 | return -1; 331 | } 332 | cpos = rcpy->tgt; 333 | } 334 | cpybuf[0] = XDL_BDOP_CPY; 335 | XDL_LE32_PUT(cpybuf + 1, rcpy->src); 336 | XDL_LE32_PUT(cpybuf + 5, rcpy->len); 337 | mb[0].ptr = (char *) cpybuf; 338 | mb[0].size = XDL_COPYOP_SIZE; 339 | if (ecb->outf(ecb->priv, mb, 1) < 0) { 340 | xrab_free_cpyarena(&aca); 341 | return -1; 342 | } 343 | cpos += rcpy->len; 344 | } 345 | xrab_free_cpyarena(&aca); 346 | if (cpos < mmb2->size) { 347 | size = mmb2->size - cpos; 348 | if (size > 255) { 349 | cpybuf[0] = XDL_BDOP_INSB; 350 | XDL_LE32_PUT(cpybuf + 1, size); 351 | mb[0].ptr = (char *) cpybuf; 352 | mb[0].size = XDL_INSBOP_SIZE; 353 | } else { 354 | cpybuf[0] = XDL_BDOP_INS; 355 | cpybuf[1] = (unsigned char) size; 356 | mb[0].ptr = (char *) cpybuf; 357 | mb[0].size = 2; 358 | } 359 | mb[1].ptr = mmb2->ptr + cpos; 360 | mb[1].size = size; 361 | if (ecb->outf(ecb->priv, mb, 2) < 0) 362 | return -1; 363 | } 364 | 365 | return 0; 366 | } 367 | 368 | 369 | int xdl_rabdiff(mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb) { 370 | mmbuffer_t mmb1, mmb2; 371 | 372 | if (!xdl_mmfile_iscompact(mmf1) || !xdl_mmfile_iscompact(mmf2)) 373 | return -1; 374 | if ((mmb1.ptr = (char *) xdl_mmfile_first(mmf1, &mmb1.size)) == NULL) 375 | mmb1.size = 0; 376 | if ((mmb2.ptr = (char *) xdl_mmfile_first(mmf2, &mmb2.size)) == NULL) 377 | mmb2.size = 0; 378 | 379 | return xdl_rabdiff_mb(&mmb1, &mmb2, ecb); 380 | } 381 | 382 | -------------------------------------------------------------------------------- /xdiff/xrabply.c: -------------------------------------------------------------------------------- 1 | #if defined(XRABPLY_TYPE64) 2 | 3 | #if !defined(XV64) 4 | #define XV64(v) ((xply_word) v ## ULL) 5 | #endif 6 | 7 | #define XRAB_ROOTPOLY XV64(0x36f7381af4d70d33) 8 | 9 | #define XRAB_SHIFT 53 10 | #define XRAB_WNDSIZE 20 11 | 12 | typedef unsigned XRABPLY_TYPE64 xply_word; 13 | 14 | static const xply_word T[256] = { 15 | XV64(0x0), XV64(0x36f7381af4d70d33), XV64(0x5b19482f1d791755), XV64(0x6dee7035e9ae1a66), 16 | XV64(0x80c5a844ce252399), XV64(0xb632905e3af22eaa), XV64(0xdbdce06bd35c34cc), XV64(0xed2bd871278b39ff), 17 | XV64(0x18b50899c4a4732), XV64(0x377c6893689d4a01), XV64(0x5a9218a681335067), XV64(0x6c6520bc75e45d54), 18 | XV64(0x814ef8cd526f64ab), XV64(0xb7b9c0d7a6b86998), XV64(0xda57b0e24f1673fe), XV64(0xeca088f8bbc17ecd), 19 | XV64(0x316a11338948e64), XV64(0x35e19909cc438357), XV64(0x580fe93c25ed9931), XV64(0x6ef8d126d13a9402), 20 | XV64(0x83d30957f6b1adfd), XV64(0xb524314d0266a0ce), XV64(0xd8ca4178ebc8baa8), XV64(0xee3d79621f1fb79b), 21 | XV64(0x29df19aa4dec956), XV64(0x346ac9805009c465), XV64(0x5984b9b5b9a7de03), XV64(0x6f7381af4d70d330), 22 | XV64(0x825859de6afbeacf), XV64(0xb4af61c49e2ce7fc), XV64(0xd94111f17782fd9a), XV64(0xefb629eb8355f0a9), 23 | XV64(0x62d422671291cc8), XV64(0x30da7a3c85fe11fb), XV64(0x5d340a096c500b9d), XV64(0x6bc33213988706ae), 24 | XV64(0x86e8ea62bf0c3f51), XV64(0xb01fd2784bdb3262), XV64(0xddf1a24da2752804), XV64(0xeb069a5756a22537), 25 | XV64(0x7a612afed635bfa), XV64(0x31512ab519b456c9), XV64(0x5cbf5a80f01a4caf), XV64(0x6a48629a04cd419c), 26 | XV64(0x8763baeb23467863), XV64(0xb19482f1d7917550), XV64(0xdc7af2c43e3f6f36), XV64(0xea8dcadecae86205), 27 | XV64(0x53be33549bd92ac), XV64(0x33ccdb2fbd6a9f9f), XV64(0x5e22ab1a54c485f9), XV64(0x68d59300a01388ca), 28 | XV64(0x85fe4b718798b135), XV64(0xb309736b734fbc06), XV64(0xdee7035e9ae1a660), XV64(0xe8103b446e36ab53), 29 | XV64(0x4b0b3bcd5f7d59e), XV64(0x32478ba62120d8ad), XV64(0x5fa9fb93c88ec2cb), XV64(0x695ec3893c59cff8), 30 | XV64(0x84751bf81bd2f607), XV64(0xb28223e2ef05fb34), XV64(0xdf6c53d706abe152), XV64(0xe99b6bcdf27cec61), 31 | XV64(0xc5a844ce2523990), XV64(0x3aadbc56168534a3), XV64(0x5743cc63ff2b2ec5), XV64(0x61b4f4790bfc23f6), 32 | XV64(0x8c9f2c082c771a09), XV64(0xba681412d8a0173a), XV64(0xd7866427310e0d5c), XV64(0xe1715c3dc5d9006f), 33 | XV64(0xdd1d4c57e187ea2), XV64(0x3b26ecdf8acf7391), XV64(0x56c89cea636169f7), XV64(0x603fa4f097b664c4), 34 | XV64(0x8d147c81b03d5d3b), XV64(0xbbe3449b44ea5008), XV64(0xd60d34aead444a6e), XV64(0xe0fa0cb45993475d), 35 | XV64(0xf4c255fdac6b7f4), XV64(0x39bb1d452e11bac7), XV64(0x54556d70c7bfa0a1), XV64(0x62a2556a3368ad92), 36 | XV64(0x8f898d1b14e3946d), XV64(0xb97eb501e034995e), XV64(0xd490c534099a8338), XV64(0xe267fd2efd4d8e0b), 37 | XV64(0xec775d6468cf0c6), XV64(0x38304dccb25bfdf5), XV64(0x55de3df95bf5e793), XV64(0x632905e3af22eaa0), 38 | XV64(0x8e02dd9288a9d35f), XV64(0xb8f5e5887c7ede6c), XV64(0xd51b95bd95d0c40a), XV64(0xe3ecada76107c939), 39 | XV64(0xa77c66a937b2558), XV64(0x3c80fe7067ac286b), XV64(0x516e8e458e02320d), XV64(0x6799b65f7ad53f3e), 40 | XV64(0x8ab26e2e5d5e06c1), XV64(0xbc455634a9890bf2), XV64(0xd1ab260140271194), XV64(0xe75c1e1bb4f01ca7), 41 | XV64(0xbfc96e30f31626a), XV64(0x3d0baef9fbe66f59), XV64(0x50e5decc1248753f), XV64(0x6612e6d6e69f780c), 42 | XV64(0x8b393ea7c11441f3), XV64(0xbdce06bd35c34cc0), XV64(0xd0207688dc6d56a6), XV64(0xe6d74e9228ba5b95), 43 | XV64(0x9616779abefab3c), XV64(0x3f965f635f38a60f), XV64(0x52782f56b696bc69), XV64(0x648f174c4241b15a), 44 | XV64(0x89a4cf3d65ca88a5), XV64(0xbf53f727911d8596), XV64(0xd2bd871278b39ff0), XV64(0xe44abf088c6492c3), 45 | XV64(0x8ea37f037a5ec0e), XV64(0x3e1d0feac372e13d), XV64(0x53f37fdf2adcfb5b), XV64(0x650447c5de0bf668), 46 | XV64(0x882f9fb4f980cf97), XV64(0xbed8a7ae0d57c2a4), XV64(0xd336d79be4f9d8c2), XV64(0xe5c1ef81102ed5f1), 47 | XV64(0x18b50899c4a47320), XV64(0x2e42308330737e13), XV64(0x43ac40b6d9dd6475), XV64(0x755b78ac2d0a6946), 48 | XV64(0x9870a0dd0a8150b9), XV64(0xae8798c7fe565d8a), XV64(0xc369e8f217f847ec), XV64(0xf59ed0e8e32f4adf), 49 | XV64(0x193e581058ee3412), XV64(0x2fc9600aac393921), XV64(0x4227103f45972347), XV64(0x74d02825b1402e74), 50 | XV64(0x99fbf05496cb178b), XV64(0xaf0cc84e621c1ab8), XV64(0xc2e2b87b8bb200de), XV64(0xf41580617f650ded), 51 | XV64(0x1ba3a98afc30fd44), XV64(0x2d54919008e7f077), XV64(0x40bae1a5e149ea11), XV64(0x764dd9bf159ee722), 52 | XV64(0x9b6601ce3215dedd), XV64(0xad9139d4c6c2d3ee), XV64(0xc07f49e12f6cc988), XV64(0xf68871fbdbbbc4bb), 53 | XV64(0x1a28f903607aba76), XV64(0x2cdfc11994adb745), XV64(0x4131b12c7d03ad23), XV64(0x77c6893689d4a010), 54 | XV64(0x9aed5147ae5f99ef), XV64(0xac1a695d5a8894dc), XV64(0xc1f41968b3268eba), XV64(0xf703217247f18389), 55 | XV64(0x1e984abfb58d6fe8), XV64(0x286f72a5415a62db), XV64(0x45810290a8f478bd), XV64(0x73763a8a5c23758e), 56 | XV64(0x9e5de2fb7ba84c71), XV64(0xa8aadae18f7f4142), XV64(0xc544aad466d15b24), XV64(0xf3b392ce92065617), 57 | XV64(0x1f131a3629c728da), XV64(0x29e4222cdd1025e9), XV64(0x440a521934be3f8f), XV64(0x72fd6a03c06932bc), 58 | XV64(0x9fd6b272e7e20b43), XV64(0xa9218a6813350670), XV64(0xc4cffa5dfa9b1c16), XV64(0xf238c2470e4c1125), 59 | XV64(0x1d8eebac8d19e18c), XV64(0x2b79d3b679ceecbf), XV64(0x4697a3839060f6d9), XV64(0x70609b9964b7fbea), 60 | XV64(0x9d4b43e8433cc215), XV64(0xabbc7bf2b7ebcf26), XV64(0xc6520bc75e45d540), XV64(0xf0a533ddaa92d873), 61 | XV64(0x1c05bb251153a6be), XV64(0x2af2833fe584ab8d), XV64(0x471cf30a0c2ab1eb), XV64(0x71ebcb10f8fdbcd8), 62 | XV64(0x9cc01361df768527), XV64(0xaa372b7b2ba18814), XV64(0xc7d95b4ec20f9272), XV64(0xf12e635436d89f41), 63 | XV64(0x14ef8cd526f64ab0), XV64(0x2218b4cfd2214783), XV64(0x4ff6c4fa3b8f5de5), XV64(0x7901fce0cf5850d6), 64 | XV64(0x942a2491e8d36929), XV64(0xa2dd1c8b1c04641a), XV64(0xcf336cbef5aa7e7c), XV64(0xf9c454a4017d734f), 65 | XV64(0x1564dc5cbabc0d82), XV64(0x2393e4464e6b00b1), XV64(0x4e7d9473a7c51ad7), XV64(0x788aac69531217e4), 66 | XV64(0x95a1741874992e1b), XV64(0xa3564c02804e2328), XV64(0xceb83c3769e0394e), XV64(0xf84f042d9d37347d), 67 | XV64(0x17f92dc61e62c4d4), XV64(0x210e15dceab5c9e7), XV64(0x4ce065e9031bd381), XV64(0x7a175df3f7ccdeb2), 68 | XV64(0x973c8582d047e74d), XV64(0xa1cbbd982490ea7e), XV64(0xcc25cdadcd3ef018), XV64(0xfad2f5b739e9fd2b), 69 | XV64(0x16727d4f822883e6), XV64(0x2085455576ff8ed5), XV64(0x4d6b35609f5194b3), XV64(0x7b9c0d7a6b869980), 70 | XV64(0x96b7d50b4c0da07f), XV64(0xa040ed11b8daad4c), XV64(0xcdae9d245174b72a), XV64(0xfb59a53ea5a3ba19), 71 | XV64(0x12c2cef357df5678), XV64(0x2435f6e9a3085b4b), XV64(0x49db86dc4aa6412d), XV64(0x7f2cbec6be714c1e), 72 | XV64(0x920766b799fa75e1), XV64(0xa4f05ead6d2d78d2), XV64(0xc91e2e98848362b4), XV64(0xffe9168270546f87), 73 | XV64(0x13499e7acb95114a), XV64(0x25bea6603f421c79), XV64(0x4850d655d6ec061f), XV64(0x7ea7ee4f223b0b2c), 74 | XV64(0x938c363e05b032d3), XV64(0xa57b0e24f1673fe0), XV64(0xc8957e1118c92586), XV64(0xfe62460bec1e28b5), 75 | XV64(0x11d46fe06f4bd81c), XV64(0x272357fa9b9cd52f), XV64(0x4acd27cf7232cf49), XV64(0x7c3a1fd586e5c27a), 76 | XV64(0x9111c7a4a16efb85), XV64(0xa7e6ffbe55b9f6b6), XV64(0xca088f8bbc17ecd0), XV64(0xfcffb79148c0e1e3), 77 | XV64(0x105f3f69f3019f2e), XV64(0x26a8077307d6921d), XV64(0x4b467746ee78887b), XV64(0x7db14f5c1aaf8548), 78 | XV64(0x909a972d3d24bcb7), XV64(0xa66daf37c9f3b184), XV64(0xcb83df02205dabe2), XV64(0xfd74e718d48aa6d1) 79 | }; 80 | 81 | static const xply_word U[256] = { 82 | XV64(0x0), XV64(0x1c3eb44b122426b2), XV64(0xe8a508cd09f4057), XV64(0x12b4e4c7c2bb66e5), 83 | XV64(0x1d14a119a13e80ae), XV64(0x12a1552b31aa61c), XV64(0x139ef19571a1c0f9), XV64(0xfa045de6385e64b), 84 | XV64(0xcde7a29b6aa0c6f), XV64(0x10e0ce62a48e2add), XV64(0x2542aa566354c38), XV64(0x1e6a9eee74116a8a), 85 | XV64(0x11cadb3017948cc1), XV64(0xdf46f7b05b0aa73), XV64(0x1f408bbcc70bcc96), XV64(0x37e3ff7d52fea24), 86 | XV64(0x19bcf4536d5418de), XV64(0x58240187f703e6c), XV64(0x1736a4dfbdcb5889), XV64(0xb081094afef7e3b), 87 | XV64(0x4a8554acc6a9870), XV64(0x1896e101de4ebec2), XV64(0xa2205c61cf5d827), XV64(0x161cb18d0ed1fe95), 88 | XV64(0x15628e7adbfe14b1), XV64(0x95c3a31c9da3203), XV64(0x1be8def60b6154e6), XV64(0x7d66abd19457254), 89 | XV64(0x8762f637ac0941f), XV64(0x14489b2868e4b2ad), XV64(0x6fc7fefaa5fd448), XV64(0x1ac2cba4b87bf2fa), 90 | XV64(0x58ed0bc2e7f3c8f), XV64(0x19b064f73c5b1a3d), XV64(0xb048030fee07cd8), XV64(0x173a347becc45a6a), 91 | XV64(0x189a71a58f41bc21), XV64(0x4a4c5ee9d659a93), XV64(0x161021295fdefc76), XV64(0xa2e95624dfadac4), 92 | XV64(0x950aa9598d530e0), XV64(0x156e1ede8af11652), XV64(0x7dafa19484a70b7), XV64(0x1be44e525a6e5605), 93 | XV64(0x14440b8c39ebb04e), XV64(0x87abfc72bcf96fc), XV64(0x1ace5b00e974f019), XV64(0x6f0ef4bfb50d6ab), 94 | XV64(0x1c3224ef432b2451), XV64(0xc90a4510f02e3), XV64(0x12b8746393b46406), XV64(0xe86c028819042b4), 95 | XV64(0x12685f6e215a4ff), XV64(0x1d1831bdf031824d), XV64(0xfacd57a328ae4a8), XV64(0x1392613120aec21a), 96 | XV64(0x10ec5ec6f581283e), XV64(0xcd2ea8de7a50e8c), XV64(0x1e660e4a251e6869), XV64(0x258ba01373a4edb), 97 | XV64(0xdf8ffdf54bfa890), XV64(0x11c64b94469b8e22), XV64(0x372af538420e8c7), XV64(0x1f4c1b189604ce75), 98 | XV64(0xb1da1785cfe791e), XV64(0x172315334eda5fac), XV64(0x597f1f48c613949), XV64(0x19a945bf9e451ffb), 99 | XV64(0x16090061fdc0f9b0), XV64(0xa37b42aefe4df02), XV64(0x188350ed2d5fb9e7), XV64(0x4bde4a63f7b9f55), 100 | XV64(0x7c3db51ea547571), XV64(0x1bfd6f1af87053c3), XV64(0x9498bdd3acb3526), XV64(0x15773f9628ef1394), 101 | XV64(0x1ad77a484b6af5df), XV64(0x6e9ce03594ed36d), XV64(0x145d2ac49bf5b588), XV64(0x8639e8f89d1933a), 102 | XV64(0x12a1552b31aa61c0), XV64(0xe9fe160238e4772), XV64(0x1c2b05a7e1352197), XV64(0x15b1ecf3110725), 103 | XV64(0xfb5f4329094e16e), XV64(0x138b407982b0c7dc), XV64(0x13fa4be400ba139), XV64(0x1d0110f5522f878b), 104 | XV64(0x1e7f2f0287006daf), XV64(0x2419b4995244b1d), XV64(0x10f57f8e579f2df8), XV64(0xccbcbc545bb0b4a), 105 | XV64(0x36b8e1b263eed01), XV64(0x1f553a50341acbb3), XV64(0xde1de97f6a1ad56), XV64(0x11df6adce4858be4), 106 | XV64(0xe9371c472814591), XV64(0x12adc58f60a56323), XV64(0x192148a21e05c6), XV64(0x1c279503b03a2374), 107 | XV64(0x1387d0ddd3bfc53f), XV64(0xfb96496c19be38d), XV64(0x1d0d805103208568), XV64(0x133341a1104a3da), 108 | XV64(0x24d0bedc42b49fe), XV64(0x1e73bfa6d60f6f4c), XV64(0xcc75b6114b409a9), XV64(0x10f9ef2a06902f1b), 109 | XV64(0x1f59aaf46515c950), XV64(0x3671ebf7731efe2), XV64(0x11d3fa78b58a8907), XV64(0xded4e33a7aeafb5), 110 | XV64(0x172f85971fd55d4f), XV64(0xb1131dc0df17bfd), XV64(0x19a5d51bcf4a1d18), XV64(0x59b6150dd6e3baa), 111 | XV64(0xa3b248ebeebdde1), XV64(0x160590c5accffb53), XV64(0x4b174026e749db6), XV64(0x188fc0497c50bb04), 112 | XV64(0x1bf1ffbea97f5120), XV64(0x7cf4bf5bb5b7792), XV64(0x157baf3279e01177), XV64(0x9451b796bc437c5), 113 | XV64(0x6e55ea70841d18e), XV64(0x1adbeaec1a65f73c), XV64(0x86f0e2bd8de91d9), XV64(0x1451ba60cafab76b), 114 | XV64(0x163b42f0b9fcf23c), XV64(0xa05f6bbabd8d48e), XV64(0x18b1127c6963b26b), XV64(0x48fa6377b4794d9), 115 | XV64(0xb2fe3e918c27292), XV64(0x171157a20ae65420), XV64(0x5a5b365c85d32c5), XV64(0x199b072eda791477), 116 | XV64(0x1ae538d90f56fe53), XV64(0x6db8c921d72d8e1), XV64(0x146f6855dfc9be04), XV64(0x851dc1ecded98b6), 117 | XV64(0x7f199c0ae687efd), XV64(0x1bcf2d8bbc4c584f), XV64(0x97bc94c7ef73eaa), XV64(0x15457d076cd31818), 118 | XV64(0xf87b6a3d4a8eae2), XV64(0x13b902e8c68ccc50), XV64(0x10de62f0437aab5), XV64(0x1d33526416138c07), 119 | XV64(0x129317ba75966a4c), XV64(0xeada3f167b24cfe), XV64(0x1c194736a5092a1b), XV64(0x27f37db72d0ca9), 120 | XV64(0x359cc8a6202e68d), XV64(0x1f6778c17026c03f), XV64(0xdd39c06b29da6da), XV64(0x11ed284da0b98068), 121 | XV64(0x1e4d6d93c33c6623), XV64(0x273d9d8d1184091), XV64(0x10c73d1f13a32674), XV64(0xcf98954018700c6), 122 | XV64(0x13b5924c9783ceb3), XV64(0xf8b260785a7e801), XV64(0x1d3fc2c0471c8ee4), XV64(0x101768b5538a856), 123 | XV64(0xea1335536bd4e1d), XV64(0x129f871e249968af), XV64(0x2b63d9e6220e4a), XV64(0x1c15d792f40628f8), 124 | XV64(0x1f6be8652129c2dc), XV64(0x3555c2e330de46e), XV64(0x11e1b8e9f1b6828b), XV64(0xddf0ca2e392a439), 125 | XV64(0x27f497c80174272), XV64(0x1e41fd37923364c0), XV64(0xcf519f050880225), XV64(0x10cbadbb42ac2497), 126 | XV64(0xa09661ffad7d66d), XV64(0x1637d254e8f3f0df), XV64(0x48336932a48963a), XV64(0x18bd82d8386cb088), 127 | XV64(0x171dc7065be956c3), XV64(0xb23734d49cd7071), XV64(0x1997978a8b761694), XV64(0x5a923c199523026), 128 | XV64(0x6d71c364c7dda02), XV64(0x1ae9a87d5e59fcb0), XV64(0x85d4cba9ce29a55), XV64(0x1463f8f18ec6bce7), 129 | XV64(0x1bc3bd2fed435aac), XV64(0x7fd0964ff677c1e), XV64(0x1549eda33ddc1afb), XV64(0x97759e82ff83c49), 130 | XV64(0x1d26e388e5028b22), XV64(0x11857c3f726ad90), XV64(0x13acb304359dcb75), XV64(0xf92074f27b9edc7), 131 | XV64(0x324291443c0b8c), XV64(0x1c0cf6da56182d3e), XV64(0xeb8121d94a34bdb), XV64(0x1286a65686876d69), 132 | XV64(0x11f899a153a8874d), XV64(0xdc62dea418ca1ff), XV64(0x1f72c92d8337c71a), XV64(0x34c7d669113e1a8), 133 | XV64(0xcec38b8f29607e3), XV64(0x10d28cf3e0b22151), XV64(0x2666834220947b4), XV64(0x1e58dc7f302d6106), 134 | XV64(0x49a17db885693fc), XV64(0x18a4a3909a72b54e), XV64(0xa10475758c9d3ab), XV64(0x162ef31c4aedf519), 135 | XV64(0x198eb6c229681352), XV64(0x5b002893b4c35e0), XV64(0x1704e64ef9f75305), XV64(0xb3a5205ebd375b7), 136 | XV64(0x8446df23efc9f93), XV64(0x147ad9b92cd8b921), XV64(0x6ce3d7eee63dfc4), XV64(0x1af08935fc47f976), 137 | XV64(0x1550cceb9fc21f3d), XV64(0x96e78a08de6398f), XV64(0x1bda9c674f5d5f6a), XV64(0x7e4282c5d7979d8), 138 | XV64(0x18a83334cb7db7ad), XV64(0x496877fd959911f), XV64(0x162263b81be2f7fa), XV64(0xa1cd7f309c6d148), 139 | XV64(0x5bc922d6a433703), XV64(0x19822666786711b1), XV64(0xb36c2a1badc7754), XV64(0x170876eaa8f851e6), 140 | XV64(0x1476491d7dd7bbc2), XV64(0x848fd566ff39d70), XV64(0x1afc1991ad48fb95), XV64(0x6c2addabf6cdd27), 141 | XV64(0x962e804dce93b6c), XV64(0x155c5c4fcecd1dde), XV64(0x7e8b8880c767b3b), XV64(0x1bd60cc31e525d89), 142 | XV64(0x114c767a629af73), XV64(0x1d2a732cb40d89c1), XV64(0xf9e97eb76b6ef24), XV64(0x13a023a06492c996), 143 | XV64(0x1c00667e07172fdd), XV64(0x3ed2351533096f), XV64(0x128a36f2d7886f8a), XV64(0xeb482b9c5ac4938), 144 | XV64(0xdcabd4e1083a31c), XV64(0x11f4090502a785ae), XV64(0x340edc2c01ce34b), XV64(0x1f7e5989d238c5f9), 145 | XV64(0x10de1c57b1bd23b2), XV64(0xce0a81ca3990500), XV64(0x1e544cdb612263e5), XV64(0x26af89073064557) 146 | }; 147 | 148 | #endif /* if defined(XRABPLY_TYPE64) */ 149 | 150 | #if defined(XRABPLY_TYPE32) 151 | 152 | #if !defined(XV32) 153 | #define XV32(v) ((xply_word) v ## ULL) 154 | #endif 155 | 156 | #define XRAB_ROOTPOLY XV32(0xabd1f37b) 157 | 158 | #define XRAB_SHIFT 23 159 | #define XRAB_WNDSIZE 20 160 | 161 | typedef unsigned XRABPLY_TYPE32 xply_word; 162 | 163 | static const xply_word T[256] = { 164 | XV32(0x0), XV32(0xabd1f37b), XV32(0x57a3e6f6), XV32(0xfc72158d), 165 | XV32(0x4963e97), XV32(0xaf47cdec), XV32(0x5335d861), XV32(0xf8e42b1a), 166 | XV32(0x92c7d2e), XV32(0xa2fd8e55), XV32(0x5e8f9bd8), XV32(0xf55e68a3), 167 | XV32(0xdba43b9), XV32(0xa66bb0c2), XV32(0x5a19a54f), XV32(0xf1c85634), 168 | XV32(0x1258fa5c), XV32(0xb9890927), XV32(0x45fb1caa), XV32(0xee2aefd1), 169 | XV32(0x16cec4cb), XV32(0xbd1f37b0), XV32(0x416d223d), XV32(0xeabcd146), 170 | XV32(0x1b748772), XV32(0xb0a57409), XV32(0x4cd76184), XV32(0xe70692ff), 171 | XV32(0x1fe2b9e5), XV32(0xb4334a9e), XV32(0x48415f13), XV32(0xe390ac68), 172 | XV32(0x24b1f4b8), XV32(0x8f6007c3), XV32(0x7312124e), XV32(0xd8c3e135), 173 | XV32(0x2027ca2f), XV32(0x8bf63954), XV32(0x77842cd9), XV32(0xdc55dfa2), 174 | XV32(0x2d9d8996), XV32(0x864c7aed), XV32(0x7a3e6f60), XV32(0xd1ef9c1b), 175 | XV32(0x290bb701), XV32(0x82da447a), XV32(0x7ea851f7), XV32(0xd579a28c), 176 | XV32(0x36e90ee4), XV32(0x9d38fd9f), XV32(0x614ae812), XV32(0xca9b1b69), 177 | XV32(0x327f3073), XV32(0x99aec308), XV32(0x65dcd685), XV32(0xce0d25fe), 178 | XV32(0x3fc573ca), XV32(0x941480b1), XV32(0x6866953c), XV32(0xc3b76647), 179 | XV32(0x3b534d5d), XV32(0x9082be26), XV32(0x6cf0abab), XV32(0xc72158d0), 180 | XV32(0x4963e970), XV32(0xe2b21a0b), XV32(0x1ec00f86), XV32(0xb511fcfd), 181 | XV32(0x4df5d7e7), XV32(0xe624249c), XV32(0x1a563111), XV32(0xb187c26a), 182 | XV32(0x404f945e), XV32(0xeb9e6725), XV32(0x17ec72a8), XV32(0xbc3d81d3), 183 | XV32(0x44d9aac9), XV32(0xef0859b2), XV32(0x137a4c3f), XV32(0xb8abbf44), 184 | XV32(0x5b3b132c), XV32(0xf0eae057), XV32(0xc98f5da), XV32(0xa74906a1), 185 | XV32(0x5fad2dbb), XV32(0xf47cdec0), XV32(0x80ecb4d), XV32(0xa3df3836), 186 | XV32(0x52176e02), XV32(0xf9c69d79), XV32(0x5b488f4), XV32(0xae657b8f), 187 | XV32(0x56815095), XV32(0xfd50a3ee), XV32(0x122b663), XV32(0xaaf34518), 188 | XV32(0x6dd21dc8), XV32(0xc603eeb3), XV32(0x3a71fb3e), XV32(0x91a00845), 189 | XV32(0x6944235f), XV32(0xc295d024), XV32(0x3ee7c5a9), XV32(0x953636d2), 190 | XV32(0x64fe60e6), XV32(0xcf2f939d), XV32(0x335d8610), XV32(0x988c756b), 191 | XV32(0x60685e71), XV32(0xcbb9ad0a), XV32(0x37cbb887), XV32(0x9c1a4bfc), 192 | XV32(0x7f8ae794), XV32(0xd45b14ef), XV32(0x28290162), XV32(0x83f8f219), 193 | XV32(0x7b1cd903), XV32(0xd0cd2a78), XV32(0x2cbf3ff5), XV32(0x876ecc8e), 194 | XV32(0x76a69aba), XV32(0xdd7769c1), XV32(0x21057c4c), XV32(0x8ad48f37), 195 | XV32(0x7230a42d), XV32(0xd9e15756), XV32(0x259342db), XV32(0x8e42b1a0), 196 | XV32(0x3916219b), XV32(0x92c7d2e0), XV32(0x6eb5c76d), XV32(0xc5643416), 197 | XV32(0x3d801f0c), XV32(0x9651ec77), XV32(0x6a23f9fa), XV32(0xc1f20a81), 198 | XV32(0x303a5cb5), XV32(0x9bebafce), XV32(0x6799ba43), XV32(0xcc484938), 199 | XV32(0x34ac6222), XV32(0x9f7d9159), XV32(0x630f84d4), XV32(0xc8de77af), 200 | XV32(0x2b4edbc7), XV32(0x809f28bc), XV32(0x7ced3d31), XV32(0xd73cce4a), 201 | XV32(0x2fd8e550), XV32(0x8409162b), XV32(0x787b03a6), XV32(0xd3aaf0dd), 202 | XV32(0x2262a6e9), XV32(0x89b35592), XV32(0x75c1401f), XV32(0xde10b364), 203 | XV32(0x26f4987e), XV32(0x8d256b05), XV32(0x71577e88), XV32(0xda868df3), 204 | XV32(0x1da7d523), XV32(0xb6762658), XV32(0x4a0433d5), XV32(0xe1d5c0ae), 205 | XV32(0x1931ebb4), XV32(0xb2e018cf), XV32(0x4e920d42), XV32(0xe543fe39), 206 | XV32(0x148ba80d), XV32(0xbf5a5b76), XV32(0x43284efb), XV32(0xe8f9bd80), 207 | XV32(0x101d969a), XV32(0xbbcc65e1), XV32(0x47be706c), XV32(0xec6f8317), 208 | XV32(0xfff2f7f), XV32(0xa42edc04), XV32(0x585cc989), XV32(0xf38d3af2), 209 | XV32(0xb6911e8), XV32(0xa0b8e293), XV32(0x5ccaf71e), XV32(0xf71b0465), 210 | XV32(0x6d35251), XV32(0xad02a12a), XV32(0x5170b4a7), XV32(0xfaa147dc), 211 | XV32(0x2456cc6), XV32(0xa9949fbd), XV32(0x55e68a30), XV32(0xfe37794b), 212 | XV32(0x7075c8eb), XV32(0xdba43b90), XV32(0x27d62e1d), XV32(0x8c07dd66), 213 | XV32(0x74e3f67c), XV32(0xdf320507), XV32(0x2340108a), XV32(0x8891e3f1), 214 | XV32(0x7959b5c5), XV32(0xd28846be), XV32(0x2efa5333), XV32(0x852ba048), 215 | XV32(0x7dcf8b52), XV32(0xd61e7829), XV32(0x2a6c6da4), XV32(0x81bd9edf), 216 | XV32(0x622d32b7), XV32(0xc9fcc1cc), XV32(0x358ed441), XV32(0x9e5f273a), 217 | XV32(0x66bb0c20), XV32(0xcd6aff5b), XV32(0x3118ead6), XV32(0x9ac919ad), 218 | XV32(0x6b014f99), XV32(0xc0d0bce2), XV32(0x3ca2a96f), XV32(0x97735a14), 219 | XV32(0x6f97710e), XV32(0xc4468275), XV32(0x383497f8), XV32(0x93e56483), 220 | XV32(0x54c43c53), XV32(0xff15cf28), XV32(0x367daa5), XV32(0xa8b629de), 221 | XV32(0x505202c4), XV32(0xfb83f1bf), XV32(0x7f1e432), XV32(0xac201749), 222 | XV32(0x5de8417d), XV32(0xf639b206), XV32(0xa4ba78b), XV32(0xa19a54f0), 223 | XV32(0x597e7fea), XV32(0xf2af8c91), XV32(0xedd991c), XV32(0xa50c6a67), 224 | XV32(0x469cc60f), XV32(0xed4d3574), XV32(0x113f20f9), XV32(0xbaeed382), 225 | XV32(0x420af898), XV32(0xe9db0be3), XV32(0x15a91e6e), XV32(0xbe78ed15), 226 | XV32(0x4fb0bb21), XV32(0xe461485a), XV32(0x18135dd7), XV32(0xb3c2aeac), 227 | XV32(0x4b2685b6), XV32(0xe0f776cd), XV32(0x1c856340), XV32(0xb754903b) 228 | }; 229 | 230 | static const xply_word U[256] = { 231 | XV32(0x0), XV32(0x5ce33923), XV32(0x1217813d), XV32(0x4ef4b81e), 232 | XV32(0x242f027a), XV32(0x78cc3b59), XV32(0x36388347), XV32(0x6adbba64), 233 | XV32(0x485e04f4), XV32(0x14bd3dd7), XV32(0x5a4985c9), XV32(0x6aabcea), 234 | XV32(0x6c71068e), XV32(0x30923fad), XV32(0x7e6687b3), XV32(0x2285be90), 235 | XV32(0x3b6dfa93), XV32(0x678ec3b0), XV32(0x297a7bae), XV32(0x7599428d), 236 | XV32(0x1f42f8e9), XV32(0x43a1c1ca), XV32(0xd5579d4), XV32(0x51b640f7), 237 | XV32(0x7333fe67), XV32(0x2fd0c744), XV32(0x61247f5a), XV32(0x3dc74679), 238 | XV32(0x571cfc1d), XV32(0xbffc53e), XV32(0x450b7d20), XV32(0x19e84403), 239 | XV32(0x76dbf526), XV32(0x2a38cc05), XV32(0x64cc741b), XV32(0x382f4d38), 240 | XV32(0x52f4f75c), XV32(0xe17ce7f), XV32(0x40e37661), XV32(0x1c004f42), 241 | XV32(0x3e85f1d2), XV32(0x6266c8f1), XV32(0x2c9270ef), XV32(0x707149cc), 242 | XV32(0x1aaaf3a8), XV32(0x4649ca8b), XV32(0x8bd7295), XV32(0x545e4bb6), 243 | XV32(0x4db60fb5), XV32(0x11553696), XV32(0x5fa18e88), XV32(0x342b7ab), 244 | XV32(0x69990dcf), XV32(0x357a34ec), XV32(0x7b8e8cf2), XV32(0x276db5d1), 245 | XV32(0x5e80b41), XV32(0x590b3262), XV32(0x17ff8a7c), XV32(0x4b1cb35f), 246 | XV32(0x21c7093b), XV32(0x7d243018), XV32(0x33d08806), XV32(0x6f33b125), 247 | XV32(0x46661937), XV32(0x1a852014), XV32(0x5471980a), XV32(0x892a129), 248 | XV32(0x62491b4d), XV32(0x3eaa226e), XV32(0x705e9a70), XV32(0x2cbda353), 249 | XV32(0xe381dc3), XV32(0x52db24e0), XV32(0x1c2f9cfe), XV32(0x40cca5dd), 250 | XV32(0x2a171fb9), XV32(0x76f4269a), XV32(0x38009e84), XV32(0x64e3a7a7), 251 | XV32(0x7d0be3a4), XV32(0x21e8da87), XV32(0x6f1c6299), XV32(0x33ff5bba), 252 | XV32(0x5924e1de), XV32(0x5c7d8fd), XV32(0x4b3360e3), XV32(0x17d059c0), 253 | XV32(0x3555e750), XV32(0x69b6de73), XV32(0x2742666d), XV32(0x7ba15f4e), 254 | XV32(0x117ae52a), XV32(0x4d99dc09), XV32(0x36d6417), XV32(0x5f8e5d34), 255 | XV32(0x30bdec11), XV32(0x6c5ed532), XV32(0x22aa6d2c), XV32(0x7e49540f), 256 | XV32(0x1492ee6b), XV32(0x4871d748), XV32(0x6856f56), XV32(0x5a665675), 257 | XV32(0x78e3e8e5), XV32(0x2400d1c6), XV32(0x6af469d8), XV32(0x361750fb), 258 | XV32(0x5cccea9f), XV32(0x2fd3bc), XV32(0x4edb6ba2), XV32(0x12385281), 259 | XV32(0xbd01682), XV32(0x57332fa1), XV32(0x19c797bf), XV32(0x4524ae9c), 260 | XV32(0x2fff14f8), XV32(0x731c2ddb), XV32(0x3de895c5), XV32(0x610bace6), 261 | XV32(0x438e1276), XV32(0x1f6d2b55), XV32(0x5199934b), XV32(0xd7aaa68), 262 | XV32(0x67a1100c), XV32(0x3b42292f), XV32(0x75b69131), XV32(0x2955a812), 263 | XV32(0x271dc115), XV32(0x7bfef836), XV32(0x350a4028), XV32(0x69e9790b), 264 | XV32(0x332c36f), XV32(0x5fd1fa4c), XV32(0x11254252), XV32(0x4dc67b71), 265 | XV32(0x6f43c5e1), XV32(0x33a0fcc2), XV32(0x7d5444dc), XV32(0x21b77dff), 266 | XV32(0x4b6cc79b), XV32(0x178ffeb8), XV32(0x597b46a6), XV32(0x5987f85), 267 | XV32(0x1c703b86), XV32(0x409302a5), XV32(0xe67babb), XV32(0x52848398), 268 | XV32(0x385f39fc), XV32(0x64bc00df), XV32(0x2a48b8c1), XV32(0x76ab81e2), 269 | XV32(0x542e3f72), XV32(0x8cd0651), XV32(0x4639be4f), XV32(0x1ada876c), 270 | XV32(0x70013d08), XV32(0x2ce2042b), XV32(0x6216bc35), XV32(0x3ef58516), 271 | XV32(0x51c63433), XV32(0xd250d10), XV32(0x43d1b50e), XV32(0x1f328c2d), 272 | XV32(0x75e93649), XV32(0x290a0f6a), XV32(0x67feb774), XV32(0x3b1d8e57), 273 | XV32(0x199830c7), XV32(0x457b09e4), XV32(0xb8fb1fa), XV32(0x576c88d9), 274 | XV32(0x3db732bd), XV32(0x61540b9e), XV32(0x2fa0b380), XV32(0x73438aa3), 275 | XV32(0x6aabcea0), XV32(0x3648f783), XV32(0x78bc4f9d), XV32(0x245f76be), 276 | XV32(0x4e84ccda), XV32(0x1267f5f9), XV32(0x5c934de7), XV32(0x7074c4), 277 | XV32(0x22f5ca54), XV32(0x7e16f377), XV32(0x30e24b69), XV32(0x6c01724a), 278 | XV32(0x6dac82e), XV32(0x5a39f10d), XV32(0x14cd4913), XV32(0x482e7030), 279 | XV32(0x617bd822), XV32(0x3d98e101), XV32(0x736c591f), XV32(0x2f8f603c), 280 | XV32(0x4554da58), XV32(0x19b7e37b), XV32(0x57435b65), XV32(0xba06246), 281 | XV32(0x2925dcd6), XV32(0x75c6e5f5), XV32(0x3b325deb), XV32(0x67d164c8), 282 | XV32(0xd0adeac), XV32(0x51e9e78f), XV32(0x1f1d5f91), XV32(0x43fe66b2), 283 | XV32(0x5a1622b1), XV32(0x6f51b92), XV32(0x4801a38c), XV32(0x14e29aaf), 284 | XV32(0x7e3920cb), XV32(0x22da19e8), XV32(0x6c2ea1f6), XV32(0x30cd98d5), 285 | XV32(0x12482645), XV32(0x4eab1f66), XV32(0x5fa778), XV32(0x5cbc9e5b), 286 | XV32(0x3667243f), XV32(0x6a841d1c), XV32(0x2470a502), XV32(0x78939c21), 287 | XV32(0x17a02d04), XV32(0x4b431427), XV32(0x5b7ac39), XV32(0x5954951a), 288 | XV32(0x338f2f7e), XV32(0x6f6c165d), XV32(0x2198ae43), XV32(0x7d7b9760), 289 | XV32(0x5ffe29f0), XV32(0x31d10d3), XV32(0x4de9a8cd), XV32(0x110a91ee), 290 | XV32(0x7bd12b8a), XV32(0x273212a9), XV32(0x69c6aab7), XV32(0x35259394), 291 | XV32(0x2ccdd797), XV32(0x702eeeb4), XV32(0x3eda56aa), XV32(0x62396f89), 292 | XV32(0x8e2d5ed), XV32(0x5401ecce), XV32(0x1af554d0), XV32(0x46166df3), 293 | XV32(0x6493d363), XV32(0x3870ea40), XV32(0x7684525e), XV32(0x2a676b7d), 294 | XV32(0x40bcd119), XV32(0x1c5fe83a), XV32(0x52ab5024), XV32(0xe486907) 295 | }; 296 | 297 | #endif /* if defined(XRABPLY_TYPE32) */ 298 | 299 | -------------------------------------------------------------------------------- /xdiff/xtypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XTYPES_H) 24 | #define XTYPES_H 25 | 26 | 27 | 28 | typedef struct s_chanode { 29 | struct s_chanode *next; 30 | long icurr; 31 | } chanode_t; 32 | 33 | typedef struct s_chastore { 34 | chanode_t *head, *tail; 35 | long isize, nsize; 36 | chanode_t *ancur; 37 | chanode_t *sncur; 38 | long scurr; 39 | } chastore_t; 40 | 41 | typedef struct s_xrecord { 42 | struct s_xrecord *next; 43 | char const *ptr; 44 | long size; 45 | unsigned long ha; 46 | } xrecord_t; 47 | 48 | typedef struct s_xdfile { 49 | chastore_t rcha; 50 | long nrec; 51 | unsigned int hbits; 52 | xrecord_t **rhash; 53 | long dstart, dend; 54 | xrecord_t **recs; 55 | char *rchg; 56 | long *rindex; 57 | long nreff; 58 | unsigned long *ha; 59 | } xdfile_t; 60 | 61 | typedef struct s_xdfenv { 62 | xdfile_t xdf1, xdf2; 63 | } xdfenv_t; 64 | 65 | 66 | 67 | #endif /* #if !defined(XTYPES_H) */ 68 | 69 | -------------------------------------------------------------------------------- /xdiff/xutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | 27 | #define XDL_GUESS_NLINES 256 28 | 29 | 30 | 31 | 32 | long xdl_bogosqrt(long n) { 33 | long i; 34 | 35 | /* 36 | * Classical integer square root approximation using shifts. 37 | */ 38 | for (i = 1; n > 0; n >>= 2) 39 | i <<= 1; 40 | 41 | return i; 42 | } 43 | 44 | 45 | int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize, 46 | xdemitcb_t *ecb) { 47 | int i = 2; 48 | mmbuffer_t mb[3]; 49 | 50 | mb[0].ptr = (char *) pre; 51 | mb[0].size = psize; 52 | mb[1].ptr = (char *) rec; 53 | mb[1].size = size; 54 | if (size > 0 && rec[size - 1] != '\n') { 55 | mb[2].ptr = (char *) "\n\\ No newline at end of file\n"; 56 | mb[2].size = strlen(mb[2].ptr); 57 | i++; 58 | } 59 | if (ecb->outf(ecb->priv, mb, i) < 0) { 60 | 61 | return -1; 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | 68 | int xdl_init_mmfile(mmfile_t *mmf, long bsize, unsigned long flags) { 69 | 70 | mmf->flags = flags; 71 | mmf->head = mmf->tail = NULL; 72 | mmf->bsize = bsize; 73 | mmf->fsize = 0; 74 | mmf->rcur = mmf->wcur = NULL; 75 | mmf->rpos = 0; 76 | 77 | return 0; 78 | } 79 | 80 | 81 | void xdl_free_mmfile(mmfile_t *mmf) { 82 | mmblock_t *cur, *tmp; 83 | 84 | for (cur = mmf->head; (tmp = cur) != NULL;) { 85 | cur = cur->next; 86 | xdl_free(tmp); 87 | } 88 | } 89 | 90 | 91 | int xdl_mmfile_iscompact(mmfile_t *mmf) { 92 | 93 | return mmf->head == mmf->tail; 94 | } 95 | 96 | 97 | int xdl_seek_mmfile(mmfile_t *mmf, long off) { 98 | long bsize; 99 | 100 | if (xdl_mmfile_first(mmf, &bsize)) { 101 | do { 102 | if (off < bsize) { 103 | mmf->rpos = off; 104 | return 0; 105 | } 106 | off -= bsize; 107 | } while (xdl_mmfile_next(mmf, &bsize)); 108 | } 109 | 110 | return -1; 111 | } 112 | 113 | 114 | long xdl_read_mmfile(mmfile_t *mmf, void *data, long size) { 115 | long rsize, csize; 116 | char *ptr = data; 117 | mmblock_t *rcur; 118 | 119 | for (rsize = 0, rcur = mmf->rcur; rcur && rsize < size;) { 120 | if (mmf->rpos >= rcur->size) { 121 | if (!(mmf->rcur = rcur = rcur->next)) 122 | break; 123 | mmf->rpos = 0; 124 | } 125 | csize = XDL_MIN(size - rsize, rcur->size - mmf->rpos); 126 | memcpy(ptr, rcur->ptr + mmf->rpos, csize); 127 | rsize += csize; 128 | ptr += csize; 129 | mmf->rpos += csize; 130 | } 131 | 132 | return rsize; 133 | } 134 | 135 | 136 | long xdl_write_mmfile(mmfile_t *mmf, void const *data, long size) { 137 | long wsize, bsize, csize; 138 | mmblock_t *wcur; 139 | 140 | for (wsize = 0; wsize < size;) { 141 | wcur = mmf->wcur; 142 | if (wcur && (wcur->flags & XDL_MMB_READONLY)) 143 | return wsize; 144 | if (!wcur || wcur->size == wcur->bsize || 145 | (mmf->flags & XDL_MMF_ATOMIC && wcur->size + size > wcur->bsize)) { 146 | bsize = XDL_MAX(mmf->bsize, size); 147 | if (!(wcur = (mmblock_t *) xdl_malloc(sizeof(mmblock_t) + bsize))) { 148 | 149 | return wsize; 150 | } 151 | wcur->flags = 0; 152 | wcur->ptr = (char *) wcur + sizeof(mmblock_t); 153 | wcur->size = 0; 154 | wcur->bsize = bsize; 155 | wcur->next = NULL; 156 | if (!mmf->head) 157 | mmf->head = wcur; 158 | if (mmf->tail) 159 | mmf->tail->next = wcur; 160 | mmf->tail = wcur; 161 | mmf->wcur = wcur; 162 | } 163 | csize = XDL_MIN(size - wsize, wcur->bsize - wcur->size); 164 | memcpy(wcur->ptr + wcur->size, (char const *) data + wsize, csize); 165 | wsize += csize; 166 | wcur->size += csize; 167 | mmf->fsize += csize; 168 | } 169 | 170 | return size; 171 | } 172 | 173 | 174 | long xdl_writem_mmfile(mmfile_t *mmf, mmbuffer_t *mb, int nbuf) { 175 | int i; 176 | long size; 177 | char *data; 178 | 179 | for (i = 0, size = 0; i < nbuf; i++) 180 | size += mb[i].size; 181 | if (!(data = (char *) xdl_mmfile_writeallocate(mmf, size))) 182 | return -1; 183 | for (i = 0; i < nbuf; i++) { 184 | memcpy(data, mb[i].ptr, mb[i].size); 185 | data += mb[i].size; 186 | } 187 | 188 | return size; 189 | } 190 | 191 | 192 | void *xdl_mmfile_writeallocate(mmfile_t *mmf, long size) { 193 | long bsize; 194 | mmblock_t *wcur; 195 | char *blk; 196 | 197 | if (!(wcur = mmf->wcur) || wcur->size + size > wcur->bsize) { 198 | bsize = XDL_MAX(mmf->bsize, size); 199 | if (!(wcur = (mmblock_t *) xdl_malloc(sizeof(mmblock_t) + bsize))) { 200 | 201 | return NULL; 202 | } 203 | wcur->flags = 0; 204 | wcur->ptr = (char *) wcur + sizeof(mmblock_t); 205 | wcur->size = 0; 206 | wcur->bsize = bsize; 207 | wcur->next = NULL; 208 | if (!mmf->head) 209 | mmf->head = wcur; 210 | if (mmf->tail) 211 | mmf->tail->next = wcur; 212 | mmf->tail = wcur; 213 | mmf->wcur = wcur; 214 | } 215 | 216 | blk = wcur->ptr + wcur->size; 217 | wcur->size += size; 218 | mmf->fsize += size; 219 | 220 | return blk; 221 | } 222 | 223 | 224 | long xdl_mmfile_ptradd(mmfile_t *mmf, char *ptr, long size, unsigned long flags) { 225 | mmblock_t *wcur; 226 | 227 | if (!(wcur = (mmblock_t *) xdl_malloc(sizeof(mmblock_t)))) { 228 | 229 | return -1; 230 | } 231 | wcur->flags = flags; 232 | wcur->ptr = ptr; 233 | wcur->size = wcur->bsize = size; 234 | wcur->next = NULL; 235 | if (!mmf->head) 236 | mmf->head = wcur; 237 | if (mmf->tail) 238 | mmf->tail->next = wcur; 239 | mmf->tail = wcur; 240 | mmf->wcur = wcur; 241 | 242 | mmf->fsize += size; 243 | 244 | return size; 245 | } 246 | 247 | 248 | long xdl_copy_mmfile(mmfile_t *mmf, long size, xdemitcb_t *ecb) { 249 | long rsize, csize; 250 | mmblock_t *rcur; 251 | mmbuffer_t mb; 252 | 253 | for (rsize = 0, rcur = mmf->rcur; rcur && rsize < size;) { 254 | if (mmf->rpos >= rcur->size) { 255 | if (!(mmf->rcur = rcur = rcur->next)) 256 | break; 257 | mmf->rpos = 0; 258 | } 259 | csize = XDL_MIN(size - rsize, rcur->size - mmf->rpos); 260 | mb.ptr = rcur->ptr + mmf->rpos; 261 | mb.size = csize; 262 | if (ecb->outf(ecb->priv, &mb, 1) < 0) { 263 | 264 | return rsize; 265 | } 266 | rsize += csize; 267 | mmf->rpos += csize; 268 | } 269 | 270 | return rsize; 271 | } 272 | 273 | 274 | void *xdl_mmfile_first(mmfile_t *mmf, long *size) { 275 | 276 | if (!(mmf->rcur = mmf->head)) 277 | return NULL; 278 | 279 | *size = mmf->rcur->size; 280 | 281 | return mmf->rcur->ptr; 282 | } 283 | 284 | 285 | void *xdl_mmfile_next(mmfile_t *mmf, long *size) { 286 | 287 | if (!mmf->rcur || !(mmf->rcur = mmf->rcur->next)) 288 | return NULL; 289 | 290 | *size = mmf->rcur->size; 291 | 292 | return mmf->rcur->ptr; 293 | } 294 | 295 | 296 | long xdl_mmfile_size(mmfile_t *mmf) { 297 | 298 | return mmf->fsize; 299 | } 300 | 301 | 302 | int xdl_mmfile_cmp(mmfile_t *mmf1, mmfile_t *mmf2) { 303 | int cres; 304 | long size, bsize1, bsize2, size1, size2; 305 | char const *blk1, *cur1, *top1; 306 | char const *blk2, *cur2, *top2; 307 | 308 | if ((cur1 = blk1 = xdl_mmfile_first(mmf1, &bsize1)) != NULL) 309 | top1 = blk1 + bsize1; 310 | if ((cur2 = blk2 = xdl_mmfile_first(mmf2, &bsize2)) != NULL) 311 | top2 = blk2 + bsize2; 312 | if (!cur1) { 313 | if (!cur2 || xdl_mmfile_size(mmf2) == 0) 314 | return 0; 315 | return -*cur2; 316 | } else if (!cur2) 317 | return xdl_mmfile_size(mmf1) ? *cur1: 0; 318 | for (;;) { 319 | if (cur1 >= top1) { 320 | if ((cur1 = blk1 = xdl_mmfile_next(mmf1, &bsize1)) != NULL) 321 | top1 = blk1 + bsize1; 322 | } 323 | if (cur2 >= top2) { 324 | if ((cur2 = blk2 = xdl_mmfile_next(mmf2, &bsize2)) != NULL) 325 | top2 = blk2 + bsize2; 326 | } 327 | if (!cur1) { 328 | if (!cur2) 329 | break; 330 | return -*cur2; 331 | } else if (!cur2) 332 | return *cur1; 333 | size1 = top1 - cur1; 334 | size2 = top2 - cur2; 335 | size = XDL_MIN(size1, size2); 336 | if ((cres = memcmp(cur1, cur2, size)) != 0) 337 | return cres; 338 | cur1 += size; 339 | cur2 += size; 340 | } 341 | 342 | return 0; 343 | } 344 | 345 | 346 | int xdl_mmfile_compact(mmfile_t *mmfo, mmfile_t *mmfc, long bsize, unsigned long flags) { 347 | long fsize = xdl_mmfile_size(mmfo), size; 348 | char *data; 349 | char const *blk; 350 | 351 | if (xdl_init_mmfile(mmfc, bsize, flags) < 0) { 352 | 353 | return -1; 354 | } 355 | if (!(data = (char *) xdl_mmfile_writeallocate(mmfc, fsize))) { 356 | 357 | xdl_free_mmfile(mmfc); 358 | return -1; 359 | } 360 | if ((blk = (char const *) xdl_mmfile_first(mmfo, &size)) != NULL) { 361 | do { 362 | memcpy(data, blk, size); 363 | data += size; 364 | } while ((blk = (char const *) xdl_mmfile_next(mmfo, &size)) != NULL); 365 | } 366 | 367 | return 0; 368 | } 369 | 370 | 371 | int xdl_mmfile_outf(void *priv, mmbuffer_t *mb, int nbuf) { 372 | mmfile_t *mmf = priv; 373 | 374 | if (xdl_writem_mmfile(mmf, mb, nbuf) < 0) { 375 | 376 | return -1; 377 | } 378 | 379 | return 0; 380 | } 381 | 382 | 383 | int xdl_cha_init(chastore_t *cha, long isize, long icount) { 384 | 385 | cha->head = cha->tail = NULL; 386 | cha->isize = isize; 387 | cha->nsize = icount * isize; 388 | cha->ancur = cha->sncur = NULL; 389 | cha->scurr = 0; 390 | 391 | return 0; 392 | } 393 | 394 | 395 | void xdl_cha_free(chastore_t *cha) { 396 | chanode_t *cur, *tmp; 397 | 398 | for (cur = cha->head; (tmp = cur) != NULL;) { 399 | cur = cur->next; 400 | xdl_free(tmp); 401 | } 402 | } 403 | 404 | 405 | void *xdl_cha_alloc(chastore_t *cha) { 406 | chanode_t *ancur; 407 | void *data; 408 | 409 | if (!(ancur = cha->ancur) || ancur->icurr == cha->nsize) { 410 | if (!(ancur = (chanode_t *) xdl_malloc(sizeof(chanode_t) + cha->nsize))) { 411 | 412 | return NULL; 413 | } 414 | ancur->icurr = 0; 415 | ancur->next = NULL; 416 | if (cha->tail) 417 | cha->tail->next = ancur; 418 | if (!cha->head) 419 | cha->head = ancur; 420 | cha->tail = ancur; 421 | cha->ancur = ancur; 422 | } 423 | 424 | data = (char *) ancur + sizeof(chanode_t) + ancur->icurr; 425 | ancur->icurr += cha->isize; 426 | 427 | return data; 428 | } 429 | 430 | 431 | void *xdl_cha_first(chastore_t *cha) { 432 | chanode_t *sncur; 433 | 434 | if (!(cha->sncur = sncur = cha->head)) 435 | return NULL; 436 | 437 | cha->scurr = 0; 438 | 439 | return (char *) sncur + sizeof(chanode_t) + cha->scurr; 440 | } 441 | 442 | 443 | void *xdl_cha_next(chastore_t *cha) { 444 | chanode_t *sncur; 445 | 446 | if (!(sncur = cha->sncur)) 447 | return NULL; 448 | cha->scurr += cha->isize; 449 | if (cha->scurr == sncur->icurr) { 450 | if (!(sncur = cha->sncur = sncur->next)) 451 | return NULL; 452 | cha->scurr = 0; 453 | } 454 | 455 | return (char *) sncur + sizeof(chanode_t) + cha->scurr; 456 | } 457 | 458 | 459 | long xdl_guess_lines(mmfile_t *mf) { 460 | long nl = 0, size, tsize = 0; 461 | char const *data, *cur, *top; 462 | 463 | if ((cur = data = xdl_mmfile_first(mf, &size)) != NULL) { 464 | for (top = data + size; nl < XDL_GUESS_NLINES;) { 465 | if (cur >= top) { 466 | tsize += (long) (cur - data); 467 | if (!(cur = data = xdl_mmfile_next(mf, &size))) 468 | break; 469 | top = data + size; 470 | } 471 | nl++; 472 | if (!(cur = memchr(cur, '\n', top - cur))) 473 | cur = top; 474 | else 475 | cur++; 476 | } 477 | tsize += (long) (cur - data); 478 | } 479 | 480 | if (nl && tsize) 481 | nl = xdl_mmfile_size(mf) / (tsize / nl); 482 | 483 | return nl + 1; 484 | } 485 | 486 | 487 | unsigned long xdl_hash_record(char const **data, char const *top) { 488 | unsigned long ha = 5381; 489 | char const *ptr = *data; 490 | 491 | for (; ptr < top && *ptr != '\n'; ptr++) { 492 | ha += (ha << 5); 493 | ha ^= (unsigned long) *ptr; 494 | } 495 | *data = ptr < top ? ptr + 1: ptr; 496 | 497 | return ha; 498 | } 499 | 500 | 501 | unsigned int xdl_hashbits(unsigned int size) { 502 | unsigned int val = 1, bits = 0; 503 | 504 | for (; val < size && bits < CHAR_BIT * sizeof(unsigned int); val <<= 1, bits++); 505 | return bits ? bits: 1; 506 | } 507 | 508 | 509 | int xdl_num_out(char *out, long val) { 510 | char *ptr, *str = out; 511 | char buf[32]; 512 | 513 | ptr = buf + sizeof(buf) - 1; 514 | *ptr = '\0'; 515 | if (val < 0) { 516 | *--ptr = '-'; 517 | val = -val; 518 | } 519 | for (; val && ptr > buf; val /= 10) 520 | *--ptr = "0123456789"[val % 10]; 521 | if (*ptr) 522 | for (; *ptr; ptr++, str++) 523 | *str = *ptr; 524 | else 525 | *str++ = '0'; 526 | *str = '\0'; 527 | 528 | return str - out; 529 | } 530 | 531 | 532 | long xdl_atol(char const *str, char const **next) { 533 | long val, base; 534 | char const *top; 535 | 536 | for (top = str; XDL_ISDIGIT(*top); top++); 537 | if (next) 538 | *next = top; 539 | for (val = 0, base = 1, top--; top >= str; top--, base *= 10) 540 | val += base * (long)(*top - '0'); 541 | return val; 542 | } 543 | 544 | 545 | int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb) { 546 | int nb = 0; 547 | mmbuffer_t mb; 548 | char buf[128]; 549 | 550 | memcpy(buf, "@@ -", 4); 551 | nb += 4; 552 | 553 | nb += xdl_num_out(buf + nb, c1 ? s1: s1 - 1); 554 | 555 | memcpy(buf + nb, ",", 1); 556 | nb += 1; 557 | 558 | nb += xdl_num_out(buf + nb, c1); 559 | 560 | memcpy(buf + nb, " +", 2); 561 | nb += 2; 562 | 563 | nb += xdl_num_out(buf + nb, c2 ? s2: s2 - 1); 564 | 565 | memcpy(buf + nb, ",", 1); 566 | nb += 1; 567 | 568 | nb += xdl_num_out(buf + nb, c2); 569 | 570 | memcpy(buf + nb, " @@\n", 4); 571 | nb += 4; 572 | 573 | mb.ptr = buf; 574 | mb.size = nb; 575 | if (ecb->outf(ecb->priv, &mb, 1) < 0) 576 | return -1; 577 | 578 | return 0; 579 | } 580 | 581 | -------------------------------------------------------------------------------- /xdiff/xutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #if !defined(XUTILS_H) 24 | #define XUTILS_H 25 | 26 | 27 | 28 | long xdl_bogosqrt(long n); 29 | int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize, 30 | xdemitcb_t *ecb); 31 | int xdl_mmfile_outf(void *priv, mmbuffer_t *mb, int nbuf); 32 | int xdl_cha_init(chastore_t *cha, long isize, long icount); 33 | void xdl_cha_free(chastore_t *cha); 34 | void *xdl_cha_alloc(chastore_t *cha); 35 | void *xdl_cha_first(chastore_t *cha); 36 | void *xdl_cha_next(chastore_t *cha); 37 | long xdl_guess_lines(mmfile_t *mf); 38 | unsigned long xdl_hash_record(char const **data, char const *top); 39 | unsigned int xdl_hashbits(unsigned int size); 40 | int xdl_num_out(char *out, long val); 41 | long xdl_atol(char const *str, char const **next); 42 | int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb); 43 | 44 | 45 | 46 | #endif /* #if !defined(XUTILS_H) */ 47 | 48 | -------------------------------------------------------------------------------- /xdiff/xversion.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LibXDiff by Davide Libenzi ( File Differential Library ) 3 | * Copyright (C) 2003 Davide Libenzi 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Davide Libenzi 20 | * 21 | */ 22 | 23 | #include "xinclude.h" 24 | 25 | 26 | char libxdiff_version[] = "LibXDiff v" PACKAGE_VERSION " by Davide Libenzi "; 27 | 28 | --------------------------------------------------------------------------------