dockerfile
This commit is contained in:
13
.dockerignore
Normal file
13
.dockerignore
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
log
|
||||||
|
tmp
|
||||||
|
ext
|
||||||
|
build
|
||||||
|
/bin
|
||||||
|
node_modules
|
||||||
|
profiler
|
||||||
|
.bundle
|
||||||
|
.vscode
|
||||||
|
launch.json
|
||||||
|
settings.json
|
||||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -4,6 +4,13 @@
|
|||||||
# or operating system, you probably want to add a global ignore instead:
|
# or operating system, you probably want to add a global ignore instead:
|
||||||
# git config --global core.excludesfile '~/.gitignore_global'
|
# git config --global core.excludesfile '~/.gitignore_global'
|
||||||
|
|
||||||
|
build
|
||||||
|
tmp
|
||||||
|
*.bundle
|
||||||
|
lib/xdiff
|
||||||
|
ext/xdiff/Makefile
|
||||||
|
ext/xdiff/xdiff
|
||||||
|
|
||||||
# Ignore bundler config.
|
# Ignore bundler config.
|
||||||
/.bundle
|
/.bundle
|
||||||
|
|
||||||
|
|||||||
67
Dockerfile
Normal file
67
Dockerfile
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
FROM ruby:3.2.0 AS native-gems
|
||||||
|
RUN rm -f /etc/apt/apt.conf.d/docker-clean; \
|
||||||
|
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
|
||||||
|
RUN \
|
||||||
|
--mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
|
cmake
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
RUN gem install bundler -v '2.4.5'
|
||||||
|
COPY gems gems
|
||||||
|
WORKDIR /usr/src/app/gems/xdiff-rb
|
||||||
|
RUN bundle install
|
||||||
|
RUN rake compile
|
||||||
|
WORKDIR /usr/src/app/gems/rb-bsdiff
|
||||||
|
RUN bundle install
|
||||||
|
RUN rake compile
|
||||||
|
|
||||||
|
# Primary image
|
||||||
|
FROM ruby:3.2.0
|
||||||
|
|
||||||
|
# set up nodejs 18.x deb repo
|
||||||
|
RUN mkdir -p /etc/apt/keyrings && \
|
||||||
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
|
||||||
|
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" \
|
||||||
|
| tee /etc/apt/sources.list.d/nodesource.list
|
||||||
|
|
||||||
|
# apt caching & install packages
|
||||||
|
RUN rm -f /etc/apt/apt.conf.d/docker-clean; \
|
||||||
|
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
|
||||||
|
RUN \
|
||||||
|
--mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install --no-install-recommends --no-install-suggests -y \
|
||||||
|
libblas-dev liblapack-dev libvips42 ca-certificates curl gnupg nodejs
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
RUN gem install bundler -v '2.4.6'
|
||||||
|
RUN bundle config --global frozen 1
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
# install gems
|
||||||
|
COPY Gemfile Gemfile.lock ./
|
||||||
|
COPY gems gems
|
||||||
|
RUN bundle install
|
||||||
|
|
||||||
|
# install js dependencies
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
RUN npm install -g yarn && \
|
||||||
|
rails yarn:install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
COPY --from=native-gems /usr/src/app/gems/xdiff-rb/lib/xdiff gems/xdiff-rb/lib/xdiff
|
||||||
|
COPY --from=native-gems /usr/src/app/gems/rb-bsdiff/lib gems/rb-bsdiff/lib
|
||||||
|
|
||||||
|
# precompile assets
|
||||||
|
ENV RAILS_ENV production
|
||||||
|
RUN rails assets:precompile
|
||||||
|
|
||||||
|
ENV RAILS_ENV worker
|
||||||
|
ENV proxy direct
|
||||||
|
# CMD ["bundle" "exec" "good_job" "--max-threads=2"]
|
||||||
|
CMD ["/bin/bash"]
|
||||||
4
Gemfile
4
Gemfile
@@ -82,11 +82,11 @@ group :test do
|
|||||||
gem "rspec-rails"
|
gem "rspec-rails"
|
||||||
end
|
end
|
||||||
|
|
||||||
gem "xdiff", path: "../xdiff-rb"
|
gem "xdiff", path: "gems/xdiff-rb"
|
||||||
|
|
||||||
# for legacy import
|
# for legacy import
|
||||||
gem "diffy"
|
gem "diffy"
|
||||||
gem "rb-bsdiff", path: "../rb-bsdiff"
|
gem "rb-bsdiff", path: "gems/rb-bsdiff"
|
||||||
|
|
||||||
gem "ruby-prof"
|
gem "ruby-prof"
|
||||||
gem "ruby-prof-speedscope"
|
gem "ruby-prof-speedscope"
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ GIT
|
|||||||
activerecord (>= 6)
|
activerecord (>= 6)
|
||||||
|
|
||||||
PATH
|
PATH
|
||||||
remote: ../rb-bsdiff
|
remote: gems/rb-bsdiff
|
||||||
specs:
|
specs:
|
||||||
rb-bsdiff (0.1.0)
|
rb-bsdiff (0.1.0)
|
||||||
|
|
||||||
PATH
|
PATH
|
||||||
remote: ../xdiff-rb
|
remote: gems/xdiff-rb
|
||||||
specs:
|
specs:
|
||||||
xdiff (0.0.1)
|
xdiff (0.0.1)
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ default: &default
|
|||||||
|
|
||||||
redux_prod: &redux_prod
|
redux_prod: &redux_prod
|
||||||
adapter: postgresql
|
adapter: postgresql
|
||||||
host: postgres.local
|
host: 10.166.33.171
|
||||||
port: 5432
|
port: 5432
|
||||||
database: redux_prod
|
database: redux_prod
|
||||||
username: scraper_redux
|
username: scraper_redux
|
||||||
@@ -37,7 +37,7 @@ redux_dev: &redux_dev
|
|||||||
|
|
||||||
legacy_prod: &legacy_prod
|
legacy_prod: &legacy_prod
|
||||||
adapter: postgresql
|
adapter: postgresql
|
||||||
host: postgres.local
|
host: 10.166.33.171
|
||||||
port: 5432
|
port: 5432
|
||||||
database: legacy_prod
|
database: legacy_prod
|
||||||
username: scraper_redux
|
username: scraper_redux
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ staging:
|
|||||||
bucket: "redux_scraper_dev"
|
bucket: "redux_scraper_dev"
|
||||||
|
|
||||||
production:
|
production:
|
||||||
host: "http://grafana.local:8086"
|
host: "http://10.166.33.66:8086"
|
||||||
bucket: "redux_scraper_prod"
|
bucket: "redux_scraper_prod"
|
||||||
|
|
||||||
worker:
|
worker:
|
||||||
host: "http://grafana.local:8086"
|
host: "http://10.166.33.66:8086"
|
||||||
bucket: "redux_scraper_prod"
|
bucket: "redux_scraper_prod"
|
||||||
|
|
||||||
test:
|
test:
|
||||||
host: "http://grafana.local:8086"
|
host: "http://10.166.33.66:8086"
|
||||||
bucket: "redux_scraper_test"
|
bucket: "redux_scraper_test"
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ default: &default
|
|||||||
gallery_dl: http://localhost:5001
|
gallery_dl: http://localhost:5001
|
||||||
|
|
||||||
proxy-1:
|
proxy-1:
|
||||||
http: http://proxy-1.local:9292
|
http: http://10.166.33.10:9292
|
||||||
gallery_dl: http://proxy-1.local:5001
|
gallery_dl: http://10.166.33.10:5001
|
||||||
|
|
||||||
dedipath-1:
|
dedipath-1:
|
||||||
http: http://10.200.0.6:9292
|
http: http://10.200.0.6:9292
|
||||||
|
|||||||
5
gems/rb-bsdiff/Gemfile
Normal file
5
gems/rb-bsdiff/Gemfile
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
||||||
|
|
||||||
|
gemspec
|
||||||
24
gems/rb-bsdiff/Gemfile.lock
Normal file
24
gems/rb-bsdiff/Gemfile.lock
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
PATH
|
||||||
|
remote: .
|
||||||
|
specs:
|
||||||
|
rb-bsdiff (0.1.0)
|
||||||
|
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
minitest (5.18.0)
|
||||||
|
rake (13.0.6)
|
||||||
|
rake-compiler (1.2.1)
|
||||||
|
rake
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
arm64-darwin-21
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
minitest
|
||||||
|
rake (>= 1.9.1)
|
||||||
|
rake-compiler (>= 0.8.3)
|
||||||
|
rb-bsdiff!
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.4.1
|
||||||
27
gems/rb-bsdiff/LICENSE
Normal file
27
gems/rb-bsdiff/LICENSE
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2012, Todd Fisher
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. All advertising materials mentioning features or use of this software
|
||||||
|
must display the following acknowledgement:
|
||||||
|
This product includes software developed by the <organization>.
|
||||||
|
4. Neither the name of the <organization> nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
6
gems/rb-bsdiff/README
Normal file
6
gems/rb-bsdiff/README
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Ruby bindings to bsdiff and bspatch
|
||||||
|
|
||||||
|
BSDiff.diff('ext/b0', 'ext/b1', 'p0')
|
||||||
|
|
||||||
|
# apply patch to bspatch.o as bspatch2.o
|
||||||
|
BSDiff.patch('ext/b0', 'b3', 'p0')
|
||||||
25
gems/rb-bsdiff/Rakefile
Normal file
25
gems/rb-bsdiff/Rakefile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
require "rake/clean"
|
||||||
|
require "rake/testtask"
|
||||||
|
require "rake/extensiontask"
|
||||||
|
|
||||||
|
gemspec = Gem::Specification.load("rb-bsdiff.gemspec")
|
||||||
|
Rake::ExtensionTask.new do |ext|
|
||||||
|
ext.name = "bsdiff"
|
||||||
|
ext.source_pattern = "*.{c,cc,h}"
|
||||||
|
ext.ext_dir = "ext"
|
||||||
|
ext.lib_dir = "lib"
|
||||||
|
ext.gem_spec = gemspec
|
||||||
|
end
|
||||||
|
task :default => [:compile, :test]
|
||||||
|
|
||||||
|
CLEAN.include([
|
||||||
|
"pkg/",
|
||||||
|
"tmp/",
|
||||||
|
"ext/Makefile",
|
||||||
|
"lib/bsdiff.so",
|
||||||
|
])
|
||||||
|
|
||||||
|
Rake::TestTask.new(:test) do |t|
|
||||||
|
t.libs << "lib"
|
||||||
|
t.test_files = FileList["test.rb"]
|
||||||
|
end
|
||||||
BIN
gems/rb-bsdiff/ext/b0
Normal file
BIN
gems/rb-bsdiff/ext/b0
Normal file
Binary file not shown.
BIN
gems/rb-bsdiff/ext/b1
Normal file
BIN
gems/rb-bsdiff/ext/b1
Normal file
Binary file not shown.
417
gems/rb-bsdiff/ext/bsdiff.c
Normal file
417
gems/rb-bsdiff/ext/bsdiff.c
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright 2003-2005 Colin Percival
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted providing that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c,v 1.1 2005/08/06 01:59:05 cperciva Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <bzlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <ruby.h>
|
||||||
|
|
||||||
|
#define MIN(x,y) (((x)<(y)) ? (x) : (y))
|
||||||
|
|
||||||
|
static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h)
|
||||||
|
{
|
||||||
|
off_t i,j,k,x,tmp,jj,kk;
|
||||||
|
|
||||||
|
if(len<16) {
|
||||||
|
for(k=start;k<start+len;k+=j) {
|
||||||
|
j=1;x=V[I[k]+h];
|
||||||
|
for(i=1;k+i<start+len;i++) {
|
||||||
|
if(V[I[k+i]+h]<x) {
|
||||||
|
x=V[I[k+i]+h];
|
||||||
|
j=0;
|
||||||
|
};
|
||||||
|
if(V[I[k+i]+h]==x) {
|
||||||
|
tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
|
||||||
|
j++;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
|
||||||
|
if(j==1) I[k]=-1;
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
x=V[I[start+len/2]+h];
|
||||||
|
jj=0;kk=0;
|
||||||
|
for(i=start;i<start+len;i++) {
|
||||||
|
if(V[I[i]+h]<x) jj++;
|
||||||
|
if(V[I[i]+h]==x) kk++;
|
||||||
|
};
|
||||||
|
jj+=start;kk+=jj;
|
||||||
|
|
||||||
|
i=start;j=0;k=0;
|
||||||
|
while(i<jj) {
|
||||||
|
if(V[I[i]+h]<x) {
|
||||||
|
i++;
|
||||||
|
} else if(V[I[i]+h]==x) {
|
||||||
|
tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
|
||||||
|
k++;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
while(jj+j<kk) {
|
||||||
|
if(V[I[jj+j]+h]==x) {
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
|
||||||
|
k++;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if(jj>start) split(I,V,start,jj-start,h);
|
||||||
|
|
||||||
|
for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
|
||||||
|
if(jj==kk-1) I[jj]=-1;
|
||||||
|
|
||||||
|
if(start+len>kk) split(I,V,kk,start+len-kk,h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize)
|
||||||
|
{
|
||||||
|
off_t buckets[256];
|
||||||
|
off_t i,h,len;
|
||||||
|
|
||||||
|
for(i=0;i<256;i++) buckets[i]=0;
|
||||||
|
for(i=0;i<oldsize;i++) buckets[old[i]]++;
|
||||||
|
for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
|
||||||
|
for(i=255;i>0;i--) buckets[i]=buckets[i-1];
|
||||||
|
buckets[0]=0;
|
||||||
|
|
||||||
|
for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
|
||||||
|
I[0]=oldsize;
|
||||||
|
for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
|
||||||
|
V[oldsize]=0;
|
||||||
|
for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
|
||||||
|
I[0]=-1;
|
||||||
|
|
||||||
|
for(h=1;I[0]!=-(oldsize+1);h+=h) {
|
||||||
|
len=0;
|
||||||
|
for(i=0;i<oldsize+1;) {
|
||||||
|
if(I[i]<0) {
|
||||||
|
len-=I[i];
|
||||||
|
i-=I[i];
|
||||||
|
} else {
|
||||||
|
if(len) I[i-len]=-len;
|
||||||
|
len=V[I[i]]+1-i;
|
||||||
|
split(I,V,i,len,h);
|
||||||
|
i+=len;
|
||||||
|
len=0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if(len) I[i-len]=-len;
|
||||||
|
};
|
||||||
|
|
||||||
|
for(i=0;i<oldsize+1;i++) I[V[i]]=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static off_t matchlen(u_char *old,off_t oldsize,u_char *new,off_t newsize)
|
||||||
|
{
|
||||||
|
off_t i;
|
||||||
|
|
||||||
|
for(i=0;(i<oldsize)&&(i<newsize);i++)
|
||||||
|
if(old[i]!=new[i]) break;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static off_t search(off_t *I,u_char *old,off_t oldsize,
|
||||||
|
u_char *new,off_t newsize,off_t st,off_t en,off_t *pos)
|
||||||
|
{
|
||||||
|
off_t x,y;
|
||||||
|
|
||||||
|
if(en-st<2) {
|
||||||
|
x=matchlen(old+I[st],oldsize-I[st],new,newsize);
|
||||||
|
y=matchlen(old+I[en],oldsize-I[en],new,newsize);
|
||||||
|
|
||||||
|
if(x>y) {
|
||||||
|
*pos=I[st];
|
||||||
|
return x;
|
||||||
|
} else {
|
||||||
|
*pos=I[en];
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
x=st+(en-st)/2;
|
||||||
|
if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
|
||||||
|
return search(I,old,oldsize,new,newsize,x,en,pos);
|
||||||
|
} else {
|
||||||
|
return search(I,old,oldsize,new,newsize,st,x,pos);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void offtout(off_t x,u_char *buf)
|
||||||
|
{
|
||||||
|
off_t y;
|
||||||
|
|
||||||
|
if(x<0) y=-x; else y=x;
|
||||||
|
|
||||||
|
buf[0]=y%256;y-=buf[0];
|
||||||
|
y=y/256;buf[1]=y%256;y-=buf[1];
|
||||||
|
y=y/256;buf[2]=y%256;y-=buf[2];
|
||||||
|
y=y/256;buf[3]=y%256;y-=buf[3];
|
||||||
|
y=y/256;buf[4]=y%256;y-=buf[4];
|
||||||
|
y=y/256;buf[5]=y%256;y-=buf[5];
|
||||||
|
y=y/256;buf[6]=y%256;y-=buf[6];
|
||||||
|
y=y/256;buf[7]=y%256;
|
||||||
|
|
||||||
|
if(x<0) buf[7]|=0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a patch file from oldfile diff'ed by newfile */
|
||||||
|
int bsdiff_files(const char *oldfile, const char *newfile, const char *patchfile)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
u_char *old,*new;
|
||||||
|
off_t oldsize,newsize;
|
||||||
|
off_t *I,*V;
|
||||||
|
off_t scan,pos=0,len;
|
||||||
|
off_t lastscan,lastpos,lastoffset;
|
||||||
|
off_t oldscore,scsc;
|
||||||
|
off_t s,Sf,lenf,Sb,lenb;
|
||||||
|
off_t overlap,Ss,lens;
|
||||||
|
off_t i;
|
||||||
|
off_t dblen,eblen;
|
||||||
|
u_char *db,*eb;
|
||||||
|
u_char buf[8];
|
||||||
|
u_char header[32];
|
||||||
|
FILE * pf;
|
||||||
|
BZFILE * pfbz2;
|
||||||
|
int bz2err;
|
||||||
|
|
||||||
|
/* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
|
||||||
|
that we never try to malloc(0) and get a NULL pointer */
|
||||||
|
if(((fd=open(oldfile,O_RDONLY,0))<0) ||
|
||||||
|
((oldsize=lseek(fd,0,SEEK_END))==-1) ||
|
||||||
|
((old=malloc(oldsize+1))==NULL) ||
|
||||||
|
(lseek(fd,0,SEEK_SET)!=0) ||
|
||||||
|
(read(fd,old,oldsize)!=oldsize) ||
|
||||||
|
(close(fd)==-1)) {
|
||||||
|
rb_raise(rb_eRuntimeError, "%s",oldfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((I=malloc((oldsize+1)*sizeof(off_t)))==NULL) ||
|
||||||
|
((V=malloc((oldsize+1)*sizeof(off_t)))==NULL)) rb_raise(rb_eRuntimeError, "malloc error");
|
||||||
|
|
||||||
|
qsufsort(I,V,old,oldsize);
|
||||||
|
|
||||||
|
free(V);
|
||||||
|
|
||||||
|
/* Allocate newsize+1 bytes instead of newsize bytes to ensure
|
||||||
|
that we never try to malloc(0) and get a NULL pointer */
|
||||||
|
if(((fd=open(newfile,O_RDONLY,0))<0) ||
|
||||||
|
((newsize=lseek(fd,0,SEEK_END))==-1) ||
|
||||||
|
((new=malloc(newsize+1))==NULL) ||
|
||||||
|
(lseek(fd,0,SEEK_SET)!=0) ||
|
||||||
|
(read(fd,new,newsize)!=newsize) ||
|
||||||
|
(close(fd)==-1)) rb_raise(rb_eRuntimeError, "%s",newfile);
|
||||||
|
|
||||||
|
if(((db=malloc(newsize+1))==NULL) ||
|
||||||
|
((eb=malloc(newsize+1))==NULL)) rb_raise(rb_eRuntimeError,"malloc error");
|
||||||
|
dblen=0;
|
||||||
|
eblen=0;
|
||||||
|
|
||||||
|
/* Create the patch file */
|
||||||
|
if ((pf = fopen(patchfile, "w")) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "%s", patchfile);
|
||||||
|
|
||||||
|
/* Header is
|
||||||
|
0 8 "BSDIFF40"
|
||||||
|
8 8 length of bzip2ed ctrl block
|
||||||
|
16 8 length of bzip2ed diff block
|
||||||
|
24 8 length of new file */
|
||||||
|
/* File is
|
||||||
|
0 32 Header
|
||||||
|
32 ?? Bzip2ed ctrl block
|
||||||
|
?? ?? Bzip2ed diff block
|
||||||
|
?? ?? Bzip2ed extra block */
|
||||||
|
memcpy(header,"BSDIFF40",8);
|
||||||
|
offtout(0, header + 8);
|
||||||
|
offtout(0, header + 16);
|
||||||
|
offtout(newsize, header + 24);
|
||||||
|
if (fwrite(header, 32, 1, pf) != 1)
|
||||||
|
rb_raise(rb_eRuntimeError, "fwrite(%s)", patchfile);
|
||||||
|
|
||||||
|
/* Compute the differences, writing ctrl as we go */
|
||||||
|
if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
|
||||||
|
scan=0;len=0;
|
||||||
|
lastscan=0;lastpos=0;lastoffset=0;
|
||||||
|
while(scan<newsize) {
|
||||||
|
oldscore=0;
|
||||||
|
|
||||||
|
for(scsc=scan+=len;scan<newsize;scan++) {
|
||||||
|
len=search(I,old,oldsize,new+scan,newsize-scan,
|
||||||
|
0,oldsize,&pos);
|
||||||
|
|
||||||
|
for(;scsc<scan+len;scsc++)
|
||||||
|
if((scsc+lastoffset<oldsize) &&
|
||||||
|
(old[scsc+lastoffset] == new[scsc]))
|
||||||
|
oldscore++;
|
||||||
|
|
||||||
|
if(((len==oldscore) && (len!=0)) ||
|
||||||
|
(len>oldscore+8)) break;
|
||||||
|
|
||||||
|
if((scan+lastoffset<oldsize) &&
|
||||||
|
(old[scan+lastoffset] == new[scan]))
|
||||||
|
oldscore--;
|
||||||
|
};
|
||||||
|
|
||||||
|
if((len!=oldscore) || (scan==newsize)) {
|
||||||
|
s=0;Sf=0;lenf=0;
|
||||||
|
for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
|
||||||
|
if(old[lastpos+i]==new[lastscan+i]) s++;
|
||||||
|
i++;
|
||||||
|
if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
|
||||||
|
};
|
||||||
|
|
||||||
|
lenb=0;
|
||||||
|
if(scan<newsize) {
|
||||||
|
s=0;Sb=0;
|
||||||
|
for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
|
||||||
|
if(old[pos-i]==new[scan-i]) s++;
|
||||||
|
if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if(lastscan+lenf>scan-lenb) {
|
||||||
|
overlap=(lastscan+lenf)-(scan-lenb);
|
||||||
|
s=0;Ss=0;lens=0;
|
||||||
|
for(i=0;i<overlap;i++) {
|
||||||
|
if(new[lastscan+lenf-overlap+i]==
|
||||||
|
old[lastpos+lenf-overlap+i]) s++;
|
||||||
|
if(new[scan-lenb+i]==
|
||||||
|
old[pos-lenb+i]) s--;
|
||||||
|
if(s>Ss) { Ss=s; lens=i+1; };
|
||||||
|
};
|
||||||
|
|
||||||
|
lenf+=lens-overlap;
|
||||||
|
lenb-=lens;
|
||||||
|
};
|
||||||
|
|
||||||
|
for(i=0;i<lenf;i++)
|
||||||
|
db[dblen+i]=new[lastscan+i]-old[lastpos+i];
|
||||||
|
for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
|
||||||
|
eb[eblen+i]=new[lastscan+lenf+i];
|
||||||
|
|
||||||
|
dblen+=lenf;
|
||||||
|
eblen+=(scan-lenb)-(lastscan+lenf);
|
||||||
|
|
||||||
|
offtout(lenf,buf);
|
||||||
|
BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
|
||||||
|
if (bz2err != BZ_OK)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWrite, bz2err = %d", bz2err);
|
||||||
|
|
||||||
|
offtout((scan-lenb)-(lastscan+lenf),buf);
|
||||||
|
BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
|
||||||
|
if (bz2err != BZ_OK)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWrite, bz2err = %d", bz2err);
|
||||||
|
|
||||||
|
offtout((pos-lenb)-(lastpos+lenf),buf);
|
||||||
|
BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
|
||||||
|
if (bz2err != BZ_OK)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWrite, bz2err = %d", bz2err);
|
||||||
|
|
||||||
|
lastscan=scan-lenb;
|
||||||
|
lastpos=pos-lenb;
|
||||||
|
lastoffset=pos-scan;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
|
||||||
|
if (bz2err != BZ_OK)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWriteClose, bz2err = %d", bz2err);
|
||||||
|
|
||||||
|
/* Compute size of compressed ctrl data */
|
||||||
|
if ((len = ftello(pf)) == -1)
|
||||||
|
rb_raise(rb_eRuntimeError, "ftello");
|
||||||
|
offtout(len-32, header + 8);
|
||||||
|
|
||||||
|
/* Write compressed diff data */
|
||||||
|
if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
|
||||||
|
BZ2_bzWrite(&bz2err, pfbz2, db, dblen);
|
||||||
|
if (bz2err != BZ_OK)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWrite, bz2err = %d", bz2err);
|
||||||
|
BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
|
||||||
|
if (bz2err != BZ_OK)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWriteClose, bz2err = %d", bz2err);
|
||||||
|
|
||||||
|
/* Compute size of compressed diff data */
|
||||||
|
if ((newsize = ftello(pf)) == -1)
|
||||||
|
rb_raise(rb_eRuntimeError, "ftello");
|
||||||
|
offtout(newsize - len, header + 16);
|
||||||
|
|
||||||
|
/* Write compressed extra data */
|
||||||
|
if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
|
||||||
|
BZ2_bzWrite(&bz2err, pfbz2, eb, eblen);
|
||||||
|
if (bz2err != BZ_OK)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWrite, bz2err = %d", bz2err);
|
||||||
|
BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
|
||||||
|
if (bz2err != BZ_OK)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzWriteClose, bz2err = %d", bz2err);
|
||||||
|
|
||||||
|
/* Seek to the beginning, write the header, and close the file */
|
||||||
|
if (fseeko(pf, 0, SEEK_SET))
|
||||||
|
rb_raise(rb_eRuntimeError, "fseeko");
|
||||||
|
if (fwrite(header, 32, 1, pf) != 1)
|
||||||
|
rb_raise(rb_eRuntimeError, "fwrite(%s)", patchfile);
|
||||||
|
if (fclose(pf))
|
||||||
|
rb_raise(rb_eRuntimeError, "fclose");
|
||||||
|
|
||||||
|
/* Free the memory we used */
|
||||||
|
free(db);
|
||||||
|
free(eb);
|
||||||
|
free(I);
|
||||||
|
free(old);
|
||||||
|
free(new);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create a patch buffer from oldbfufer diff'ed by newbfufer
|
||||||
|
*
|
||||||
|
* same as bsdiff_files, except works in memory
|
||||||
|
*
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
//char* bsdiff_buffer(const char *oldbuffer, const char *newbuffer)
|
||||||
|
//{
|
||||||
|
//}
|
||||||
6
gems/rb-bsdiff/ext/bsdiff.h
Normal file
6
gems/rb-bsdiff/ext/bsdiff.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef RB_BSDIFF_H
|
||||||
|
#define RB_BSDIFF_H
|
||||||
|
|
||||||
|
int bsdiff_files(const char *oldfile, const char *newfile, const char *patchfile);
|
||||||
|
|
||||||
|
#endif
|
||||||
203
gems/rb-bsdiff/ext/bspatch.c
Normal file
203
gems/rb-bsdiff/ext/bspatch.c
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright 2003-2005 Colin Percival
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted providing that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <bzlib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <ruby.h>
|
||||||
|
|
||||||
|
static off_t offtin(u_char *buf)
|
||||||
|
{
|
||||||
|
off_t y;
|
||||||
|
|
||||||
|
y=buf[7]&0x7F;
|
||||||
|
y=y*256;y+=buf[6];
|
||||||
|
y=y*256;y+=buf[5];
|
||||||
|
y=y*256;y+=buf[4];
|
||||||
|
y=y*256;y+=buf[3];
|
||||||
|
y=y*256;y+=buf[2];
|
||||||
|
y=y*256;y+=buf[1];
|
||||||
|
y=y*256;y+=buf[0];
|
||||||
|
|
||||||
|
if(buf[7]&0x80) y=-y;
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bspatch_files(const char *oldfile, const char *newfile, const char *patchfile)
|
||||||
|
{
|
||||||
|
FILE * f, * cpf, * dpf, * epf;
|
||||||
|
BZFILE * cpfbz2, * dpfbz2, * epfbz2;
|
||||||
|
int cbz2err, dbz2err, ebz2err;
|
||||||
|
int fd;
|
||||||
|
ssize_t oldsize,newsize;
|
||||||
|
ssize_t bzctrllen,bzdatalen;
|
||||||
|
u_char header[32],buf[8];
|
||||||
|
u_char *old, *new;
|
||||||
|
off_t oldpos,newpos;
|
||||||
|
off_t ctrl[3];
|
||||||
|
off_t lenread;
|
||||||
|
off_t i;
|
||||||
|
|
||||||
|
/* Open patch file */
|
||||||
|
if ((f = fopen(patchfile, "r")) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "fopen(%s)", patchfile);
|
||||||
|
|
||||||
|
/*
|
||||||
|
File format:
|
||||||
|
0 8 "BSDIFF40"
|
||||||
|
8 8 X
|
||||||
|
16 8 Y
|
||||||
|
24 8 sizeof(newfile)
|
||||||
|
32 X bzip2(control block)
|
||||||
|
32+X Y bzip2(diff block)
|
||||||
|
32+X+Y ??? bzip2(extra block)
|
||||||
|
with control block a set of triples (x,y,z) meaning "add x bytes
|
||||||
|
from oldfile to x bytes from the diff block; copy y bytes from the
|
||||||
|
extra block; seek forwards in oldfile by z bytes".
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Read header */
|
||||||
|
if (fread(header, 1, 32, f) < 32) {
|
||||||
|
if (feof(f))
|
||||||
|
rb_raise(rb_eRuntimeError,"Corrupt patch\n");
|
||||||
|
rb_raise(rb_eRuntimeError, "fread(%s)", patchfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for appropriate magic */
|
||||||
|
if (memcmp(header, "BSDIFF40", 8) != 0)
|
||||||
|
rb_raise(rb_eRuntimeError, "Corrupt patch\n");
|
||||||
|
|
||||||
|
/* Read lengths from header */
|
||||||
|
bzctrllen=offtin(header+8);
|
||||||
|
bzdatalen=offtin(header+16);
|
||||||
|
newsize=offtin(header+24);
|
||||||
|
if((bzctrllen<0) || (bzdatalen<0) || (newsize<0))
|
||||||
|
rb_raise(rb_eRuntimeError,"Corrupt patch\n");
|
||||||
|
|
||||||
|
/* Close patch file and re-open it via libbzip2 at the right places */
|
||||||
|
if (fclose(f))
|
||||||
|
rb_raise(rb_eRuntimeError, "fclose(%s)", patchfile);
|
||||||
|
if ((cpf = fopen(patchfile, "r")) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "fopen(%s)", patchfile);
|
||||||
|
if (fseeko(cpf, 32, SEEK_SET))
|
||||||
|
rb_raise(rb_eRuntimeError, "fseeko(%s, %lld)", patchfile,
|
||||||
|
(long long)32);
|
||||||
|
if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
|
||||||
|
if ((dpf = fopen(patchfile, "r")) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "fopen(%s)", patchfile);
|
||||||
|
if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
|
||||||
|
rb_raise(rb_eRuntimeError, "fseeko(%s, %lld)", patchfile,
|
||||||
|
(long long)(32 + bzctrllen));
|
||||||
|
if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
|
||||||
|
if ((epf = fopen(patchfile, "r")) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "fopen(%s)", patchfile);
|
||||||
|
if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
|
||||||
|
rb_raise(rb_eRuntimeError, "fseeko(%s, %lld)", patchfile,
|
||||||
|
(long long)(32 + bzctrllen + bzdatalen));
|
||||||
|
if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
|
||||||
|
rb_raise(rb_eRuntimeError, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
|
||||||
|
|
||||||
|
if(((fd=open(oldfile,O_RDONLY,0))<0) ||
|
||||||
|
((oldsize=lseek(fd,0,SEEK_END))==-1) ||
|
||||||
|
((old=malloc(oldsize+1))==NULL) ||
|
||||||
|
(lseek(fd,0,SEEK_SET)!=0) ||
|
||||||
|
(read(fd,old,oldsize)!=oldsize) ||
|
||||||
|
(close(fd)==-1)) rb_raise(rb_eRuntimeError,"%s",oldfile);
|
||||||
|
if((new=malloc(newsize+1))==NULL) rb_raise(rb_eRuntimeError,"malloc");
|
||||||
|
|
||||||
|
oldpos=0;newpos=0;
|
||||||
|
while(newpos<newsize) {
|
||||||
|
/* Read control data */
|
||||||
|
for(i=0;i<=2;i++) {
|
||||||
|
lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
|
||||||
|
if ((lenread < 8) || ((cbz2err != BZ_OK) &&
|
||||||
|
(cbz2err != BZ_STREAM_END)))
|
||||||
|
rb_raise(rb_eRuntimeError, "Corrupt patch\n");
|
||||||
|
ctrl[i]=offtin(buf);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Sanity-check */
|
||||||
|
if(newpos+ctrl[0]>newsize)
|
||||||
|
rb_raise(rb_eRuntimeError,"Corrupt patch\n");
|
||||||
|
|
||||||
|
/* Read diff string */
|
||||||
|
lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
|
||||||
|
if ((lenread < ctrl[0]) ||
|
||||||
|
((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
|
||||||
|
rb_raise(rb_eRuntimeError, "Corrupt patch\n");
|
||||||
|
|
||||||
|
/* Add old data to diff string */
|
||||||
|
for(i=0;i<ctrl[0];i++)
|
||||||
|
if((oldpos+i>=0) && (oldpos+i<oldsize))
|
||||||
|
new[newpos+i]+=old[oldpos+i];
|
||||||
|
|
||||||
|
/* Adjust pointers */
|
||||||
|
newpos+=ctrl[0];
|
||||||
|
oldpos+=ctrl[0];
|
||||||
|
|
||||||
|
/* Sanity-check */
|
||||||
|
if(newpos+ctrl[1]>newsize)
|
||||||
|
rb_raise(rb_eRuntimeError,"Corrupt patch\n");
|
||||||
|
|
||||||
|
/* Read extra string */
|
||||||
|
lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
|
||||||
|
if ((lenread < ctrl[1]) ||
|
||||||
|
((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
|
||||||
|
rb_raise(rb_eRuntimeError, "Corrupt patch\n");
|
||||||
|
|
||||||
|
/* Adjust pointers */
|
||||||
|
newpos+=ctrl[1];
|
||||||
|
oldpos+=ctrl[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Clean up the bzip2 reads */
|
||||||
|
BZ2_bzReadClose(&cbz2err, cpfbz2);
|
||||||
|
BZ2_bzReadClose(&dbz2err, dpfbz2);
|
||||||
|
BZ2_bzReadClose(&ebz2err, epfbz2);
|
||||||
|
if (fclose(cpf) || fclose(dpf) || fclose(epf))
|
||||||
|
rb_raise(rb_eRuntimeError, "fclose(%s)", patchfile);
|
||||||
|
|
||||||
|
/* Write the new file */
|
||||||
|
if(((fd=open(newfile,O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
|
||||||
|
(write(fd,new,newsize)!=newsize) || (close(fd)==-1))
|
||||||
|
rb_raise(rb_eRuntimeError,"%s",newfile);
|
||||||
|
|
||||||
|
free(new);
|
||||||
|
free(old);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
6
gems/rb-bsdiff/ext/bspatch.h
Normal file
6
gems/rb-bsdiff/ext/bspatch.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef BS_PATCH_H
|
||||||
|
#define BS_PATCH_H
|
||||||
|
|
||||||
|
int bspatch_files(const char *oldfile, const char *newfile, const char *patchfile);
|
||||||
|
|
||||||
|
#endif
|
||||||
10
gems/rb-bsdiff/ext/extconf.rb
Normal file
10
gems/rb-bsdiff/ext/extconf.rb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
require 'mkmf'
|
||||||
|
|
||||||
|
dir_config('bsdiff')
|
||||||
|
fail unless have_header('unistd.h')
|
||||||
|
fail unless have_header('bzlib.h')
|
||||||
|
fail unless have_library('bz2')
|
||||||
|
fail unless have_func('BZ2_bzWrite','bzlib.h')
|
||||||
|
fail unless have_macro('BZ_OK','bzlib.h')
|
||||||
|
create_header('bsdiff_config.h')
|
||||||
|
create_makefile('bsdiff')
|
||||||
30
gems/rb-bsdiff/ext/rb_bsdiff.c
Normal file
30
gems/rb-bsdiff/ext/rb_bsdiff.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include <ruby.h>
|
||||||
|
#include "bsdiff.h"
|
||||||
|
#include "bspatch.h"
|
||||||
|
|
||||||
|
VALUE BSDiff;
|
||||||
|
|
||||||
|
static VALUE bsdiff_diff(VALUE mod, VALUE oldfile, VALUE newfile, VALUE patchfile)
|
||||||
|
{
|
||||||
|
if( bsdiff_files(StringValuePtr(oldfile), StringValuePtr(newfile), StringValuePtr(patchfile)) ) {
|
||||||
|
return Qfalse;
|
||||||
|
}
|
||||||
|
return Qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE bsdiff_patch(VALUE mod, VALUE oldfile, VALUE newfile, VALUE patchfile)
|
||||||
|
{
|
||||||
|
if( bspatch_files(StringValuePtr(oldfile), StringValuePtr(newfile), StringValuePtr(patchfile)) ) {
|
||||||
|
return Qfalse;
|
||||||
|
}
|
||||||
|
return Qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main entry point */
|
||||||
|
void Init_bsdiff()
|
||||||
|
{
|
||||||
|
BSDiff = rb_define_module("BSDiff");
|
||||||
|
|
||||||
|
rb_define_singleton_method(BSDiff, "diff", bsdiff_diff, 3);
|
||||||
|
rb_define_singleton_method(BSDiff, "patch", bsdiff_patch, 3);
|
||||||
|
}
|
||||||
33
gems/rb-bsdiff/rb-bsdiff.gemspec
Normal file
33
gems/rb-bsdiff/rb-bsdiff.gemspec
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
Gem::Specification.new do |s|
|
||||||
|
s.name = %q{rb-bsdiff}
|
||||||
|
s.version = "0.1.0"
|
||||||
|
|
||||||
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||||
|
s.authors = ["Todd Fisher"]
|
||||||
|
s.date = %q{2009-07-19}
|
||||||
|
s.description = %q{Ruby bindings to bindary diff tools bsdiff and bspatch}
|
||||||
|
s.email = %q{todd.fisher@gmail.com}
|
||||||
|
s.extensions = ["ext/extconf.rb"]
|
||||||
|
s.files = [
|
||||||
|
"README", "Rakefile", "rb-bsdiff.gemspec", "test.rb", "ext/b0",
|
||||||
|
"ext/b1", "ext/bsdiff.c", "ext/bsdiff.h", "ext/bspatch.c",
|
||||||
|
"ext/bspatch.h", "ext/extconf.rb", "ext/rb_bsdiff.c",
|
||||||
|
]
|
||||||
|
s.homepage = %q{http://github.com/taf2/rb-bsdiff}
|
||||||
|
s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
|
||||||
|
s.require_paths = ["lib"]
|
||||||
|
s.rubyforge_project = %q{rb-bsdiff}
|
||||||
|
s.rubygems_version = %q{1.3.0}
|
||||||
|
s.summary = %q{Ruby bindings to bindary diff tools bsdiff and bspatch}
|
||||||
|
|
||||||
|
if s.respond_to? :specification_version
|
||||||
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||||
|
s.specification_version = 2
|
||||||
|
end
|
||||||
|
|
||||||
|
s.add_development_dependency "rake", ">= 1.9.1"
|
||||||
|
s.add_development_dependency "rake-compiler", ">= 0.8.3"
|
||||||
|
s.add_development_dependency "minitest"
|
||||||
|
end
|
||||||
35
gems/rb-bsdiff/test.rb
Normal file
35
gems/rb-bsdiff/test.rb
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
require "openssl"
|
||||||
|
require "test/unit"
|
||||||
|
require "bsdiff"
|
||||||
|
|
||||||
|
class TestPatch < Test::Unit::TestCase
|
||||||
|
def setup
|
||||||
|
File.unlink("b3") if File.exist?("b3")
|
||||||
|
File.unlink("p0") if File.exist?("p0")
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
File.unlink("b3") if File.exist?("b3")
|
||||||
|
File.unlink("p0") if File.exist?("p0")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_diff_and_patch
|
||||||
|
|
||||||
|
#../bsdiff b0 b1 p0
|
||||||
|
#../bspatch b0 b3 p0
|
||||||
|
|
||||||
|
b0_chk = OpenSSL::Digest::MD5.hexdigest(File.read("ext/b0"))
|
||||||
|
b1_chk = OpenSSL::Digest::MD5.hexdigest(File.read("ext/b1"))
|
||||||
|
|
||||||
|
# create patch file from bspatch.o to bsdiff.o
|
||||||
|
BSDiff.diff("ext/b0", "ext/b1", "p0")
|
||||||
|
|
||||||
|
# apply patch to bspatch.o as bspatch2.o
|
||||||
|
BSDiff.patch("ext/b0", "b3", "p0")
|
||||||
|
|
||||||
|
b3_chk = OpenSSL::Digest::MD5.hexdigest(File.read("b3"))
|
||||||
|
|
||||||
|
# bspatch2.o should equal bsdiff.o
|
||||||
|
assert_equal(b1_chk, b3_chk)
|
||||||
|
end
|
||||||
|
end
|
||||||
5
gems/xdiff-rb/Gemfile
Normal file
5
gems/xdiff-rb/Gemfile
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
||||||
|
|
||||||
|
gemspec
|
||||||
26
gems/xdiff-rb/Gemfile.lock
Normal file
26
gems/xdiff-rb/Gemfile.lock
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
PATH
|
||||||
|
remote: .
|
||||||
|
specs:
|
||||||
|
xdiff (0.0.1)
|
||||||
|
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
minitest (5.17.0)
|
||||||
|
rake (13.0.6)
|
||||||
|
rake-compiler (1.2.1)
|
||||||
|
rake
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
aarch64-linux
|
||||||
|
arm64-darwin-22
|
||||||
|
x86_64-linux
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
minitest
|
||||||
|
rake (>= 1.9.1)
|
||||||
|
rake-compiler (>= 0.8.3)
|
||||||
|
xdiff!
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.4.5
|
||||||
34
gems/xdiff-rb/Rakefile
Normal file
34
gems/xdiff-rb/Rakefile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
require "bundler/gem_tasks"
|
||||||
|
require "rake/testtask"
|
||||||
|
require "rake/extensiontask"
|
||||||
|
require "rake/clean"
|
||||||
|
|
||||||
|
Rake::TestTask.new(:test) do |t|
|
||||||
|
t.libs << "test"
|
||||||
|
t.libs << "lib"
|
||||||
|
t.test_files = FileList["test/**/*_test.rb"]
|
||||||
|
end
|
||||||
|
|
||||||
|
gemspec = Gem::Specification.load("xdiff.gemspec")
|
||||||
|
Rake::ExtensionTask.new do |ext|
|
||||||
|
ext.name = "extension"
|
||||||
|
ext.source_pattern = "*.{c,cc,h}"
|
||||||
|
ext.ext_dir = "ext/xdiff"
|
||||||
|
ext.lib_dir = "lib/xdiff"
|
||||||
|
ext.gem_spec = gemspec
|
||||||
|
end
|
||||||
|
|
||||||
|
task :benchmark_patch do
|
||||||
|
require "xdiff"
|
||||||
|
XDiff::Native.patch(nil, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
task :default => [:compile, :test]
|
||||||
|
CLEAN.include([
|
||||||
|
"pkg/",
|
||||||
|
"tmp/",
|
||||||
|
"ext/xdiff/xdiff",
|
||||||
|
"ext/xdiff/xdiff_build",
|
||||||
|
"ext/xdiff/Makefile",
|
||||||
|
"lib/xdiff/*.so",
|
||||||
|
])
|
||||||
57
gems/xdiff-rb/ext/xdiff/extconf.rb
Normal file
57
gems/xdiff-rb/ext/xdiff/extconf.rb
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
require "mkmf"
|
||||||
|
require "timeout"
|
||||||
|
|
||||||
|
BASE_DIR = File.absolute_path(File.dirname(__FILE__))
|
||||||
|
|
||||||
|
# append_cppflags "-std=c++17 -O3"
|
||||||
|
# append_cppflags "-I#{BASE_DIR}/xdiff/xdiff"
|
||||||
|
$CXXFLAGS += " -std=c++17 -O3 "
|
||||||
|
$CXXFLAGS += " -I#{BASE_DIR}/xdiff/xdiff "
|
||||||
|
|
||||||
|
if !find_executable("cmake")
|
||||||
|
abort "ERROR: cmake is required."
|
||||||
|
end
|
||||||
|
|
||||||
|
if !find_executable("make")
|
||||||
|
abort "ERROR: make is required."
|
||||||
|
end
|
||||||
|
|
||||||
|
def sys(cmd)
|
||||||
|
puts "(#{Dir.pwd}) -- #{cmd}"
|
||||||
|
unless ret = xsystem(cmd)
|
||||||
|
raise "ERROR: '#{cmd}' failed"
|
||||||
|
end
|
||||||
|
ret
|
||||||
|
end
|
||||||
|
|
||||||
|
# helper to invoke cmake
|
||||||
|
def run_cmake(timeout, args)
|
||||||
|
# Set to process group so we can kill it and its children
|
||||||
|
pgroup = Gem.win_platform? ? :new_pgroup : :pgroup
|
||||||
|
pid = Process.spawn("cmake #{args}", pgroup => true)
|
||||||
|
|
||||||
|
Timeout.timeout(timeout) do
|
||||||
|
Process.waitpid(pid)
|
||||||
|
end
|
||||||
|
rescue Timeout::Error
|
||||||
|
# Kill it, #detach is essentially a background wait, since we don't actually
|
||||||
|
# care about waiting for it now
|
||||||
|
Process.kill(-9, pid)
|
||||||
|
Process.detach(pid)
|
||||||
|
raise StandardError.new("cmake has exceeded its timeout of #{timeout}s")
|
||||||
|
end
|
||||||
|
|
||||||
|
Dir.chdir("#{BASE_DIR}") do
|
||||||
|
sys("tar -xzf xdiff.tar.gz") unless Dir.exist?("xdiff")
|
||||||
|
Dir.mkdir("xdiff_build") unless Dir.exist?("xdiff_build")
|
||||||
|
Dir.chdir("xdiff_build") do
|
||||||
|
run_cmake(30, "#{BASE_DIR}/xdiff -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=C++17")
|
||||||
|
sys("make")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
$srcs = ["extension.cc"]
|
||||||
|
append_ldflags "-L#{BASE_DIR}/xdiff_build"
|
||||||
|
append_ldflags "-lxdiff"
|
||||||
|
|
||||||
|
create_makefile "xdiff/extension"
|
||||||
188
gems/xdiff-rb/ext/xdiff/extension.cc
Normal file
188
gems/xdiff-rb/ext/xdiff/extension.cc
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
#include "ruby/ruby.h"
|
||||||
|
#include "xdiff.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class scope_guard {
|
||||||
|
public:
|
||||||
|
template<class Callable>
|
||||||
|
scope_guard(Callable && undo_func) try : f(std::forward<Callable>(undo_func)) {
|
||||||
|
} catch(...) {
|
||||||
|
undo_func();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_guard(scope_guard && other) : f(std::move(other.f)) {
|
||||||
|
other.f = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
~scope_guard() {
|
||||||
|
if(f) f(); // must not throw
|
||||||
|
}
|
||||||
|
|
||||||
|
void dismiss() noexcept {
|
||||||
|
f = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope_guard(const scope_guard&) = delete;
|
||||||
|
void operator = (const scope_guard&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::function<void()> f;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void* wrap_malloc(void* priv, unsigned int size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrap_free(void* priv, void* ptr) {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* wrap_realloc(void* priv, void* ptr, unsigned int size) {
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
VALUE init(VALUE self) {
|
||||||
|
if (initialized) {
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
memallocator_t malt;
|
||||||
|
malt.priv = NULL;
|
||||||
|
malt.malloc = wrap_malloc;
|
||||||
|
malt.free = wrap_free;
|
||||||
|
malt.realloc = wrap_realloc;
|
||||||
|
xdl_set_allocator(&malt);
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DiffWriter {
|
||||||
|
std::string accum;
|
||||||
|
|
||||||
|
static int write(void* writer_, mmbuffer_t* bufs, int bufsize) {
|
||||||
|
assert(bufsize > 0);
|
||||||
|
DiffWriter* writer = reinterpret_cast<DiffWriter*>(writer_);
|
||||||
|
|
||||||
|
for (auto i = 0; i < bufsize; i++) {
|
||||||
|
writer->accumulate_buf(bufs[i].ptr, bufs[i].size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void accumulate_buf(const char* str, size_t len) {
|
||||||
|
accum.append(str, len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string get_diff(
|
||||||
|
char* base,
|
||||||
|
size_t base_len,
|
||||||
|
char* against,
|
||||||
|
size_t against_len
|
||||||
|
) {
|
||||||
|
mmbuffer_t base_mm;
|
||||||
|
base_mm.ptr = base;
|
||||||
|
base_mm.size = base_len;
|
||||||
|
|
||||||
|
mmbuffer_t against_mm;
|
||||||
|
against_mm.ptr = against;
|
||||||
|
against_mm.size = against_len;
|
||||||
|
|
||||||
|
bdiffparam_t bdp;
|
||||||
|
bdp.bsize = 16;
|
||||||
|
|
||||||
|
DiffWriter writer;
|
||||||
|
xdemitcb_t ecb;
|
||||||
|
ecb.priv = &writer;
|
||||||
|
ecb.outf = DiffWriter::write;
|
||||||
|
|
||||||
|
int err = xdl_bdiff_mb(&base_mm, &against_mm, &bdp, &ecb);
|
||||||
|
if (err < 0) {
|
||||||
|
return std::string("(error)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(writer.accum);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string get_patched(
|
||||||
|
char *base,
|
||||||
|
size_t base_len,
|
||||||
|
char *patch,
|
||||||
|
size_t patch_len
|
||||||
|
) {
|
||||||
|
mmfile_t base_mm;
|
||||||
|
mmfile_t patch_mm;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
if ((ret = xdl_init_mmfile(&base_mm, base_len, XDL_MMF_ATOMIC))) {
|
||||||
|
return "(xdl_init_mmfile error - base)";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto free_base_guard = scope_guard([&] { xdl_free_mmfile(&base_mm); });
|
||||||
|
|
||||||
|
if ((ret = xdl_init_mmfile(&patch_mm, patch_len, XDL_MMF_ATOMIC))) {
|
||||||
|
return "(xdl_init_mmfile error - patch)";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto free_patch_guard = scope_guard([&] { xdl_free_mmfile(&patch_mm); });
|
||||||
|
|
||||||
|
if (xdl_write_mmfile(&base_mm, base, base_len) != base_len) {
|
||||||
|
return "(xdl_write_mmfile error - base)";
|
||||||
|
}
|
||||||
|
if (xdl_write_mmfile(&patch_mm, patch, patch_len) != patch_len) {
|
||||||
|
return "(xdl_write_mmfile error - patch)";
|
||||||
|
}
|
||||||
|
|
||||||
|
DiffWriter writer;
|
||||||
|
xdemitcb_t ecb;
|
||||||
|
ecb.priv = &writer;
|
||||||
|
ecb.outf = DiffWriter::write;
|
||||||
|
|
||||||
|
auto err = xdl_bpatch(&base_mm, &patch_mm, &ecb);
|
||||||
|
if (err != 0) {
|
||||||
|
return "(xdl_bpatch error)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(writer.accum);
|
||||||
|
}
|
||||||
|
VALUE diff(VALUE self, VALUE base, VALUE against) {
|
||||||
|
std::string patch = get_diff(
|
||||||
|
StringValuePtr(base),
|
||||||
|
RSTRING_LEN(base),
|
||||||
|
StringValuePtr(against),
|
||||||
|
RSTRING_LEN(against)
|
||||||
|
);
|
||||||
|
|
||||||
|
return rb_str_new(patch.c_str(), patch.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE patch(VALUE self, VALUE base, VALUE patch) {
|
||||||
|
std::string patched = get_patched(
|
||||||
|
StringValuePtr(base),
|
||||||
|
RSTRING_LEN(base),
|
||||||
|
StringValuePtr(patch),
|
||||||
|
RSTRING_LEN(patch)
|
||||||
|
);
|
||||||
|
|
||||||
|
return rb_str_new(patched.c_str(), patched.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void Init_extension(void) {
|
||||||
|
#ifdef RB_EXT_RACTOR_SAFE
|
||||||
|
rb_ext_ractor_safe(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VALUE XDiff = rb_define_module("XDiff");
|
||||||
|
VALUE Native = rb_define_class_under(XDiff, "Native", rb_cObject);
|
||||||
|
rb_define_singleton_method(Native, "patch", patch, 2);
|
||||||
|
rb_define_singleton_method(Native, "diff", diff, 2);
|
||||||
|
rb_define_singleton_method(Native, "init", init, 0);
|
||||||
|
}
|
||||||
BIN
gems/xdiff-rb/ext/xdiff/xdiff.tar.gz
Normal file
BIN
gems/xdiff-rb/ext/xdiff/xdiff.tar.gz
Normal file
Binary file not shown.
2
gems/xdiff-rb/ext/xdiff/xdiff/AUTHORS
Normal file
2
gems/xdiff-rb/ext/xdiff/xdiff/AUTHORS
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
|
||||||
122
gems/xdiff-rb/ext/xdiff/xdiff/CMakeLists.txt
Normal file
122
gems/xdiff-rb/ext/xdiff/xdiff/CMakeLists.txt
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
|
||||||
|
|
||||||
|
# Project definition
|
||||||
|
|
||||||
|
PROJECT(LibXDiff)
|
||||||
|
|
||||||
|
# Package name and version
|
||||||
|
|
||||||
|
SET(PACKAGE_NAME xdiff)
|
||||||
|
|
||||||
|
SET(PACKAGE_MAJOR_VERSION 0)
|
||||||
|
SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.23")
|
||||||
|
|
||||||
|
# Some options to customise the build
|
||||||
|
|
||||||
|
OPTION(ENABLE_TESTS "Enable the tests to be built" OFF)
|
||||||
|
OPTION(ENABLE_TOOLS "Enable the tools to be built" OFF)
|
||||||
|
|
||||||
|
# Check for some include files and functions
|
||||||
|
|
||||||
|
INCLUDE(CheckIncludeFiles)
|
||||||
|
INCLUDE(CheckFunctionExists)
|
||||||
|
|
||||||
|
CHECK_INCLUDE_FILES(limits.h HAVE_LIMITS_H)
|
||||||
|
CHECK_FUNCTION_EXISTS(memchr HAVE_MEMCHR)
|
||||||
|
CHECK_FUNCTION_EXISTS(memcmp HAVE_MEMCMP)
|
||||||
|
CHECK_FUNCTION_EXISTS(memcpy HAVE_MEMCPY)
|
||||||
|
CHECK_FUNCTION_EXISTS(memset HAVE_MEMSET)
|
||||||
|
CHECK_INCLUDE_FILES(stdio.h HAVE_STDIO_H)
|
||||||
|
CHECK_INCLUDE_FILES(stdlib.h HAVE_STDLIB_H)
|
||||||
|
CHECK_INCLUDE_FILES(string.h HAVE_STRING_H)
|
||||||
|
CHECK_FUNCTION_EXISTS(strlen HAVE_STRLEN)
|
||||||
|
CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
|
||||||
|
|
||||||
|
# Configure LibXDiff
|
||||||
|
|
||||||
|
CONFIGURE_FILE(config.h.in config.h)
|
||||||
|
|
||||||
|
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
|
||||||
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
# Build LibXDiff
|
||||||
|
|
||||||
|
IF(WIN32)
|
||||||
|
ADD_DEFINITIONS(-DLIBXDIFF_DLL_EXPORT)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
ADD_LIBRARY(${PACKAGE_NAME} STATIC
|
||||||
|
xdiff/xadler32.c
|
||||||
|
xdiff/xalloc.c
|
||||||
|
xdiff/xbdiff.c
|
||||||
|
xdiff/xbpatchi.c
|
||||||
|
xdiff/xdiffi.c
|
||||||
|
xdiff/xemit.c
|
||||||
|
xdiff/xmerge3.c
|
||||||
|
xdiff/xmissing.c
|
||||||
|
xdiff/xpatchi.c
|
||||||
|
xdiff/xprepare.c
|
||||||
|
xdiff/xrabdiff.c
|
||||||
|
xdiff/xrabply.c
|
||||||
|
xdiff/xutils.c
|
||||||
|
xdiff/xversion.c
|
||||||
|
)
|
||||||
|
|
||||||
|
SET_TARGET_PROPERTIES(${PACKAGE_NAME} PROPERTIES VERSION ${PACKAGE_VERSION})
|
||||||
|
SET_TARGET_PROPERTIES(${PACKAGE_NAME} PROPERTIES SOVERSION ${PACKAGE_MAJOR_VERSION})
|
||||||
|
|
||||||
|
# Install LibXDiff
|
||||||
|
|
||||||
|
INSTALL(TARGETS ${PACKAGE_NAME}
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
ARCHIVE DESTINATION lib)
|
||||||
|
|
||||||
|
INSTALL(FILES xdiff/xdiff.h
|
||||||
|
DESTINATION include)
|
||||||
|
|
||||||
|
# Set the RPATH information on Linux and macOS
|
||||||
|
|
||||||
|
IF(ENABLE_TESTS OR ENABLE_TOOLS)
|
||||||
|
IF(APPLE)
|
||||||
|
SET(CMAKE_INSTALL_RPATH "@executable_path/../lib")
|
||||||
|
ELSEIF(NOT WIN32)
|
||||||
|
SET(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Build the tests, if requested
|
||||||
|
|
||||||
|
IF(ENABLE_TESTS)
|
||||||
|
INCLUDE_DIRECTORIES(xdiff)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(xdiff_test
|
||||||
|
test/xdiff_test.c
|
||||||
|
test/xtestutils.c
|
||||||
|
)
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(xdiff_test ${PACKAGE_NAME})
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(xregression
|
||||||
|
test/xregression.c
|
||||||
|
test/xtestutils.c
|
||||||
|
)
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(xregression ${PACKAGE_NAME})
|
||||||
|
|
||||||
|
INSTALL(TARGETS xregression
|
||||||
|
RUNTIME DESTINATION bin)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Build the tools, if requested
|
||||||
|
|
||||||
|
IF(ENABLE_TOOLS)
|
||||||
|
ADD_EXECUTABLE(xrabin
|
||||||
|
tools/xrabin.c
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALL(TARGETS xrabin
|
||||||
|
RUNTIME DESTINATION bin)
|
||||||
|
ENDIF()
|
||||||
504
gems/xdiff-rb/ext/xdiff/xdiff/COPYING
Normal file
504
gems/xdiff-rb/ext/xdiff/xdiff/COPYING
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
|
|
||||||
|
|
||||||
5
gems/xdiff-rb/ext/xdiff/xdiff/ChangeLog
Normal file
5
gems/xdiff-rb/ext/xdiff/xdiff/ChangeLog
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
* Sun, Mar 26 2006 - Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
|
||||||
|
Fixed the missing end of line problem for text diff and patch.
|
||||||
|
|
||||||
34
gems/xdiff-rb/ext/xdiff/xdiff/README
Normal file
34
gems/xdiff-rb/ext/xdiff/xdiff/README
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
LibXDiff 0.23 (http://www.xmailserver.org/xdiff-lib.html)
|
||||||
|
|
||||||
|
The LibXDiff library implements basic and yet complete functionalities to create
|
||||||
|
file differences/patches to both binary and text files. The library uses memory
|
||||||
|
files as file abstraction to achieve both performance and portability. For
|
||||||
|
binary files, LibXDiff implements both (with some modification) the algorithm
|
||||||
|
described in File System Support for Delta Compression by Joshua P. MacDonald,
|
||||||
|
and the algorithm described in Fingerprinting By Random Polynomials by Michael
|
||||||
|
O. Rabin. While for text files it follows directives described in An O(ND)
|
||||||
|
Difference Algorithm and Its Variations by Eugene W. Myers. Memory files used by
|
||||||
|
the library are basically a collection of buffers that store the file content.
|
||||||
|
There are two different requirements for memory files when passed to diff/patch
|
||||||
|
functions. Text files for diff/patch functions require that a single line do not
|
||||||
|
have to spawn across two different memory file blocks. Binary diff/patch
|
||||||
|
functions require memory files to be compact. A compact memory files is a file
|
||||||
|
whose content is stored inside a single block. Functionalities inside the
|
||||||
|
library are available to satisfy these rules. Using the XDL_MMF_ATOMIC memory
|
||||||
|
file flag it is possible to make writes to not split the written record across
|
||||||
|
different blocks, while the functions xdl_mmfile_iscompact() ,
|
||||||
|
xdl_mmfile_compact() and xdl_mmfile_writeallocate() are usefull to test if the
|
||||||
|
file is compact and to create a compacted version of the file itself. The text
|
||||||
|
file differential output uses the raw unified output format, by omitting the
|
||||||
|
file header since the result is always relative to a single compare operation
|
||||||
|
(between two files). The output format of the binary patch file is proprietary
|
||||||
|
(and binary) and it is basically a collection of copy and insert commands, like
|
||||||
|
described inside the MacDonald paper. The library is compatible with almost
|
||||||
|
every Unix implementation (configure script) and it is also compatible with
|
||||||
|
Windows through custom (nmake) make files. Examples are available inside the
|
||||||
|
test subdirectory of the distribution tarball that show how to use the library.
|
||||||
|
Also, inside the same subdirectory, a regression test in available that tests
|
||||||
|
the library with random data by requiring a diff followed by a patch and
|
||||||
|
comparing results. Regression tests ran successfully for days on my Linux,
|
||||||
|
Solaris, FreeBSD and Windows boxes, and this makes me believe that the library
|
||||||
|
itself is completely ready for production (despite the version number).
|
||||||
34
gems/xdiff-rb/ext/xdiff/xdiff/config.h.in
Normal file
34
gems/xdiff-rb/ext/xdiff/xdiff/config.h.in
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/* config.h.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <limits.h> header file. */
|
||||||
|
#cmakedefine HAVE_LIMITS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memchr' function. */
|
||||||
|
#cmakedefine HAVE_MEMCHR 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memcmp' function. */
|
||||||
|
#cmakedefine HAVE_MEMCMP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memcpy' function. */
|
||||||
|
#cmakedefine HAVE_MEMCPY 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memset' function. */
|
||||||
|
#cmakedefine HAVE_MEMSET 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdio.h> header file. */
|
||||||
|
#cmakedefine HAVE_STDIO_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#cmakedefine HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#cmakedefine HAVE_STRING_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strlen' function. */
|
||||||
|
#cmakedefine HAVE_STRLEN 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#cmakedefine HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||||
105
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff-lib.html
Normal file
105
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff-lib.html
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="Author" content="Davide Libenzi">
|
||||||
|
<meta name="GENERATOR" content="Mozilla 1.2">
|
||||||
|
<meta name="Keywords"
|
||||||
|
content="diff,patch,library,portable,file,difference,binary diff,binary patch,myers,macdonald">
|
||||||
|
<title>LibXDiff Home Page</title>
|
||||||
|
</head>
|
||||||
|
<body style="color: rgb(0, 0, 255);">
|
||||||
|
<p style="font-family: monospace;" align="center"><b>LibXDiff</b><br>
|
||||||
|
</p>
|
||||||
|
<p style="font-family: monospace;" align="left"> <br>
|
||||||
|
The <b>LibXDiff</b> library implements basic and yet complete
|
||||||
|
functionalities to create file differences/patches to both binary and
|
||||||
|
text files. The library uses memory files as file abstraction to
|
||||||
|
achieve
|
||||||
|
both performance and portability. For binary files, <b>LibXDiff</b>
|
||||||
|
implements both (with some modification) the algorithm described in <i>File
|
||||||
|
System Support for Delta Compression</i> by <i>Joshua P. MacDonald</i>,
|
||||||
|
and the algorithm described in <span style="font-style: italic;">Fingerprinting
|
||||||
|
By Random Polynomials</span> by <span style="font-style: italic;">Michael
|
||||||
|
O. Rabin</span>. While for text files it follows directives described
|
||||||
|
in <i>An O(ND)
|
||||||
|
Difference Algorithm and Its Variations</i> by <i>Eugene W. Myers</i>.
|
||||||
|
Memory files used by the library are basically a collection of buffers
|
||||||
|
that store the file content. There are two different requirements for
|
||||||
|
memory files when passed to diff/patch functions. Text files for
|
||||||
|
diff/patch functions require that a single line do not have to spawn
|
||||||
|
across two different memory file blocks. Binary diff/patch functions
|
||||||
|
require memory files to be compact. A compact memory files is a file
|
||||||
|
whose content is stored inside a single block. Functionalities inside
|
||||||
|
the library are available to satisfy these rules. Using the <b>XDL_MMF_ATOMIC</b>
|
||||||
|
memory file flag it is possible to make writes to not split the written
|
||||||
|
record across different blocks, while the functions <b>xdl_mmfile_iscompact</b>()
|
||||||
|
, <b>xdl_mmfile_compact</b>() and <b>xdl_mmfile_writeallocate</b>()
|
||||||
|
are usefull to test if the file is compact and to create a compacted
|
||||||
|
version of the file itself. The text file differential output uses the
|
||||||
|
raw unified output format, by omitting the file header since the result
|
||||||
|
is always relative to a single compare operation (between two files).
|
||||||
|
The output format of the binary patch file is proprietary (and binary)
|
||||||
|
and it is basically a collection of copy and insert commands, like
|
||||||
|
described inside the MacDonald paper. The library is compatible with
|
||||||
|
almost every Unix implementation (configure script) and it is also
|
||||||
|
compatible with Windows through custom (nmake) make files. Examples are
|
||||||
|
available inside the <span style="font-style: italic;">test</span>
|
||||||
|
subdirectory of the distribution tarball that show how to use the
|
||||||
|
library. Also, inside the same subdirectory, a regression test in
|
||||||
|
available that tests the library with random data by requiring a diff
|
||||||
|
followed by a patch and comparing results. Regression tests ran
|
||||||
|
successfully for days on my Linux, Solaris, FreeBSD and Windows boxes,
|
||||||
|
and this makes me believe that the library itself is completely ready
|
||||||
|
for production (despite the version number).<br>
|
||||||
|
</p>
|
||||||
|
<p style="font-family: monospace;" align="left"><br>
|
||||||
|
</p>
|
||||||
|
<p style="text-align: center; font-family: monospace;"><b>Documentation<br>
|
||||||
|
</b></p>
|
||||||
|
<div style="text-align: left; font-family: monospace;"><br>
|
||||||
|
The <span style="font-weight: bold;">LibXDiff</span> library man page
|
||||||
|
is available : <a href="xdiff.html">HTML</a> <a
|
||||||
|
href="xdiff.txt">TXT</a> <a href="xdiff.pdf">PDF<br>
|
||||||
|
</a><br>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
<p style="font-family: monospace;" align="center"><b>License
|
||||||
|
and Software</b></p>
|
||||||
|
<p style="font-family: monospace;" align="left"><span
|
||||||
|
style="font-weight: bold;">LibXDiff</span>
|
||||||
|
is made available through the <a
|
||||||
|
href="http://www.gnu.org/copyleft/lesser.html">GNU LGPL</a> license
|
||||||
|
together with the complete sources. Please read carefully the <a
|
||||||
|
href="http://www.gnu.org/copyleft/lesser.html">license</a> before
|
||||||
|
using
|
||||||
|
the software. The latest library package is available here :</p>
|
||||||
|
<p style="font-family: monospace;" align="left"><a
|
||||||
|
href="http://www.xmailserver.org/libxdiff-0.23.tar.gz">Version
|
||||||
|
0.23</a></p>
|
||||||
|
<p style="font-family: monospace;" align="left"><br>
|
||||||
|
</p>
|
||||||
|
<p style="text-align: center; font-family: monospace;"><b>Links And Docs<br>
|
||||||
|
</b></p>
|
||||||
|
<div style="text-align: left; font-family: monospace;"><a
|
||||||
|
href="http://freshmeat.net/projects/xdiff-lib">LibXDiff FreshMeat Home
|
||||||
|
Page</a><a href="http://www.gnu.org/software/diffutils/diffutils.html"><br>
|
||||||
|
GNU DiffUtil</a><br>
|
||||||
|
<a href="diff2.pdf"><span style="font-style: italic;">An O(ND)
|
||||||
|
Difference Algorithm and Its Variations</span> by <i>Eugene W. Myers</i></a><br>
|
||||||
|
<a href="xdfs.pdf"><i>File System Support for Delta Compression</i> by <i>Joshua
|
||||||
|
P. MacDonald</i></a><br>
|
||||||
|
<a href="rabin.pdf"><i>Fingerprinting By Random Polynomials</i> by <i>Michael
|
||||||
|
O. Rabin</i></a><br>
|
||||||
|
<a href="rabin_impl.pdf"><i>Fingerprinting Using Polynomial</i> by <i>Calvin
|
||||||
|
Chan</i> and <i>Hahua Lu</i></a><br>
|
||||||
|
<a href="rabin_apps.pdf"><i>Some Applications of Rabin's Fingerprinting
|
||||||
|
Method</i> by <i>Andrei Z. Broder</i></a><br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<a href="davide.html">Back Home</a><br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
871
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff.3
Normal file
871
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff.3
Normal file
@@ -0,0 +1,871 @@
|
|||||||
|
.\"
|
||||||
|
.\" LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
.\" Copyright (C) 2003 Davide Libenzi
|
||||||
|
.\"
|
||||||
|
.\" This library is free software; you can redistribute it and/or
|
||||||
|
.\" modify it under the terms of the GNU Lesser General Public
|
||||||
|
.\" License as published by the Free Software Foundation; either
|
||||||
|
.\" version 2.1 of the License, or (at your option) any later version.
|
||||||
|
.\"
|
||||||
|
.\" This library is distributed in the hope that it will be useful,
|
||||||
|
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
.\" Lesser General Public License for more details.
|
||||||
|
.\"
|
||||||
|
.\" You should have received a copy of the GNU General Public License
|
||||||
|
.\" along with this program; if not, write to the Free Software
|
||||||
|
.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
.\"
|
||||||
|
.\" Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
.\"
|
||||||
|
.na
|
||||||
|
.TH LibXDiff 3 "0.23" "GNU" "File Differential Library"
|
||||||
|
.SH NAME
|
||||||
|
|
||||||
|
xdl_set_allocator, xdl_malloc, xdl_free, xdl_realloc, xdl_init_mmfile, xdl_free_mmfile,
|
||||||
|
xdl_mmfile_iscompact, xdl_seek_mmfile, xdl_read_mmfile, xdl_write_mmfile, xdl_writem_mmfile,
|
||||||
|
xdl_mmfile_writeallocate, xdl_mmfile_ptradd, xdl_mmfile_first, xdl_mmfile_next, xdl_mmfile_size, xdl_mmfile_cmp,
|
||||||
|
xdl_mmfile_compact, xdl_diff, xdl_patch, xdl_merge3, xdl_bdiff_mb, xdl_bdiff, xdl_rabdiff_mb, xdl_rabdiff,
|
||||||
|
xdl_bdiff_tgsize, xdl_bpatch \- File Differential Library support functions
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <xdiff.h>
|
||||||
|
.sp
|
||||||
|
.BI "int xdl_set_allocator(memallocator_t const *" malt ");"
|
||||||
|
.nl
|
||||||
|
.BI "void *xdl_malloc(unsigned int " size ");"
|
||||||
|
.nl
|
||||||
|
.BI "void xdl_free(void *" ptr ");"
|
||||||
|
.nl
|
||||||
|
.BI "void *xdl_realloc(void *" ptr ", unsigned int " nsize ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_init_mmfile(mmfile_t *" mmf ", long " bsize ", unsigned long " flags ");"
|
||||||
|
.nl
|
||||||
|
.BI "void xdl_free_mmfile(mmfile_t *" mmf ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_mmfile_iscompact(mmfile_t *" mmf ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_seek_mmfile(mmfile_t *" mmf ", long " off ");"
|
||||||
|
.nl
|
||||||
|
.BI "long xdl_read_mmfile(mmfile_t *" mmf ", void *" data ", long " size ");"
|
||||||
|
.nl
|
||||||
|
.BI "long xdl_write_mmfile(mmfile_t *" mmf ", void const *" data ", long " size ");"
|
||||||
|
.nl
|
||||||
|
.BI "long xdl_writem_mmfile(mmfile_t *" mmf ", mmbuffer_t *" mb ", int " nbuf ");"
|
||||||
|
.nl
|
||||||
|
.BI "void *xdl_mmfile_writeallocate(mmfile_t *" mmf ", long " size ");"
|
||||||
|
.nl
|
||||||
|
.BI "long xdl_mmfile_ptradd(mmfile_t *" mmf ", char *" ptr ", long " size ", unsigned long " flags ");"
|
||||||
|
.nl
|
||||||
|
.BI "void *xdl_mmfile_first(mmfile_t *" mmf ", long *" size ");"
|
||||||
|
.nl
|
||||||
|
.BI "void *xdl_mmfile_next(mmfile_t *" mmf ", long *" size ");"
|
||||||
|
.nl
|
||||||
|
.BI "long xdl_mmfile_size(mmfile_t *" mmf ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_mmfile_cmp(mmfile_t *" mmf1 ", mmfile_t *" mmf2 ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_mmfile_compact(mmfile_t *" mmfo ", mmfile_t *" mmfc ", long " bsize ", unsigned long " flags ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_diff(mmfile_t *" mmf1 ", mmfile_t *" mmf2 ", xpparam_t const *" xpp ", xdemitconf_t const *" xecfg ", xdemitcb_t *" ecb ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_patch(mmfile_t *" mmf ", mmfile_t *" mmfp ", int " mode ", xdemitcb_t *" ecb ", xdemitcb_t *" rjecb ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_merge3(mmfile_t *" mmfo ", mmfile_t *" mmf1 ", mmfile_t *" mmf2 ", xdemitcb_t *" ecb ", xdemitcb_t *" rjecb ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_bdiff_mb(mmbuffer_t *" mmb1 ", mmbuffer_t *" mmb2 ", bdiffparam_t const *" bdp ", xdemitcb_t *" ecb ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_bdiff(mmfile_t *" mmf1 ", mmfile_t *" mmf2 ", bdiffparam_t const *" bdp ", xdemitcb_t *" ecb ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_rabdiff_mb(mmbuffer_t *" mmb1 ", mmbuffer_t *" mmb2 ", xdemitcb_t *" ecb ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_rabdiff(mmfile_t *" mmf1 ", mmfile_t *" mmf2 ", xdemitcb_t *" ecb ");"
|
||||||
|
.nl
|
||||||
|
.BI "long xdl_bdiff_tgsize(mmfile_t *" mmfp ");"
|
||||||
|
.nl
|
||||||
|
.BI "int xdl_bpatch(mmfile_t *" mmf ", mmfile_t *" mmfp ", xdemitcb_t *" ecb ");"
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The
|
||||||
|
.B LibXDiff
|
||||||
|
library implements basic and yet complete functionalities to create
|
||||||
|
file differences/patches to both binary and text files. The library
|
||||||
|
uses memory files as file abstraction to achieve both performance and
|
||||||
|
portability. For binary files,
|
||||||
|
.B LibXDiff
|
||||||
|
implements both (with some modification) the algorithm described in
|
||||||
|
.IR "File System Support for Delta Compression" " by " "Joshua P. MacDonald" ,
|
||||||
|
and the method described in
|
||||||
|
.IR "Fingerprinting by Random Polynomials" " by " "Michael O. Rabin" "."
|
||||||
|
While for text files it follows directives described in
|
||||||
|
.IR "An O(ND) Difference Algorithm and Its Variations" " by " "Eugene W. Myers" .
|
||||||
|
Memory files used by the library are basically a collection of buffers
|
||||||
|
that store the file content. There are two different requirements for memory
|
||||||
|
files when passed to diff/patch functions. Text files for diff/patch functions
|
||||||
|
require that a single line do not have to spawn across two different memory
|
||||||
|
file blocks. Binary diff/patch functions require memory files to be compact.
|
||||||
|
A compact memory files is a file whose content is stored inside a single block.
|
||||||
|
Functionalities inside the library are available to satisfy these rules.
|
||||||
|
Using the
|
||||||
|
.B XDL_MMF_ATOMIC
|
||||||
|
memory file flag it is possible to make writes to not split the written
|
||||||
|
record across different blocks, while the functions
|
||||||
|
.BR xdl_mmfile_iscompact ()
|
||||||
|
,
|
||||||
|
.BR xdl_mmfile_compact ()
|
||||||
|
and
|
||||||
|
.BR xdl_mmfile_writeallocate ()
|
||||||
|
are usefull to test if the file is compact and to create a compacted version
|
||||||
|
of the file itself. The text file differential output uses the raw unified output
|
||||||
|
format, by omitting the file header since the result is always relative to
|
||||||
|
a single compare operation (between two files). The output format of the binary
|
||||||
|
patch file is proprietary (and binary) and it is basically a collection of
|
||||||
|
copy and insert commands, like described inside the MacDonald paper.
|
||||||
|
|
||||||
|
|
||||||
|
.SS Functions
|
||||||
|
The following functions are defined:
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_set_allocator(memallocator_t const *" malt ");"
|
||||||
|
|
||||||
|
The
|
||||||
|
.B LibXDiff
|
||||||
|
library enable the user to set its own memory allocator, that will be used
|
||||||
|
for all the following memory requests. The allocator must be set before
|
||||||
|
to start calling the
|
||||||
|
.B LibXDiff
|
||||||
|
library with a call to
|
||||||
|
.BR xdl_set_allocator ().
|
||||||
|
The memory allocator structure contains the following members:
|
||||||
|
.nf
|
||||||
|
|
||||||
|
typedef struct s_memallocator {
|
||||||
|
void *priv;
|
||||||
|
void *(*malloc)(void *priv, unsigned int size);
|
||||||
|
void (*free)(void *priv, void *ptr);
|
||||||
|
void *(*realloc)(void *priv, void *ptr, unsigned int nsize);
|
||||||
|
} memallocator_t;
|
||||||
|
|
||||||
|
.fi
|
||||||
|
The
|
||||||
|
.BR malloc ()
|
||||||
|
function pointer will be used by
|
||||||
|
.B LibXDiff
|
||||||
|
to request a memory block of
|
||||||
|
.I size
|
||||||
|
bytes. The
|
||||||
|
.BR free ()
|
||||||
|
function pointer will be called to free a previously allocated block
|
||||||
|
.I ptr
|
||||||
|
, while the
|
||||||
|
.BR realloc ()
|
||||||
|
will be used to resize the
|
||||||
|
.I ptr
|
||||||
|
to a new
|
||||||
|
.I nsize
|
||||||
|
size in bytes. The
|
||||||
|
.B priv
|
||||||
|
structure member will be passed to the
|
||||||
|
.BR malloc (), free (), realloc ()
|
||||||
|
functions as first parameter. The
|
||||||
|
.B LibXDiff
|
||||||
|
user must call
|
||||||
|
.BR xdl_set_allocator ()
|
||||||
|
before starting using the library, otherwise
|
||||||
|
.B LibXDiff
|
||||||
|
functions will fail due to the lack of memory allocation support.
|
||||||
|
A typical initialization sequence for
|
||||||
|
.B POSIX
|
||||||
|
systems will use the standard
|
||||||
|
.BR malloc (3),
|
||||||
|
.BR free (3),
|
||||||
|
.BR realloc (3)
|
||||||
|
and will look like:
|
||||||
|
.nf
|
||||||
|
|
||||||
|
void *wrap_malloc(void *priv, unsigned int size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrap_free(void *priv, void *ptr) {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wrap_realloc(void *priv, void *ptr, unsigned int size) {
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void my_init_xdiff(void) {
|
||||||
|
memallocator_t malt;
|
||||||
|
|
||||||
|
malt.priv = NULL;
|
||||||
|
malt.malloc = wrap_malloc;
|
||||||
|
malt.free = wrap_free;
|
||||||
|
malt.realloc = wrap_realloc;
|
||||||
|
xdl_set_allocator(&malt);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "void *xdl_malloc(unsigned int " size ");"
|
||||||
|
|
||||||
|
Allocates a memory block of
|
||||||
|
.I size
|
||||||
|
bytes using the
|
||||||
|
.B LibXDiff
|
||||||
|
memory allocator. The user can specify its own allocator using the
|
||||||
|
.BR xdl_set_allocator ()
|
||||||
|
function. The
|
||||||
|
.BR xdl_malloc ()
|
||||||
|
return a pointer to the newly allocated block, or
|
||||||
|
.B NULL
|
||||||
|
in case of failure.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "void xdl_free(void *" ptr ");"
|
||||||
|
|
||||||
|
Free a previously allocated memory block pointed by
|
||||||
|
.IR ptr .
|
||||||
|
The
|
||||||
|
.I ptr
|
||||||
|
block must has been allocated using either
|
||||||
|
.BR xdl_malloc ()
|
||||||
|
or
|
||||||
|
.BR xdl_realloc ().
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "void *xdl_realloc(void *" ptr ", unsigned int " nsize ");"
|
||||||
|
|
||||||
|
Resizes the memory block pointed by
|
||||||
|
.I ptr
|
||||||
|
to a new size
|
||||||
|
.IR nsize .
|
||||||
|
Return the resized block if successful, or
|
||||||
|
.B NULL
|
||||||
|
in case the reallocation fails. After a successful reallocation, the old
|
||||||
|
.I ptr
|
||||||
|
block is to be considered no more valid.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_init_mmfile(mmfile_t *" mmf ", long " bsize ", unsigned long " flags ");"
|
||||||
|
|
||||||
|
Initialize the memory file
|
||||||
|
.I mmf
|
||||||
|
by requiring an internal block size of
|
||||||
|
.IR bsize .
|
||||||
|
The
|
||||||
|
.I flags
|
||||||
|
parameter is a combination of the following flags :
|
||||||
|
.br
|
||||||
|
.IP
|
||||||
|
.B XDL_MMF_ATOMIC
|
||||||
|
Writes on the memory file will be atomic. That is, the data will not be split
|
||||||
|
on two or more different blocks.
|
||||||
|
|
||||||
|
Once an
|
||||||
|
.BR xdl_init_mmfile ()
|
||||||
|
succeeded, a matching
|
||||||
|
.BR xdl_free_mmfile ()
|
||||||
|
must be called when the user has done using the memory file, otherwise serious
|
||||||
|
memory leaks will happen.
|
||||||
|
The function return 0 if succeed or -1 if an error is encountered.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "void xdl_free_mmfile(mmfile_t *" mmf ");"
|
||||||
|
|
||||||
|
Free all the data associated with the
|
||||||
|
.I mmf
|
||||||
|
memory file.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_mmfile_iscompact(mmfile_t *" mmf ");"
|
||||||
|
|
||||||
|
Returns an integer different from 0 if the
|
||||||
|
.I mmf
|
||||||
|
memory file is compact, 0 otherwise. A compact memory file is one that have
|
||||||
|
the whole content stored inside a single block.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_seek_mmfile(mmfile_t *" mmf ", long " off ");"
|
||||||
|
|
||||||
|
Set the current data pointer of the memory file
|
||||||
|
.I mmf
|
||||||
|
to the specified offset
|
||||||
|
.I off
|
||||||
|
from the beginning of the file itself. Returns 0 if successful or -1 if an error
|
||||||
|
happened.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "long xdl_read_mmfile(mmfile_t *" mmf ", void *" data ", long " size ");"
|
||||||
|
|
||||||
|
Request to read
|
||||||
|
.I size
|
||||||
|
bytes from the memory file
|
||||||
|
.I mmf
|
||||||
|
by storing the data inside the
|
||||||
|
.I data
|
||||||
|
buffer. Returns the number of bytes read into the
|
||||||
|
.I data
|
||||||
|
buffer. The amount of data read can be lower than the specified
|
||||||
|
.IR size .
|
||||||
|
The function returns -1 if an error happened.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "long xdl_write_mmfile(mmfile_t *" mmf ", void const *" data ", long " size ");"
|
||||||
|
|
||||||
|
Request to write
|
||||||
|
.I size
|
||||||
|
bytes from the specified buffer
|
||||||
|
.I data
|
||||||
|
into the memory file
|
||||||
|
.IR mmf .
|
||||||
|
If the memory file has been created using the
|
||||||
|
.B XDL_MMF_ATOMIC
|
||||||
|
flag, the write request will not be split across different blocks.
|
||||||
|
Note that all write operations done on memory files do append data at the end
|
||||||
|
the file, and writes in the middle of it are allowed. This is because the library
|
||||||
|
memory file abstraction does not need this functionality to be available.
|
||||||
|
The function returns the number of bytes written or a number lower than
|
||||||
|
.I size
|
||||||
|
if an error happened.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "long xdl_writem_mmfile(mmfile_t *" mmf ", mmbuffer_t *" mb ", int " nbuf ");"
|
||||||
|
|
||||||
|
Request to sequentially write
|
||||||
|
.I nbuf
|
||||||
|
memory buffers passed inside the array
|
||||||
|
.I mb
|
||||||
|
into the memory file
|
||||||
|
.IR mmf .
|
||||||
|
The memory buffer structure is defined as :
|
||||||
|
.nf
|
||||||
|
|
||||||
|
typedef struct s_mmbuffer {
|
||||||
|
char *ptr;
|
||||||
|
long size;
|
||||||
|
} mmbuffer_t;
|
||||||
|
|
||||||
|
.fi
|
||||||
|
The
|
||||||
|
.I ptr
|
||||||
|
field is a pointer to the user data, whose size is specified inside the
|
||||||
|
.I size
|
||||||
|
structure field. The function returns the total number of bytes written
|
||||||
|
or a lower number if an error happened.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "void *xdl_mmfile_writeallocate(mmfile_t *" mmf ", long " size ");"
|
||||||
|
|
||||||
|
The function request to allocate a write buffer of
|
||||||
|
.I size
|
||||||
|
bytes in the
|
||||||
|
.I mmf
|
||||||
|
memory file and returns the pointer to the allocated buffer. The user will
|
||||||
|
have the responsibility to store
|
||||||
|
.I size
|
||||||
|
bytes (no more, no less) inside the memory region pointed to by the returned pointer.
|
||||||
|
The files size will grow of
|
||||||
|
.I size
|
||||||
|
bytes as a consequence of this operation. The function will return
|
||||||
|
.B NULL
|
||||||
|
if an error happened.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "long xdl_mmfile_ptradd(mmfile_t *" mmf ", char *" ptr ", long " size ", unsigned long " flags ");"
|
||||||
|
|
||||||
|
The function adds a user specified block to the end of the memory file
|
||||||
|
.IR mmf .
|
||||||
|
The block first byte is pointed to by
|
||||||
|
.I ptr
|
||||||
|
and its length is
|
||||||
|
.I size
|
||||||
|
bytes. The
|
||||||
|
.I flags
|
||||||
|
parameter can be used to specify attributes of the user memory block. Currently
|
||||||
|
supported attributes are:
|
||||||
|
.br
|
||||||
|
.IP
|
||||||
|
.B XDL_MMB_READONLY
|
||||||
|
Specify that the added memory block must be treated as read-only, and
|
||||||
|
every attempt to write on it should result in a failure of the memory file
|
||||||
|
writing functions.
|
||||||
|
|
||||||
|
The purpose of this function is basically to avoid copying memory around,
|
||||||
|
by helping the library to not drain the CPU cache. The function returns
|
||||||
|
.I size
|
||||||
|
in case of success, or -1 in case of error.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "void *xdl_mmfile_first(mmfile_t *" mmf ", long *" size ");"
|
||||||
|
|
||||||
|
The function is used to return the first block of the
|
||||||
|
.I mmf
|
||||||
|
memory file block chain. The
|
||||||
|
.I size
|
||||||
|
parameter will receive the size of the block, while the function will return
|
||||||
|
the pointer the the first byte of the block itself. The function returns
|
||||||
|
.B NULL
|
||||||
|
if the file is empty.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "void *xdl_mmfile_next(mmfile_t *" mmf ", long *" size ");"
|
||||||
|
|
||||||
|
The function is used to return the next block of the
|
||||||
|
.I mmf
|
||||||
|
memory file block chain. The
|
||||||
|
.I size
|
||||||
|
parameter will receive the size of the block, while the function will return
|
||||||
|
the pointer the the first byte of the block itself. The function returns
|
||||||
|
.B NULL
|
||||||
|
if the current block is the last one of the chain.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "long xdl_mmfile_size(mmfile_t *" mmf ");"
|
||||||
|
|
||||||
|
The function returns the size of the specified memory file
|
||||||
|
.IR mmf .
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_mmfile_cmp(mmfile_t *" mmf1 ", mmfile_t *" mmf2 ");"
|
||||||
|
|
||||||
|
Request to compare two memory files
|
||||||
|
.IR mmf1 " and " mmf2
|
||||||
|
and returns 0 if files are identical, or a value different from 0 if
|
||||||
|
files are different.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_mmfile_compact(mmfile_t *" mmfo ", mmfile_t *" mmfc ", long " bsize ", unsigned long " flags ");"
|
||||||
|
|
||||||
|
Request to create a compact version of the memory file
|
||||||
|
.I mmfo
|
||||||
|
into the (uninitialized) memory file
|
||||||
|
.IR mmfc .
|
||||||
|
The
|
||||||
|
.I bsize
|
||||||
|
parameter specify the requested block size and
|
||||||
|
.I flags
|
||||||
|
specify flags to be used to create the new
|
||||||
|
.I mmfc
|
||||||
|
memory file (see
|
||||||
|
.BR xdl_init_mmfile ()
|
||||||
|
). The function returns 0 if succedded or -1 if an error happened.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_diff(mmfile_t *" mmf1 ", mmfile_t *" mmf2 ", xpparam_t const *" xpp ", xdemitconf_t const *" xecfg ", xdemitcb_t *" ecb ");"
|
||||||
|
|
||||||
|
Request to create the difference between the two text memory files
|
||||||
|
.IR mmf1 " and " mmf2 .
|
||||||
|
The
|
||||||
|
.I mmf1
|
||||||
|
memory files is considered the "old" file while
|
||||||
|
.I mmf2
|
||||||
|
is considered the "new" file. So the function will create a patch file
|
||||||
|
that once applied to
|
||||||
|
.I mmf1
|
||||||
|
will give
|
||||||
|
.I mmf2
|
||||||
|
as result. Files
|
||||||
|
.IR mmf1 " and " mmf2
|
||||||
|
must be atomic from a line point of view (or, as an extreme, compact), that
|
||||||
|
means that a single test line cannot spread among different memory file blocks.
|
||||||
|
The
|
||||||
|
.I xpp
|
||||||
|
parameter is a pointer to a structure :
|
||||||
|
.nf
|
||||||
|
|
||||||
|
typedef struct s_xpparam {
|
||||||
|
unsigned long flags;
|
||||||
|
} xpparam_t;
|
||||||
|
|
||||||
|
.fi
|
||||||
|
that is used to specify parameters to be used by the file differential algorithm.
|
||||||
|
The
|
||||||
|
.I flags
|
||||||
|
field is a combination of the following flags :
|
||||||
|
|
||||||
|
.IP
|
||||||
|
.B XDF_NEED_MINIMAL
|
||||||
|
Requires the minimal edit script to be found by the algorithm (may be slow).
|
||||||
|
|
||||||
|
The
|
||||||
|
.I xecfg
|
||||||
|
parameter point to a structure :
|
||||||
|
.nf
|
||||||
|
|
||||||
|
typedef struct s_xdemitconf {
|
||||||
|
long ctxlen;
|
||||||
|
} xdemitconf_t;
|
||||||
|
|
||||||
|
.fi
|
||||||
|
that is used to configure the algorithm responsible of the creation the the
|
||||||
|
differential file from an edit script. The
|
||||||
|
.I ctxlen
|
||||||
|
field is used to specify the amount of context to be emitted inside the
|
||||||
|
differential file (the value 3 is suggested for normal operations).
|
||||||
|
The parameter
|
||||||
|
.I ecb
|
||||||
|
is a pointer to a structure :
|
||||||
|
.nf
|
||||||
|
|
||||||
|
typedef struct s_xdemitcb {
|
||||||
|
void *priv;
|
||||||
|
int (*outf)(void *, mmbuffer_t *, int);
|
||||||
|
} xdemitcb_t;
|
||||||
|
|
||||||
|
.fi
|
||||||
|
that is used by the differential file creation algorithm to emit the created
|
||||||
|
data. The
|
||||||
|
.I priv
|
||||||
|
field is an opaque pointer to a user specified data, while the
|
||||||
|
.I outf
|
||||||
|
field point to a callback function that is called internally to emit algorithm
|
||||||
|
generated data rappresenting the differential file. The first parameter of the
|
||||||
|
callback is the same
|
||||||
|
.I priv
|
||||||
|
field specified inside the
|
||||||
|
.B xdemitcb_t
|
||||||
|
structure. The second parameter point to an array of
|
||||||
|
.B mmbuffer_t
|
||||||
|
(see above for a definition of the structure) whose element count is specified
|
||||||
|
inside the last parameter of the callback itself. The callback will always be
|
||||||
|
called with entire records (lines) and never a record (line) will be emitted
|
||||||
|
using two different callback calls. This is important because if the called will
|
||||||
|
use another memory file to store the result, by creating the target memory file with
|
||||||
|
.B XDL_MMF_ATOMIC
|
||||||
|
will guarantee the "atomicity" of the memory file itself.
|
||||||
|
The function returns 0 if succeeded or -1 if an error occurred.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_patch(mmfile_t *" mmf ", mmfile_t *" mmfp ", int " mode ", xdemitcb_t *" ecb ", xdemitcb_t *" rjecb ");"
|
||||||
|
|
||||||
|
Request to patch the memory file
|
||||||
|
.I mmf
|
||||||
|
using the patch file stored in
|
||||||
|
.IR mmfp .
|
||||||
|
The
|
||||||
|
.I mmf
|
||||||
|
memory file
|
||||||
|
.B is not
|
||||||
|
changed during the operation and can be considered as read only.
|
||||||
|
The
|
||||||
|
.I mode
|
||||||
|
parameter can be one of the following values :
|
||||||
|
.IP
|
||||||
|
.B XDL_PATCH_NORMAL
|
||||||
|
Perform standard patching like if the patch memory file
|
||||||
|
.I mmfp
|
||||||
|
has been created using
|
||||||
|
.I mmf
|
||||||
|
as "old" file.
|
||||||
|
.IP
|
||||||
|
.B XDL_PATCH_REVERSE
|
||||||
|
Apply the reverse patch. That means that the
|
||||||
|
.I mmf
|
||||||
|
memory file has to be considered as if it was specified as "new" file during
|
||||||
|
the differential operation (
|
||||||
|
.BR xdl_diff ()
|
||||||
|
). The result of the operation will then be the file content that was used
|
||||||
|
as "old" file during the differential operation.
|
||||||
|
|
||||||
|
The following flags can be specified (by or-ing them) to one of the above:
|
||||||
|
.IP
|
||||||
|
.B XDL_PATCH_IGNOREBSPACE
|
||||||
|
Ignore the whitespace at the beginning and the end of the line.
|
||||||
|
|
||||||
|
The
|
||||||
|
.I ecb
|
||||||
|
will be used by the patch algorithm to create the result file while the
|
||||||
|
.I rjecb
|
||||||
|
will be used to emit all differential chunks that cannot be applied.
|
||||||
|
Like explained above, callbacks are always called with entire records to guarantee
|
||||||
|
atomicity of the resulting output.
|
||||||
|
The function returns 0 if succeeded without performing any fuzzy hunk detection,
|
||||||
|
a positive value if it secceeded with fuzzy hunk detection or -1 if an error occurred
|
||||||
|
during the patch operation.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_merge3(mmfile_t *" mmfo ", mmfile_t *" mmf1 ", mmfile_t *" mmf2 ", xdemitcb_t *" ecb ", xdemitcb_t *" rjecb ");"
|
||||||
|
|
||||||
|
Merges three files together. The
|
||||||
|
.I mmfo
|
||||||
|
file is the original one, while
|
||||||
|
.IR mmf1 " and " mmf2
|
||||||
|
are two modified versions of
|
||||||
|
.IR mmfo .
|
||||||
|
The function works by creating a differential between
|
||||||
|
.IR mmfo " and " mmf2
|
||||||
|
and by applying the resulting patch to
|
||||||
|
.IR mmf1 .
|
||||||
|
Because of this sequence,
|
||||||
|
.I mmf1
|
||||||
|
changes will be privileged against the ones of
|
||||||
|
.IR mmf2 .
|
||||||
|
The
|
||||||
|
.I ecb
|
||||||
|
will be used by the patch algorithm to create the result file while the
|
||||||
|
.I rjecb
|
||||||
|
will be used to emit all differential chunks that cannot be applied.
|
||||||
|
Like explained above, callbacks are always called with entire records to guarantee
|
||||||
|
atomicity of the resulting output.
|
||||||
|
The function returns 0 if succeeded or -1 if an error occurred during the patch operation.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_bdiff(mmfile_t *" mmf1 ", mmfile_t *" mmf2 ", bdiffparam_t const *" bdp ", xdemitcb_t *" ecb ");"
|
||||||
|
|
||||||
|
Request to create the difference between the two text memory files
|
||||||
|
.IR mmf1 " and " mmf2 .
|
||||||
|
The
|
||||||
|
.I mmf1
|
||||||
|
memory files is considered the "old" file while
|
||||||
|
.I mmf2
|
||||||
|
is considered the "new" file. So the function will create a patch file
|
||||||
|
that once applied to
|
||||||
|
.I mmf1
|
||||||
|
will give
|
||||||
|
.I mmf2
|
||||||
|
as result. Files
|
||||||
|
.IR mmf1 " and " mmf2
|
||||||
|
must be compact to make it easy and faster to perform the difference operation.
|
||||||
|
Functions are available to check for compactness (
|
||||||
|
.BR xdl_mmfile_iscompact ()
|
||||||
|
) and to make compact a non-compact file (
|
||||||
|
.BR xdl_mmfile_compact ()
|
||||||
|
). An example of how to create a compact memory file (described inside the test
|
||||||
|
subdirectory) is :
|
||||||
|
.nf
|
||||||
|
|
||||||
|
int xdlt_load_mmfile(char const *fname, mmfile_t *mf, int binmode) {
|
||||||
|
char cc;
|
||||||
|
int fd;
|
||||||
|
long size, bsize;
|
||||||
|
char *blk;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mf, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0)
|
||||||
|
return -1;
|
||||||
|
if ((fd = open(fname, O_RDONLY)) == -1) {
|
||||||
|
perror(fname);
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((size = bsize = lseek(fd, 0, SEEK_END)) > 0 && !binmode) {
|
||||||
|
if (lseek(fd, -1, SEEK_END) != (off_t) -1 &&
|
||||||
|
read(fd, &cc, 1) && cc != '\\n')
|
||||||
|
bsize++;
|
||||||
|
}
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
if (!(blk = (char *) xdl_mmfile_writeallocate(mf, bsize))) {
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (read(fd, blk, (size_t) size) != (size_t) size) {
|
||||||
|
perror(fname);
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
if (bsize > size)
|
||||||
|
blk[size] = '\\n';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fi
|
||||||
|
The
|
||||||
|
.I bdp
|
||||||
|
parameter points to a structure :
|
||||||
|
.nf
|
||||||
|
|
||||||
|
typedef struct s_bdiffparam {
|
||||||
|
long bsize;
|
||||||
|
} bdiffparam_t;
|
||||||
|
|
||||||
|
.fi
|
||||||
|
that is used to pass information to the binary file differential algorithm.
|
||||||
|
The
|
||||||
|
.I bsize
|
||||||
|
parameter specify the size of the block that will be used to decompose
|
||||||
|
.I mmf1
|
||||||
|
during the block classification phase of the algorithm (see MacDonald paper).
|
||||||
|
Suggested values go from 16 to 64, with a preferred power of two characteristic.
|
||||||
|
The
|
||||||
|
.I ecb
|
||||||
|
parameter is used to pass the emission callback to the algorithm responsible
|
||||||
|
of the output file creation.
|
||||||
|
The function returns 0 if succeede or -1 if an error is occurred.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_bdiff_mb(mmbuffer_t *" mmb1 ", mmbuffer_t *" mmb2 ", bdiffparam_t const *" bdp ", xdemitcb_t *" ecb ");"
|
||||||
|
|
||||||
|
Same as
|
||||||
|
.BR xdl_bdiff ()
|
||||||
|
but it works on memory buffer directly. The
|
||||||
|
.BR xdl_bdiff ()
|
||||||
|
is implemented internally with a
|
||||||
|
.BR xdl_bdiff_mb ()
|
||||||
|
after having setup the two memory buffers from the passed memory files (that must be compact,
|
||||||
|
as described above). The memory buffer structure is defined as :
|
||||||
|
.nf
|
||||||
|
|
||||||
|
typedef struct s_mmbuffer {
|
||||||
|
char *ptr;
|
||||||
|
long size;
|
||||||
|
} mmbuffer_t;
|
||||||
|
|
||||||
|
.fi
|
||||||
|
An empty memory buffer is specified by setting the
|
||||||
|
.I ptr
|
||||||
|
member as
|
||||||
|
.B NULL
|
||||||
|
and the
|
||||||
|
.I size
|
||||||
|
member as zero. The reason of having this function is to avoid the memory file
|
||||||
|
preparation, that might involve copying memory from other sources. Using
|
||||||
|
the
|
||||||
|
.BR xdl_bdiff_mb (),
|
||||||
|
the caller can setup the two memory buffer by using, for example,
|
||||||
|
.BR mmap (2),
|
||||||
|
and hence avoiding unnecessary memory copies. The other parameters and the return value
|
||||||
|
of the function
|
||||||
|
.BR xdl_bdiff_mb ()
|
||||||
|
are the same as the ones already described in
|
||||||
|
.BR xdl_bdiff ().
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_rabdiff(mmfile_t *" mmf1 ", mmfile_t *" mmf2 ", xdemitcb_t *" ecb ");"
|
||||||
|
|
||||||
|
Request to create the difference between the two text memory files
|
||||||
|
.IR mmf1 " and " mmf2
|
||||||
|
using the Rabin's polynomial fingerprinting algorithm. This algorithm typically
|
||||||
|
performs faster and produces smaller deltas, when compared to the XDelta-like one.
|
||||||
|
The
|
||||||
|
.I mmf1
|
||||||
|
memory files is considered the "old" file while
|
||||||
|
.I mmf2
|
||||||
|
is considered the "new" file. So the function will create a patch file
|
||||||
|
that once applied to
|
||||||
|
.I mmf1
|
||||||
|
will give
|
||||||
|
.I mmf2
|
||||||
|
as result. Files
|
||||||
|
.IR mmf1 " and " mmf2
|
||||||
|
must be compact to make it easy and faster to perform the difference operation.
|
||||||
|
Functions are available to check for compactness (
|
||||||
|
.BR xdl_mmfile_iscompact ()
|
||||||
|
) and to make compact a non-compact file (
|
||||||
|
.BR xdl_mmfile_compact ()
|
||||||
|
). The
|
||||||
|
.I ecb
|
||||||
|
parameter is used to pass the emission callback to the algorithm responsible
|
||||||
|
of the output file creation.
|
||||||
|
The function returns 0 if succeede or -1 if an error is occurred.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_rabdiff_mb(mmbuffer_t *" mmb1 ", mmbuffer_t *" mmb2 ", xdemitcb_t *" ecb ");"
|
||||||
|
|
||||||
|
Same as
|
||||||
|
.BR xdl_rabdiff ()
|
||||||
|
but it works on memory buffer directly. The memory buffer structure is defined as :
|
||||||
|
.nf
|
||||||
|
|
||||||
|
typedef struct s_mmbuffer {
|
||||||
|
char *ptr;
|
||||||
|
long size;
|
||||||
|
} mmbuffer_t;
|
||||||
|
|
||||||
|
.fi
|
||||||
|
An empty memory buffer is specified by setting the
|
||||||
|
.I ptr
|
||||||
|
member as
|
||||||
|
.B NULL
|
||||||
|
and the
|
||||||
|
.I size
|
||||||
|
member as zero. The reason of having this function is to avoid the memory file
|
||||||
|
preparation, that might involve copying memory from other sources. Using
|
||||||
|
the
|
||||||
|
.BR xdl_rabdiff_mb (),
|
||||||
|
the caller can setup the two memory buffer by using, for example,
|
||||||
|
.BR mmap (2),
|
||||||
|
and hence avoiding unnecessary memory copies. The other parameters and the return value
|
||||||
|
of the function
|
||||||
|
.BR xdl_rabdiff_mb ()
|
||||||
|
are the same as the ones already described in
|
||||||
|
.BR xdl_rabdiff ().
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "long xdl_bdiff_tgsize(mmfile_t *" mmfp ");"
|
||||||
|
|
||||||
|
Given a binary memory file patch, it returns the size that the result file
|
||||||
|
will have once the patch is applied to the target file. It can be used to
|
||||||
|
pre-allocate (or write-allocate) a memory block to store the patch result
|
||||||
|
so that a compact file will be available at the end of the operation. The
|
||||||
|
function returns the requested size, or -1 if an error occurred during the operation.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "int xdl_bpatch(mmfile_t *" mmf ", mmfile_t *" mmfp ", xdemitcb_t *" ecb ");"
|
||||||
|
|
||||||
|
Request to patch the binary memory file
|
||||||
|
.I mmf
|
||||||
|
using the binary patch file stored in
|
||||||
|
.IR mmfp .
|
||||||
|
The
|
||||||
|
.I mmf
|
||||||
|
memory file
|
||||||
|
.B is not
|
||||||
|
changed during the operation and can be considered as read only. The binary
|
||||||
|
patch algorithm has no notion of context, so the patch operation cannot be
|
||||||
|
partial (either success or failure). The
|
||||||
|
.I ecb
|
||||||
|
parameter contain the callabck (see above for description) used by the binary
|
||||||
|
patch algorithm to emit the result file. The function returns 0 if succeeded
|
||||||
|
or -1 if an error occurred during the patch operation.
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
Two papers drove the content of this library and these are :
|
||||||
|
.br
|
||||||
|
.IP o
|
||||||
|
.IR "File System Support for Delta Compression" " by " "Joshua P. MacDonald"
|
||||||
|
.BR http://www.xmailserver.org/xdfs.pdf
|
||||||
|
.br
|
||||||
|
.IP o
|
||||||
|
.IR "Fingerprinting by Random Polynomials" " by " "Michael O. Rabin"
|
||||||
|
.BR http://www.xmailserver.org/rabin.pdf
|
||||||
|
.br
|
||||||
|
.IP o
|
||||||
|
.IR "An O(ND) Difference Algorithm and Its Variations" " by " "Eugene W. Myers"
|
||||||
|
.BR http://www.xmailserver.org/diff2.pdf
|
||||||
|
.PP
|
||||||
|
|
||||||
|
Also usefull information can be looked up inside the
|
||||||
|
.B diffutil
|
||||||
|
GNU package :
|
||||||
|
|
||||||
|
.BR http://www.gnu.org/software/diffutils/diffutils.html
|
||||||
|
|
||||||
|
.SH LICENSE
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
A copy of the license is available at :
|
||||||
|
|
||||||
|
.BR http://www.gnu.org/copyleft/lesser.html
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
Developed by Davide Libenzi
|
||||||
|
.RB < davidel@xmailserver.org >
|
||||||
|
|
||||||
|
.SH AVAILABILITY
|
||||||
|
The latest version of
|
||||||
|
.B LibXDiff
|
||||||
|
can be found at :
|
||||||
|
|
||||||
|
.BR http://www.xmailserver.org/xdiff-lib.html
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
There are no known bugs. Bug reports and comments to Davide Libenzi
|
||||||
|
.RB < davidel@xmailserver.org >
|
||||||
|
|
||||||
1109
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff.html
Normal file
1109
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff.html
Normal file
File diff suppressed because it is too large
Load Diff
BIN
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff.pdf
Normal file
BIN
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff.pdf
Normal file
Binary file not shown.
611
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff.txt
Normal file
611
gems/xdiff-rb/ext/xdiff/xdiff/man/xdiff.txt
Normal file
@@ -0,0 +1,611 @@
|
|||||||
|
LibXDiff(3) File Differential Library LibXDiff(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NAME
|
||||||
|
xdl_set_allocator, xdl_malloc, xdl_free, xdl_realloc, xdl_init_mmfile,
|
||||||
|
xdl_free_mmfile, xdl_mmfile_iscompact, xdl_seek_mmfile,
|
||||||
|
xdl_read_mmfile, xdl_write_mmfile, xdl_writem_mmfile,
|
||||||
|
xdl_mmfile_writeallocate, xdl_mmfile_ptradd, xdl_mmfile_first,
|
||||||
|
xdl_mmfile_next, xdl_mmfile_size, xdl_mmfile_cmp, xdl_mmfile_compact,
|
||||||
|
xdl_diff, xdl_patch, xdl_merge3, xdl_bdiff_mb, xdl_bdiff, xdl_rabd-
|
||||||
|
iff_mb, xdl_rabdiff, xdl_bdiff_tgsize, xdl_bpatch - File Differential
|
||||||
|
Library support functions
|
||||||
|
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
#include <xdiff.h>
|
||||||
|
|
||||||
|
int xdl_set_allocator(memallocator_t const *malt);
|
||||||
|
void *xdl_malloc(unsigned int size);
|
||||||
|
void xdl_free(void *ptr);
|
||||||
|
void *xdl_realloc(void *ptr, unsigned int nsize);
|
||||||
|
int xdl_init_mmfile(mmfile_t *mmf, long bsize, unsigned long flags);
|
||||||
|
void xdl_free_mmfile(mmfile_t *mmf);
|
||||||
|
int xdl_mmfile_iscompact(mmfile_t *mmf);
|
||||||
|
int xdl_seek_mmfile(mmfile_t *mmf, long off);
|
||||||
|
long xdl_read_mmfile(mmfile_t *mmf, void *data, long size);
|
||||||
|
long xdl_write_mmfile(mmfile_t *mmf, void const *data, long size);
|
||||||
|
long xdl_writem_mmfile(mmfile_t *mmf, mmbuffer_t *mb, int nbuf);
|
||||||
|
void *xdl_mmfile_writeallocate(mmfile_t *mmf, long size);
|
||||||
|
long xdl_mmfile_ptradd(mmfile_t *mmf, char *ptr, long size, unsigned long flags);
|
||||||
|
void *xdl_mmfile_first(mmfile_t *mmf, long *size);
|
||||||
|
void *xdl_mmfile_next(mmfile_t *mmf, long *size);
|
||||||
|
long xdl_mmfile_size(mmfile_t *mmf);
|
||||||
|
int xdl_mmfile_cmp(mmfile_t *mmf1, mmfile_t *mmf2);
|
||||||
|
int xdl_mmfile_compact(mmfile_t *mmfo, mmfile_t *mmfc, long bsize, unsigned long flags);
|
||||||
|
int xdl_diff(mmfile_t *mmf1, mmfile_t *mmf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);
|
||||||
|
int xdl_patch(mmfile_t *mmf, mmfile_t *mmfp, int mode, xdemitcb_t *ecb, xdemitcb_t *rjecb);
|
||||||
|
int xdl_merge3(mmfile_t *mmfo, mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb, xdemitcb_t *rjecb);
|
||||||
|
int xdl_bdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, bdiffparam_t const *bdp, xdemitcb_t *ecb);
|
||||||
|
int xdl_bdiff(mmfile_t *mmf1, mmfile_t *mmf2, bdiffparam_t const *bdp, xdemitcb_t *ecb);
|
||||||
|
int xdl_rabdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, xdemitcb_t *ecb);
|
||||||
|
int xdl_rabdiff(mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb);
|
||||||
|
long xdl_bdiff_tgsize(mmfile_t *mmfp);
|
||||||
|
int xdl_bpatch(mmfile_t *mmf, mmfile_t *mmfp, xdemitcb_t *ecb);
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
The LibXDiff library implements basic and yet complete functionalities
|
||||||
|
to create file differences/patches to both binary and text files. The
|
||||||
|
library uses memory files as file abstraction to achieve both perfor-
|
||||||
|
mance and portability. For binary files, LibXDiff implements both (with
|
||||||
|
some modification) the algorithm described in File System Support for
|
||||||
|
Delta Compression by Joshua P. MacDonald, and the method described in
|
||||||
|
Fingerprinting by Random Polynomials by Michael O. Rabin. While for
|
||||||
|
text files it follows directives described in An O(ND) Difference Algo-
|
||||||
|
rithm and Its Variations by Eugene W. Myers. Memory files used by the
|
||||||
|
library are basically a collection of buffers that store the file con-
|
||||||
|
tent. There are two different requirements for memory files when passed
|
||||||
|
to diff/patch functions. Text files for diff/patch functions require
|
||||||
|
that a single line do not have to spawn across two different memory
|
||||||
|
file blocks. Binary diff/patch functions require memory files to be
|
||||||
|
compact. A compact memory files is a file whose content is stored
|
||||||
|
inside a single block. Functionalities inside the library are avail-
|
||||||
|
able to satisfy these rules. Using the XDL_MMF_ATOMIC memory file flag
|
||||||
|
it is possible to make writes to not split the written record across
|
||||||
|
different blocks, while the functions xdl_mmfile_iscompact() ,
|
||||||
|
xdl_mmfile_compact() and xdl_mmfile_writeallocate() are usefull to test
|
||||||
|
if the file is compact and to create a compacted version of the file
|
||||||
|
itself. The text file differential output uses the raw unified output
|
||||||
|
format, by omitting the file header since the result is always relative
|
||||||
|
to a single compare operation (between two files). The output format of
|
||||||
|
the binary patch file is proprietary (and binary) and it is basically a
|
||||||
|
collection of copy and insert commands, like described inside the Mac-
|
||||||
|
Donald paper.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Functions
|
||||||
|
The following functions are defined:
|
||||||
|
|
||||||
|
int xdl_set_allocator(memallocator_t const *malt);
|
||||||
|
|
||||||
|
The LibXDiff library enable the user to set its own memory allo-
|
||||||
|
cator, that will be used for all the following memory requests.
|
||||||
|
The allocator must be set before to start calling the LibXDiff
|
||||||
|
library with a call to xdl_set_allocator(). The memory alloca-
|
||||||
|
tor structure contains the following members:
|
||||||
|
|
||||||
|
typedef struct s_memallocator {
|
||||||
|
void *priv;
|
||||||
|
void *(*malloc)(void *priv, unsigned int size);
|
||||||
|
void (*free)(void *priv, void *ptr);
|
||||||
|
void *(*realloc)(void *priv, void *ptr, unsigned int nsize);
|
||||||
|
} memallocator_t;
|
||||||
|
|
||||||
|
The malloc() function pointer will be used by LibXDiff to
|
||||||
|
request a memory block of size bytes. The free() function
|
||||||
|
pointer will be called to free a previously allocated block ptr
|
||||||
|
, while the realloc() will be used to resize the ptr to a new
|
||||||
|
nsize size in bytes. The priv structure member will be passed to
|
||||||
|
the malloc(),free(),realloc() functions as first parameter. The
|
||||||
|
LibXDiff user must call xdl_set_allocator() before starting
|
||||||
|
using the library, otherwise LibXDiff functions will fail due to
|
||||||
|
the lack of memory allocation support. A typical initialization
|
||||||
|
sequence for POSIX systems will use the standard malloc(3),
|
||||||
|
free(3), realloc(3) and will look like:
|
||||||
|
|
||||||
|
void *wrap_malloc(void *priv, unsigned int size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrap_free(void *priv, void *ptr) {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *wrap_realloc(void *priv, void *ptr, unsigned int size) {
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void my_init_xdiff(void) {
|
||||||
|
memallocator_t malt;
|
||||||
|
|
||||||
|
malt.priv = NULL;
|
||||||
|
malt.malloc = wrap_malloc;
|
||||||
|
malt.free = wrap_free;
|
||||||
|
malt.realloc = wrap_realloc;
|
||||||
|
xdl_set_allocator(&malt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_malloc(unsigned int size);
|
||||||
|
|
||||||
|
Allocates a memory block of size bytes using the LibXDiff memory
|
||||||
|
allocator. The user can specify its own allocator using the
|
||||||
|
xdl_set_allocator() function. The xdl_malloc() return a pointer
|
||||||
|
to the newly allocated block, or NULL in case of failure.
|
||||||
|
|
||||||
|
|
||||||
|
void xdl_free(void *ptr);
|
||||||
|
|
||||||
|
Free a previously allocated memory block pointed by ptr. The
|
||||||
|
ptr block must has been allocated using either xdl_malloc() or
|
||||||
|
xdl_realloc().
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_realloc(void *ptr, unsigned int nsize);
|
||||||
|
|
||||||
|
Resizes the memory block pointed by ptr to a new size nsize.
|
||||||
|
Return the resized block if successful, or NULL in case the
|
||||||
|
reallocation fails. After a successful reallocation, the old ptr
|
||||||
|
block is to be considered no more valid.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_init_mmfile(mmfile_t *mmf, long bsize, unsigned long flags);
|
||||||
|
|
||||||
|
Initialize the memory file mmf by requiring an internal block
|
||||||
|
size of bsize. The flags parameter is a combination of the fol-
|
||||||
|
lowing flags :
|
||||||
|
|
||||||
|
XDL_MMF_ATOMIC Writes on the memory file will be atomic. That
|
||||||
|
is, the data will not be split on two or more different blocks.
|
||||||
|
|
||||||
|
Once an xdl_init_mmfile() succeeded, a matching
|
||||||
|
xdl_free_mmfile() must be called when the user has done using
|
||||||
|
the memory file, otherwise serious memory leaks will happen.
|
||||||
|
The function return 0 if succeed or -1 if an error is encoun-
|
||||||
|
tered.
|
||||||
|
|
||||||
|
|
||||||
|
void xdl_free_mmfile(mmfile_t *mmf);
|
||||||
|
|
||||||
|
Free all the data associated with the mmf memory file.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_mmfile_iscompact(mmfile_t *mmf);
|
||||||
|
|
||||||
|
Returns an integer different from 0 if the mmf memory file is
|
||||||
|
compact, 0 otherwise. A compact memory file is one that have the
|
||||||
|
whole content stored inside a single block.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_seek_mmfile(mmfile_t *mmf, long off);
|
||||||
|
|
||||||
|
Set the current data pointer of the memory file mmf to the spec-
|
||||||
|
ified offset off from the beginning of the file itself. Returns
|
||||||
|
0 if successful or -1 if an error happened.
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_read_mmfile(mmfile_t *mmf, void *data, long size);
|
||||||
|
|
||||||
|
Request to read size bytes from the memory file mmf by storing
|
||||||
|
the data inside the data buffer. Returns the number of bytes
|
||||||
|
read into the data buffer. The amount of data read can be lower
|
||||||
|
than the specified size. The function returns -1 if an error
|
||||||
|
happened.
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_write_mmfile(mmfile_t *mmf, void const *data, long size);
|
||||||
|
|
||||||
|
Request to write size bytes from the specified buffer data into
|
||||||
|
the memory file mmf. If the memory file has been created using
|
||||||
|
the XDL_MMF_ATOMIC flag, the write request will not be split
|
||||||
|
across different blocks. Note that all write operations done on
|
||||||
|
memory files do append data at the end the file, and writes in
|
||||||
|
the middle of it are allowed. This is because the library memory
|
||||||
|
file abstraction does not need this functionality to be avail-
|
||||||
|
able. The function returns the number of bytes written or a
|
||||||
|
number lower than size if an error happened.
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_writem_mmfile(mmfile_t *mmf, mmbuffer_t *mb, int nbuf);
|
||||||
|
|
||||||
|
Request to sequentially write nbuf memory buffers passed inside
|
||||||
|
the array mb into the memory file mmf. The memory buffer struc-
|
||||||
|
ture is defined as :
|
||||||
|
|
||||||
|
typedef struct s_mmbuffer {
|
||||||
|
char *ptr;
|
||||||
|
long size;
|
||||||
|
} mmbuffer_t;
|
||||||
|
|
||||||
|
The ptr field is a pointer to the user data, whose size is spec-
|
||||||
|
ified inside the size structure field. The function returns the
|
||||||
|
total number of bytes written or a lower number if an error hap-
|
||||||
|
pened.
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_mmfile_writeallocate(mmfile_t *mmf, long size);
|
||||||
|
|
||||||
|
The function request to allocate a write buffer of size bytes in
|
||||||
|
the mmf memory file and returns the pointer to the allocated
|
||||||
|
buffer. The user will have the responsibility to store size
|
||||||
|
bytes (no more, no less) inside the memory region pointed to by
|
||||||
|
the returned pointer. The files size will grow of size bytes as
|
||||||
|
a consequence of this operation. The function will return NULL
|
||||||
|
if an error happened.
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_mmfile_ptradd(mmfile_t *mmf, char *ptr, long size, unsigned
|
||||||
|
long flags);
|
||||||
|
|
||||||
|
The function adds a user specified block to the end of the mem-
|
||||||
|
ory file mmf. The block first byte is pointed to by ptr and its
|
||||||
|
length is size bytes. The flags parameter can be used to specify
|
||||||
|
attributes of the user memory block. Currently supported
|
||||||
|
attributes are:
|
||||||
|
|
||||||
|
XDL_MMB_READONLY Specify that the added memory block must be
|
||||||
|
treated as read-only, and every attempt to write on it should
|
||||||
|
result in a failure of the memory file writing functions.
|
||||||
|
|
||||||
|
The purpose of this function is basically to avoid copying mem-
|
||||||
|
ory around, by helping the library to not drain the CPU cache.
|
||||||
|
The function returns size in case of success, or -1 in case of
|
||||||
|
error.
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_mmfile_first(mmfile_t *mmf, long *size);
|
||||||
|
|
||||||
|
The function is used to return the first block of the mmf memory
|
||||||
|
file block chain. The size parameter will receive the size of
|
||||||
|
the block, while the function will return the pointer the the
|
||||||
|
first byte of the block itself. The function returns NULL if the
|
||||||
|
file is empty.
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_mmfile_next(mmfile_t *mmf, long *size);
|
||||||
|
|
||||||
|
The function is used to return the next block of the mmf memory
|
||||||
|
file block chain. The size parameter will receive the size of
|
||||||
|
the block, while the function will return the pointer the the
|
||||||
|
first byte of the block itself. The function returns NULL if the
|
||||||
|
current block is the last one of the chain.
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_mmfile_size(mmfile_t *mmf);
|
||||||
|
|
||||||
|
The function returns the size of the specified memory file mmf.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_mmfile_cmp(mmfile_t *mmf1, mmfile_t *mmf2);
|
||||||
|
|
||||||
|
Request to compare two memory files mmf1 and mmf2 and returns 0
|
||||||
|
if files are identical, or a value different from 0 if files are
|
||||||
|
different.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_mmfile_compact(mmfile_t *mmfo, mmfile_t *mmfc, long bsize,
|
||||||
|
unsigned long flags);
|
||||||
|
|
||||||
|
Request to create a compact version of the memory file mmfo into
|
||||||
|
the (uninitialized) memory file mmfc. The bsize parameter spec-
|
||||||
|
ify the requested block size and flags specify flags to be used
|
||||||
|
to create the new mmfc memory file (see xdl_init_mmfile() ). The
|
||||||
|
function returns 0 if succedded or -1 if an error happened.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_diff(mmfile_t *mmf1, mmfile_t *mmf2, xpparam_t const *xpp,
|
||||||
|
xdemitconf_t const *xecfg, xdemitcb_t *ecb);
|
||||||
|
|
||||||
|
Request to create the difference between the two text memory
|
||||||
|
files mmf1 and mmf2. The mmf1 memory files is considered the
|
||||||
|
"old" file while mmf2 is considered the "new" file. So the func-
|
||||||
|
tion will create a patch file that once applied to mmf1 will
|
||||||
|
give mmf2 as result. Files mmf1 and mmf2 must be atomic from a
|
||||||
|
line point of view (or, as an extreme, compact), that means that
|
||||||
|
a single test line cannot spread among different memory file
|
||||||
|
blocks. The xpp parameter is a pointer to a structure :
|
||||||
|
|
||||||
|
typedef struct s_xpparam {
|
||||||
|
unsigned long flags;
|
||||||
|
} xpparam_t;
|
||||||
|
|
||||||
|
that is used to specify parameters to be used by the file dif-
|
||||||
|
ferential algorithm. The flags field is a combination of the
|
||||||
|
following flags :
|
||||||
|
|
||||||
|
|
||||||
|
XDF_NEED_MINIMAL Requires the minimal edit script to be found by
|
||||||
|
the algorithm (may be slow).
|
||||||
|
|
||||||
|
The xecfg parameter point to a structure :
|
||||||
|
|
||||||
|
typedef struct s_xdemitconf {
|
||||||
|
long ctxlen;
|
||||||
|
} xdemitconf_t;
|
||||||
|
|
||||||
|
that is used to configure the algorithm responsible of the
|
||||||
|
creation the the differential file from an edit script. The
|
||||||
|
ctxlen field is used to specify the amount of context to be
|
||||||
|
emitted inside the differential file (the value 3 is suggested
|
||||||
|
for normal operations). The parameter ecb is a pointer to a
|
||||||
|
structure :
|
||||||
|
|
||||||
|
typedef struct s_xdemitcb {
|
||||||
|
void *priv;
|
||||||
|
int (*outf)(void *, mmbuffer_t *, int);
|
||||||
|
} xdemitcb_t;
|
||||||
|
|
||||||
|
that is used by the differential file creation algorithm to emit
|
||||||
|
the created data. The priv field is an opaque pointer to a user
|
||||||
|
specified data, while the outf field point to a callback func-
|
||||||
|
tion that is called internally to emit algorithm generated data
|
||||||
|
rappresenting the differential file. The first parameter of the
|
||||||
|
callback is the same priv field specified inside the xdemitcb_t
|
||||||
|
structure. The second parameter point to an array of mmbuffer_t
|
||||||
|
(see above for a definition of the structure) whose element
|
||||||
|
count is specified inside the last parameter of the callback
|
||||||
|
itself. The callback will always be called with entire records
|
||||||
|
(lines) and never a record (line) will be emitted using two dif-
|
||||||
|
ferent callback calls. This is important because if the called
|
||||||
|
will use another memory file to store the result, by creating
|
||||||
|
the target memory file with XDL_MMF_ATOMIC will guarantee the
|
||||||
|
"atomicity" of the memory file itself. The function returns 0
|
||||||
|
if succeeded or -1 if an error occurred.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_patch(mmfile_t *mmf, mmfile_t *mmfp, int mode, xdemitcb_t *ecb,
|
||||||
|
xdemitcb_t *rjecb);
|
||||||
|
|
||||||
|
Request to patch the memory file mmf using the patch file stored
|
||||||
|
in mmfp. The mmf memory file is not changed during the opera-
|
||||||
|
tion and can be considered as read only. The mode parameter can
|
||||||
|
be one of the following values :
|
||||||
|
|
||||||
|
XDL_PATCH_NORMAL Perform standard patching like if the patch
|
||||||
|
memory file mmfp has been created using mmf as "old" file.
|
||||||
|
|
||||||
|
XDL_PATCH_REVERSE Apply the reverse patch. That means that the
|
||||||
|
mmf memory file has to be considered as if it was specified as
|
||||||
|
"new" file during the differential operation ( xdl_diff() ). The
|
||||||
|
result of the operation will then be the file content that was
|
||||||
|
used as "old" file during the differential operation.
|
||||||
|
|
||||||
|
The following flags can be specified (by or-ing them) to one of
|
||||||
|
the above:
|
||||||
|
|
||||||
|
XDL_PATCH_IGNOREBSPACE Ignore the whitespace at the beginning
|
||||||
|
and the end of the line.
|
||||||
|
|
||||||
|
The ecb will be used by the patch algorithm to create the result
|
||||||
|
file while the rjecb will be used to emit all differential
|
||||||
|
chunks that cannot be applied. Like explained above, callbacks
|
||||||
|
are always called with entire records to guarantee atomicity of
|
||||||
|
the resulting output. The function returns 0 if succeeded with-
|
||||||
|
out performing any fuzzy hunk detection, a positive value if it
|
||||||
|
secceeded with fuzzy hunk detection or -1 if an error occurred
|
||||||
|
during the patch operation.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_merge3(mmfile_t *mmfo, mmfile_t *mmf1, mmfile_t *mmf2,
|
||||||
|
xdemitcb_t *ecb, xdemitcb_t *rjecb);
|
||||||
|
|
||||||
|
Merges three files together. The mmfo file is the original one,
|
||||||
|
while mmf1 and mmf2 are two modified versions of mmfo. The
|
||||||
|
function works by creating a differential between mmfo and mmf2
|
||||||
|
and by applying the resulting patch to mmf1. Because of this
|
||||||
|
sequence, mmf1 changes will be privileged against the ones of
|
||||||
|
mmf2. The ecb will be used by the patch algorithm to create the
|
||||||
|
result file while the rjecb will be used to emit all differen-
|
||||||
|
tial chunks that cannot be applied. Like explained above, call-
|
||||||
|
backs are always called with entire records to guarantee atomic-
|
||||||
|
ity of the resulting output. The function returns 0 if suc-
|
||||||
|
ceeded or -1 if an error occurred during the patch operation.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_bdiff(mmfile_t *mmf1, mmfile_t *mmf2, bdiffparam_t const *bdp,
|
||||||
|
xdemitcb_t *ecb);
|
||||||
|
|
||||||
|
Request to create the difference between the two text memory
|
||||||
|
files mmf1 and mmf2. The mmf1 memory files is considered the
|
||||||
|
"old" file while mmf2 is considered the "new" file. So the func-
|
||||||
|
tion will create a patch file that once applied to mmf1 will
|
||||||
|
give mmf2 as result. Files mmf1 and mmf2 must be compact to make
|
||||||
|
it easy and faster to perform the difference operation. Func-
|
||||||
|
tions are available to check for compactness ( xdl_mmfile_iscom-
|
||||||
|
pact() ) and to make compact a non-compact file (
|
||||||
|
xdl_mmfile_compact() ). An example of how to create a compact
|
||||||
|
memory file (described inside the test subdirectory) is :
|
||||||
|
|
||||||
|
int xdlt_load_mmfile(char const *fname, mmfile_t *mf, int binmode) {
|
||||||
|
char cc;
|
||||||
|
int fd;
|
||||||
|
long size, bsize;
|
||||||
|
char *blk;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mf, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0)
|
||||||
|
return -1;
|
||||||
|
if ((fd = open(fname, O_RDONLY)) == -1) {
|
||||||
|
perror(fname);
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((size = bsize = lseek(fd, 0, SEEK_END)) > 0 && !binmode) {
|
||||||
|
if (lseek(fd, -1, SEEK_END) != (off_t) -1 &&
|
||||||
|
read(fd, &cc, 1) && cc != '\n')
|
||||||
|
bsize++;
|
||||||
|
}
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
if (!(blk = (char *) xdl_mmfile_writeallocate(mf, bsize))) {
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (read(fd, blk, (size_t) size) != (size_t) size) {
|
||||||
|
perror(fname);
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
if (bsize > size)
|
||||||
|
blk[size] = '\n';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
The bdp parameter points to a structure :
|
||||||
|
|
||||||
|
typedef struct s_bdiffparam {
|
||||||
|
long bsize;
|
||||||
|
} bdiffparam_t;
|
||||||
|
|
||||||
|
that is used to pass information to the binary file differential
|
||||||
|
algorithm. The bsize parameter specify the size of the block
|
||||||
|
that will be used to decompose mmf1 during the block classifica-
|
||||||
|
tion phase of the algorithm (see MacDonald paper). Suggested
|
||||||
|
values go from 16 to 64, with a preferred power of two charac-
|
||||||
|
teristic. The ecb parameter is used to pass the emission call-
|
||||||
|
back to the algorithm responsible of the output file creation.
|
||||||
|
The function returns 0 if succeede or -1 if an error is
|
||||||
|
occurred.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_bdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, bdiffparam_t const
|
||||||
|
*bdp, xdemitcb_t *ecb);
|
||||||
|
|
||||||
|
Same as xdl_bdiff() but it works on memory buffer directly. The
|
||||||
|
xdl_bdiff() is implemented internally with a xdl_bdiff_mb()
|
||||||
|
after having setup the two memory buffers from the passed memory
|
||||||
|
files (that must be compact, as described above). The memory
|
||||||
|
buffer structure is defined as :
|
||||||
|
|
||||||
|
typedef struct s_mmbuffer {
|
||||||
|
char *ptr;
|
||||||
|
long size;
|
||||||
|
} mmbuffer_t;
|
||||||
|
|
||||||
|
An empty memory buffer is specified by setting the ptr member as
|
||||||
|
NULL and the size member as zero. The reason of having this
|
||||||
|
function is to avoid the memory file preparation, that might
|
||||||
|
involve copying memory from other sources. Using the
|
||||||
|
xdl_bdiff_mb(), the caller can setup the two memory buffer by
|
||||||
|
using, for example, mmap(2), and hence avoiding unnecessary mem-
|
||||||
|
ory copies. The other parameters and the return value of the
|
||||||
|
function xdl_bdiff_mb() are the same as the ones already
|
||||||
|
described in xdl_bdiff().
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_rabdiff(mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb);
|
||||||
|
|
||||||
|
Request to create the difference between the two text memory
|
||||||
|
files mmf1 and mmf2 using the Rabin's polynomial fingerprinting
|
||||||
|
algorithm. This algorithm typically performs faster and produces
|
||||||
|
smaller deltas, when compared to the XDelta-like one. The mmf1
|
||||||
|
memory files is considered the "old" file while mmf2 is consid-
|
||||||
|
ered the "new" file. So the function will create a patch file
|
||||||
|
that once applied to mmf1 will give mmf2 as result. Files mmf1
|
||||||
|
and mmf2 must be compact to make it easy and faster to perform
|
||||||
|
the difference operation. Functions are available to check for
|
||||||
|
compactness ( xdl_mmfile_iscompact() ) and to make compact a
|
||||||
|
non-compact file ( xdl_mmfile_compact() ). The ecb parameter is
|
||||||
|
used to pass the emission callback to the algorithm responsible
|
||||||
|
of the output file creation. The function returns 0 if succeede
|
||||||
|
or -1 if an error is occurred.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_rabdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, xdemitcb_t
|
||||||
|
*ecb);
|
||||||
|
|
||||||
|
Same as xdl_rabdiff() but it works on memory buffer directly.
|
||||||
|
The memory buffer structure is defined as :
|
||||||
|
|
||||||
|
typedef struct s_mmbuffer {
|
||||||
|
char *ptr;
|
||||||
|
long size;
|
||||||
|
} mmbuffer_t;
|
||||||
|
|
||||||
|
An empty memory buffer is specified by setting the ptr member as
|
||||||
|
NULL and the size member as zero. The reason of having this
|
||||||
|
function is to avoid the memory file preparation, that might
|
||||||
|
involve copying memory from other sources. Using the xdl_rabd-
|
||||||
|
iff_mb(), the caller can setup the two memory buffer by using,
|
||||||
|
for example, mmap(2), and hence avoiding unnecessary memory
|
||||||
|
copies. The other parameters and the return value of the func-
|
||||||
|
tion xdl_rabdiff_mb() are the same as the ones already described
|
||||||
|
in xdl_rabdiff().
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_bdiff_tgsize(mmfile_t *mmfp);
|
||||||
|
|
||||||
|
Given a binary memory file patch, it returns the size that the
|
||||||
|
result file will have once the patch is applied to the target
|
||||||
|
file. It can be used to pre-allocate (or write-allocate) a mem-
|
||||||
|
ory block to store the patch result so that a compact file will
|
||||||
|
be available at the end of the operation. The function returns
|
||||||
|
the requested size, or -1 if an error occurred during the opera-
|
||||||
|
tion.
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_bpatch(mmfile_t *mmf, mmfile_t *mmfp, xdemitcb_t *ecb);
|
||||||
|
|
||||||
|
Request to patch the binary memory file mmf using the binary
|
||||||
|
patch file stored in mmfp. The mmf memory file is not changed
|
||||||
|
during the operation and can be considered as read only. The
|
||||||
|
binary patch algorithm has no notion of context, so the patch
|
||||||
|
operation cannot be partial (either success or failure). The ecb
|
||||||
|
parameter contain the callabck (see above for description) used
|
||||||
|
by the binary patch algorithm to emit the result file. The func-
|
||||||
|
tion returns 0 if succeeded or -1 if an error occurred during
|
||||||
|
the patch operation.
|
||||||
|
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
Two papers drove the content of this library and these are :
|
||||||
|
|
||||||
|
o File System Support for Delta Compression by Joshua P. MacDonald
|
||||||
|
http://www.xmailserver.org/xdfs.pdf
|
||||||
|
|
||||||
|
o Fingerprinting by Random Polynomials by Michael O. Rabin
|
||||||
|
http://www.xmailserver.org/rabin.pdf
|
||||||
|
|
||||||
|
o An O(ND) Difference Algorithm and Its Variations by Eugene W.
|
||||||
|
Myers http://www.xmailserver.org/diff2.pdf
|
||||||
|
|
||||||
|
|
||||||
|
Also usefull information can be looked up inside the diffutil GNU pack-
|
||||||
|
age :
|
||||||
|
|
||||||
|
http://www.gnu.org/software/diffutils/diffutils.html
|
||||||
|
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
This library is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. A copy of the license is available
|
||||||
|
at :
|
||||||
|
|
||||||
|
http://www.gnu.org/copyleft/lesser.html
|
||||||
|
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
Developed by Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
|
||||||
|
|
||||||
|
AVAILABILITY
|
||||||
|
The latest version of LibXDiff can be found at :
|
||||||
|
|
||||||
|
http://www.xmailserver.org/xdiff-lib.html
|
||||||
|
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
There are no known bugs. Bug reports and comments to Davide Libenzi
|
||||||
|
<davidel@xmailserver.org>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GNU 0.23 LibXDiff(3)
|
||||||
202
gems/xdiff-rb/ext/xdiff/xdiff/test/xdiff_test.c
Normal file
202
gems/xdiff-rb/ext/xdiff/xdiff/test/xdiff_test.c
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "xdiff.h"
|
||||||
|
#include "xtestutils.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int xdlt_outf(void *priv, mmbuffer_t *mb, int nbuf) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < nbuf; i++)
|
||||||
|
if (!fwrite(mb[i].ptr, mb[i].size, 1, (FILE *) priv))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void usage(char const *prg) {
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"use: %s --diff [-C N] from-file to-file\n"
|
||||||
|
" %s --patch orig-file patch-file\n"
|
||||||
|
" %s --bdiff [-B N] from-file to-file\n"
|
||||||
|
" %s --rabdiff from-file to-file\n"
|
||||||
|
" %s --bpatch orig-file patch-file\n",
|
||||||
|
prg, prg, prg, prg, prg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *wrap_malloc(void *priv, unsigned int size) {
|
||||||
|
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wrap_free(void *priv, void *ptr) {
|
||||||
|
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *wrap_realloc(void *priv, void *ptr, unsigned int size) {
|
||||||
|
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int i = 1, ctxlen = 3, bsize = 16, do_diff, do_patch, do_bdiff, do_bpatch, do_rabdiff;
|
||||||
|
memallocator_t malt;
|
||||||
|
mmfile_t mf1, mf2;
|
||||||
|
xpparam_t xpp;
|
||||||
|
xdemitconf_t xecfg;
|
||||||
|
bdiffparam_t bdp;
|
||||||
|
xdemitcb_t ecb, rjecb;
|
||||||
|
|
||||||
|
if (argc < 4) {
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
malt.priv = NULL;
|
||||||
|
malt.malloc = wrap_malloc;
|
||||||
|
malt.free = wrap_free;
|
||||||
|
malt.realloc = wrap_realloc;
|
||||||
|
xdl_set_allocator(&malt);
|
||||||
|
|
||||||
|
do_diff = do_patch = do_bdiff = do_bpatch = do_rabdiff = 0;
|
||||||
|
if (!strcmp(argv[i], "--diff")) {
|
||||||
|
i++;
|
||||||
|
do_diff = 1;
|
||||||
|
for (; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "-C") == 0) {
|
||||||
|
if (++i < argc)
|
||||||
|
ctxlen = atoi(argv[i]);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(argv[i], "--patch")) {
|
||||||
|
i++;
|
||||||
|
do_patch = 1;
|
||||||
|
} else if (!strcmp(argv[i], "--bdiff")) {
|
||||||
|
i++;
|
||||||
|
do_bdiff = 1;
|
||||||
|
for (; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "-B") == 0) {
|
||||||
|
if (++i < argc)
|
||||||
|
bsize = atoi(argv[i]);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!strcmp(argv[i], "--rabdiff")) {
|
||||||
|
i++;
|
||||||
|
do_rabdiff = 1;
|
||||||
|
} else if (!strcmp(argv[i], "--bpatch")) {
|
||||||
|
i++;
|
||||||
|
do_bpatch = 1;
|
||||||
|
} else {
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (argc - i < 2) {
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xpp.flags = 0;
|
||||||
|
xecfg.ctxlen = ctxlen;
|
||||||
|
bdp.bsize = bsize;
|
||||||
|
if (xdlt_load_mmfile(argv[i], &mf1, do_bdiff || do_bpatch) < 0) {
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (xdlt_load_mmfile(argv[i + 1], &mf2, do_bdiff || do_bpatch) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (do_diff) {
|
||||||
|
ecb.priv = stdout;
|
||||||
|
ecb.outf = xdlt_outf;
|
||||||
|
|
||||||
|
if (xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
} else if (do_bdiff) {
|
||||||
|
ecb.priv = stdout;
|
||||||
|
ecb.outf = xdlt_outf;
|
||||||
|
if (xdl_bdiff(&mf1, &mf2, &bdp, &ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
} else if (do_rabdiff) {
|
||||||
|
ecb.priv = stdout;
|
||||||
|
ecb.outf = xdlt_outf;
|
||||||
|
if (xdl_rabdiff(&mf1, &mf2, &ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
} else if (do_bpatch) {
|
||||||
|
ecb.priv = stdout;
|
||||||
|
ecb.outf = xdlt_outf;
|
||||||
|
if (xdl_bpatch(&mf1, &mf2, &ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
} else if (do_patch) {
|
||||||
|
ecb.priv = stdout;
|
||||||
|
ecb.outf = xdlt_outf;
|
||||||
|
rjecb.priv = stderr;
|
||||||
|
rjecb.outf = xdlt_outf;
|
||||||
|
if (xdl_patch(&mf1, &mf2, XDL_PATCH_NORMAL, &ecb, &rjecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
132
gems/xdiff-rb/ext/xdiff/xdiff/test/xregression.c
Normal file
132
gems/xdiff-rb/ext/xdiff/xdiff/test/xregression.c
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "xdiff.h"
|
||||||
|
#include "xtestutils.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void *wrap_malloc(void *priv, unsigned int size) {
|
||||||
|
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wrap_free(void *priv, void *ptr) {
|
||||||
|
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *wrap_realloc(void *priv, void *ptr, unsigned int size) {
|
||||||
|
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int i, chmax = 64;
|
||||||
|
long size = 1024 * 100;
|
||||||
|
double rmod = 0.1;
|
||||||
|
xpparam_t xpp;
|
||||||
|
xdemitconf_t xecfg;
|
||||||
|
bdiffparam_t bdp;
|
||||||
|
memallocator_t malt;
|
||||||
|
|
||||||
|
malt.priv = NULL;
|
||||||
|
malt.malloc = wrap_malloc;
|
||||||
|
malt.free = wrap_free;
|
||||||
|
malt.realloc = wrap_realloc;
|
||||||
|
xdl_set_allocator(&malt);
|
||||||
|
|
||||||
|
xpp.flags = 0;
|
||||||
|
xecfg.ctxlen = 3;
|
||||||
|
bdp.bsize = 16;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (!strcmp(argv[i], "--size")) {
|
||||||
|
if (++i < argc)
|
||||||
|
size = atol(argv[i]);
|
||||||
|
} else if (!strcmp(argv[i], "--rmod")) {
|
||||||
|
if (++i < argc)
|
||||||
|
rmod = atof(argv[i]);
|
||||||
|
} else if (!strcmp(argv[i], "--ctxlen")) {
|
||||||
|
if (++i < argc)
|
||||||
|
xecfg.ctxlen = atol(argv[i]);
|
||||||
|
} else if (!strcmp(argv[i], "--chmax")) {
|
||||||
|
if (++i < argc)
|
||||||
|
chmax = atoi(argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
for (i = 0;; i++) {
|
||||||
|
fprintf(stderr, "Running TEXT test : %d ... ", i);
|
||||||
|
if (xdlt_auto_regress(&xpp, &xecfg, size, rmod, chmax) < 0) {
|
||||||
|
|
||||||
|
fprintf(stderr, "FAIL\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fprintf(stderr, "OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Running BIN test : %d ... ", i);
|
||||||
|
if (xdlt_auto_binregress(&bdp, size, rmod, chmax) < 0) {
|
||||||
|
|
||||||
|
fprintf(stderr, "FAIL\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fprintf(stderr, "OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Running RBIN test : %d ... ", i);
|
||||||
|
if (xdlt_auto_rabinregress(size, rmod, chmax) < 0) {
|
||||||
|
|
||||||
|
fprintf(stderr, "FAIL\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fprintf(stderr, "OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Running MBIN test : %d ... ", i);
|
||||||
|
if (xdlt_auto_mbinregress(&bdp, size, rmod, chmax, 32) != 0) {
|
||||||
|
|
||||||
|
fprintf(stderr, "FAIL\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fprintf(stderr, "OK\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
631
gems/xdiff-rb/ext/xdiff/xdiff/test/xtestutils.c
Normal file
631
gems/xdiff-rb/ext/xdiff/xdiff/test/xtestutils.c
Normal file
@@ -0,0 +1,631 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(_WIN32)
|
||||||
|
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
#define write _write
|
||||||
|
#define read _read
|
||||||
|
#define lseek _lseek
|
||||||
|
#define close _close
|
||||||
|
#define O_CREAT _O_CREAT
|
||||||
|
#define O_WRONLY _O_WRONLY
|
||||||
|
#define O_RDONLY _O_RDONLY
|
||||||
|
#define off_t long
|
||||||
|
#define size_t int
|
||||||
|
|
||||||
|
#else /* #if defined(WIN32) || defined(_WIN32) */
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#endif /* #if defined(WIN32) || defined(_WIN32) */
|
||||||
|
|
||||||
|
#include "xmacros.h"
|
||||||
|
#include "xdiff.h"
|
||||||
|
#include "xtestutils.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define XDLT_STD_BLKSIZE (1024 * 8)
|
||||||
|
#define XDLT_MAX_LINE_SIZE 80
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int xdlt_mmfile_outf(void *priv, mmbuffer_t *mb, int nbuf);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_dump_mmfile(char const *fname, mmfile_t *mmf) {
|
||||||
|
int fd;
|
||||||
|
long size;
|
||||||
|
char *blk;
|
||||||
|
|
||||||
|
if ((fd = open(fname, O_CREAT | O_WRONLY, 0644)) == -1) {
|
||||||
|
perror(fname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((blk = (char *) xdl_mmfile_first(mmf, &size)) != NULL) {
|
||||||
|
do {
|
||||||
|
if (write(fd, blk, (size_t) size) != (size_t) size) {
|
||||||
|
perror(fname);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while ((blk = (char *) xdl_mmfile_next(mmf, &size)) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_load_mmfile(char const *fname, mmfile_t *mf, int binmode) {
|
||||||
|
char cc;
|
||||||
|
int fd;
|
||||||
|
long size;
|
||||||
|
char *blk;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mf, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((fd = open(fname, O_RDONLY)) == -1) {
|
||||||
|
perror(fname);
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size = lseek(fd, 0, SEEK_END);
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
if (!(blk = (char *) xdl_mmfile_writeallocate(mf, size))) {
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (read(fd, blk, (size_t) size) != (size_t) size) {
|
||||||
|
perror(fname);
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdlt_mmfile_outf(void *priv, mmbuffer_t *mb, int nbuf) {
|
||||||
|
mmfile_t *mmf = priv;
|
||||||
|
|
||||||
|
if (xdl_writem_mmfile(mmf, mb, nbuf) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdemitconf_t const *xecfg, mmfile_t *mfp) {
|
||||||
|
xdemitcb_t ecb;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mfp, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ecb.priv = mfp;
|
||||||
|
ecb.outf = xdlt_mmfile_outf;
|
||||||
|
if (xdl_diff(mf1, mf2, xpp, xecfg, &ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_do_patch(mmfile_t *mfo, mmfile_t *mfp, int mode, mmfile_t *mfr) {
|
||||||
|
xdemitcb_t ecb, rjecb;
|
||||||
|
mmfile_t mmfrj;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mfr, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_init_mmfile(&mmfrj, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ecb.priv = mfr;
|
||||||
|
ecb.outf = xdlt_mmfile_outf;
|
||||||
|
rjecb.priv = &mmfrj;
|
||||||
|
rjecb.outf = xdlt_mmfile_outf;
|
||||||
|
if (xdl_patch(mfo, mfp, mode, &ecb, &rjecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mmfrj);
|
||||||
|
xdl_free_mmfile(mfr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mmfrj.fsize > 0) {
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
xdlt_dump_mmfile("xregr.orig", mfo);
|
||||||
|
xdlt_dump_mmfile("xregr.patch", mfp);
|
||||||
|
xdlt_dump_mmfile("xregr.rej", &mmfrj);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mmfrj);
|
||||||
|
xdl_free_mmfile(mfr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mmfrj);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_do_regress(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdemitconf_t const *xecfg) {
|
||||||
|
mmfile_t mfp, mfr;
|
||||||
|
|
||||||
|
if (xdlt_do_diff(mf1, mf2, xpp, xecfg, &mfp) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdlt_do_patch(mf1, &mfp, XDL_PATCH_NORMAL, &mfr) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_mmfile_cmp(&mfr, mf2)) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfr);
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mfr);
|
||||||
|
if (xdlt_do_patch(mf2, &mfp, XDL_PATCH_REVERSE, &mfr) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_mmfile_cmp(&mfr, mf1)) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfr);
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mfr);
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdlt_gen_line(char *buf, long msize) {
|
||||||
|
long i, size;
|
||||||
|
static const char ab[] =
|
||||||
|
"zxcvbnmlkjhgfdsaqwertyuiop"
|
||||||
|
"ZXCVBNMLKJHGFDSAQWERTYUIOP"
|
||||||
|
"0123456789 ";
|
||||||
|
static const int absize = sizeof(ab) - 1;
|
||||||
|
|
||||||
|
if (msize > 0)
|
||||||
|
size = rand() % (msize - 1);
|
||||||
|
else
|
||||||
|
size = -msize - 1;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
buf[i] = ab[rand() % absize];
|
||||||
|
buf[i] = '\n';
|
||||||
|
return size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_create_file(mmfile_t *mf, long size) {
|
||||||
|
long lnsize, csize;
|
||||||
|
char *data;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mf, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(data = xdl_mmfile_writeallocate(mf, size))) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (csize = 0; size - csize > XDLT_MAX_LINE_SIZE;) {
|
||||||
|
lnsize = xdlt_gen_line(data, XDLT_MAX_LINE_SIZE);
|
||||||
|
data += lnsize;
|
||||||
|
csize += lnsize;
|
||||||
|
}
|
||||||
|
if (csize < size)
|
||||||
|
xdlt_gen_line(data, -(size - csize));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_change_file(mmfile_t *mfo, mmfile_t *mfr, double rmod,
|
||||||
|
int chmax) {
|
||||||
|
long skipln, lnsize, bsize;
|
||||||
|
char const *blk, *cur, *top, *eol;
|
||||||
|
char lnbuf[XDLT_MAX_LINE_SIZE + 1];
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mfr, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((blk = xdl_mmfile_first(mfo, &bsize)) != NULL) {
|
||||||
|
for (cur = blk, top = blk + bsize, skipln = 0;;) {
|
||||||
|
if (cur >= top) {
|
||||||
|
if ((blk = xdl_mmfile_next(mfo, &bsize)) == NULL)
|
||||||
|
break;
|
||||||
|
cur = blk;
|
||||||
|
top = blk + bsize;
|
||||||
|
}
|
||||||
|
if (!(eol = memchr(cur, '\n', top - cur)))
|
||||||
|
eol = top;
|
||||||
|
if (!skipln) {
|
||||||
|
if (DBL_RAND() < rmod) {
|
||||||
|
skipln = rand() % chmax;
|
||||||
|
if (rand() & 1) {
|
||||||
|
for (; skipln > 0; skipln--) {
|
||||||
|
lnsize = xdlt_gen_line(lnbuf, XDLT_MAX_LINE_SIZE);
|
||||||
|
if (xdl_write_mmfile(mfr, lnbuf, lnsize) != lnsize) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lnsize = (eol - cur) + 1;
|
||||||
|
if (xdl_write_mmfile(mfr, cur, lnsize) != lnsize) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
skipln--;
|
||||||
|
|
||||||
|
cur = eol + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_auto_regress(xpparam_t const *xpp, xdemitconf_t const *xecfg, long size,
|
||||||
|
double rmod, int chmax) {
|
||||||
|
mmfile_t mf1, mf2;
|
||||||
|
|
||||||
|
if (xdlt_create_file(&mf1, size) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdlt_change_file(&mf1, &mf2, rmod, chmax) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdlt_do_regress(&mf1, &mf2, xpp, xecfg) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_do_bindiff(mmfile_t *mf1, mmfile_t *mf2, bdiffparam_t const *bdp, mmfile_t *mfp) {
|
||||||
|
xdemitcb_t ecb;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mfp, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ecb.priv = mfp;
|
||||||
|
ecb.outf = xdlt_mmfile_outf;
|
||||||
|
if (xdl_bdiff(mf1, mf2, bdp, &ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_do_rabdiff(mmfile_t *mf1, mmfile_t *mf2, mmfile_t *mfp) {
|
||||||
|
xdemitcb_t ecb;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mfp, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ecb.priv = mfp;
|
||||||
|
ecb.outf = xdlt_mmfile_outf;
|
||||||
|
if (xdl_rabdiff(mf1, mf2, &ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_do_binpatch(mmfile_t *mf, mmfile_t *mfp, mmfile_t *mfr) {
|
||||||
|
xdemitcb_t ecb;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mfr, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ecb.priv = mfr;
|
||||||
|
ecb.outf = xdlt_mmfile_outf;
|
||||||
|
if (xdl_bpatch(mf, mfp, &ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_do_binregress(mmfile_t *mf1, mmfile_t *mf2, bdiffparam_t const *bdp) {
|
||||||
|
mmfile_t mfp, mfr;
|
||||||
|
|
||||||
|
if (xdlt_do_bindiff(mf1, mf2, bdp, &mfp) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdlt_do_binpatch(mf1, &mfp, &mfr) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_mmfile_cmp(&mfr, mf2)) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfr);
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mfr);
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_do_rabinregress(mmfile_t *mf1, mmfile_t *mf2) {
|
||||||
|
mmfile_t mfp, mfr;
|
||||||
|
|
||||||
|
if (xdlt_do_rabdiff(mf1, mf2, &mfp) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdlt_do_binpatch(mf1, &mfp, &mfr) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_mmfile_cmp(&mfr, mf2)) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfr);
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mfr);
|
||||||
|
xdl_free_mmfile(&mfp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_auto_binregress(bdiffparam_t const *bdp, long size,
|
||||||
|
double rmod, int chmax) {
|
||||||
|
mmfile_t mf1, mf2, mf2c;
|
||||||
|
|
||||||
|
if (xdlt_create_file(&mf1, size) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdlt_change_file(&mf1, &mf2, rmod, chmax) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_mmfile_compact(&mf2, &mf2c, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
if (xdlt_do_binregress(&mf1, &mf2c, bdp) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2c);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mf2c);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_auto_rabinregress(long size, double rmod, int chmax) {
|
||||||
|
mmfile_t mf1, mf2, mf2c;
|
||||||
|
|
||||||
|
if (xdlt_create_file(&mf1, size) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdlt_change_file(&mf1, &mf2, rmod, chmax) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_mmfile_compact(&mf2, &mf2c, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mf2);
|
||||||
|
if (xdlt_do_rabinregress(&mf1, &mf2c) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mf2c);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mf2c);
|
||||||
|
xdl_free_mmfile(&mf1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_auto_mbinregress(bdiffparam_t const *bdp, long size,
|
||||||
|
double rmod, int chmax, int n) {
|
||||||
|
int i, res;
|
||||||
|
mmbuffer_t *mbb;
|
||||||
|
mmfile_t *mf, *mfc, *mfx;
|
||||||
|
mmfile_t mfn, mff, mfd, mfb;
|
||||||
|
xdemitcb_t ecb;
|
||||||
|
|
||||||
|
if ((mbb = (mmbuffer_t *) xdl_malloc((n + 2) * sizeof(mmbuffer_t))) == NULL) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((mf = mfc = (mmfile_t *) xdl_malloc((n + 2) * sizeof(mmfile_t))) == NULL) {
|
||||||
|
|
||||||
|
xdl_free(mbb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdlt_create_file(mfc, size) < 0) {
|
||||||
|
|
||||||
|
xdl_free(mf);
|
||||||
|
xdl_free(mbb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mbb[0].ptr = (char *) xdl_mmfile_first(mfc, &mbb[0].size);
|
||||||
|
mfc++;
|
||||||
|
mfx = mf;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (xdlt_change_file(mfx, &mfn, rmod, chmax) < 0) {
|
||||||
|
|
||||||
|
if (mfx != mf) xdl_free_mmfile(mfx);
|
||||||
|
for (; i >= 0; i--)
|
||||||
|
xdl_free_mmfile(mf + i);
|
||||||
|
xdl_free(mf);
|
||||||
|
xdl_free(mbb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_mmfile_compact(&mfn, &mff, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfn);
|
||||||
|
if (mfx != mf) xdl_free_mmfile(mfx);
|
||||||
|
for (; i >= 0; i--)
|
||||||
|
xdl_free_mmfile(mf + i);
|
||||||
|
xdl_free(mf);
|
||||||
|
xdl_free(mbb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_mmfile(&mfn);
|
||||||
|
if (xdlt_do_bindiff(mfx, &mff, bdp, &mfd) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mff);
|
||||||
|
if (mfx != mf) xdl_free_mmfile(mfx);
|
||||||
|
for (; i >= 0; i--)
|
||||||
|
xdl_free_mmfile(mf + i);
|
||||||
|
xdl_free(mf);
|
||||||
|
xdl_free(mbb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (mfx != mf) xdl_free_mmfile(mfx);
|
||||||
|
mfx = &mfb;
|
||||||
|
*mfx = mff;
|
||||||
|
if (xdl_mmfile_compact(&mfd, mfc, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mfd);
|
||||||
|
xdl_free_mmfile(mfx);
|
||||||
|
for (; i >= 0; i--)
|
||||||
|
xdl_free_mmfile(mf + i);
|
||||||
|
xdl_free(mf);
|
||||||
|
xdl_free(mbb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mbb[i + 1].ptr = (char *) xdl_mmfile_first(mfc, &mbb[i + 1].size);
|
||||||
|
mfc++;
|
||||||
|
xdl_free_mmfile(&mfd);
|
||||||
|
}
|
||||||
|
if (xdl_init_mmfile(mfc, XDLT_STD_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfx);
|
||||||
|
for (i = n; i >= 0; i--)
|
||||||
|
xdl_free_mmfile(mf + i);
|
||||||
|
xdl_free(mf);
|
||||||
|
xdl_free(mbb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ecb.priv = mfc;
|
||||||
|
ecb.outf = xdlt_mmfile_outf;
|
||||||
|
if ((res = xdl_bpatch_multi(&mbb[0], &mbb[1], n, &ecb)) == 0)
|
||||||
|
res = xdl_mmfile_cmp(mfx, mfc);
|
||||||
|
|
||||||
|
xdl_free_mmfile(mfx);
|
||||||
|
for (i = n + 1; i >= 0; i--)
|
||||||
|
xdl_free_mmfile(mf + i);
|
||||||
|
xdl_free(mf);
|
||||||
|
xdl_free(mbb);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
57
gems/xdiff-rb/ext/xdiff/xdiff/test/xtestutils.h
Normal file
57
gems/xdiff-rb/ext/xdiff/xdiff/test/xtestutils.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XTESTUTILS_H)
|
||||||
|
#define XTESTUTILS_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define DBL_RAND() (((double) rand()) / (1.0 + (double) RAND_MAX))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int xdlt_dump_mmfile(char const *fname, mmfile_t *mmf);
|
||||||
|
int xdlt_load_mmfile(char const *fname, mmfile_t *mf, int binmode);
|
||||||
|
int xdlt_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdemitconf_t const *xecfg, mmfile_t *mfp);
|
||||||
|
int xdlt_do_patch(mmfile_t *mfo, mmfile_t *mfp, int mode, mmfile_t *mfr);
|
||||||
|
int xdlt_do_regress(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdemitconf_t const *xecfg);
|
||||||
|
long xdlt_gen_line(char *buf, long msize);
|
||||||
|
int xdlt_create_file(mmfile_t *mf, long size);
|
||||||
|
int xdlt_change_file(mmfile_t *mfo, mmfile_t *mfr, double rmod, int chmax);
|
||||||
|
int xdlt_auto_regress(xpparam_t const *xpp, xdemitconf_t const *xecfg, long size,
|
||||||
|
double rmod, int chmax);
|
||||||
|
int xdlt_do_bindiff(mmfile_t *mf1, mmfile_t *mf2, bdiffparam_t const *bdp, mmfile_t *mfp);
|
||||||
|
int xdlt_do_rabdiff(mmfile_t *mf1, mmfile_t *mf2, mmfile_t *mfp);
|
||||||
|
int xdlt_do_binpatch(mmfile_t *mf, mmfile_t *mfp, mmfile_t *mfr);
|
||||||
|
int xdlt_do_binregress(mmfile_t *mf1, mmfile_t *mf2, bdiffparam_t const *bdp);
|
||||||
|
int xdlt_do_rabinregress(mmfile_t *mf1, mmfile_t *mf2);
|
||||||
|
int xdlt_auto_binregress(bdiffparam_t const *bdp, long size,
|
||||||
|
double rmod, int chmax);
|
||||||
|
int xdlt_auto_rabinregress(long size, double rmod, int chmax);
|
||||||
|
int xdlt_auto_mbinregress(bdiffparam_t const *bdp, long size,
|
||||||
|
double rmod, int chmax, int n);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XTESTUTILS_H) */
|
||||||
|
|
||||||
296
gems/xdiff-rb/ext/xdiff/xdiff/tools/xrabin.c
Normal file
296
gems/xdiff-rb/ext/xdiff/xdiff/tools/xrabin.c
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
/*
|
||||||
|
* xrabin by Davide Libenzi (Rabin's polynomial generator)
|
||||||
|
* Copyright (C) 2006 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Hints, ideas and code for the implementation came from:
|
||||||
|
*
|
||||||
|
* Rabin's original paper: http://www.xmailserver.org/rabin.pdf
|
||||||
|
* Chan & Lu's paper: http://www.xmailserver.org/rabin_impl.pdf
|
||||||
|
* Broder's paper: http://www.xmailserver.org/rabin_apps.pdf
|
||||||
|
* LBFS source code: http://www.fs.net/sfswww/lbfs/
|
||||||
|
* Geert Bosch's post: http://marc.theaimsgroup.com/?l=git&m=114565424620771&w=2
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
#define strtoll _strtoi64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(XRAB_WORD_TYPE)
|
||||||
|
#if defined(WIN32)
|
||||||
|
#define XRAB_WORD_TYPE __int64
|
||||||
|
|
||||||
|
#else /* #if defined(WIN32) */
|
||||||
|
#define XRAB_WORD_TYPE long long
|
||||||
|
|
||||||
|
#endif /* #if defined(WIN32) */
|
||||||
|
#endif /* #if !defined(XRAB_WORD_TYPE) */
|
||||||
|
|
||||||
|
#if !defined(XRAB_WORD_PFMT)
|
||||||
|
#if defined(WIN32)
|
||||||
|
#define XRAB_WORD_PFMT "0x%I64x"
|
||||||
|
|
||||||
|
#else /* #if defined(WIN32) */
|
||||||
|
#define XRAB_WORD_PFMT "0x%llx"
|
||||||
|
|
||||||
|
#endif /* #if defined(WIN32) */
|
||||||
|
#endif /* #if !defined(XRAB_WORD_PFMT) */
|
||||||
|
|
||||||
|
#define XPLYW_BITS (sizeof(xply_word) * 8)
|
||||||
|
#define XPLYW_MSB ((xply_word) 1 << (sizeof(xply_word) * 8 - 1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef unsigned XRAB_WORD_TYPE xply_word;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int xrab_isprime(int n) {
|
||||||
|
|
||||||
|
if (n > 3) {
|
||||||
|
if (n & 1) {
|
||||||
|
int i, hn = n / 2;
|
||||||
|
|
||||||
|
for (i = 3; i < hn; i += 2)
|
||||||
|
if (!(n % i))
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xrab_fls(xply_word v) {
|
||||||
|
int r, s;
|
||||||
|
xply_word mask = ~(((xply_word) 1 << (XPLYW_BITS / 2)) - 1);
|
||||||
|
|
||||||
|
if (v == 0)
|
||||||
|
return 0;
|
||||||
|
for (r = XPLYW_BITS, s = r / 2; s != 0;) {
|
||||||
|
if ((v & mask) == 0) {
|
||||||
|
v <<= s;
|
||||||
|
r -= s;
|
||||||
|
}
|
||||||
|
s /= 2;
|
||||||
|
mask <<= s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static xply_word xrab_polymod(xply_word nh, xply_word nl, xply_word d) {
|
||||||
|
int i, k = xrab_fls(d) - 1;
|
||||||
|
|
||||||
|
d <<= (XPLYW_BITS - 1) - k;
|
||||||
|
if (nh) {
|
||||||
|
if (nh & XPLYW_MSB)
|
||||||
|
nh ^= d;
|
||||||
|
for (i = XPLYW_BITS - 2; i >= 0; i--)
|
||||||
|
if (nh & ((xply_word) 1) << i) {
|
||||||
|
nh ^= d >> (XPLYW_BITS - 1) - i;
|
||||||
|
nl ^= d << i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = XPLYW_BITS - 1; i >= k; i--)
|
||||||
|
if (nl & ((xply_word) 1 << i))
|
||||||
|
nl ^= d >> (XPLYW_BITS - 1) - i;
|
||||||
|
|
||||||
|
return nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static xply_word xrab_polygcd(xply_word x, xply_word y) {
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (!y)
|
||||||
|
return x;
|
||||||
|
x = xrab_polymod(0, x, y);
|
||||||
|
if (!x)
|
||||||
|
return y;
|
||||||
|
y = xrab_polymod(0, y, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xrab_polymult(xply_word *php, xply_word *plp, xply_word x,
|
||||||
|
xply_word y) {
|
||||||
|
int i;
|
||||||
|
xply_word ph = 0, pl = 0;
|
||||||
|
|
||||||
|
if (x & 1)
|
||||||
|
pl = y;
|
||||||
|
for (i = 1; i < XPLYW_BITS; i++)
|
||||||
|
if (x & (((xply_word) 1) << i)) {
|
||||||
|
ph ^= y >> (XPLYW_BITS - i);
|
||||||
|
pl ^= y << i;
|
||||||
|
}
|
||||||
|
if (php)
|
||||||
|
*php = ph;
|
||||||
|
if (plp)
|
||||||
|
*plp = pl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static xply_word xrab_polymmult(xply_word x, xply_word y, xply_word d) {
|
||||||
|
xply_word h, l;
|
||||||
|
|
||||||
|
xrab_polymult(&h, &l, x, y);
|
||||||
|
|
||||||
|
return xrab_polymod(h, l, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xrab_polyirreducible(xply_word f) {
|
||||||
|
xply_word u = 2;
|
||||||
|
int i, m = (xrab_fls(f) - 1) >> 1;
|
||||||
|
|
||||||
|
for (i = 0; i < m; i++) {
|
||||||
|
u = xrab_polymmult(u, u, f);
|
||||||
|
if (xrab_polygcd(f, u ^ 2) != 1)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xrab_rndgen(xply_word *f) {
|
||||||
|
unsigned int i;
|
||||||
|
xply_word g;
|
||||||
|
|
||||||
|
for (i = 0, g = 0; i < sizeof(xply_word); i++)
|
||||||
|
g ^= (g << 11) + (unsigned int) rand() + (g >> 7);
|
||||||
|
*f = g;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xrab_polygen(int degree, xply_word *ply) {
|
||||||
|
xply_word msb, mask, f;
|
||||||
|
|
||||||
|
if (degree <= 0 || degree >= XPLYW_BITS)
|
||||||
|
return -1;
|
||||||
|
msb = ((xply_word) 1) << degree;
|
||||||
|
mask = msb - 1;
|
||||||
|
srand(time(NULL));
|
||||||
|
do {
|
||||||
|
xrab_rndgen(&f);
|
||||||
|
f = (f & mask) | msb;
|
||||||
|
} while (!xrab_polyirreducible(f));
|
||||||
|
*ply = f;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xarb_calc_tu(xply_word poly, int size, xply_word *t, xply_word *u) {
|
||||||
|
int j, xshift, shift;
|
||||||
|
xply_word t1, ssh;
|
||||||
|
|
||||||
|
xshift = xrab_fls(poly) - 1;
|
||||||
|
shift = xshift - 8;
|
||||||
|
if (shift < 0)
|
||||||
|
return -1;
|
||||||
|
t1 = xrab_polymod(0, ((xply_word) 1) << xshift, poly);
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
t[j] = xrab_polymmult(j, t1, poly) | ((xply_word) j << xshift);
|
||||||
|
for (j = 1, ssh = 1; j < size; j++)
|
||||||
|
ssh = (ssh << 8) ^ t[ssh >> shift];
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
u[j] = xrab_polymmult(j, ssh, poly);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int ac, char **av) {
|
||||||
|
int i, size = 20, degree = 0, shift;
|
||||||
|
xply_word ply = 0, t[256], u[256];
|
||||||
|
|
||||||
|
for (i = 1; i < ac; i++) {
|
||||||
|
if (strcmp(av[i], "-s") == 0) {
|
||||||
|
if (++i < ac)
|
||||||
|
size = atol(av[i]);
|
||||||
|
} else if (strcmp(av[i], "-p") == 0) {
|
||||||
|
if (++i < ac)
|
||||||
|
ply = (xply_word) strtoll(av[i], NULL, 16);
|
||||||
|
} else if (strcmp(av[i], "-d") == 0) {
|
||||||
|
if (++i < ac)
|
||||||
|
degree = atol(av[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (degree && (degree < 8 || degree >= XPLYW_BITS)) {
|
||||||
|
fprintf(stderr, "degree (%d) out of bound for the poly word size (8..%u)\n",
|
||||||
|
degree, XPLYW_BITS);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (degree == 0)
|
||||||
|
for (degree = XPLYW_BITS - 1; !xrab_isprime(degree); degree--);
|
||||||
|
if (ply == 0 && xrab_polygen(degree, &ply) < 0)
|
||||||
|
return 2;
|
||||||
|
shift = (xrab_fls(ply) - 1) - 8;
|
||||||
|
fprintf(stderr, "found poly = " XRAB_WORD_PFMT " (shift %d)\n",
|
||||||
|
ply, shift);
|
||||||
|
if (xarb_calc_tu(ply, size, t, u) < 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
fprintf(stdout, "#if defined(XRABPLY_TYPE%d)\n\n", XPLYW_BITS);
|
||||||
|
fprintf(stdout, "#if !defined(XV%d)\n", XPLYW_BITS);
|
||||||
|
fprintf(stdout, "#define XV%d(v) ((xply_word) v ## ULL)\n", XPLYW_BITS);
|
||||||
|
fprintf(stdout, "#endif\n\n");
|
||||||
|
fprintf(stdout, "#define XRAB_ROOTPOLY XV%d(" XRAB_WORD_PFMT ")\n\n",
|
||||||
|
XPLYW_BITS, ply);
|
||||||
|
fprintf(stdout, "#define XRAB_SHIFT %d\n", shift);
|
||||||
|
fprintf(stdout, "#define XRAB_WNDSIZE %d\n\n", size);
|
||||||
|
fprintf(stdout, "typedef unsigned XRABPLY_TYPE%d xply_word;\n\n", XPLYW_BITS);
|
||||||
|
fprintf(stdout, "static const xply_word T[256] = {\n");
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
if (i) {
|
||||||
|
fputs(",", stdout);
|
||||||
|
if (i % 4 == 0)
|
||||||
|
fputs("\n\t", stdout);
|
||||||
|
else
|
||||||
|
fputs(" ", stdout);
|
||||||
|
} else
|
||||||
|
fputs("\t", stdout);
|
||||||
|
fprintf(stdout, "XV%d(" XRAB_WORD_PFMT ")", XPLYW_BITS, t[i]);
|
||||||
|
}
|
||||||
|
fprintf(stdout, "\n};\n\n");
|
||||||
|
|
||||||
|
fprintf(stdout, "static const xply_word U[256] = {\n");
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
if (i) {
|
||||||
|
fputs(",", stdout);
|
||||||
|
if (i % 4 == 0)
|
||||||
|
fputs("\n\t", stdout);
|
||||||
|
else
|
||||||
|
fputs(" ", stdout);
|
||||||
|
} else
|
||||||
|
fputs("\t", stdout);
|
||||||
|
fprintf(stdout, "XV%d(" XRAB_WORD_PFMT ")", XPLYW_BITS, u[i]);
|
||||||
|
}
|
||||||
|
fprintf(stdout, "\n};\n\n");
|
||||||
|
|
||||||
|
fprintf(stdout, "#endif /* if defined(XRABPLY_TYPE%d) */\n\n", XPLYW_BITS);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
70
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xadler32.c
Normal file
70
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xadler32.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* largest prime smaller than 65536 */
|
||||||
|
#define BASE 65521L
|
||||||
|
|
||||||
|
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||||
|
#define NMAX 5552
|
||||||
|
|
||||||
|
|
||||||
|
#define DO1(buf, i) { s1 += buf[i]; s2 += s1; }
|
||||||
|
#define DO2(buf, i) DO1(buf, i); DO1(buf, i + 1);
|
||||||
|
#define DO4(buf, i) DO2(buf, i); DO2(buf, i + 2);
|
||||||
|
#define DO8(buf, i) DO4(buf, i); DO4(buf, i + 4);
|
||||||
|
#define DO16(buf) DO8(buf, 0); DO8(buf, 8);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long xdl_adler32(unsigned long adler, unsigned char const *buf,
|
||||||
|
unsigned int len) {
|
||||||
|
int k;
|
||||||
|
unsigned long s1 = adler & 0xffff;
|
||||||
|
unsigned long s2 = (adler >> 16) & 0xffff;
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
k = len < NMAX ? len :NMAX;
|
||||||
|
len -= k;
|
||||||
|
while (k >= 16) {
|
||||||
|
DO16(buf);
|
||||||
|
buf += 16;
|
||||||
|
k -= 16;
|
||||||
|
}
|
||||||
|
if (k != 0)
|
||||||
|
do {
|
||||||
|
s1 += *buf++;
|
||||||
|
s2 += s1;
|
||||||
|
} while (--k);
|
||||||
|
s1 %= BASE;
|
||||||
|
s2 %= BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (s2 << 16) | s1;
|
||||||
|
}
|
||||||
|
|
||||||
34
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xadler32.h
Normal file
34
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xadler32.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XADLER32_H)
|
||||||
|
#define XADLER32_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long xdl_adler32(unsigned long adler, unsigned char const *buf,
|
||||||
|
unsigned int len);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XADLER32_H) */
|
||||||
|
|
||||||
51
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xalloc.c
Normal file
51
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xalloc.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static memallocator_t xmalt = {NULL, NULL, NULL};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_set_allocator(memallocator_t const *malt) {
|
||||||
|
xmalt = *malt;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_malloc(unsigned int size) {
|
||||||
|
return xmalt.malloc ? xmalt.malloc(xmalt.priv, size): NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xdl_free(void *ptr) {
|
||||||
|
if (xmalt.free)
|
||||||
|
xmalt.free(xmalt.priv, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_realloc(void *ptr, unsigned int size) {
|
||||||
|
return xmalt.realloc ? xmalt.realloc(xmalt.priv, ptr, size): NULL;
|
||||||
|
}
|
||||||
|
|
||||||
315
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xbdiff.c
Normal file
315
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xbdiff.c
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct s_bdrecord {
|
||||||
|
struct s_bdrecord *next;
|
||||||
|
unsigned long fp;
|
||||||
|
char const *ptr;
|
||||||
|
} bdrecord_t;
|
||||||
|
|
||||||
|
typedef struct s_bdfile {
|
||||||
|
char const *data, *top;
|
||||||
|
chastore_t cha;
|
||||||
|
unsigned int fphbits;
|
||||||
|
bdrecord_t **fphash;
|
||||||
|
} bdfile_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_prepare_bdfile(mmbuffer_t *mmb, long fpbsize, bdfile_t *bdf) {
|
||||||
|
unsigned int fphbits;
|
||||||
|
long i, size, hsize;
|
||||||
|
char const *base, *data, *top;
|
||||||
|
bdrecord_t *brec;
|
||||||
|
bdrecord_t **fphash;
|
||||||
|
|
||||||
|
fphbits = xdl_hashbits((unsigned int) (mmb->size / fpbsize) + 1);
|
||||||
|
hsize = 1 << fphbits;
|
||||||
|
if (!(fphash = (bdrecord_t **) xdl_malloc(hsize * sizeof(bdrecord_t *)))) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < hsize; i++)
|
||||||
|
fphash[i] = NULL;
|
||||||
|
|
||||||
|
if (xdl_cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1) < 0) {
|
||||||
|
|
||||||
|
xdl_free(fphash);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(size = mmb->size)) {
|
||||||
|
bdf->data = bdf->top = NULL;
|
||||||
|
} else {
|
||||||
|
bdf->data = data = base = mmb->ptr;
|
||||||
|
bdf->top = top = mmb->ptr + mmb->size;
|
||||||
|
|
||||||
|
if ((data += (size / fpbsize) * fpbsize) == top)
|
||||||
|
data -= fpbsize;
|
||||||
|
|
||||||
|
for (; data >= base; data -= fpbsize) {
|
||||||
|
if (!(brec = (bdrecord_t *) xdl_cha_alloc(&bdf->cha))) {
|
||||||
|
|
||||||
|
xdl_cha_free(&bdf->cha);
|
||||||
|
xdl_free(fphash);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
brec->fp = xdl_adler32(0, (unsigned char const *) data,
|
||||||
|
XDL_MIN(fpbsize, (long) (top - data)));
|
||||||
|
brec->ptr = data;
|
||||||
|
|
||||||
|
i = (long) XDL_HASHLONG(brec->fp, fphbits);
|
||||||
|
brec->next = fphash[i];
|
||||||
|
fphash[i] = brec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bdf->fphbits = fphbits;
|
||||||
|
bdf->fphash = fphash;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void xdl_free_bdfile(bdfile_t *bdf) {
|
||||||
|
|
||||||
|
xdl_free(bdf->fphash);
|
||||||
|
xdl_cha_free(&bdf->cha);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long xdl_mmb_adler32(mmbuffer_t *mmb) {
|
||||||
|
|
||||||
|
return mmb->size ? xdl_adler32(0, (unsigned char const *) mmb->ptr, mmb->size): 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long xdl_mmf_adler32(mmfile_t *mmf) {
|
||||||
|
unsigned long fp = 0;
|
||||||
|
long size;
|
||||||
|
char const *blk;
|
||||||
|
|
||||||
|
if ((blk = (char const *) xdl_mmfile_first(mmf, &size)) != NULL) {
|
||||||
|
do {
|
||||||
|
fp = xdl_adler32(fp, (unsigned char const *) blk, size);
|
||||||
|
} while ((blk = (char const *) xdl_mmfile_next(mmf, &size)) != NULL);
|
||||||
|
}
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_bdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, bdiffparam_t const *bdp, xdemitcb_t *ecb) {
|
||||||
|
long i, rsize, size, bsize, csize, msize, moff;
|
||||||
|
unsigned long fp;
|
||||||
|
char const *blk, *base, *data, *top, *ptr1, *ptr2;
|
||||||
|
bdrecord_t *brec;
|
||||||
|
bdfile_t bdf;
|
||||||
|
mmbuffer_t mb[2];
|
||||||
|
unsigned char cpybuf[32];
|
||||||
|
|
||||||
|
if ((bsize = bdp->bsize) < XDL_MIN_BLKSIZE)
|
||||||
|
bsize = XDL_MIN_BLKSIZE;
|
||||||
|
if (xdl_prepare_bdfile(mmb1, bsize, &bdf) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare and emit the binary patch file header. It will be used
|
||||||
|
* to verify that that file being patched matches in size and fingerprint
|
||||||
|
* the one that generated the patch.
|
||||||
|
*/
|
||||||
|
fp = xdl_mmb_adler32(mmb1);
|
||||||
|
size = mmb1->size;
|
||||||
|
XDL_LE32_PUT(cpybuf, fp);
|
||||||
|
XDL_LE32_PUT(cpybuf + 4, size);
|
||||||
|
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = 4 + 4;
|
||||||
|
|
||||||
|
if (ecb->outf(ecb->priv, mb, 1) < 0) {
|
||||||
|
|
||||||
|
xdl_free_bdfile(&bdf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((blk = (char const *) mmb2->ptr) != NULL) {
|
||||||
|
size = mmb2->size;
|
||||||
|
for (base = data = blk, top = data + size; data < top;) {
|
||||||
|
rsize = XDL_MIN(bsize, (long) (top - data));
|
||||||
|
fp = xdl_adler32(0, (unsigned char const *) data, rsize);
|
||||||
|
|
||||||
|
i = (long) XDL_HASHLONG(fp, bdf.fphbits);
|
||||||
|
for (msize = 0, brec = bdf.fphash[i]; brec; brec = brec->next)
|
||||||
|
if (brec->fp == fp) {
|
||||||
|
csize = XDL_MIN((long) (top - data), (long) (bdf.top - brec->ptr));
|
||||||
|
for (ptr1 = brec->ptr, ptr2 = data; csize && *ptr1 == *ptr2;
|
||||||
|
csize--, ptr1++, ptr2++);
|
||||||
|
|
||||||
|
if ((csize = (long) (ptr1 - brec->ptr)) > msize) {
|
||||||
|
moff = (long) (brec->ptr - bdf.data);
|
||||||
|
msize = csize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msize < XDL_COPYOP_SIZE) {
|
||||||
|
data++;
|
||||||
|
} else {
|
||||||
|
if (data > base) {
|
||||||
|
i = (long) (data - base);
|
||||||
|
if (i > 255) {
|
||||||
|
cpybuf[0] = XDL_BDOP_INSB;
|
||||||
|
XDL_LE32_PUT(cpybuf + 1, i);
|
||||||
|
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = XDL_INSBOP_SIZE;
|
||||||
|
} else {
|
||||||
|
cpybuf[0] = XDL_BDOP_INS;
|
||||||
|
cpybuf[1] = (unsigned char) i;
|
||||||
|
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = 2;
|
||||||
|
}
|
||||||
|
mb[1].ptr = (char *) base;
|
||||||
|
mb[1].size = i;
|
||||||
|
|
||||||
|
if (ecb->outf(ecb->priv, mb, 2) < 0) {
|
||||||
|
|
||||||
|
xdl_free_bdfile(&bdf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data += msize;
|
||||||
|
|
||||||
|
cpybuf[0] = XDL_BDOP_CPY;
|
||||||
|
XDL_LE32_PUT(cpybuf + 1, moff);
|
||||||
|
XDL_LE32_PUT(cpybuf + 5, msize);
|
||||||
|
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = XDL_COPYOP_SIZE;
|
||||||
|
|
||||||
|
if (ecb->outf(ecb->priv, mb, 1) < 0) {
|
||||||
|
|
||||||
|
xdl_free_bdfile(&bdf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
base = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data > base) {
|
||||||
|
i = (long) (data - base);
|
||||||
|
if (i > 255) {
|
||||||
|
cpybuf[0] = XDL_BDOP_INSB;
|
||||||
|
XDL_LE32_PUT(cpybuf + 1, i);
|
||||||
|
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = XDL_INSBOP_SIZE;
|
||||||
|
} else {
|
||||||
|
cpybuf[0] = XDL_BDOP_INS;
|
||||||
|
cpybuf[1] = (unsigned char) i;
|
||||||
|
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = 2;
|
||||||
|
}
|
||||||
|
mb[1].ptr = (char *) base;
|
||||||
|
mb[1].size = i;
|
||||||
|
|
||||||
|
if (ecb->outf(ecb->priv, mb, 2) < 0) {
|
||||||
|
|
||||||
|
xdl_free_bdfile(&bdf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xdl_free_bdfile(&bdf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_bdiff(mmfile_t *mmf1, mmfile_t *mmf2, bdiffparam_t const *bdp, xdemitcb_t *ecb) {
|
||||||
|
mmbuffer_t mmb1, mmb2;
|
||||||
|
|
||||||
|
if (!xdl_mmfile_iscompact(mmf1) || !xdl_mmfile_iscompact(mmf2)) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mmb1.ptr = (char *) xdl_mmfile_first(mmf1, &mmb1.size)) == NULL)
|
||||||
|
mmb1.size = 0;
|
||||||
|
if ((mmb2.ptr = (char *) xdl_mmfile_first(mmf2, &mmb2.size)) == NULL)
|
||||||
|
mmb2.size = 0;
|
||||||
|
|
||||||
|
return xdl_bdiff_mb(&mmb1, &mmb2, bdp, ecb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_bdiff_tgsize(mmfile_t *mmfp) {
|
||||||
|
long tgsize = 0, size, off, csize;
|
||||||
|
char const *blk;
|
||||||
|
unsigned char const *data, *top;
|
||||||
|
|
||||||
|
if ((blk = (char const *) xdl_mmfile_first(mmfp, &size)) == NULL ||
|
||||||
|
size < XDL_BPATCH_HDR_SIZE) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
blk += XDL_BPATCH_HDR_SIZE;
|
||||||
|
size -= XDL_BPATCH_HDR_SIZE;
|
||||||
|
|
||||||
|
do {
|
||||||
|
for (data = (unsigned char const *) blk, top = data + size;
|
||||||
|
data < top;) {
|
||||||
|
if (*data == XDL_BDOP_INS) {
|
||||||
|
data++;
|
||||||
|
csize = (long) *data++;
|
||||||
|
tgsize += csize;
|
||||||
|
data += csize;
|
||||||
|
} else if (*data == XDL_BDOP_INSB) {
|
||||||
|
data++;
|
||||||
|
XDL_LE32_GET(data, csize);
|
||||||
|
data += 4;
|
||||||
|
tgsize += csize;
|
||||||
|
data += csize;
|
||||||
|
} else if (*data == XDL_BDOP_CPY) {
|
||||||
|
data++;
|
||||||
|
XDL_LE32_GET(data, off);
|
||||||
|
data += 4;
|
||||||
|
XDL_LE32_GET(data, csize);
|
||||||
|
data += 4;
|
||||||
|
tgsize += csize;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ((blk = (char const *) xdl_mmfile_next(mmfp, &size)) != NULL);
|
||||||
|
|
||||||
|
return tgsize;
|
||||||
|
}
|
||||||
|
|
||||||
40
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xbdiff.h
Normal file
40
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xbdiff.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XBDIFF_H)
|
||||||
|
#define XBDIFF_H
|
||||||
|
|
||||||
|
|
||||||
|
#define XDL_BPATCH_HDR_SIZE (4 + 4)
|
||||||
|
#define XDL_MIN_BLKSIZE 16
|
||||||
|
#define XDL_INSBOP_SIZE (1 + 4)
|
||||||
|
#define XDL_COPYOP_SIZE (1 + 4 + 4)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long xdl_mmb_adler32(mmbuffer_t *mmb);
|
||||||
|
unsigned long xdl_mmf_adler32(mmfile_t *mmf);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XBDIFF_H) */
|
||||||
|
|
||||||
336
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xbpatchi.c
Normal file
336
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xbpatchi.c
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define XDL_MOBF_MINALLOC 128
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct s_mmoffbuffer {
|
||||||
|
long off, size;
|
||||||
|
char *ptr;
|
||||||
|
} mmoffbuffer_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_copy_range(mmfile_t *mmf, long off, long size, xdemitcb_t *ecb) {
|
||||||
|
if (xdl_seek_mmfile(mmf, off) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_copy_mmfile(mmf, size, ecb) != size) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_bpatch(mmfile_t *mmf, mmfile_t *mmfp, xdemitcb_t *ecb) {
|
||||||
|
long size, off, csize, osize;
|
||||||
|
unsigned long fp, ofp;
|
||||||
|
char const *blk;
|
||||||
|
unsigned char const *data, *top;
|
||||||
|
mmbuffer_t mb;
|
||||||
|
|
||||||
|
if ((blk = (char const *) xdl_mmfile_first(mmfp, &size)) == NULL ||
|
||||||
|
size < XDL_BPATCH_HDR_SIZE) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ofp = xdl_mmf_adler32(mmf);
|
||||||
|
osize = xdl_mmfile_size(mmf);
|
||||||
|
XDL_LE32_GET(blk, fp);
|
||||||
|
XDL_LE32_GET(blk + 4, csize);
|
||||||
|
if (fp != ofp || csize != osize) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk += XDL_BPATCH_HDR_SIZE;
|
||||||
|
size -= XDL_BPATCH_HDR_SIZE;
|
||||||
|
|
||||||
|
do {
|
||||||
|
for (data = (unsigned char const *) blk, top = data + size;
|
||||||
|
data < top;) {
|
||||||
|
if (*data == XDL_BDOP_INS) {
|
||||||
|
data++;
|
||||||
|
|
||||||
|
mb.size = (long) *data++;
|
||||||
|
mb.ptr = (char *) data;
|
||||||
|
data += mb.size;
|
||||||
|
|
||||||
|
if (ecb->outf(ecb->priv, &mb, 1) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (*data == XDL_BDOP_INSB) {
|
||||||
|
data++;
|
||||||
|
XDL_LE32_GET(data, csize);
|
||||||
|
data += 4;
|
||||||
|
|
||||||
|
mb.size = csize;
|
||||||
|
mb.ptr = (char *) data;
|
||||||
|
data += mb.size;
|
||||||
|
|
||||||
|
if (ecb->outf(ecb->priv, &mb, 1) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (*data == XDL_BDOP_CPY) {
|
||||||
|
data++;
|
||||||
|
XDL_LE32_GET(data, off);
|
||||||
|
data += 4;
|
||||||
|
XDL_LE32_GET(data, csize);
|
||||||
|
data += 4;
|
||||||
|
|
||||||
|
if (xdl_copy_range(mmf, off, csize, ecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ((blk = (char const *) xdl_mmfile_next(mmfp, &size)) != NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned long xdl_mmob_adler32(mmoffbuffer_t *obf, int n) {
|
||||||
|
unsigned long ha;
|
||||||
|
|
||||||
|
for (ha = 0; n > 0; n--, obf++)
|
||||||
|
ha = xdl_adler32(ha, (unsigned char const *) obf->ptr, obf->size);
|
||||||
|
|
||||||
|
return ha;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static long xdl_mmob_size(mmoffbuffer_t *obf, int n) {
|
||||||
|
|
||||||
|
return n > 0 ? obf[n - 1].off + obf[n - 1].size: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static mmoffbuffer_t *xdl_mmob_new(mmoffbuffer_t **probf, int *pnobf, int *paobf) {
|
||||||
|
int aobf;
|
||||||
|
mmoffbuffer_t *cobf, *rrobf;
|
||||||
|
|
||||||
|
if (*pnobf >= *paobf) {
|
||||||
|
aobf = 2 * (*paobf) + 1;
|
||||||
|
if ((rrobf = (mmoffbuffer_t *)
|
||||||
|
xdl_realloc(*probf, aobf * sizeof(mmoffbuffer_t))) == NULL) {
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*probf = rrobf;
|
||||||
|
*paobf = aobf;
|
||||||
|
}
|
||||||
|
cobf = (*probf) + (*pnobf);
|
||||||
|
(*pnobf)++;
|
||||||
|
|
||||||
|
return cobf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_mmob_find_cntr(mmoffbuffer_t *obf, int n, long off) {
|
||||||
|
int i, lo, hi;
|
||||||
|
|
||||||
|
for (lo = -1, hi = n; hi - lo > 1;) {
|
||||||
|
i = (hi + lo) / 2;
|
||||||
|
if (off < obf[i].off)
|
||||||
|
hi = i;
|
||||||
|
else
|
||||||
|
lo = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (lo >= 0 && off >= obf[lo].off && off < obf[lo].off + obf[lo].size) ? lo: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_bmerge(mmoffbuffer_t *obf, int n, mmbuffer_t *mbfp, mmoffbuffer_t **probf,
|
||||||
|
int *pnobf) {
|
||||||
|
int i, aobf, nobf;
|
||||||
|
long ooff, off, csize;
|
||||||
|
unsigned long fp, ofp;
|
||||||
|
unsigned char const *data, *top;
|
||||||
|
mmoffbuffer_t *robf, *cobf;
|
||||||
|
|
||||||
|
if (mbfp->size < XDL_BPATCH_HDR_SIZE) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data = (unsigned char const *) mbfp->ptr;
|
||||||
|
top = data + mbfp->size;
|
||||||
|
|
||||||
|
ofp = xdl_mmob_adler32(obf, n);
|
||||||
|
XDL_LE32_GET(data, fp);
|
||||||
|
data += 4;
|
||||||
|
XDL_LE32_GET(data, csize);
|
||||||
|
data += 4;
|
||||||
|
if (fp != ofp || csize != xdl_mmob_size(obf, n)) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
aobf = XDL_MOBF_MINALLOC;
|
||||||
|
nobf = 0;
|
||||||
|
if ((robf = (mmoffbuffer_t *) xdl_malloc(aobf * sizeof(mmoffbuffer_t))) == NULL) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ooff = 0; data < top;) {
|
||||||
|
if (*data == XDL_BDOP_INS) {
|
||||||
|
data++;
|
||||||
|
|
||||||
|
if ((cobf = xdl_mmob_new(&robf, &nobf, &aobf)) == NULL) {
|
||||||
|
|
||||||
|
xdl_free(robf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cobf->off = ooff;
|
||||||
|
cobf->size = (long) *data++;
|
||||||
|
cobf->ptr = (char *) data;
|
||||||
|
|
||||||
|
data += cobf->size;
|
||||||
|
ooff += cobf->size;
|
||||||
|
} else if (*data == XDL_BDOP_INSB) {
|
||||||
|
data++;
|
||||||
|
XDL_LE32_GET(data, csize);
|
||||||
|
data += 4;
|
||||||
|
|
||||||
|
if ((cobf = xdl_mmob_new(&robf, &nobf, &aobf)) == NULL) {
|
||||||
|
|
||||||
|
xdl_free(robf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cobf->off = ooff;
|
||||||
|
cobf->size = csize;
|
||||||
|
cobf->ptr = (char *) data;
|
||||||
|
|
||||||
|
data += cobf->size;
|
||||||
|
ooff += cobf->size;
|
||||||
|
} else if (*data == XDL_BDOP_CPY) {
|
||||||
|
data++;
|
||||||
|
XDL_LE32_GET(data, off);
|
||||||
|
data += 4;
|
||||||
|
XDL_LE32_GET(data, csize);
|
||||||
|
data += 4;
|
||||||
|
|
||||||
|
if ((i = xdl_mmob_find_cntr(obf, n, off)) < 0) {
|
||||||
|
|
||||||
|
xdl_free(robf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
off -= obf[i].off;
|
||||||
|
for (; i < n && csize > 0; i++, off = 0) {
|
||||||
|
if ((cobf = xdl_mmob_new(&robf, &nobf, &aobf)) == NULL) {
|
||||||
|
|
||||||
|
xdl_free(robf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cobf->off = ooff;
|
||||||
|
cobf->size = XDL_MIN(csize, obf[i].size - off);
|
||||||
|
cobf->ptr = obf[i].ptr + off;
|
||||||
|
|
||||||
|
ooff += cobf->size;
|
||||||
|
csize -= cobf->size;
|
||||||
|
}
|
||||||
|
if (csize > 0) {
|
||||||
|
|
||||||
|
xdl_free(robf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
xdl_free(robf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*probf = robf;
|
||||||
|
*pnobf = nobf;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_bmerge_synt(mmoffbuffer_t *obf, int n, xdemitcb_t *ecb) {
|
||||||
|
int i;
|
||||||
|
mmbuffer_t *mb;
|
||||||
|
|
||||||
|
if ((mb = (mmbuffer_t *) xdl_malloc(n * sizeof(mmbuffer_t))) == NULL) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
mb[i].ptr = obf[i].ptr;
|
||||||
|
mb[i].size = obf[i].size;
|
||||||
|
}
|
||||||
|
if (ecb->outf(ecb->priv, mb, n) < 0) {
|
||||||
|
|
||||||
|
xdl_free(mb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free(mb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_bpatch_multi(mmbuffer_t *base, mmbuffer_t *mbpch, int n, xdemitcb_t *ecb) {
|
||||||
|
int i, nobf, fnobf;
|
||||||
|
mmoffbuffer_t *obf, *fobf;
|
||||||
|
|
||||||
|
nobf = 1;
|
||||||
|
if ((obf = (mmoffbuffer_t *) xdl_malloc(nobf * sizeof(mmoffbuffer_t))) == NULL) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
obf->off = 0;
|
||||||
|
obf->ptr = base->ptr;
|
||||||
|
obf->size = base->size;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (xdl_bmerge(obf, nobf, &mbpch[i], &fobf, &fnobf) < 0) {
|
||||||
|
|
||||||
|
xdl_free(obf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free(obf);
|
||||||
|
|
||||||
|
obf = fobf;
|
||||||
|
nobf = fnobf;
|
||||||
|
}
|
||||||
|
if (xdl_bmerge_synt(obf, nobf, ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free(obf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free(obf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
144
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xdiff.h
Normal file
144
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xdiff.h
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XDIFF_H)
|
||||||
|
#define XDIFF_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* #ifdef __cplusplus */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef LIBXDIFF_DLL_EXPORT
|
||||||
|
#define LIBXDIFF_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define LIBXDIFF_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define LIBXDIFF_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define XDF_NEED_MINIMAL (1 << 1)
|
||||||
|
|
||||||
|
#define XDL_PATCH_NORMAL '-'
|
||||||
|
#define XDL_PATCH_REVERSE '+'
|
||||||
|
#define XDL_PATCH_MODEMASK ((1 << 8) - 1)
|
||||||
|
#define XDL_PATCH_IGNOREBSPACE (1 << 8)
|
||||||
|
|
||||||
|
#define XDL_MMB_READONLY (1 << 0)
|
||||||
|
|
||||||
|
#define XDL_MMF_ATOMIC (1 << 0)
|
||||||
|
|
||||||
|
#define XDL_BDOP_INS 1
|
||||||
|
#define XDL_BDOP_CPY 2
|
||||||
|
#define XDL_BDOP_INSB 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT typedef struct s_memallocator {
|
||||||
|
void *priv;
|
||||||
|
void *(*malloc)(void *, unsigned int);
|
||||||
|
void (*free)(void *, void *);
|
||||||
|
void *(*realloc)(void *, void *, unsigned int);
|
||||||
|
} memallocator_t;
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT typedef struct s_mmblock {
|
||||||
|
struct s_mmblock *next;
|
||||||
|
unsigned long flags;
|
||||||
|
long size, bsize;
|
||||||
|
char *ptr;
|
||||||
|
} mmblock_t;
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT typedef struct s_mmfile {
|
||||||
|
unsigned long flags;
|
||||||
|
mmblock_t *head, *tail;
|
||||||
|
long bsize, fsize, rpos;
|
||||||
|
mmblock_t *rcur, *wcur;
|
||||||
|
} mmfile_t;
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT typedef struct s_mmbuffer {
|
||||||
|
char *ptr;
|
||||||
|
long size;
|
||||||
|
} mmbuffer_t;
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT typedef struct s_xpparam {
|
||||||
|
unsigned long flags;
|
||||||
|
} xpparam_t;
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT typedef struct s_xdemitcb {
|
||||||
|
void *priv;
|
||||||
|
int (*outf)(void *, mmbuffer_t *, int);
|
||||||
|
} xdemitcb_t;
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT typedef struct s_xdemitconf {
|
||||||
|
long ctxlen;
|
||||||
|
} xdemitconf_t;
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT typedef struct s_bdiffparam {
|
||||||
|
long bsize;
|
||||||
|
} bdiffparam_t;
|
||||||
|
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT int xdl_set_allocator(memallocator_t const *malt);
|
||||||
|
LIBXDIFF_EXPORT void *xdl_malloc(unsigned int size);
|
||||||
|
LIBXDIFF_EXPORT void xdl_free(void *ptr);
|
||||||
|
LIBXDIFF_EXPORT void *xdl_realloc(void *ptr, unsigned int size);
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT int xdl_init_mmfile(mmfile_t *mmf, long bsize, unsigned long flags);
|
||||||
|
LIBXDIFF_EXPORT void xdl_free_mmfile(mmfile_t *mmf);
|
||||||
|
LIBXDIFF_EXPORT int xdl_mmfile_iscompact(mmfile_t *mmf);
|
||||||
|
LIBXDIFF_EXPORT int xdl_seek_mmfile(mmfile_t *mmf, long off);
|
||||||
|
LIBXDIFF_EXPORT long xdl_read_mmfile(mmfile_t *mmf, void *data, long size);
|
||||||
|
LIBXDIFF_EXPORT long xdl_write_mmfile(mmfile_t *mmf, void const *data, long size);
|
||||||
|
LIBXDIFF_EXPORT long xdl_writem_mmfile(mmfile_t *mmf, mmbuffer_t *mb, int nbuf);
|
||||||
|
LIBXDIFF_EXPORT void *xdl_mmfile_writeallocate(mmfile_t *mmf, long size);
|
||||||
|
LIBXDIFF_EXPORT long xdl_mmfile_ptradd(mmfile_t *mmf, char *ptr, long size, unsigned long flags);
|
||||||
|
LIBXDIFF_EXPORT long xdl_copy_mmfile(mmfile_t *mmf, long size, xdemitcb_t *ecb);
|
||||||
|
LIBXDIFF_EXPORT void *xdl_mmfile_first(mmfile_t *mmf, long *size);
|
||||||
|
LIBXDIFF_EXPORT void *xdl_mmfile_next(mmfile_t *mmf, long *size);
|
||||||
|
LIBXDIFF_EXPORT long xdl_mmfile_size(mmfile_t *mmf);
|
||||||
|
LIBXDIFF_EXPORT int xdl_mmfile_cmp(mmfile_t *mmf1, mmfile_t *mmf2);
|
||||||
|
LIBXDIFF_EXPORT int xdl_mmfile_compact(mmfile_t *mmfo, mmfile_t *mmfc, long bsize, unsigned long flags);
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdemitconf_t const *xecfg, xdemitcb_t *ecb);
|
||||||
|
LIBXDIFF_EXPORT int xdl_patch(mmfile_t *mf, mmfile_t *mfp, int mode, xdemitcb_t *ecb,
|
||||||
|
xdemitcb_t *rjecb);
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT int xdl_merge3(mmfile_t *mmfo, mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb,
|
||||||
|
xdemitcb_t *rjecb);
|
||||||
|
|
||||||
|
LIBXDIFF_EXPORT int xdl_bdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, bdiffparam_t const *bdp, xdemitcb_t *ecb);
|
||||||
|
LIBXDIFF_EXPORT int xdl_bdiff(mmfile_t *mmf1, mmfile_t *mmf2, bdiffparam_t const *bdp, xdemitcb_t *ecb);
|
||||||
|
LIBXDIFF_EXPORT int xdl_rabdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, xdemitcb_t *ecb);
|
||||||
|
LIBXDIFF_EXPORT int xdl_rabdiff(mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb);
|
||||||
|
LIBXDIFF_EXPORT long xdl_bdiff_tgsize(mmfile_t *mmfp);
|
||||||
|
LIBXDIFF_EXPORT int xdl_bpatch(mmfile_t *mmf, mmfile_t *mmfp, xdemitcb_t *ecb);
|
||||||
|
LIBXDIFF_EXPORT int xdl_bpatch_multi(mmbuffer_t *base, mmbuffer_t *mbpch, int n, xdemitcb_t *ecb);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* #ifdef __cplusplus */
|
||||||
|
|
||||||
|
#endif /* #if !defined(XDIFF_H) */
|
||||||
|
|
||||||
556
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xdiffi.c
Normal file
556
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xdiffi.c
Normal file
@@ -0,0 +1,556 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define XDL_MAX_COST_MIN 256
|
||||||
|
#define XDL_HEUR_MIN_COST 256
|
||||||
|
#define XDL_LINE_MAX (long)((1UL << (8 * sizeof(long) - 1)) - 1)
|
||||||
|
#define XDL_SNAKE_CNT 20
|
||||||
|
#define XDL_K_HEUR 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct s_xdpsplit {
|
||||||
|
long i1, i2;
|
||||||
|
int min_lo, min_hi;
|
||||||
|
} xdpsplit_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers.
|
||||||
|
* Basically considers a "box" (off1, off2, lim1, lim2) and scan from both
|
||||||
|
* the forward diagonal starting from (off1, off2) and the backward diagonal
|
||||||
|
* starting from (lim1, lim2). If the K values on the same diagonal crosses
|
||||||
|
* returns the furthest point of reach. We might end up having to expensive
|
||||||
|
* cases using this algorithm is full, so a little bit of heuristic is needed
|
||||||
|
* to cut the search and to return a suboptimal point.
|
||||||
|
*/
|
||||||
|
static long xdl_split(unsigned long const *ha1, long off1, long lim1,
|
||||||
|
unsigned long const *ha2, long off2, long lim2,
|
||||||
|
long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl,
|
||||||
|
xdalgoenv_t *xenv) {
|
||||||
|
long dmin = off1 - lim2, dmax = lim1 - off2;
|
||||||
|
long fmid = off1 - off2, bmid = lim1 - lim2;
|
||||||
|
long odd = (fmid - bmid) & 1;
|
||||||
|
long fmin = fmid, fmax = fmid;
|
||||||
|
long bmin = bmid, bmax = bmid;
|
||||||
|
long ec, d, i1, i2, prev1, best, dd, v, k;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set initial diagonal values for both forward and backward path.
|
||||||
|
*/
|
||||||
|
kvdf[fmid] = off1;
|
||||||
|
kvdb[bmid] = lim1;
|
||||||
|
|
||||||
|
for (ec = 1;; ec++) {
|
||||||
|
int got_snake = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to extent the diagonal "domain" by one. If the next
|
||||||
|
* values exits the box boundaries we need to change it in the
|
||||||
|
* opposite direction because (max - min) must be a power of two.
|
||||||
|
* Also we initialize the extenal K value to -1 so that we can
|
||||||
|
* avoid extra conditions check inside the core loop.
|
||||||
|
*/
|
||||||
|
if (fmin > dmin)
|
||||||
|
kvdf[--fmin - 1] = -1;
|
||||||
|
else
|
||||||
|
++fmin;
|
||||||
|
if (fmax < dmax)
|
||||||
|
kvdf[++fmax + 1] = -1;
|
||||||
|
else
|
||||||
|
--fmax;
|
||||||
|
|
||||||
|
for (d = fmax; d >= fmin; d -= 2) {
|
||||||
|
if (kvdf[d - 1] >= kvdf[d + 1])
|
||||||
|
i1 = kvdf[d - 1] + 1;
|
||||||
|
else
|
||||||
|
i1 = kvdf[d + 1];
|
||||||
|
prev1 = i1;
|
||||||
|
i2 = i1 - d;
|
||||||
|
for (; i1 < lim1 && i2 < lim2 && ha1[i1] == ha2[i2]; i1++, i2++);
|
||||||
|
if (i1 - prev1 > xenv->snake_cnt)
|
||||||
|
got_snake = 1;
|
||||||
|
kvdf[d] = i1;
|
||||||
|
if (odd && bmin <= d && d <= bmax && kvdb[d] <= i1) {
|
||||||
|
spl->i1 = i1;
|
||||||
|
spl->i2 = i2;
|
||||||
|
spl->min_lo = spl->min_hi = 1;
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to extent the diagonal "domain" by one. If the next
|
||||||
|
* values exits the box boundaries we need to change it in the
|
||||||
|
* opposite direction because (max - min) must be a power of two.
|
||||||
|
* Also we initialize the extenal K value to -1 so that we can
|
||||||
|
* avoid extra conditions check inside the core loop.
|
||||||
|
*/
|
||||||
|
if (bmin > dmin)
|
||||||
|
kvdb[--bmin - 1] = XDL_LINE_MAX;
|
||||||
|
else
|
||||||
|
++bmin;
|
||||||
|
if (bmax < dmax)
|
||||||
|
kvdb[++bmax + 1] = XDL_LINE_MAX;
|
||||||
|
else
|
||||||
|
--bmax;
|
||||||
|
|
||||||
|
for (d = bmax; d >= bmin; d -= 2) {
|
||||||
|
if (kvdb[d - 1] < kvdb[d + 1])
|
||||||
|
i1 = kvdb[d - 1];
|
||||||
|
else
|
||||||
|
i1 = kvdb[d + 1] - 1;
|
||||||
|
prev1 = i1;
|
||||||
|
i2 = i1 - d;
|
||||||
|
for (; i1 > off1 && i2 > off2 && ha1[i1 - 1] == ha2[i2 - 1]; i1--, i2--);
|
||||||
|
if (prev1 - i1 > xenv->snake_cnt)
|
||||||
|
got_snake = 1;
|
||||||
|
kvdb[d] = i1;
|
||||||
|
if (!odd && fmin <= d && d <= fmax && i1 <= kvdf[d]) {
|
||||||
|
spl->i1 = i1;
|
||||||
|
spl->i2 = i2;
|
||||||
|
spl->min_lo = spl->min_hi = 1;
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_min)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the edit cost is above the heuristic trigger and if
|
||||||
|
* we got a good snake, we sample current diagonals to see
|
||||||
|
* if some of the, have reached an "interesting" path. Our
|
||||||
|
* measure is a function of the distance from the diagonal
|
||||||
|
* corner (i1 + i2) penalized with the distance from the
|
||||||
|
* mid diagonal itself. If this value is above the current
|
||||||
|
* edit cost times a magic factor (XDL_K_HEUR) we consider
|
||||||
|
* it interesting.
|
||||||
|
*/
|
||||||
|
if (got_snake && ec > xenv->heur_min) {
|
||||||
|
for (best = 0, d = fmax; d >= fmin; d -= 2) {
|
||||||
|
dd = d > fmid ? d - fmid: fmid - d;
|
||||||
|
i1 = kvdf[d];
|
||||||
|
i2 = i1 - d;
|
||||||
|
v = (i1 - off1) + (i2 - off2) - dd;
|
||||||
|
|
||||||
|
if (v > XDL_K_HEUR * ec && v > best &&
|
||||||
|
off1 + xenv->snake_cnt <= i1 && i1 < lim1 &&
|
||||||
|
off2 + xenv->snake_cnt <= i2 && i2 < lim2) {
|
||||||
|
for (k = 1; ha1[i1 - k] == ha2[i2 - k]; k++)
|
||||||
|
if (k == xenv->snake_cnt) {
|
||||||
|
best = v;
|
||||||
|
spl->i1 = i1;
|
||||||
|
spl->i2 = i2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (best > 0) {
|
||||||
|
spl->min_lo = 1;
|
||||||
|
spl->min_hi = 0;
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (best = 0, d = bmax; d >= bmin; d -= 2) {
|
||||||
|
dd = d > bmid ? d - bmid: bmid - d;
|
||||||
|
i1 = kvdb[d];
|
||||||
|
i2 = i1 - d;
|
||||||
|
v = (lim1 - i1) + (lim2 - i2) - dd;
|
||||||
|
|
||||||
|
if (v > XDL_K_HEUR * ec && v > best &&
|
||||||
|
off1 < i1 && i1 <= lim1 - xenv->snake_cnt &&
|
||||||
|
off2 < i2 && i2 <= lim2 - xenv->snake_cnt) {
|
||||||
|
for (k = 0; ha1[i1 + k] == ha2[i2 + k]; k++)
|
||||||
|
if (k == xenv->snake_cnt - 1) {
|
||||||
|
best = v;
|
||||||
|
spl->i1 = i1;
|
||||||
|
spl->i2 = i2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (best > 0) {
|
||||||
|
spl->min_lo = 0;
|
||||||
|
spl->min_hi = 1;
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enough is enough. We spent too much time here and now we collect
|
||||||
|
* the furthest reaching path using the (i1 + i2) measure.
|
||||||
|
*/
|
||||||
|
if (ec >= xenv->mxcost) {
|
||||||
|
long fbest, fbest1, bbest, bbest1;
|
||||||
|
|
||||||
|
fbest = -1;
|
||||||
|
for (d = fmax; d >= fmin; d -= 2) {
|
||||||
|
i1 = XDL_MIN(kvdf[d], lim1);
|
||||||
|
i2 = i1 - d;
|
||||||
|
if (lim2 < i2)
|
||||||
|
i1 = lim2 + d, i2 = lim2;
|
||||||
|
if (fbest < i1 + i2) {
|
||||||
|
fbest = i1 + i2;
|
||||||
|
fbest1 = i1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bbest = XDL_LINE_MAX;
|
||||||
|
for (d = bmax; d >= bmin; d -= 2) {
|
||||||
|
i1 = XDL_MAX(off1, kvdb[d]);
|
||||||
|
i2 = i1 - d;
|
||||||
|
if (i2 < off2)
|
||||||
|
i1 = off2 + d, i2 = off2;
|
||||||
|
if (i1 + i2 < bbest) {
|
||||||
|
bbest = i1 + i2;
|
||||||
|
bbest1 = i1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lim1 + lim2) - bbest < fbest - (off1 + off2)) {
|
||||||
|
spl->i1 = fbest1;
|
||||||
|
spl->i2 = fbest - fbest1;
|
||||||
|
spl->min_lo = 1;
|
||||||
|
spl->min_hi = 0;
|
||||||
|
} else {
|
||||||
|
spl->i1 = bbest1;
|
||||||
|
spl->i2 = bbest - bbest1;
|
||||||
|
spl->min_lo = 0;
|
||||||
|
spl->min_hi = 1;
|
||||||
|
}
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rule: "Divide et Impera". Recursively split the box in sub-boxes by calling
|
||||||
|
* the box splitting function. Note that the real job (marking changed lines)
|
||||||
|
* is done in the two boundary reaching checks.
|
||||||
|
*/
|
||||||
|
int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
|
||||||
|
diffdata_t *dd2, long off2, long lim2,
|
||||||
|
long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv) {
|
||||||
|
unsigned long const *ha1 = dd1->ha, *ha2 = dd2->ha;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shrink the box by walking through each diagonal snake (SW and NE).
|
||||||
|
*/
|
||||||
|
for (; off1 < lim1 && off2 < lim2 && ha1[off1] == ha2[off2]; off1++, off2++);
|
||||||
|
for (; off1 < lim1 && off2 < lim2 && ha1[lim1 - 1] == ha2[lim2 - 1]; lim1--, lim2--);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If one dimension is empty, then all records on the other one must
|
||||||
|
* be obviously changed.
|
||||||
|
*/
|
||||||
|
if (off1 == lim1) {
|
||||||
|
char *rchg2 = dd2->rchg;
|
||||||
|
long *rindex2 = dd2->rindex;
|
||||||
|
|
||||||
|
for (; off2 < lim2; off2++)
|
||||||
|
rchg2[rindex2[off2]] = 1;
|
||||||
|
} else if (off2 == lim2) {
|
||||||
|
char *rchg1 = dd1->rchg;
|
||||||
|
long *rindex1 = dd1->rindex;
|
||||||
|
|
||||||
|
for (; off1 < lim1; off1++)
|
||||||
|
rchg1[rindex1[off1]] = 1;
|
||||||
|
} else {
|
||||||
|
long ec;
|
||||||
|
xdpsplit_t spl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Divide ...
|
||||||
|
*/
|
||||||
|
if ((ec = xdl_split(ha1, off1, lim1, ha2, off2, lim2, kvdf, kvdb,
|
||||||
|
need_min, &spl, xenv)) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ... et Impera.
|
||||||
|
*/
|
||||||
|
if (xdl_recs_cmp(dd1, off1, spl.i1, dd2, off2, spl.i2,
|
||||||
|
kvdf, kvdb, spl.min_lo, xenv) < 0 ||
|
||||||
|
xdl_recs_cmp(dd1, spl.i1, lim1, dd2, spl.i2, lim2,
|
||||||
|
kvdf, kvdb, spl.min_hi, xenv) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdfenv_t *xe) {
|
||||||
|
long ndiags;
|
||||||
|
long *kvd, *kvdf, *kvdb;
|
||||||
|
xdalgoenv_t xenv;
|
||||||
|
diffdata_t dd1, dd2;
|
||||||
|
|
||||||
|
if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and setup K vectors to be used by the differential algorithm.
|
||||||
|
* One is to store the forward path and one to store the backward path.
|
||||||
|
*/
|
||||||
|
ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
|
||||||
|
if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) {
|
||||||
|
|
||||||
|
xdl_free_env(xe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
kvdf = kvd;
|
||||||
|
kvdb = kvdf + ndiags;
|
||||||
|
kvdf += xe->xdf2.nreff + 1;
|
||||||
|
kvdb += xe->xdf2.nreff + 1;
|
||||||
|
|
||||||
|
xenv.mxcost = xdl_bogosqrt(ndiags);
|
||||||
|
if (xenv.mxcost < XDL_MAX_COST_MIN)
|
||||||
|
xenv.mxcost = XDL_MAX_COST_MIN;
|
||||||
|
xenv.snake_cnt = XDL_SNAKE_CNT;
|
||||||
|
xenv.heur_min = XDL_HEUR_MIN_COST;
|
||||||
|
|
||||||
|
dd1.nrec = xe->xdf1.nreff;
|
||||||
|
dd1.ha = xe->xdf1.ha;
|
||||||
|
dd1.rchg = xe->xdf1.rchg;
|
||||||
|
dd1.rindex = xe->xdf1.rindex;
|
||||||
|
dd2.nrec = xe->xdf2.nreff;
|
||||||
|
dd2.ha = xe->xdf2.ha;
|
||||||
|
dd2.rchg = xe->xdf2.rchg;
|
||||||
|
dd2.rindex = xe->xdf2.rindex;
|
||||||
|
|
||||||
|
if (xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
|
||||||
|
kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0, &xenv) < 0) {
|
||||||
|
|
||||||
|
xdl_free(kvd);
|
||||||
|
xdl_free_env(xe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xdl_free(kvd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2) {
|
||||||
|
xdchange_t *xch;
|
||||||
|
|
||||||
|
if (!(xch = (xdchange_t *) xdl_malloc(sizeof(xdchange_t))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
xch->next = xscr;
|
||||||
|
xch->i1 = i1;
|
||||||
|
xch->i2 = i2;
|
||||||
|
xch->chg1 = chg1;
|
||||||
|
xch->chg2 = chg2;
|
||||||
|
|
||||||
|
return xch;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) {
|
||||||
|
long ix, ixo, ixs, ixref, grpsiz, nrec = xdf->nrec;
|
||||||
|
char *rchg = xdf->rchg, *rchgo = xdfo->rchg;
|
||||||
|
xrecord_t **recs = xdf->recs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the same of what GNU diff does. Move back and forward
|
||||||
|
* change groups for a consistent and pretty diff output. This also
|
||||||
|
* helps in finding joineable change groups and reduce the diff size.
|
||||||
|
*/
|
||||||
|
for (ix = ixo = 0;;) {
|
||||||
|
/*
|
||||||
|
* Find the first changed line in the to-be-compacted file.
|
||||||
|
* We need to keep track of both indexes, so if we find a
|
||||||
|
* changed lines group on the other file, while scanning the
|
||||||
|
* to-be-compacted file, we need to skip it properly. Note
|
||||||
|
* that loops that are testing for changed lines on rchg* do
|
||||||
|
* not need index bounding since the array is prepared with
|
||||||
|
* a zero at position -1 and N.
|
||||||
|
*/
|
||||||
|
for (; ix < nrec && !rchg[ix]; ix++)
|
||||||
|
while (rchgo[ixo++]);
|
||||||
|
if (ix == nrec)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record the start of a changed-group in the to-be-compacted file
|
||||||
|
* and find the end of it, on both to-be-compacted and other file
|
||||||
|
* indexes (ix and ixo).
|
||||||
|
*/
|
||||||
|
ixs = ix;
|
||||||
|
for (ix++; rchg[ix]; ix++);
|
||||||
|
for (; rchgo[ixo]; ixo++);
|
||||||
|
|
||||||
|
do {
|
||||||
|
grpsiz = ix - ixs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the line before the current change group, is equal to
|
||||||
|
* the last line of the current change group, shift backward
|
||||||
|
* the group.
|
||||||
|
*/
|
||||||
|
while (ixs > 0 && recs[ixs - 1]->ha == recs[ix - 1]->ha &&
|
||||||
|
XDL_RECMATCH(recs[ixs - 1], recs[ix - 1])) {
|
||||||
|
rchg[--ixs] = 1;
|
||||||
|
rchg[--ix] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This change might have joined two change groups,
|
||||||
|
* so we try to take this scenario in account by moving
|
||||||
|
* the start index accordingly (and so the other-file
|
||||||
|
* end-of-group index).
|
||||||
|
*/
|
||||||
|
for (; rchg[ixs - 1]; ixs--);
|
||||||
|
while (rchgo[--ixo]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record the end-of-group position in case we are matched
|
||||||
|
* with a group of changes in the other file (that is, the
|
||||||
|
* change record before the enf-of-group index in the other
|
||||||
|
* file is set).
|
||||||
|
*/
|
||||||
|
ixref = rchgo[ixo - 1] ? ix: nrec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the first line of the current change group, is equal to
|
||||||
|
* the line next of the current change group, shift forward
|
||||||
|
* the group.
|
||||||
|
*/
|
||||||
|
while (ix < nrec && recs[ixs]->ha == recs[ix]->ha &&
|
||||||
|
XDL_RECMATCH(recs[ixs], recs[ix])) {
|
||||||
|
rchg[ixs++] = 0;
|
||||||
|
rchg[ix++] = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This change might have joined two change groups,
|
||||||
|
* so we try to take this scenario in account by moving
|
||||||
|
* the start index accordingly (and so the other-file
|
||||||
|
* end-of-group index). Keep tracking the reference
|
||||||
|
* index in case we are shifting together with a
|
||||||
|
* corresponding group of changes in the other file.
|
||||||
|
*/
|
||||||
|
for (; rchg[ix]; ix++);
|
||||||
|
while (rchgo[++ixo])
|
||||||
|
ixref = ix;
|
||||||
|
}
|
||||||
|
} while (grpsiz != ix - ixs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to move back the possibly merged group of changes, to match
|
||||||
|
* the recorded postion in the other file.
|
||||||
|
*/
|
||||||
|
while (ixref < ix) {
|
||||||
|
rchg[--ixs] = 1;
|
||||||
|
rchg[--ix] = 0;
|
||||||
|
while (rchgo[--ixo]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr) {
|
||||||
|
xdchange_t *cscr = NULL, *xch;
|
||||||
|
char *rchg1 = xe->xdf1.rchg, *rchg2 = xe->xdf2.rchg;
|
||||||
|
long i1, i2, l1, l2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trivial. Collects "groups" of changes and creates an edit script.
|
||||||
|
*/
|
||||||
|
for (i1 = xe->xdf1.nrec, i2 = xe->xdf2.nrec; i1 >= 0 || i2 >= 0; i1--, i2--)
|
||||||
|
if (rchg1[i1 - 1] || rchg2[i2 - 1]) {
|
||||||
|
for (l1 = i1; rchg1[i1 - 1]; i1--);
|
||||||
|
for (l2 = i2; rchg2[i2 - 1]; i2--);
|
||||||
|
|
||||||
|
if (!(xch = xdl_add_change(cscr, i1, i2, l1 - i1, l2 - i2))) {
|
||||||
|
xdl_free_script(cscr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cscr = xch;
|
||||||
|
}
|
||||||
|
|
||||||
|
*xscr = cscr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xdl_free_script(xdchange_t *xscr) {
|
||||||
|
xdchange_t *xch;
|
||||||
|
|
||||||
|
while ((xch = xscr) != NULL) {
|
||||||
|
xscr = xscr->next;
|
||||||
|
xdl_free(xch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
|
||||||
|
xdchange_t *xscr;
|
||||||
|
xdfenv_t xe;
|
||||||
|
|
||||||
|
if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_change_compact(&xe.xdf1, &xe.xdf2) < 0 ||
|
||||||
|
xdl_change_compact(&xe.xdf2, &xe.xdf1) < 0 ||
|
||||||
|
xdl_build_script(&xe, &xscr) < 0) {
|
||||||
|
|
||||||
|
xdl_free_env(&xe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xscr) {
|
||||||
|
if (xdl_emit_diff(&xe, xscr, ecb, xecfg) < 0) {
|
||||||
|
|
||||||
|
xdl_free_script(xscr);
|
||||||
|
xdl_free_env(&xe);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_script(xscr);
|
||||||
|
}
|
||||||
|
xdl_free_env(&xe);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
60
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xdiffi.h
Normal file
60
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xdiffi.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XDIFFI_H)
|
||||||
|
#define XDIFFI_H
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct s_diffdata {
|
||||||
|
long nrec;
|
||||||
|
unsigned long const *ha;
|
||||||
|
long *rindex;
|
||||||
|
char *rchg;
|
||||||
|
} diffdata_t;
|
||||||
|
|
||||||
|
typedef struct s_xdalgoenv {
|
||||||
|
long mxcost;
|
||||||
|
long snake_cnt;
|
||||||
|
long heur_min;
|
||||||
|
} xdalgoenv_t;
|
||||||
|
|
||||||
|
typedef struct s_xdchange {
|
||||||
|
struct s_xdchange *next;
|
||||||
|
long i1, i2;
|
||||||
|
long chg1, chg2;
|
||||||
|
} xdchange_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
|
||||||
|
diffdata_t *dd2, long off2, long lim2,
|
||||||
|
long *kvdf, long *kvdb, int need_min, xdalgoenv_t *xenv);
|
||||||
|
int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdfenv_t *xe);
|
||||||
|
int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr);
|
||||||
|
void xdl_free_script(xdchange_t *xscr);
|
||||||
|
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
||||||
|
xdemitconf_t const *xecfg);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XDIFFI_H) */
|
||||||
|
|
||||||
132
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xemit.c
Normal file
132
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xemit.c
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) {
|
||||||
|
|
||||||
|
*rec = xdf->recs[ri]->ptr;
|
||||||
|
|
||||||
|
return xdf->recs[ri]->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) {
|
||||||
|
long size, psize = strlen(pre);
|
||||||
|
char const *rec;
|
||||||
|
|
||||||
|
size = xdl_get_rec(xdf, ri, &rec);
|
||||||
|
if (xdl_emit_diffrec(rec, size, pre, psize, ecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Starting at the passed change atom, find the latest change atom to be included
|
||||||
|
* inside the differential hunk according to the specified configuration.
|
||||||
|
*/
|
||||||
|
static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
|
||||||
|
xdchange_t *xch, *xchp;
|
||||||
|
|
||||||
|
for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
|
||||||
|
if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return xchp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
||||||
|
xdemitconf_t const *xecfg) {
|
||||||
|
long s1, s2, e1, e2, lctx;
|
||||||
|
xdchange_t *xch, *xche;
|
||||||
|
|
||||||
|
for (xch = xche = xscr; xch; xch = xche->next) {
|
||||||
|
xche = xdl_get_hunk(xch, xecfg);
|
||||||
|
|
||||||
|
s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
|
||||||
|
s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
|
||||||
|
|
||||||
|
lctx = xecfg->ctxlen;
|
||||||
|
lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1));
|
||||||
|
lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2));
|
||||||
|
|
||||||
|
e1 = xche->i1 + xche->chg1 + lctx;
|
||||||
|
e2 = xche->i2 + xche->chg2 + lctx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit current hunk header.
|
||||||
|
*/
|
||||||
|
if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, ecb) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit pre-context.
|
||||||
|
*/
|
||||||
|
for (; s1 < xch->i1; s1++)
|
||||||
|
if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (s1 = xch->i1, s2 = xch->i2;; xch = xch->next) {
|
||||||
|
/*
|
||||||
|
* Merge previous with current change atom.
|
||||||
|
*/
|
||||||
|
for (; s1 < xch->i1 && s2 < xch->i2; s1++, s2++)
|
||||||
|
if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Removes lines from the first file.
|
||||||
|
*/
|
||||||
|
for (s1 = xch->i1; s1 < xch->i1 + xch->chg1; s1++)
|
||||||
|
if (xdl_emit_record(&xe->xdf1, s1, "-", ecb) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds lines from the second file.
|
||||||
|
*/
|
||||||
|
for (s2 = xch->i2; s2 < xch->i2 + xch->chg2; s2++)
|
||||||
|
if (xdl_emit_record(&xe->xdf2, s2, "+", ecb) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (xch == xche)
|
||||||
|
break;
|
||||||
|
s1 = xch->i1 + xch->chg1;
|
||||||
|
s2 = xch->i2 + xch->chg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit post-context.
|
||||||
|
*/
|
||||||
|
for (s1 = xche->i1 + xche->chg1; s1 < e1; s1++)
|
||||||
|
if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
34
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xemit.h
Normal file
34
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xemit.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XEMIT_H)
|
||||||
|
#define XEMIT_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
||||||
|
xdemitconf_t const *xecfg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XEMIT_H) */
|
||||||
|
|
||||||
71
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xinclude.h
Normal file
71
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xinclude.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XINCLUDE_H)
|
||||||
|
#define XINCLUDE_H
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(HAVE_WINCONFIG_H)
|
||||||
|
#include "winconfig.h"
|
||||||
|
#endif /* #if defined(HAVE_CONFIG_H) */
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include "config.h"
|
||||||
|
#endif /* #if defined(HAVE_CONFIG_H) */
|
||||||
|
|
||||||
|
#if defined(HAVE_STDIO_H)
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif /* #if defined(HAVE_STDIO_H) */
|
||||||
|
|
||||||
|
#if defined(HAVE_STDLIB_H)
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif /* #if defined(HAVE_STDLIB_H) */
|
||||||
|
|
||||||
|
#if defined(HAVE_UNISTD_H)
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif /* #if defined(HAVE_UNISTD_H) */
|
||||||
|
|
||||||
|
#if defined(HAVE_STRING_H)
|
||||||
|
#include <string.h>
|
||||||
|
#endif /* #if defined(HAVE_STRING_H) */
|
||||||
|
|
||||||
|
#if defined(HAVE_LIMITS_H)
|
||||||
|
#include <limits.h>
|
||||||
|
#endif /* #if defined(HAVE_LIMITS_H) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "xmacros.h"
|
||||||
|
#include "xmissing.h"
|
||||||
|
#include "xdiff.h"
|
||||||
|
#include "xtypes.h"
|
||||||
|
#include "xutils.h"
|
||||||
|
#include "xadler32.h"
|
||||||
|
#include "xprepare.h"
|
||||||
|
#include "xdiffi.h"
|
||||||
|
#include "xemit.h"
|
||||||
|
#include "xbdiff.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XINCLUDE_H) */
|
||||||
|
|
||||||
51
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xmacros.h
Normal file
51
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xmacros.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XMACROS_H)
|
||||||
|
#define XMACROS_H
|
||||||
|
|
||||||
|
|
||||||
|
#define XDL_MIN(a, b) ((a) < (b) ? (a): (b))
|
||||||
|
#define XDL_MAX(a, b) ((a) > (b) ? (a): (b))
|
||||||
|
#define XDL_ABS(v) ((v) >= 0 ? (v): -(v))
|
||||||
|
#define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
|
||||||
|
#define XDL_ADDBITS(v, b) ((v) + ((v) >> (b)))
|
||||||
|
#define XDL_MASKBITS(b) ((1UL << (b)) - 1)
|
||||||
|
#define XDL_HASHLONG(v, b) (XDL_ADDBITS((unsigned long) (v), b) & XDL_MASKBITS(b))
|
||||||
|
#define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0)
|
||||||
|
#define XDL_RECMATCH(r1, r2) ((r1)->size == (r2)->size && memcmp((r1)->ptr, (r2)->ptr, (r1)->size) == 0)
|
||||||
|
#define XDL_LE32_PUT(p, v) do { \
|
||||||
|
unsigned char *__p = (unsigned char *) (p); \
|
||||||
|
*__p++ = (unsigned char) (v); \
|
||||||
|
*__p++ = (unsigned char) ((v) >> 8); \
|
||||||
|
*__p++ = (unsigned char) ((v) >> 16); \
|
||||||
|
*__p = (unsigned char) ((v) >> 24); \
|
||||||
|
} while (0)
|
||||||
|
#define XDL_LE32_GET(p, v) do { \
|
||||||
|
unsigned char const *__p = (unsigned char const *) (p); \
|
||||||
|
(v) = (unsigned long) __p[0] | ((unsigned long) __p[1]) << 8 | \
|
||||||
|
((unsigned long) __p[2]) << 16 | ((unsigned long) __p[3]) << 24; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XMACROS_H) */
|
||||||
|
|
||||||
66
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xmerge3.c
Normal file
66
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xmerge3.c
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define XDL_MERGE3_BLKSIZE (1024 * 8)
|
||||||
|
#define XDL_MERGE3_CTXLEN 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_merge3(mmfile_t *mmfo, mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb,
|
||||||
|
xdemitcb_t *rjecb) {
|
||||||
|
xpparam_t xpp;
|
||||||
|
xdemitconf_t xecfg;
|
||||||
|
xdemitcb_t xecb;
|
||||||
|
mmfile_t mmfp;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(&mmfp, XDL_MERGE3_BLKSIZE, XDL_MMF_ATOMIC) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xpp.flags = 0;
|
||||||
|
|
||||||
|
xecfg.ctxlen = XDL_MERGE3_CTXLEN;
|
||||||
|
|
||||||
|
xecb.priv = &mmfp;
|
||||||
|
xecb.outf = xdl_mmfile_outf;
|
||||||
|
|
||||||
|
if (xdl_diff(mmfo, mmf2, &xpp, &xecfg, &xecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mmfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xdl_patch(mmf1, &mmfp, XDL_PATCH_NORMAL, ecb, rjecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mmfp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xdl_free_mmfile(&mmfp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
92
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xmissing.c
Normal file
92
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xmissing.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(HAVE_MEMCHR)
|
||||||
|
|
||||||
|
void *memchr(void const *p, int c, long n) {
|
||||||
|
char const *pc = p;
|
||||||
|
|
||||||
|
for (; n; n--, pc++)
|
||||||
|
if (*pc == (char) c)
|
||||||
|
return pc;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if !defined(HAVE_MEMCHR) */
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(HAVE_MEMCMP)
|
||||||
|
|
||||||
|
int memcmp(void const *p1, void const *p2, long n) {
|
||||||
|
char const *pc1 = p1, *pc2 = p2;
|
||||||
|
|
||||||
|
for (; n; n--, pc1++, pc2++)
|
||||||
|
if (*pc1 != *pc2)
|
||||||
|
return *pc1 - *pc2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if !defined(HAVE_MEMCMP) */
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(HAVE_MEMCPY)
|
||||||
|
|
||||||
|
void *memcpy(void *d, void const *s, long n) {
|
||||||
|
char *dc = d;
|
||||||
|
char const *sc = s;
|
||||||
|
|
||||||
|
for (; n; n--, dc++, sc++)
|
||||||
|
*dc = *sc;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if !defined(HAVE_MEMCPY) */
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(HAVE_MEMSET)
|
||||||
|
|
||||||
|
void *memset(void *d, int c, long n) {
|
||||||
|
char *dc = d;
|
||||||
|
|
||||||
|
for (; n; n--, dc++)
|
||||||
|
*dc = (char) c;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if !defined(HAVE_MEMSET) */
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(HAVE_STRLEN)
|
||||||
|
|
||||||
|
long strlen(char const *s) {
|
||||||
|
char const *tmp;
|
||||||
|
|
||||||
|
for (tmp = s; *s; s++);
|
||||||
|
return (long) (s - tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if !defined(HAVE_STRLEN) */
|
||||||
|
|
||||||
56
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xmissing.h
Normal file
56
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xmissing.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XMISSING_H)
|
||||||
|
#define XMISSING_H
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(CHAR_BIT)
|
||||||
|
#define CHAR_BIT 8
|
||||||
|
#endif /* #if !defined(CHAR_BIT) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(HAVE_MEMCHR)
|
||||||
|
void *memchr(void const *p, int c, long n);
|
||||||
|
#endif /* #if !defined(HAVE_MEMCHR) */
|
||||||
|
|
||||||
|
#if !defined(HAVE_MEMCMP)
|
||||||
|
int memcmp(void const *p1, void const *p2, long n);
|
||||||
|
#endif /* #if !defined(HAVE_MEMCMP) */
|
||||||
|
|
||||||
|
#if !defined(HAVE_MEMCPY)
|
||||||
|
void *memcpy(void *d, void const *s, long n);
|
||||||
|
#endif /* #if !defined(HAVE_MEMCPY) */
|
||||||
|
|
||||||
|
#if !defined(HAVE_MEMSET)
|
||||||
|
void *memset(void *d, int c, long n);
|
||||||
|
#endif /* #if !defined(HAVE_MEMSET) */
|
||||||
|
|
||||||
|
#if !defined(HAVE_STRLEN)
|
||||||
|
long strlen(char const *s);
|
||||||
|
#endif /* #if !defined(HAVE_STRLEN) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XMISSING_H) */
|
||||||
|
|
||||||
641
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xpatchi.c
Normal file
641
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xpatchi.c
Normal file
@@ -0,0 +1,641 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define XDL_MAX_FUZZ 3
|
||||||
|
#define XDL_MIN_SYNCLINES 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct s_recinfo {
|
||||||
|
char const *ptr;
|
||||||
|
long size;
|
||||||
|
} recinfo_t;
|
||||||
|
|
||||||
|
typedef struct s_recfile {
|
||||||
|
mmfile_t *mf;
|
||||||
|
long nrec;
|
||||||
|
recinfo_t *recs;
|
||||||
|
} recfile_t;
|
||||||
|
|
||||||
|
typedef struct s_hunkinfo {
|
||||||
|
long s1, s2;
|
||||||
|
long c1, c2;
|
||||||
|
long cmn, radd, rdel, pctx, sctx;
|
||||||
|
} hunkinfo_t;
|
||||||
|
|
||||||
|
typedef struct s_patchstats {
|
||||||
|
long adds, dels;
|
||||||
|
} patchstats_t;
|
||||||
|
|
||||||
|
typedef struct s_patch {
|
||||||
|
recfile_t rf;
|
||||||
|
hunkinfo_t hi;
|
||||||
|
long hkrec;
|
||||||
|
long hklen;
|
||||||
|
long flags;
|
||||||
|
patchstats_t ps;
|
||||||
|
int fuzzies;
|
||||||
|
} patch_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_load_hunk_info(char const *line, long size, hunkinfo_t *hki);
|
||||||
|
static int xdl_init_recfile(mmfile_t *mf, int ispatch, recfile_t *rf);
|
||||||
|
static void xdl_free_recfile(recfile_t *rf);
|
||||||
|
static char const *xdl_recfile_get(recfile_t *rf, long irec, long *size);
|
||||||
|
static int xdl_init_patch(mmfile_t *mf, long flags, patch_t *pch);
|
||||||
|
static void xdl_free_patch(patch_t *pch);
|
||||||
|
static int xdl_load_hunk(patch_t *pch, long hkrec);
|
||||||
|
static int xdl_first_hunk(patch_t *pch);
|
||||||
|
static int xdl_next_hunk(patch_t *pch);
|
||||||
|
static int xdl_line_match(patch_t *pch, const char *s, long ns, char const *m, long nm);
|
||||||
|
static int xdl_hunk_match(recfile_t *rf, long irec, patch_t *pch, int mode, int fuzz);
|
||||||
|
static int xdl_find_hunk(recfile_t *rf, long ibase, patch_t *pch, int mode,
|
||||||
|
int fuzz, long *hkpos, int *exact);
|
||||||
|
static int xdl_emit_rfile_line(recfile_t *rf, long line, xdemitcb_t *ecb);
|
||||||
|
static int xdl_flush_section(recfile_t *rf, long start, long top, xdemitcb_t *ecb);
|
||||||
|
static int xdl_apply_hunk(recfile_t *rf, long hkpos, patch_t *pch, int mode,
|
||||||
|
long *ibase, xdemitcb_t *ecb);
|
||||||
|
static int xdl_reject_hunk(recfile_t *rf, patch_t *pch, int mode,
|
||||||
|
xdemitcb_t *rjecb);
|
||||||
|
static int xdl_process_hunk(recfile_t *rff, patch_t *pch, long *ibase, int mode,
|
||||||
|
xdemitcb_t *ecb, xdemitcb_t *rjecb);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_load_hunk_info(char const *line, long size, hunkinfo_t *hki) {
|
||||||
|
char const *next;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The diff header format should be:
|
||||||
|
*
|
||||||
|
* @@ -OP,OC +NP,NC @@
|
||||||
|
*
|
||||||
|
* Unfortunately some software avoid to emit OP or/and NP in case
|
||||||
|
* of not existing old or new file (it should be mitted as zero).
|
||||||
|
* We need to handle both syntaxes.
|
||||||
|
*/
|
||||||
|
if (memcmp(line, "@@ -", 4))
|
||||||
|
return -1;
|
||||||
|
line += 4;
|
||||||
|
size -= 4;
|
||||||
|
|
||||||
|
if (!size || !XDL_ISDIGIT(*line))
|
||||||
|
return -1;
|
||||||
|
hki->s1 = xdl_atol(line, &next);
|
||||||
|
size -= next - line;
|
||||||
|
line = next;
|
||||||
|
if (!size)
|
||||||
|
return -1;
|
||||||
|
if (*line == ',') {
|
||||||
|
size--, line++;
|
||||||
|
if (!size || !XDL_ISDIGIT(*line))
|
||||||
|
return -1;
|
||||||
|
hki->c1 = xdl_atol(line, &next);
|
||||||
|
size -= next - line;
|
||||||
|
line = next;
|
||||||
|
if (!size || *line != ' ')
|
||||||
|
return -1;
|
||||||
|
size--, line++;
|
||||||
|
} else if (*line == ' ') {
|
||||||
|
size--, line++;
|
||||||
|
hki->c1 = hki->s1;
|
||||||
|
hki->s1 = 0;
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!size || *line != '+')
|
||||||
|
return -1;
|
||||||
|
size--, line++;
|
||||||
|
if (!size || !XDL_ISDIGIT(*line))
|
||||||
|
return -1;
|
||||||
|
hki->s2 = xdl_atol(line, &next);
|
||||||
|
size -= next - line;
|
||||||
|
line = next;
|
||||||
|
if (!size)
|
||||||
|
return -1;
|
||||||
|
if (*line == ',') {
|
||||||
|
size--, line++;
|
||||||
|
if (!size || !XDL_ISDIGIT(*line))
|
||||||
|
return -1;
|
||||||
|
hki->c2 = xdl_atol(line, &next);
|
||||||
|
size -= next - line;
|
||||||
|
line = next;
|
||||||
|
if (!size || *line != ' ')
|
||||||
|
return -1;
|
||||||
|
size--, line++;
|
||||||
|
} else if (*line == ' ') {
|
||||||
|
size--, line++;
|
||||||
|
hki->c2 = hki->s2;
|
||||||
|
hki->s2 = 0;
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
|
if (size < 2 || memcmp(line, "@@", 2) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We start from zero, so decrement by one unless it's the special position
|
||||||
|
* '0' inside the unified diff (new or deleted file).
|
||||||
|
*/
|
||||||
|
if (hki->s1 > 0 && hki->c1 > 0)
|
||||||
|
hki->s1--;
|
||||||
|
if (hki->s2 > 0 && hki->c2 > 0)
|
||||||
|
hki->s2--;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_init_recfile(mmfile_t *mf, int ispatch, recfile_t *rf) {
|
||||||
|
long narec, nrec, bsize;
|
||||||
|
recinfo_t *recs, *rrecs;
|
||||||
|
char const *blk, *cur, *top, *eol;
|
||||||
|
|
||||||
|
narec = xdl_guess_lines(mf);
|
||||||
|
if (!(recs = (recinfo_t *) xdl_malloc(narec * sizeof(recinfo_t)))) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
nrec = 0;
|
||||||
|
if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) {
|
||||||
|
for (top = blk + bsize;;) {
|
||||||
|
if (cur >= top) {
|
||||||
|
if (!(cur = blk = xdl_mmfile_next(mf, &bsize)))
|
||||||
|
break;
|
||||||
|
top = blk + bsize;
|
||||||
|
}
|
||||||
|
if (nrec >= narec) {
|
||||||
|
narec *= 2;
|
||||||
|
if (!(rrecs = (recinfo_t *)
|
||||||
|
xdl_realloc(recs, narec * sizeof(recinfo_t)))) {
|
||||||
|
|
||||||
|
xdl_free(recs);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
recs = rrecs;
|
||||||
|
}
|
||||||
|
recs[nrec].ptr = cur;
|
||||||
|
if (!(eol = memchr(cur, '\n', top - cur)))
|
||||||
|
eol = top - 1;
|
||||||
|
recs[nrec].size = (long) (eol - cur) + 1;
|
||||||
|
if (ispatch && *cur == '\\' && nrec > 0 && recs[nrec - 1].size > 0 &&
|
||||||
|
recs[nrec - 1].ptr[recs[nrec - 1].size - 1] == '\n')
|
||||||
|
recs[nrec - 1].size--;
|
||||||
|
else
|
||||||
|
nrec++;
|
||||||
|
cur = eol + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rf->mf = mf;
|
||||||
|
rf->nrec = nrec;
|
||||||
|
rf->recs = recs;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void xdl_free_recfile(recfile_t *rf) {
|
||||||
|
|
||||||
|
xdl_free(rf->recs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char const *xdl_recfile_get(recfile_t *rf, long irec, long *size) {
|
||||||
|
|
||||||
|
if (irec < 0 || irec >= rf->nrec)
|
||||||
|
return NULL;
|
||||||
|
*size = rf->recs[irec].size;
|
||||||
|
|
||||||
|
return rf->recs[irec].ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_init_patch(mmfile_t *mf, long flags, patch_t *pch) {
|
||||||
|
|
||||||
|
if (xdl_init_recfile(mf, 1, &pch->rf) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pch->hkrec = 0;
|
||||||
|
pch->hklen = 0;
|
||||||
|
pch->flags = flags;
|
||||||
|
pch->ps.adds = pch->ps.dels = 0;
|
||||||
|
pch->fuzzies = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void xdl_free_patch(patch_t *pch) {
|
||||||
|
|
||||||
|
xdl_free_recfile(&pch->rf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_load_hunk(patch_t *pch, long hkrec) {
|
||||||
|
long size, i, nb;
|
||||||
|
char const *line;
|
||||||
|
|
||||||
|
for (;; hkrec++) {
|
||||||
|
pch->hkrec = hkrec;
|
||||||
|
if (!(line = xdl_recfile_get(&pch->rf, pch->hkrec, &size)))
|
||||||
|
return 0;
|
||||||
|
if (*line == '@')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (xdl_load_hunk_info(line, size, &pch->hi) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pch->hi.cmn = pch->hi.radd = pch->hi.rdel = pch->hi.pctx = pch->hi.sctx = 0;
|
||||||
|
for (i = pch->hkrec + 1, nb = 0;
|
||||||
|
(line = xdl_recfile_get(&pch->rf, i, &size)) != NULL; i++) {
|
||||||
|
if (*line == '@' || *line == '\n')
|
||||||
|
break;
|
||||||
|
if (*line == ' ') {
|
||||||
|
nb++;
|
||||||
|
pch->hi.cmn++;
|
||||||
|
} else if (*line == '+') {
|
||||||
|
if (pch->hi.radd + pch->hi.rdel == 0)
|
||||||
|
pch->hi.pctx = nb;
|
||||||
|
nb = 0;
|
||||||
|
pch->hi.radd++;
|
||||||
|
} else if (*line == '-') {
|
||||||
|
if (pch->hi.radd + pch->hi.rdel == 0)
|
||||||
|
pch->hi.pctx = nb;
|
||||||
|
nb = 0;
|
||||||
|
pch->hi.rdel++;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pch->hi.sctx = nb;
|
||||||
|
if (pch->hi.cmn + pch->hi.radd != pch->hi.c2 ||
|
||||||
|
pch->hi.cmn + pch->hi.rdel != pch->hi.c1) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pch->hklen = i - pch->hkrec - 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_first_hunk(patch_t *pch) {
|
||||||
|
|
||||||
|
return xdl_load_hunk(pch, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_next_hunk(patch_t *pch) {
|
||||||
|
|
||||||
|
return xdl_load_hunk(pch, pch->hkrec + pch->hklen + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_line_match(patch_t *pch, const char *s, long ns, char const *m, long nm) {
|
||||||
|
|
||||||
|
for (; ns > 0 && (s[ns - 1] == '\r' || s[ns - 1] == '\n'); ns--);
|
||||||
|
for (; nm > 0 && (m[nm - 1] == '\r' || m[nm - 1] == '\n'); nm--);
|
||||||
|
if (pch->flags & XDL_PATCH_IGNOREBSPACE) {
|
||||||
|
for (; ns > 0 && (*s == ' ' || *s == '\t'); ns--, s++);
|
||||||
|
for (; ns > 0 && (s[ns - 1] == ' ' || s[ns - 1] == '\t'); ns--);
|
||||||
|
for (; nm > 0 && (*m == ' ' || *m == '\t'); nm--, m++);
|
||||||
|
for (; nm > 0 && (m[nm - 1] == ' ' || m[nm - 1] == '\t'); nm--);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ns == nm && memcmp(s, m, ns) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_hunk_match(recfile_t *rf, long irec, patch_t *pch, int mode, int fuzz) {
|
||||||
|
long i, j, z, fsize, psize, ptop, pfuzz, sfuzz, misses;
|
||||||
|
char const *fline, *pline;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Limit fuzz to not be greater than the prefix and suffix context.
|
||||||
|
*/
|
||||||
|
pfuzz = fuzz < pch->hi.pctx ? fuzz: pch->hi.pctx;
|
||||||
|
sfuzz = fuzz < pch->hi.sctx ? fuzz: pch->hi.sctx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First loop through the prefix fuzz area. In this loop we simply
|
||||||
|
* note mismatching lines. We allow missing lines here, that is,
|
||||||
|
* some prefix context lines are missing.
|
||||||
|
*/
|
||||||
|
for (z = pfuzz, misses = 0, i = irec, j = pch->hkrec + 1,
|
||||||
|
ptop = pch->hkrec + 1 + pch->hklen - sfuzz;
|
||||||
|
z > 0 && i < rf->nrec && j < ptop; i++, j++, z--) {
|
||||||
|
if (!(pline = xdl_recfile_get(&pch->rf, j, &psize)))
|
||||||
|
return 0;
|
||||||
|
if (!(fline = xdl_recfile_get(rf, i, &fsize)) ||
|
||||||
|
!xdl_line_match(pch, fline, fsize, pline + 1, psize - 1))
|
||||||
|
misses++;
|
||||||
|
}
|
||||||
|
if (misses > fuzz)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strict match loop.
|
||||||
|
*/
|
||||||
|
for (; i < rf->nrec && j < ptop; i++, j++) {
|
||||||
|
for (; j < ptop; j++) {
|
||||||
|
if (!(pline = xdl_recfile_get(&pch->rf, j, &psize)))
|
||||||
|
return 0;
|
||||||
|
if (*pline == ' ' || *pline == mode)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j == ptop)
|
||||||
|
break;
|
||||||
|
if (!(fline = xdl_recfile_get(rf, i, &fsize)) ||
|
||||||
|
!xdl_line_match(pch, fline, fsize, pline + 1, psize - 1))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (; j < ptop; j++)
|
||||||
|
if (!(pline = xdl_recfile_get(&pch->rf, j, &psize)) ||
|
||||||
|
*pline == ' ' || *pline == mode)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally loop through the suffix fuzz area. In this loop we simply
|
||||||
|
* note mismatching lines. We allow missing lines here, that is,
|
||||||
|
* some suffix context lines are missing.
|
||||||
|
*/
|
||||||
|
for (z = sfuzz; z > 0 && i < rf->nrec; i++, j++, z--) {
|
||||||
|
if (!(pline = xdl_recfile_get(&pch->rf, j, &psize)))
|
||||||
|
return 0;
|
||||||
|
if (!(fline = xdl_recfile_get(rf, i, &fsize)) ||
|
||||||
|
!xdl_line_match(pch, fline, fsize, pline + 1, psize - 1))
|
||||||
|
misses++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return misses <= fuzz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_find_hunk(recfile_t *rf, long ibase, patch_t *pch, int mode,
|
||||||
|
int fuzz, long *hkpos, int *exact) {
|
||||||
|
long hpos, hlen, i, j;
|
||||||
|
long pos[2];
|
||||||
|
|
||||||
|
hpos = mode == '-' ? pch->hi.s1: pch->hi.s2;
|
||||||
|
hlen = mode == '-' ? pch->hi.cmn + pch->hi.rdel: pch->hi.cmn + pch->hi.radd;
|
||||||
|
if (xdl_hunk_match(rf, hpos, pch, mode, fuzz)) {
|
||||||
|
*hkpos = hpos;
|
||||||
|
*exact = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (i = 1;; i++) {
|
||||||
|
/*
|
||||||
|
* We allow a negative starting hunk position, up to the
|
||||||
|
* number of prefix context lines.
|
||||||
|
*/
|
||||||
|
j = 0;
|
||||||
|
if (hpos - i >= ibase - pch->hi.pctx)
|
||||||
|
pos[j++] = hpos - i;
|
||||||
|
if (hpos + i + hlen <= rf->nrec)
|
||||||
|
pos[j++] = hpos + i;
|
||||||
|
if (!j)
|
||||||
|
break;
|
||||||
|
for (j--; j >= 0; j--)
|
||||||
|
if (xdl_hunk_match(rf, pos[j], pch, mode, fuzz)) {
|
||||||
|
*hkpos = pos[j];
|
||||||
|
*exact = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_emit_rfile_line(recfile_t *rf, long line, xdemitcb_t *ecb) {
|
||||||
|
mmbuffer_t mb;
|
||||||
|
|
||||||
|
if (!(mb.ptr = (char *) xdl_recfile_get(rf, line, &mb.size)) ||
|
||||||
|
ecb->outf(ecb->priv, &mb, 1) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_flush_section(recfile_t *rf, long start, long top, xdemitcb_t *ecb) {
|
||||||
|
long i;
|
||||||
|
|
||||||
|
for (i = start; i <= top; i++) {
|
||||||
|
if (xdl_emit_rfile_line(rf, i, ecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_apply_hunk(recfile_t *rf, long hkpos, patch_t *pch, int mode,
|
||||||
|
long *ibase, xdemitcb_t *ecb) {
|
||||||
|
long j, psize, ptop;
|
||||||
|
char const *pline;
|
||||||
|
mmbuffer_t mb;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The hunk starting position (hkpos) can be negative, up to the number
|
||||||
|
* of prefix context lines. Since this function only emit the core of
|
||||||
|
* the hunk (the remaining lines are flushed by xdl_flush_section() calls)
|
||||||
|
* we need to normalize it by adding the number of prefix context lines.
|
||||||
|
* The normalized value of the starting position is then greater/equal
|
||||||
|
* to zero.
|
||||||
|
*/
|
||||||
|
hkpos += pch->hi.pctx;
|
||||||
|
if (xdl_flush_section(rf, *ibase, hkpos - 1, ecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*ibase = hkpos;
|
||||||
|
for (j = pch->hkrec + 1 + pch->hi.pctx,
|
||||||
|
ptop = pch->hkrec + 1 + pch->hklen - pch->hi.sctx; j < ptop; j++) {
|
||||||
|
if (!(pline = xdl_recfile_get(&pch->rf, j, &psize))) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (*pline == ' ') {
|
||||||
|
if (xdl_emit_rfile_line(rf, *ibase, ecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
(*ibase)++;
|
||||||
|
} else if (*pline != mode) {
|
||||||
|
mb.ptr = (char *) pline + 1;
|
||||||
|
mb.size = psize - 1;
|
||||||
|
if (ecb->outf(ecb->priv, &mb, 1) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pch->ps.adds++;
|
||||||
|
} else {
|
||||||
|
(*ibase)++;
|
||||||
|
pch->ps.dels++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_reject_hunk(recfile_t *rf, patch_t *pch, int mode,
|
||||||
|
xdemitcb_t *rjecb) {
|
||||||
|
long i, size, s1, s2, c1, c2;
|
||||||
|
char const *line, *pre;
|
||||||
|
mmbuffer_t mb;
|
||||||
|
|
||||||
|
if (mode == '-') {
|
||||||
|
s1 = pch->hi.s1;
|
||||||
|
s2 = pch->hi.s2;
|
||||||
|
c1 = pch->hi.c1;
|
||||||
|
c2 = pch->hi.c2;
|
||||||
|
} else {
|
||||||
|
s1 = pch->hi.s2;
|
||||||
|
s2 = pch->hi.s1;
|
||||||
|
c1 = pch->hi.c2;
|
||||||
|
c2 = pch->hi.c1;
|
||||||
|
}
|
||||||
|
s1 += pch->ps.adds - pch->ps.dels;
|
||||||
|
if (xdl_emit_hunk_hdr(s1 + 1, c1, s2 + 1, c2, rjecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = pch->hkrec + 1;
|
||||||
|
(line = xdl_recfile_get(&pch->rf, i, &size)) != NULL; i++) {
|
||||||
|
if (*line == '@' || *line == '\n')
|
||||||
|
break;
|
||||||
|
if (mode == '-' || *line == ' ') {
|
||||||
|
mb.ptr = (char *) line;
|
||||||
|
mb.size = size;
|
||||||
|
if (rjecb->outf(rjecb->priv, &mb, 1) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pre = *line == '+' ? "-": "+";
|
||||||
|
if (xdl_emit_diffrec(line + 1, size - 1, pre, strlen(pre),
|
||||||
|
rjecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_process_hunk(recfile_t *rff, patch_t *pch, long *ibase, int mode,
|
||||||
|
xdemitcb_t *ecb, xdemitcb_t *rjecb) {
|
||||||
|
int fuzz, exact, hlen, maxfuzz;
|
||||||
|
long hkpos;
|
||||||
|
|
||||||
|
hlen = mode == '-' ? pch->hi.cmn + pch->hi.rdel: pch->hi.cmn + pch->hi.radd;
|
||||||
|
maxfuzz = XDL_MAX_FUZZ;
|
||||||
|
if (hlen - maxfuzz < XDL_MIN_SYNCLINES)
|
||||||
|
maxfuzz = hlen - XDL_MIN_SYNCLINES;
|
||||||
|
if (maxfuzz < 0)
|
||||||
|
maxfuzz = 0;
|
||||||
|
for (fuzz = 0; fuzz <= maxfuzz; fuzz++) {
|
||||||
|
if (xdl_find_hunk(rff, *ibase, pch, mode, fuzz,
|
||||||
|
&hkpos, &exact)) {
|
||||||
|
if (xdl_apply_hunk(rff, hkpos, pch, mode,
|
||||||
|
ibase, ecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!exact || fuzz)
|
||||||
|
pch->fuzzies++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xdl_reject_hunk(rff, pch, mode, rjecb) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_patch(mmfile_t *mf, mmfile_t *mfp, int mode, xdemitcb_t *ecb,
|
||||||
|
xdemitcb_t *rjecb) {
|
||||||
|
int hkres, exact;
|
||||||
|
long hkpos, ibase;
|
||||||
|
recfile_t rff;
|
||||||
|
patch_t pch;
|
||||||
|
|
||||||
|
if (xdl_init_recfile(mf, 0, &rff) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_init_patch(mfp, mode & ~XDL_PATCH_MODEMASK, &pch) < 0) {
|
||||||
|
|
||||||
|
xdl_free_recfile(&rff);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mode &= XDL_PATCH_MODEMASK;
|
||||||
|
ibase = 0;
|
||||||
|
if ((hkres = xdl_first_hunk(&pch)) > 0) {
|
||||||
|
do {
|
||||||
|
if (xdl_process_hunk(&rff, &pch, &ibase, mode,
|
||||||
|
ecb, rjecb) < 0) {
|
||||||
|
xdl_free_patch(&pch);
|
||||||
|
xdl_free_recfile(&rff);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while ((hkres = xdl_next_hunk(&pch)) > 0);
|
||||||
|
}
|
||||||
|
if (hkres < 0) {
|
||||||
|
|
||||||
|
xdl_free_patch(&pch);
|
||||||
|
xdl_free_recfile(&rff);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_flush_section(&rff, ibase, rff.nrec - 1, ecb) < 0) {
|
||||||
|
|
||||||
|
xdl_free_patch(&pch);
|
||||||
|
xdl_free_recfile(&rff);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xdl_free_patch(&pch);
|
||||||
|
xdl_free_recfile(&rff);
|
||||||
|
|
||||||
|
return pch.fuzzies;
|
||||||
|
}
|
||||||
|
|
||||||
456
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xprepare.c
Normal file
456
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xprepare.c
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define XDL_KPDIS_RUN 4
|
||||||
|
#define XDL_MAX_EQLIMIT 1024
|
||||||
|
#define XDL_SIMSCAN_WINDOWN 100
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct s_xdlclass {
|
||||||
|
struct s_xdlclass *next;
|
||||||
|
unsigned long ha;
|
||||||
|
char const *line;
|
||||||
|
long size;
|
||||||
|
long idx;
|
||||||
|
} xdlclass_t;
|
||||||
|
|
||||||
|
typedef struct s_xdlclassifier {
|
||||||
|
unsigned int hbits;
|
||||||
|
long hsize;
|
||||||
|
xdlclass_t **rchash;
|
||||||
|
chastore_t ncha;
|
||||||
|
long count;
|
||||||
|
} xdlclassifier_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_init_classifier(xdlclassifier_t *cf, long size) {
|
||||||
|
long i;
|
||||||
|
|
||||||
|
cf->hbits = xdl_hashbits((unsigned int) size);
|
||||||
|
cf->hsize = 1 << cf->hbits;
|
||||||
|
|
||||||
|
if (xdl_cha_init(&cf->ncha, sizeof(xdlclass_t), size / 4 + 1) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(cf->rchash = (xdlclass_t **) xdl_malloc(cf->hsize * sizeof(xdlclass_t *)))) {
|
||||||
|
|
||||||
|
xdl_cha_free(&cf->ncha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < cf->hsize; i++)
|
||||||
|
cf->rchash[i] = NULL;
|
||||||
|
|
||||||
|
cf->count = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void xdl_free_classifier(xdlclassifier_t *cf) {
|
||||||
|
xdl_free(cf->rchash);
|
||||||
|
xdl_cha_free(&cf->ncha);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_classify_record(xdlclassifier_t *cf, xrecord_t **rhash, unsigned int hbits,
|
||||||
|
xrecord_t *rec) {
|
||||||
|
long hi;
|
||||||
|
char const *line;
|
||||||
|
xdlclass_t *rcrec;
|
||||||
|
|
||||||
|
line = rec->ptr;
|
||||||
|
hi = (long) XDL_HASHLONG(rec->ha, cf->hbits);
|
||||||
|
for (rcrec = cf->rchash[hi]; rcrec; rcrec = rcrec->next)
|
||||||
|
if (rcrec->ha == rec->ha && rcrec->size == rec->size &&
|
||||||
|
!memcmp(line, rcrec->line, rec->size))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!rcrec) {
|
||||||
|
if (!(rcrec = xdl_cha_alloc(&cf->ncha))) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rcrec->idx = cf->count++;
|
||||||
|
rcrec->line = line;
|
||||||
|
rcrec->size = rec->size;
|
||||||
|
rcrec->ha = rec->ha;
|
||||||
|
rcrec->next = cf->rchash[hi];
|
||||||
|
cf->rchash[hi] = rcrec;
|
||||||
|
}
|
||||||
|
|
||||||
|
rec->ha = (unsigned long) rcrec->idx;
|
||||||
|
|
||||||
|
hi = (long) XDL_HASHLONG(rec->ha, hbits);
|
||||||
|
rec->next = rhash[hi];
|
||||||
|
rhash[hi] = rec;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_prepare_ctx(mmfile_t *mf, long narec, xpparam_t const *xpp,
|
||||||
|
xdlclassifier_t *cf, xdfile_t *xdf) {
|
||||||
|
unsigned int hbits;
|
||||||
|
long i, nrec, hsize, bsize;
|
||||||
|
unsigned long hav;
|
||||||
|
char const *blk, *cur, *top, *prev;
|
||||||
|
xrecord_t *crec;
|
||||||
|
xrecord_t **recs, **rrecs;
|
||||||
|
xrecord_t **rhash;
|
||||||
|
unsigned long *ha;
|
||||||
|
char *rchg;
|
||||||
|
long *rindex;
|
||||||
|
|
||||||
|
if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *)))) {
|
||||||
|
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hbits = xdl_hashbits((unsigned int) narec);
|
||||||
|
hsize = 1 << hbits;
|
||||||
|
if (!(rhash = (xrecord_t **) xdl_malloc(hsize * sizeof(xrecord_t *)))) {
|
||||||
|
|
||||||
|
xdl_free(recs);
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < hsize; i++)
|
||||||
|
rhash[i] = NULL;
|
||||||
|
|
||||||
|
nrec = 0;
|
||||||
|
if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) {
|
||||||
|
for (top = blk + bsize;;) {
|
||||||
|
if (cur >= top) {
|
||||||
|
if (!(cur = blk = xdl_mmfile_next(mf, &bsize)))
|
||||||
|
break;
|
||||||
|
top = blk + bsize;
|
||||||
|
}
|
||||||
|
prev = cur;
|
||||||
|
hav = xdl_hash_record(&cur, top);
|
||||||
|
if (nrec >= narec) {
|
||||||
|
narec *= 2;
|
||||||
|
if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *)))) {
|
||||||
|
|
||||||
|
xdl_free(rhash);
|
||||||
|
xdl_free(recs);
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
recs = rrecs;
|
||||||
|
}
|
||||||
|
if (!(crec = xdl_cha_alloc(&xdf->rcha))) {
|
||||||
|
|
||||||
|
xdl_free(rhash);
|
||||||
|
xdl_free(recs);
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
crec->ptr = prev;
|
||||||
|
crec->size = (long) (cur - prev);
|
||||||
|
crec->ha = hav;
|
||||||
|
recs[nrec++] = crec;
|
||||||
|
|
||||||
|
if (xdl_classify_record(cf, rhash, hbits, crec) < 0) {
|
||||||
|
|
||||||
|
xdl_free(rhash);
|
||||||
|
xdl_free(recs);
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(rchg = (char *) xdl_malloc(nrec + 2))) {
|
||||||
|
|
||||||
|
xdl_free(rhash);
|
||||||
|
xdl_free(recs);
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(rchg, 0, nrec + 2);
|
||||||
|
|
||||||
|
if (!(rindex = (long *) xdl_malloc((nrec + 1) * sizeof(long)))) {
|
||||||
|
|
||||||
|
xdl_free(rchg);
|
||||||
|
xdl_free(rhash);
|
||||||
|
xdl_free(recs);
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(ha = (unsigned long *) xdl_malloc((nrec + 1) * sizeof(unsigned long)))) {
|
||||||
|
|
||||||
|
xdl_free(rindex);
|
||||||
|
xdl_free(rchg);
|
||||||
|
xdl_free(rhash);
|
||||||
|
xdl_free(recs);
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xdf->nrec = nrec;
|
||||||
|
xdf->recs = recs;
|
||||||
|
xdf->hbits = hbits;
|
||||||
|
xdf->rhash = rhash;
|
||||||
|
xdf->rchg = rchg + 1;
|
||||||
|
xdf->rindex = rindex;
|
||||||
|
xdf->nreff = 0;
|
||||||
|
xdf->ha = ha;
|
||||||
|
xdf->dstart = 0;
|
||||||
|
xdf->dend = nrec - 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void xdl_free_ctx(xdfile_t *xdf) {
|
||||||
|
xdl_free(xdf->rhash);
|
||||||
|
xdl_free(xdf->rindex);
|
||||||
|
xdl_free(xdf->rchg - 1);
|
||||||
|
xdl_free(xdf->ha);
|
||||||
|
xdl_free(xdf->recs);
|
||||||
|
xdl_cha_free(&xdf->rcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_clean_mmatch(char const *dis, long i, long s, long e) {
|
||||||
|
long r, rdis0, rpdis0, rdis1, rpdis1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Limits the window the is examined during the similar-lines
|
||||||
|
* scan. The loops below stops when dis[i - r] == 1 (line that
|
||||||
|
* has no match), but there are corner cases where the loop
|
||||||
|
* proceed all the way to the extremities by causing huge
|
||||||
|
* performance penalties in case of big files.
|
||||||
|
*/
|
||||||
|
if (i - s > XDL_SIMSCAN_WINDOWN)
|
||||||
|
s = i - XDL_SIMSCAN_WINDOWN;
|
||||||
|
if (e - i > XDL_SIMSCAN_WINDOWN)
|
||||||
|
e = i + XDL_SIMSCAN_WINDOWN;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scans the lines before 'i' to find a run of lines that either
|
||||||
|
* have no match (dis[j] == 0) or have multiple matches (dis[j] > 1).
|
||||||
|
* Note that we always call this function with dis[i] > 1, so the
|
||||||
|
* current line (i) is already a multimatch line.
|
||||||
|
*/
|
||||||
|
for (r = 1, rdis0 = 0, rpdis0 = 1; (i - r) >= s; r++) {
|
||||||
|
if (!dis[i - r])
|
||||||
|
rdis0++;
|
||||||
|
else if (dis[i - r] == 2)
|
||||||
|
rpdis0++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If the run before the line 'i' found only multimatch lines, we
|
||||||
|
* return 0 and hence we don't make the current line (i) discarded.
|
||||||
|
* We want to discard multimatch lines only when they appear in the
|
||||||
|
* middle of runs with nomatch lines (dis[j] == 0).
|
||||||
|
*/
|
||||||
|
if (rdis0 == 0)
|
||||||
|
return 0;
|
||||||
|
for (r = 1, rdis1 = 0, rpdis1 = 1; (i + r) <= e; r++) {
|
||||||
|
if (!dis[i + r])
|
||||||
|
rdis1++;
|
||||||
|
else if (dis[i + r] == 2)
|
||||||
|
rpdis1++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If the run after the line 'i' found only multimatch lines, we
|
||||||
|
* return 0 and hence we don't make the current line (i) discarded.
|
||||||
|
*/
|
||||||
|
if (rdis1 == 0)
|
||||||
|
return 0;
|
||||||
|
rdis1 += rdis0;
|
||||||
|
rpdis1 += rpdis0;
|
||||||
|
|
||||||
|
return rpdis1 * XDL_KPDIS_RUN < (rpdis1 + rdis1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to reduce the problem complexity, discard records that have no
|
||||||
|
* matches on the other file. Also, lines that have multiple matches
|
||||||
|
* might be potentially discarded if they happear in a run of discardable.
|
||||||
|
*/
|
||||||
|
static int xdl_cleanup_records(xdfile_t *xdf1, xdfile_t *xdf2) {
|
||||||
|
long i, nm, rhi, nreff, mlim;
|
||||||
|
unsigned long hav;
|
||||||
|
xrecord_t **recs;
|
||||||
|
xrecord_t *rec;
|
||||||
|
char *dis, *dis1, *dis2;
|
||||||
|
|
||||||
|
if (!(dis = (char *) xdl_malloc(xdf1->nrec + xdf2->nrec + 2))) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(dis, 0, xdf1->nrec + xdf2->nrec + 2);
|
||||||
|
dis1 = dis;
|
||||||
|
dis2 = dis1 + xdf1->nrec + 1;
|
||||||
|
|
||||||
|
if ((mlim = xdl_bogosqrt(xdf1->nrec)) > XDL_MAX_EQLIMIT)
|
||||||
|
mlim = XDL_MAX_EQLIMIT;
|
||||||
|
for (i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; i <= xdf1->dend; i++, recs++) {
|
||||||
|
hav = (*recs)->ha;
|
||||||
|
rhi = (long) XDL_HASHLONG(hav, xdf2->hbits);
|
||||||
|
for (nm = 0, rec = xdf2->rhash[rhi]; rec; rec = rec->next)
|
||||||
|
if (rec->ha == hav && ++nm == mlim)
|
||||||
|
break;
|
||||||
|
dis1[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mlim = xdl_bogosqrt(xdf2->nrec)) > XDL_MAX_EQLIMIT)
|
||||||
|
mlim = XDL_MAX_EQLIMIT;
|
||||||
|
for (i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; i <= xdf2->dend; i++, recs++) {
|
||||||
|
hav = (*recs)->ha;
|
||||||
|
rhi = (long) XDL_HASHLONG(hav, xdf1->hbits);
|
||||||
|
for (nm = 0, rec = xdf1->rhash[rhi]; rec; rec = rec->next)
|
||||||
|
if (rec->ha == hav && ++nm == mlim)
|
||||||
|
break;
|
||||||
|
dis2[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (nreff = 0, i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart];
|
||||||
|
i <= xdf1->dend; i++, recs++) {
|
||||||
|
if (dis1[i] == 1 ||
|
||||||
|
(dis1[i] == 2 && !xdl_clean_mmatch(dis1, i, xdf1->dstart, xdf1->dend))) {
|
||||||
|
xdf1->rindex[nreff] = i;
|
||||||
|
xdf1->ha[nreff] = (*recs)->ha;
|
||||||
|
nreff++;
|
||||||
|
} else
|
||||||
|
xdf1->rchg[i] = 1;
|
||||||
|
}
|
||||||
|
xdf1->nreff = nreff;
|
||||||
|
|
||||||
|
for (nreff = 0, i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart];
|
||||||
|
i <= xdf2->dend; i++, recs++) {
|
||||||
|
if (dis2[i] == 1 ||
|
||||||
|
(dis2[i] == 2 && !xdl_clean_mmatch(dis2, i, xdf2->dstart, xdf2->dend))) {
|
||||||
|
xdf2->rindex[nreff] = i;
|
||||||
|
xdf2->ha[nreff] = (*recs)->ha;
|
||||||
|
nreff++;
|
||||||
|
} else
|
||||||
|
xdf2->rchg[i] = 1;
|
||||||
|
}
|
||||||
|
xdf2->nreff = nreff;
|
||||||
|
|
||||||
|
xdl_free(dis);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Early trim initial and terminal matching records.
|
||||||
|
*/
|
||||||
|
static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2) {
|
||||||
|
long i, lim;
|
||||||
|
xrecord_t **recs1, **recs2;
|
||||||
|
|
||||||
|
recs1 = xdf1->recs;
|
||||||
|
recs2 = xdf2->recs;
|
||||||
|
for (i = 0, lim = XDL_MIN(xdf1->nrec, xdf2->nrec); i < lim;
|
||||||
|
i++, recs1++, recs2++)
|
||||||
|
if ((*recs1)->ha != (*recs2)->ha)
|
||||||
|
break;
|
||||||
|
|
||||||
|
xdf1->dstart = xdf2->dstart = i;
|
||||||
|
|
||||||
|
recs1 = xdf1->recs + xdf1->nrec - 1;
|
||||||
|
recs2 = xdf2->recs + xdf2->nrec - 1;
|
||||||
|
for (lim -= i, i = 0; i < lim; i++, recs1--, recs2--)
|
||||||
|
if ((*recs1)->ha != (*recs2)->ha)
|
||||||
|
break;
|
||||||
|
|
||||||
|
xdf1->dend = xdf1->nrec - i - 1;
|
||||||
|
xdf2->dend = xdf2->nrec - i - 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xdl_optimize_ctxs(xdfile_t *xdf1, xdfile_t *xdf2) {
|
||||||
|
if (xdl_trim_ends(xdf1, xdf2) < 0 ||
|
||||||
|
xdl_cleanup_records(xdf1, xdf2) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdfenv_t *xe) {
|
||||||
|
long enl1, enl2;
|
||||||
|
xdlclassifier_t cf;
|
||||||
|
|
||||||
|
enl1 = xdl_guess_lines(mf1) + 1;
|
||||||
|
enl2 = xdl_guess_lines(mf2) + 1;
|
||||||
|
|
||||||
|
if (xdl_init_classifier(&cf, enl1 + enl2 + 1) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xdl_prepare_ctx(mf1, enl1, xpp, &cf, &xe->xdf1) < 0) {
|
||||||
|
|
||||||
|
xdl_free_classifier(&cf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (xdl_prepare_ctx(mf2, enl2, xpp, &cf, &xe->xdf2) < 0) {
|
||||||
|
|
||||||
|
xdl_free_ctx(&xe->xdf1);
|
||||||
|
xdl_free_classifier(&cf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xdl_free_classifier(&cf);
|
||||||
|
|
||||||
|
if (xdl_optimize_ctxs(&xe->xdf1, &xe->xdf2) < 0) {
|
||||||
|
|
||||||
|
xdl_free_ctx(&xe->xdf2);
|
||||||
|
xdl_free_ctx(&xe->xdf1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xdl_free_env(xdfenv_t *xe) {
|
||||||
|
xdl_free_ctx(&xe->xdf2);
|
||||||
|
xdl_free_ctx(&xe->xdf1);
|
||||||
|
}
|
||||||
|
|
||||||
35
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xprepare.h
Normal file
35
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xprepare.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XPREPARE_H)
|
||||||
|
#define XPREPARE_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
||||||
|
xdfenv_t *xe);
|
||||||
|
void xdl_free_env(xdfenv_t *xe);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XPREPARE_H) */
|
||||||
|
|
||||||
381
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xrabdiff.c
Normal file
381
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xrabdiff.c
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
/*
|
||||||
|
* xrabdiff by Davide Libenzi (Rabin's polynomial fingerprint based delta generator)
|
||||||
|
* Copyright (C) 2006 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Hints, ideas and code for the implementation came from:
|
||||||
|
*
|
||||||
|
* Rabin's original paper: http://www.xmailserver.org/rabin.pdf
|
||||||
|
* Chan & Lu's paper: http://www.xmailserver.org/rabin_impl.pdf
|
||||||
|
* Broder's paper: http://www.xmailserver.org/rabin_apps.pdf
|
||||||
|
* LBFS source code: http://www.fs.net/sfswww/lbfs/
|
||||||
|
* Geert Bosch's post: http://marc.theaimsgroup.com/?l=git&m=114565424620771&w=2
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(XRABPLY_TYPE32) && !defined(XRABPLY_TYPE64)
|
||||||
|
#define XRABPLY_TYPE64 long long
|
||||||
|
#define XV64(v) ((xply_word) v ## ULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "xrabply.c"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define XRAB_SLIDE(v, c) do { \
|
||||||
|
if (++wpos == XRAB_WNDSIZE) wpos = 0; \
|
||||||
|
v ^= U[wbuf[wpos]]; \
|
||||||
|
wbuf[wpos] = (c); \
|
||||||
|
v = ((v << 8) | (c)) ^ T[v >> XRAB_SHIFT]; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#define XRAB_MINCPYSIZE 12
|
||||||
|
#define XRAB_WBITS (sizeof(xply_word) * 8)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct s_xrabctx {
|
||||||
|
long idxsize;
|
||||||
|
long *idx;
|
||||||
|
unsigned char const *data;
|
||||||
|
long size;
|
||||||
|
} xrabctx_t;
|
||||||
|
|
||||||
|
typedef struct s_xrabcpyi {
|
||||||
|
long src;
|
||||||
|
long tgt;
|
||||||
|
long len;
|
||||||
|
} xrabcpyi_t;
|
||||||
|
|
||||||
|
typedef struct s_xrabcpyi_arena {
|
||||||
|
long cnt, size;
|
||||||
|
xrabcpyi_t *acpy;
|
||||||
|
} xrabcpyi_arena_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void xrab_init_cpyarena(xrabcpyi_arena_t *aca) {
|
||||||
|
aca->cnt = aca->size = 0;
|
||||||
|
aca->acpy = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void xrab_free_cpyarena(xrabcpyi_arena_t *aca) {
|
||||||
|
xdl_free(aca->acpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xrab_add_cpy(xrabcpyi_arena_t *aca, xrabcpyi_t const *rcpy) {
|
||||||
|
long size;
|
||||||
|
xrabcpyi_t *acpy;
|
||||||
|
|
||||||
|
if (aca->cnt >= aca->size) {
|
||||||
|
size = 2 * aca->size + 1024;
|
||||||
|
if ((acpy = (xrabcpyi_t *)
|
||||||
|
xdl_realloc(aca->acpy, size * sizeof(xrabcpyi_t))) == NULL)
|
||||||
|
return -1;
|
||||||
|
aca->acpy = acpy;
|
||||||
|
aca->size = size;
|
||||||
|
}
|
||||||
|
aca->acpy[aca->cnt++] = *rcpy;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static long xrab_cmnseq(unsigned char const *data, long start, long size) {
|
||||||
|
unsigned char ch = data[start];
|
||||||
|
unsigned char const *ptr, *top;
|
||||||
|
|
||||||
|
for (ptr = data + start + 1, top = data + size; ptr < top && ch == *ptr; ptr++);
|
||||||
|
|
||||||
|
return (long) (ptr - (data + start + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xrab_build_ctx(unsigned char const *data, long size, xrabctx_t *ctx) {
|
||||||
|
long i, isize, idxsize, seq, wpos = 0;
|
||||||
|
xply_word fp = 0, mask;
|
||||||
|
unsigned char ch;
|
||||||
|
unsigned char const *ptr, *eot;
|
||||||
|
long *idx;
|
||||||
|
unsigned char wbuf[XRAB_WNDSIZE];
|
||||||
|
long maxoffs[256];
|
||||||
|
long maxseq[256];
|
||||||
|
xply_word maxfp[256];
|
||||||
|
|
||||||
|
memset(wbuf, 0, sizeof(wbuf));
|
||||||
|
memset(maxseq, 0, sizeof(maxseq));
|
||||||
|
isize = 2 * (size / XRAB_WNDSIZE);
|
||||||
|
for (idxsize = 1; idxsize < isize; idxsize <<= 1);
|
||||||
|
mask = (xply_word) (idxsize - 1);
|
||||||
|
if ((idx = (long *) xdl_malloc(idxsize * sizeof(long))) == NULL)
|
||||||
|
return -1;
|
||||||
|
memset(idx, 0, idxsize * sizeof(long));
|
||||||
|
for (i = 0; i + XRAB_WNDSIZE < size; i += XRAB_WNDSIZE) {
|
||||||
|
/*
|
||||||
|
* Generate a brand new hash for the current window. Here we could
|
||||||
|
* try to perform pseudo-loop unroll by 4 blocks if necessary, and
|
||||||
|
* if we force XRAB_WNDSIZE to be a multiple of 4, we could reduce
|
||||||
|
* the branch occurence inside XRAB_SLIDE by a factor of 4.
|
||||||
|
*/
|
||||||
|
for (ptr = data + i, eot = ptr + XRAB_WNDSIZE; ptr < eot; ptr++)
|
||||||
|
XRAB_SLIDE(fp, *ptr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to scan for single value scans, and store them in the
|
||||||
|
* array according to the longest one. Before we do a fast check
|
||||||
|
* to avoid calling xrab_cmnseq() when not necessary.
|
||||||
|
*/
|
||||||
|
if ((ch = data[i]) == data[i + XRAB_WNDSIZE - 1] &&
|
||||||
|
(seq = xrab_cmnseq(data, i, size)) > XRAB_WNDSIZE &&
|
||||||
|
seq > maxseq[ch]) {
|
||||||
|
maxseq[ch] = seq;
|
||||||
|
maxfp[ch] = fp;
|
||||||
|
maxoffs[ch] = i + XRAB_WNDSIZE;
|
||||||
|
seq = (seq / XRAB_WNDSIZE) * XRAB_WNDSIZE;
|
||||||
|
i += seq - XRAB_WNDSIZE;
|
||||||
|
} else
|
||||||
|
idx[fp & mask] = i + XRAB_WNDSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore back the logest sequences by overwriting target hash buckets.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
if (maxseq[i])
|
||||||
|
idx[maxfp[i] & mask] = maxoffs[i];
|
||||||
|
ctx->idxsize = idxsize;
|
||||||
|
ctx->idx = idx;
|
||||||
|
ctx->data = data;
|
||||||
|
ctx->size = size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void xrab_free_ctx(xrabctx_t *ctx) {
|
||||||
|
|
||||||
|
xdl_free(ctx->idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xrab_diff(unsigned char const *data, long size, xrabctx_t *ctx,
|
||||||
|
xrabcpyi_arena_t *aca) {
|
||||||
|
long i, offs, ssize, src, tgt, esrc, etgt, wpos = 0;
|
||||||
|
xply_word fp = 0, mask;
|
||||||
|
long const *idx;
|
||||||
|
unsigned char const *sdata;
|
||||||
|
xrabcpyi_t rcpy;
|
||||||
|
unsigned char wbuf[XRAB_WNDSIZE];
|
||||||
|
|
||||||
|
xrab_init_cpyarena(aca);
|
||||||
|
memset(wbuf, 0, sizeof(wbuf));
|
||||||
|
for (i = 0; i < XRAB_WNDSIZE - 1 && i < size; i++)
|
||||||
|
XRAB_SLIDE(fp, data[i]);
|
||||||
|
idx = ctx->idx;
|
||||||
|
sdata = ctx->data;
|
||||||
|
ssize = ctx->size;
|
||||||
|
mask = (xply_word) (ctx->idxsize - 1);
|
||||||
|
while (i < size) {
|
||||||
|
unsigned char ch = data[i++];
|
||||||
|
|
||||||
|
XRAB_SLIDE(fp, ch);
|
||||||
|
offs = idx[fp & mask];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fast check here to probabilistically reduce false positives
|
||||||
|
* that would trigger the slow path below.
|
||||||
|
*/
|
||||||
|
if (offs == 0 || ch != sdata[offs - 1])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stretch the match both sides as far as possible.
|
||||||
|
*/
|
||||||
|
src = offs - 1;
|
||||||
|
tgt = i - 1;
|
||||||
|
for (; tgt > 0 && src > 0 && data[tgt - 1] == sdata[src - 1];
|
||||||
|
tgt--, src--);
|
||||||
|
esrc = offs;
|
||||||
|
etgt = i;
|
||||||
|
for (; etgt < size && esrc < ssize && data[etgt] == sdata[esrc];
|
||||||
|
etgt++, esrc++);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid considering copies smaller than the XRAB_MINCPYSIZE
|
||||||
|
* threshold.
|
||||||
|
*/
|
||||||
|
if (etgt - tgt >= XRAB_MINCPYSIZE) {
|
||||||
|
rcpy.src = src;
|
||||||
|
rcpy.tgt = tgt;
|
||||||
|
rcpy.len = etgt - tgt;
|
||||||
|
if (xrab_add_cpy(aca, &rcpy) < 0) {
|
||||||
|
xrab_free_cpyarena(aca);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill up the new window and exit with 'i' properly set on exit.
|
||||||
|
*/
|
||||||
|
for (i = etgt - XRAB_WNDSIZE; i < etgt; i++)
|
||||||
|
XRAB_SLIDE(fp, data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int xrab_tune_cpyarena(unsigned char const *data, long size, xrabctx_t *ctx,
|
||||||
|
xrabcpyi_arena_t *aca) {
|
||||||
|
long i, cpos;
|
||||||
|
xrabcpyi_t *rcpy;
|
||||||
|
|
||||||
|
for (cpos = size, i = aca->cnt - 1; i >= 0; i--) {
|
||||||
|
rcpy = aca->acpy + i;
|
||||||
|
if (rcpy->tgt >= cpos)
|
||||||
|
rcpy->len = 0;
|
||||||
|
else if (rcpy->tgt + rcpy->len > cpos) {
|
||||||
|
if ((rcpy->len = cpos - rcpy->tgt) >= XRAB_MINCPYSIZE)
|
||||||
|
cpos = rcpy->tgt;
|
||||||
|
else
|
||||||
|
rcpy->len = 0;
|
||||||
|
} else
|
||||||
|
cpos = rcpy->tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_rabdiff_mb(mmbuffer_t *mmb1, mmbuffer_t *mmb2, xdemitcb_t *ecb) {
|
||||||
|
long i, cpos, size;
|
||||||
|
unsigned long fp;
|
||||||
|
xrabcpyi_t *rcpy;
|
||||||
|
xrabctx_t ctx;
|
||||||
|
xrabcpyi_arena_t aca;
|
||||||
|
mmbuffer_t mb[2];
|
||||||
|
unsigned char cpybuf[32];
|
||||||
|
|
||||||
|
fp = xdl_mmb_adler32(mmb1);
|
||||||
|
if (xrab_build_ctx((unsigned char const *) mmb1->ptr, mmb1->size,
|
||||||
|
&ctx) < 0)
|
||||||
|
return -1;
|
||||||
|
if (xrab_diff((unsigned char const *) mmb2->ptr, mmb2->size, &ctx,
|
||||||
|
&aca) < 0) {
|
||||||
|
xrab_free_ctx(&ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xrab_tune_cpyarena((unsigned char const *) mmb2->ptr, mmb2->size, &ctx,
|
||||||
|
&aca);
|
||||||
|
xrab_free_ctx(&ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare and emit the binary patch file header. It will be used
|
||||||
|
* to verify that that file being patched matches in size and fingerprint
|
||||||
|
* the one that generated the patch.
|
||||||
|
*/
|
||||||
|
size = mmb1->size;
|
||||||
|
XDL_LE32_PUT(cpybuf, fp);
|
||||||
|
XDL_LE32_PUT(cpybuf + 4, size);
|
||||||
|
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = 4 + 4;
|
||||||
|
if (ecb->outf(ecb->priv, mb, 1) < 0) {
|
||||||
|
xrab_free_cpyarena(&aca);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (cpos = 0, i = 0; i < aca.cnt; i++) {
|
||||||
|
rcpy = aca.acpy + i;
|
||||||
|
if (rcpy->len == 0)
|
||||||
|
continue;
|
||||||
|
if (cpos < rcpy->tgt) {
|
||||||
|
size = rcpy->tgt - cpos;
|
||||||
|
if (size > 255) {
|
||||||
|
cpybuf[0] = XDL_BDOP_INSB;
|
||||||
|
XDL_LE32_PUT(cpybuf + 1, size);
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = XDL_INSBOP_SIZE;
|
||||||
|
} else {
|
||||||
|
cpybuf[0] = XDL_BDOP_INS;
|
||||||
|
cpybuf[1] = (unsigned char) size;
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = 2;
|
||||||
|
}
|
||||||
|
mb[1].ptr = mmb2->ptr + cpos;
|
||||||
|
mb[1].size = size;
|
||||||
|
if (ecb->outf(ecb->priv, mb, 2) < 0) {
|
||||||
|
xrab_free_cpyarena(&aca);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cpos = rcpy->tgt;
|
||||||
|
}
|
||||||
|
cpybuf[0] = XDL_BDOP_CPY;
|
||||||
|
XDL_LE32_PUT(cpybuf + 1, rcpy->src);
|
||||||
|
XDL_LE32_PUT(cpybuf + 5, rcpy->len);
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = XDL_COPYOP_SIZE;
|
||||||
|
if (ecb->outf(ecb->priv, mb, 1) < 0) {
|
||||||
|
xrab_free_cpyarena(&aca);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cpos += rcpy->len;
|
||||||
|
}
|
||||||
|
xrab_free_cpyarena(&aca);
|
||||||
|
if (cpos < mmb2->size) {
|
||||||
|
size = mmb2->size - cpos;
|
||||||
|
if (size > 255) {
|
||||||
|
cpybuf[0] = XDL_BDOP_INSB;
|
||||||
|
XDL_LE32_PUT(cpybuf + 1, size);
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = XDL_INSBOP_SIZE;
|
||||||
|
} else {
|
||||||
|
cpybuf[0] = XDL_BDOP_INS;
|
||||||
|
cpybuf[1] = (unsigned char) size;
|
||||||
|
mb[0].ptr = (char *) cpybuf;
|
||||||
|
mb[0].size = 2;
|
||||||
|
}
|
||||||
|
mb[1].ptr = mmb2->ptr + cpos;
|
||||||
|
mb[1].size = size;
|
||||||
|
if (ecb->outf(ecb->priv, mb, 2) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_rabdiff(mmfile_t *mmf1, mmfile_t *mmf2, xdemitcb_t *ecb) {
|
||||||
|
mmbuffer_t mmb1, mmb2;
|
||||||
|
|
||||||
|
if (!xdl_mmfile_iscompact(mmf1) || !xdl_mmfile_iscompact(mmf2))
|
||||||
|
return -1;
|
||||||
|
if ((mmb1.ptr = (char *) xdl_mmfile_first(mmf1, &mmb1.size)) == NULL)
|
||||||
|
mmb1.size = 0;
|
||||||
|
if ((mmb2.ptr = (char *) xdl_mmfile_first(mmf2, &mmb2.size)) == NULL)
|
||||||
|
mmb2.size = 0;
|
||||||
|
|
||||||
|
return xdl_rabdiff_mb(&mmb1, &mmb2, ecb);
|
||||||
|
}
|
||||||
|
|
||||||
298
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xrabply.c
Normal file
298
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xrabply.c
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
#if defined(XRABPLY_TYPE64)
|
||||||
|
|
||||||
|
#if !defined(XV64)
|
||||||
|
#define XV64(v) ((xply_word) v ## ULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define XRAB_ROOTPOLY XV64(0x36f7381af4d70d33)
|
||||||
|
|
||||||
|
#define XRAB_SHIFT 53
|
||||||
|
#define XRAB_WNDSIZE 20
|
||||||
|
|
||||||
|
typedef unsigned XRABPLY_TYPE64 xply_word;
|
||||||
|
|
||||||
|
static const xply_word T[256] = {
|
||||||
|
XV64(0x0), XV64(0x36f7381af4d70d33), XV64(0x5b19482f1d791755), XV64(0x6dee7035e9ae1a66),
|
||||||
|
XV64(0x80c5a844ce252399), XV64(0xb632905e3af22eaa), XV64(0xdbdce06bd35c34cc), XV64(0xed2bd871278b39ff),
|
||||||
|
XV64(0x18b50899c4a4732), XV64(0x377c6893689d4a01), XV64(0x5a9218a681335067), XV64(0x6c6520bc75e45d54),
|
||||||
|
XV64(0x814ef8cd526f64ab), XV64(0xb7b9c0d7a6b86998), XV64(0xda57b0e24f1673fe), XV64(0xeca088f8bbc17ecd),
|
||||||
|
XV64(0x316a11338948e64), XV64(0x35e19909cc438357), XV64(0x580fe93c25ed9931), XV64(0x6ef8d126d13a9402),
|
||||||
|
XV64(0x83d30957f6b1adfd), XV64(0xb524314d0266a0ce), XV64(0xd8ca4178ebc8baa8), XV64(0xee3d79621f1fb79b),
|
||||||
|
XV64(0x29df19aa4dec956), XV64(0x346ac9805009c465), XV64(0x5984b9b5b9a7de03), XV64(0x6f7381af4d70d330),
|
||||||
|
XV64(0x825859de6afbeacf), XV64(0xb4af61c49e2ce7fc), XV64(0xd94111f17782fd9a), XV64(0xefb629eb8355f0a9),
|
||||||
|
XV64(0x62d422671291cc8), XV64(0x30da7a3c85fe11fb), XV64(0x5d340a096c500b9d), XV64(0x6bc33213988706ae),
|
||||||
|
XV64(0x86e8ea62bf0c3f51), XV64(0xb01fd2784bdb3262), XV64(0xddf1a24da2752804), XV64(0xeb069a5756a22537),
|
||||||
|
XV64(0x7a612afed635bfa), XV64(0x31512ab519b456c9), XV64(0x5cbf5a80f01a4caf), XV64(0x6a48629a04cd419c),
|
||||||
|
XV64(0x8763baeb23467863), XV64(0xb19482f1d7917550), XV64(0xdc7af2c43e3f6f36), XV64(0xea8dcadecae86205),
|
||||||
|
XV64(0x53be33549bd92ac), XV64(0x33ccdb2fbd6a9f9f), XV64(0x5e22ab1a54c485f9), XV64(0x68d59300a01388ca),
|
||||||
|
XV64(0x85fe4b718798b135), XV64(0xb309736b734fbc06), XV64(0xdee7035e9ae1a660), XV64(0xe8103b446e36ab53),
|
||||||
|
XV64(0x4b0b3bcd5f7d59e), XV64(0x32478ba62120d8ad), XV64(0x5fa9fb93c88ec2cb), XV64(0x695ec3893c59cff8),
|
||||||
|
XV64(0x84751bf81bd2f607), XV64(0xb28223e2ef05fb34), XV64(0xdf6c53d706abe152), XV64(0xe99b6bcdf27cec61),
|
||||||
|
XV64(0xc5a844ce2523990), XV64(0x3aadbc56168534a3), XV64(0x5743cc63ff2b2ec5), XV64(0x61b4f4790bfc23f6),
|
||||||
|
XV64(0x8c9f2c082c771a09), XV64(0xba681412d8a0173a), XV64(0xd7866427310e0d5c), XV64(0xe1715c3dc5d9006f),
|
||||||
|
XV64(0xdd1d4c57e187ea2), XV64(0x3b26ecdf8acf7391), XV64(0x56c89cea636169f7), XV64(0x603fa4f097b664c4),
|
||||||
|
XV64(0x8d147c81b03d5d3b), XV64(0xbbe3449b44ea5008), XV64(0xd60d34aead444a6e), XV64(0xe0fa0cb45993475d),
|
||||||
|
XV64(0xf4c255fdac6b7f4), XV64(0x39bb1d452e11bac7), XV64(0x54556d70c7bfa0a1), XV64(0x62a2556a3368ad92),
|
||||||
|
XV64(0x8f898d1b14e3946d), XV64(0xb97eb501e034995e), XV64(0xd490c534099a8338), XV64(0xe267fd2efd4d8e0b),
|
||||||
|
XV64(0xec775d6468cf0c6), XV64(0x38304dccb25bfdf5), XV64(0x55de3df95bf5e793), XV64(0x632905e3af22eaa0),
|
||||||
|
XV64(0x8e02dd9288a9d35f), XV64(0xb8f5e5887c7ede6c), XV64(0xd51b95bd95d0c40a), XV64(0xe3ecada76107c939),
|
||||||
|
XV64(0xa77c66a937b2558), XV64(0x3c80fe7067ac286b), XV64(0x516e8e458e02320d), XV64(0x6799b65f7ad53f3e),
|
||||||
|
XV64(0x8ab26e2e5d5e06c1), XV64(0xbc455634a9890bf2), XV64(0xd1ab260140271194), XV64(0xe75c1e1bb4f01ca7),
|
||||||
|
XV64(0xbfc96e30f31626a), XV64(0x3d0baef9fbe66f59), XV64(0x50e5decc1248753f), XV64(0x6612e6d6e69f780c),
|
||||||
|
XV64(0x8b393ea7c11441f3), XV64(0xbdce06bd35c34cc0), XV64(0xd0207688dc6d56a6), XV64(0xe6d74e9228ba5b95),
|
||||||
|
XV64(0x9616779abefab3c), XV64(0x3f965f635f38a60f), XV64(0x52782f56b696bc69), XV64(0x648f174c4241b15a),
|
||||||
|
XV64(0x89a4cf3d65ca88a5), XV64(0xbf53f727911d8596), XV64(0xd2bd871278b39ff0), XV64(0xe44abf088c6492c3),
|
||||||
|
XV64(0x8ea37f037a5ec0e), XV64(0x3e1d0feac372e13d), XV64(0x53f37fdf2adcfb5b), XV64(0x650447c5de0bf668),
|
||||||
|
XV64(0x882f9fb4f980cf97), XV64(0xbed8a7ae0d57c2a4), XV64(0xd336d79be4f9d8c2), XV64(0xe5c1ef81102ed5f1),
|
||||||
|
XV64(0x18b50899c4a47320), XV64(0x2e42308330737e13), XV64(0x43ac40b6d9dd6475), XV64(0x755b78ac2d0a6946),
|
||||||
|
XV64(0x9870a0dd0a8150b9), XV64(0xae8798c7fe565d8a), XV64(0xc369e8f217f847ec), XV64(0xf59ed0e8e32f4adf),
|
||||||
|
XV64(0x193e581058ee3412), XV64(0x2fc9600aac393921), XV64(0x4227103f45972347), XV64(0x74d02825b1402e74),
|
||||||
|
XV64(0x99fbf05496cb178b), XV64(0xaf0cc84e621c1ab8), XV64(0xc2e2b87b8bb200de), XV64(0xf41580617f650ded),
|
||||||
|
XV64(0x1ba3a98afc30fd44), XV64(0x2d54919008e7f077), XV64(0x40bae1a5e149ea11), XV64(0x764dd9bf159ee722),
|
||||||
|
XV64(0x9b6601ce3215dedd), XV64(0xad9139d4c6c2d3ee), XV64(0xc07f49e12f6cc988), XV64(0xf68871fbdbbbc4bb),
|
||||||
|
XV64(0x1a28f903607aba76), XV64(0x2cdfc11994adb745), XV64(0x4131b12c7d03ad23), XV64(0x77c6893689d4a010),
|
||||||
|
XV64(0x9aed5147ae5f99ef), XV64(0xac1a695d5a8894dc), XV64(0xc1f41968b3268eba), XV64(0xf703217247f18389),
|
||||||
|
XV64(0x1e984abfb58d6fe8), XV64(0x286f72a5415a62db), XV64(0x45810290a8f478bd), XV64(0x73763a8a5c23758e),
|
||||||
|
XV64(0x9e5de2fb7ba84c71), XV64(0xa8aadae18f7f4142), XV64(0xc544aad466d15b24), XV64(0xf3b392ce92065617),
|
||||||
|
XV64(0x1f131a3629c728da), XV64(0x29e4222cdd1025e9), XV64(0x440a521934be3f8f), XV64(0x72fd6a03c06932bc),
|
||||||
|
XV64(0x9fd6b272e7e20b43), XV64(0xa9218a6813350670), XV64(0xc4cffa5dfa9b1c16), XV64(0xf238c2470e4c1125),
|
||||||
|
XV64(0x1d8eebac8d19e18c), XV64(0x2b79d3b679ceecbf), XV64(0x4697a3839060f6d9), XV64(0x70609b9964b7fbea),
|
||||||
|
XV64(0x9d4b43e8433cc215), XV64(0xabbc7bf2b7ebcf26), XV64(0xc6520bc75e45d540), XV64(0xf0a533ddaa92d873),
|
||||||
|
XV64(0x1c05bb251153a6be), XV64(0x2af2833fe584ab8d), XV64(0x471cf30a0c2ab1eb), XV64(0x71ebcb10f8fdbcd8),
|
||||||
|
XV64(0x9cc01361df768527), XV64(0xaa372b7b2ba18814), XV64(0xc7d95b4ec20f9272), XV64(0xf12e635436d89f41),
|
||||||
|
XV64(0x14ef8cd526f64ab0), XV64(0x2218b4cfd2214783), XV64(0x4ff6c4fa3b8f5de5), XV64(0x7901fce0cf5850d6),
|
||||||
|
XV64(0x942a2491e8d36929), XV64(0xa2dd1c8b1c04641a), XV64(0xcf336cbef5aa7e7c), XV64(0xf9c454a4017d734f),
|
||||||
|
XV64(0x1564dc5cbabc0d82), XV64(0x2393e4464e6b00b1), XV64(0x4e7d9473a7c51ad7), XV64(0x788aac69531217e4),
|
||||||
|
XV64(0x95a1741874992e1b), XV64(0xa3564c02804e2328), XV64(0xceb83c3769e0394e), XV64(0xf84f042d9d37347d),
|
||||||
|
XV64(0x17f92dc61e62c4d4), XV64(0x210e15dceab5c9e7), XV64(0x4ce065e9031bd381), XV64(0x7a175df3f7ccdeb2),
|
||||||
|
XV64(0x973c8582d047e74d), XV64(0xa1cbbd982490ea7e), XV64(0xcc25cdadcd3ef018), XV64(0xfad2f5b739e9fd2b),
|
||||||
|
XV64(0x16727d4f822883e6), XV64(0x2085455576ff8ed5), XV64(0x4d6b35609f5194b3), XV64(0x7b9c0d7a6b869980),
|
||||||
|
XV64(0x96b7d50b4c0da07f), XV64(0xa040ed11b8daad4c), XV64(0xcdae9d245174b72a), XV64(0xfb59a53ea5a3ba19),
|
||||||
|
XV64(0x12c2cef357df5678), XV64(0x2435f6e9a3085b4b), XV64(0x49db86dc4aa6412d), XV64(0x7f2cbec6be714c1e),
|
||||||
|
XV64(0x920766b799fa75e1), XV64(0xa4f05ead6d2d78d2), XV64(0xc91e2e98848362b4), XV64(0xffe9168270546f87),
|
||||||
|
XV64(0x13499e7acb95114a), XV64(0x25bea6603f421c79), XV64(0x4850d655d6ec061f), XV64(0x7ea7ee4f223b0b2c),
|
||||||
|
XV64(0x938c363e05b032d3), XV64(0xa57b0e24f1673fe0), XV64(0xc8957e1118c92586), XV64(0xfe62460bec1e28b5),
|
||||||
|
XV64(0x11d46fe06f4bd81c), XV64(0x272357fa9b9cd52f), XV64(0x4acd27cf7232cf49), XV64(0x7c3a1fd586e5c27a),
|
||||||
|
XV64(0x9111c7a4a16efb85), XV64(0xa7e6ffbe55b9f6b6), XV64(0xca088f8bbc17ecd0), XV64(0xfcffb79148c0e1e3),
|
||||||
|
XV64(0x105f3f69f3019f2e), XV64(0x26a8077307d6921d), XV64(0x4b467746ee78887b), XV64(0x7db14f5c1aaf8548),
|
||||||
|
XV64(0x909a972d3d24bcb7), XV64(0xa66daf37c9f3b184), XV64(0xcb83df02205dabe2), XV64(0xfd74e718d48aa6d1)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const xply_word U[256] = {
|
||||||
|
XV64(0x0), XV64(0x1c3eb44b122426b2), XV64(0xe8a508cd09f4057), XV64(0x12b4e4c7c2bb66e5),
|
||||||
|
XV64(0x1d14a119a13e80ae), XV64(0x12a1552b31aa61c), XV64(0x139ef19571a1c0f9), XV64(0xfa045de6385e64b),
|
||||||
|
XV64(0xcde7a29b6aa0c6f), XV64(0x10e0ce62a48e2add), XV64(0x2542aa566354c38), XV64(0x1e6a9eee74116a8a),
|
||||||
|
XV64(0x11cadb3017948cc1), XV64(0xdf46f7b05b0aa73), XV64(0x1f408bbcc70bcc96), XV64(0x37e3ff7d52fea24),
|
||||||
|
XV64(0x19bcf4536d5418de), XV64(0x58240187f703e6c), XV64(0x1736a4dfbdcb5889), XV64(0xb081094afef7e3b),
|
||||||
|
XV64(0x4a8554acc6a9870), XV64(0x1896e101de4ebec2), XV64(0xa2205c61cf5d827), XV64(0x161cb18d0ed1fe95),
|
||||||
|
XV64(0x15628e7adbfe14b1), XV64(0x95c3a31c9da3203), XV64(0x1be8def60b6154e6), XV64(0x7d66abd19457254),
|
||||||
|
XV64(0x8762f637ac0941f), XV64(0x14489b2868e4b2ad), XV64(0x6fc7fefaa5fd448), XV64(0x1ac2cba4b87bf2fa),
|
||||||
|
XV64(0x58ed0bc2e7f3c8f), XV64(0x19b064f73c5b1a3d), XV64(0xb048030fee07cd8), XV64(0x173a347becc45a6a),
|
||||||
|
XV64(0x189a71a58f41bc21), XV64(0x4a4c5ee9d659a93), XV64(0x161021295fdefc76), XV64(0xa2e95624dfadac4),
|
||||||
|
XV64(0x950aa9598d530e0), XV64(0x156e1ede8af11652), XV64(0x7dafa19484a70b7), XV64(0x1be44e525a6e5605),
|
||||||
|
XV64(0x14440b8c39ebb04e), XV64(0x87abfc72bcf96fc), XV64(0x1ace5b00e974f019), XV64(0x6f0ef4bfb50d6ab),
|
||||||
|
XV64(0x1c3224ef432b2451), XV64(0xc90a4510f02e3), XV64(0x12b8746393b46406), XV64(0xe86c028819042b4),
|
||||||
|
XV64(0x12685f6e215a4ff), XV64(0x1d1831bdf031824d), XV64(0xfacd57a328ae4a8), XV64(0x1392613120aec21a),
|
||||||
|
XV64(0x10ec5ec6f581283e), XV64(0xcd2ea8de7a50e8c), XV64(0x1e660e4a251e6869), XV64(0x258ba01373a4edb),
|
||||||
|
XV64(0xdf8ffdf54bfa890), XV64(0x11c64b94469b8e22), XV64(0x372af538420e8c7), XV64(0x1f4c1b189604ce75),
|
||||||
|
XV64(0xb1da1785cfe791e), XV64(0x172315334eda5fac), XV64(0x597f1f48c613949), XV64(0x19a945bf9e451ffb),
|
||||||
|
XV64(0x16090061fdc0f9b0), XV64(0xa37b42aefe4df02), XV64(0x188350ed2d5fb9e7), XV64(0x4bde4a63f7b9f55),
|
||||||
|
XV64(0x7c3db51ea547571), XV64(0x1bfd6f1af87053c3), XV64(0x9498bdd3acb3526), XV64(0x15773f9628ef1394),
|
||||||
|
XV64(0x1ad77a484b6af5df), XV64(0x6e9ce03594ed36d), XV64(0x145d2ac49bf5b588), XV64(0x8639e8f89d1933a),
|
||||||
|
XV64(0x12a1552b31aa61c0), XV64(0xe9fe160238e4772), XV64(0x1c2b05a7e1352197), XV64(0x15b1ecf3110725),
|
||||||
|
XV64(0xfb5f4329094e16e), XV64(0x138b407982b0c7dc), XV64(0x13fa4be400ba139), XV64(0x1d0110f5522f878b),
|
||||||
|
XV64(0x1e7f2f0287006daf), XV64(0x2419b4995244b1d), XV64(0x10f57f8e579f2df8), XV64(0xccbcbc545bb0b4a),
|
||||||
|
XV64(0x36b8e1b263eed01), XV64(0x1f553a50341acbb3), XV64(0xde1de97f6a1ad56), XV64(0x11df6adce4858be4),
|
||||||
|
XV64(0xe9371c472814591), XV64(0x12adc58f60a56323), XV64(0x192148a21e05c6), XV64(0x1c279503b03a2374),
|
||||||
|
XV64(0x1387d0ddd3bfc53f), XV64(0xfb96496c19be38d), XV64(0x1d0d805103208568), XV64(0x133341a1104a3da),
|
||||||
|
XV64(0x24d0bedc42b49fe), XV64(0x1e73bfa6d60f6f4c), XV64(0xcc75b6114b409a9), XV64(0x10f9ef2a06902f1b),
|
||||||
|
XV64(0x1f59aaf46515c950), XV64(0x3671ebf7731efe2), XV64(0x11d3fa78b58a8907), XV64(0xded4e33a7aeafb5),
|
||||||
|
XV64(0x172f85971fd55d4f), XV64(0xb1131dc0df17bfd), XV64(0x19a5d51bcf4a1d18), XV64(0x59b6150dd6e3baa),
|
||||||
|
XV64(0xa3b248ebeebdde1), XV64(0x160590c5accffb53), XV64(0x4b174026e749db6), XV64(0x188fc0497c50bb04),
|
||||||
|
XV64(0x1bf1ffbea97f5120), XV64(0x7cf4bf5bb5b7792), XV64(0x157baf3279e01177), XV64(0x9451b796bc437c5),
|
||||||
|
XV64(0x6e55ea70841d18e), XV64(0x1adbeaec1a65f73c), XV64(0x86f0e2bd8de91d9), XV64(0x1451ba60cafab76b),
|
||||||
|
XV64(0x163b42f0b9fcf23c), XV64(0xa05f6bbabd8d48e), XV64(0x18b1127c6963b26b), XV64(0x48fa6377b4794d9),
|
||||||
|
XV64(0xb2fe3e918c27292), XV64(0x171157a20ae65420), XV64(0x5a5b365c85d32c5), XV64(0x199b072eda791477),
|
||||||
|
XV64(0x1ae538d90f56fe53), XV64(0x6db8c921d72d8e1), XV64(0x146f6855dfc9be04), XV64(0x851dc1ecded98b6),
|
||||||
|
XV64(0x7f199c0ae687efd), XV64(0x1bcf2d8bbc4c584f), XV64(0x97bc94c7ef73eaa), XV64(0x15457d076cd31818),
|
||||||
|
XV64(0xf87b6a3d4a8eae2), XV64(0x13b902e8c68ccc50), XV64(0x10de62f0437aab5), XV64(0x1d33526416138c07),
|
||||||
|
XV64(0x129317ba75966a4c), XV64(0xeada3f167b24cfe), XV64(0x1c194736a5092a1b), XV64(0x27f37db72d0ca9),
|
||||||
|
XV64(0x359cc8a6202e68d), XV64(0x1f6778c17026c03f), XV64(0xdd39c06b29da6da), XV64(0x11ed284da0b98068),
|
||||||
|
XV64(0x1e4d6d93c33c6623), XV64(0x273d9d8d1184091), XV64(0x10c73d1f13a32674), XV64(0xcf98954018700c6),
|
||||||
|
XV64(0x13b5924c9783ceb3), XV64(0xf8b260785a7e801), XV64(0x1d3fc2c0471c8ee4), XV64(0x101768b5538a856),
|
||||||
|
XV64(0xea1335536bd4e1d), XV64(0x129f871e249968af), XV64(0x2b63d9e6220e4a), XV64(0x1c15d792f40628f8),
|
||||||
|
XV64(0x1f6be8652129c2dc), XV64(0x3555c2e330de46e), XV64(0x11e1b8e9f1b6828b), XV64(0xddf0ca2e392a439),
|
||||||
|
XV64(0x27f497c80174272), XV64(0x1e41fd37923364c0), XV64(0xcf519f050880225), XV64(0x10cbadbb42ac2497),
|
||||||
|
XV64(0xa09661ffad7d66d), XV64(0x1637d254e8f3f0df), XV64(0x48336932a48963a), XV64(0x18bd82d8386cb088),
|
||||||
|
XV64(0x171dc7065be956c3), XV64(0xb23734d49cd7071), XV64(0x1997978a8b761694), XV64(0x5a923c199523026),
|
||||||
|
XV64(0x6d71c364c7dda02), XV64(0x1ae9a87d5e59fcb0), XV64(0x85d4cba9ce29a55), XV64(0x1463f8f18ec6bce7),
|
||||||
|
XV64(0x1bc3bd2fed435aac), XV64(0x7fd0964ff677c1e), XV64(0x1549eda33ddc1afb), XV64(0x97759e82ff83c49),
|
||||||
|
XV64(0x1d26e388e5028b22), XV64(0x11857c3f726ad90), XV64(0x13acb304359dcb75), XV64(0xf92074f27b9edc7),
|
||||||
|
XV64(0x324291443c0b8c), XV64(0x1c0cf6da56182d3e), XV64(0xeb8121d94a34bdb), XV64(0x1286a65686876d69),
|
||||||
|
XV64(0x11f899a153a8874d), XV64(0xdc62dea418ca1ff), XV64(0x1f72c92d8337c71a), XV64(0x34c7d669113e1a8),
|
||||||
|
XV64(0xcec38b8f29607e3), XV64(0x10d28cf3e0b22151), XV64(0x2666834220947b4), XV64(0x1e58dc7f302d6106),
|
||||||
|
XV64(0x49a17db885693fc), XV64(0x18a4a3909a72b54e), XV64(0xa10475758c9d3ab), XV64(0x162ef31c4aedf519),
|
||||||
|
XV64(0x198eb6c229681352), XV64(0x5b002893b4c35e0), XV64(0x1704e64ef9f75305), XV64(0xb3a5205ebd375b7),
|
||||||
|
XV64(0x8446df23efc9f93), XV64(0x147ad9b92cd8b921), XV64(0x6ce3d7eee63dfc4), XV64(0x1af08935fc47f976),
|
||||||
|
XV64(0x1550cceb9fc21f3d), XV64(0x96e78a08de6398f), XV64(0x1bda9c674f5d5f6a), XV64(0x7e4282c5d7979d8),
|
||||||
|
XV64(0x18a83334cb7db7ad), XV64(0x496877fd959911f), XV64(0x162263b81be2f7fa), XV64(0xa1cd7f309c6d148),
|
||||||
|
XV64(0x5bc922d6a433703), XV64(0x19822666786711b1), XV64(0xb36c2a1badc7754), XV64(0x170876eaa8f851e6),
|
||||||
|
XV64(0x1476491d7dd7bbc2), XV64(0x848fd566ff39d70), XV64(0x1afc1991ad48fb95), XV64(0x6c2addabf6cdd27),
|
||||||
|
XV64(0x962e804dce93b6c), XV64(0x155c5c4fcecd1dde), XV64(0x7e8b8880c767b3b), XV64(0x1bd60cc31e525d89),
|
||||||
|
XV64(0x114c767a629af73), XV64(0x1d2a732cb40d89c1), XV64(0xf9e97eb76b6ef24), XV64(0x13a023a06492c996),
|
||||||
|
XV64(0x1c00667e07172fdd), XV64(0x3ed2351533096f), XV64(0x128a36f2d7886f8a), XV64(0xeb482b9c5ac4938),
|
||||||
|
XV64(0xdcabd4e1083a31c), XV64(0x11f4090502a785ae), XV64(0x340edc2c01ce34b), XV64(0x1f7e5989d238c5f9),
|
||||||
|
XV64(0x10de1c57b1bd23b2), XV64(0xce0a81ca3990500), XV64(0x1e544cdb612263e5), XV64(0x26af89073064557)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* if defined(XRABPLY_TYPE64) */
|
||||||
|
|
||||||
|
#if defined(XRABPLY_TYPE32)
|
||||||
|
|
||||||
|
#if !defined(XV32)
|
||||||
|
#define XV32(v) ((xply_word) v ## ULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define XRAB_ROOTPOLY XV32(0xabd1f37b)
|
||||||
|
|
||||||
|
#define XRAB_SHIFT 23
|
||||||
|
#define XRAB_WNDSIZE 20
|
||||||
|
|
||||||
|
typedef unsigned XRABPLY_TYPE32 xply_word;
|
||||||
|
|
||||||
|
static const xply_word T[256] = {
|
||||||
|
XV32(0x0), XV32(0xabd1f37b), XV32(0x57a3e6f6), XV32(0xfc72158d),
|
||||||
|
XV32(0x4963e97), XV32(0xaf47cdec), XV32(0x5335d861), XV32(0xf8e42b1a),
|
||||||
|
XV32(0x92c7d2e), XV32(0xa2fd8e55), XV32(0x5e8f9bd8), XV32(0xf55e68a3),
|
||||||
|
XV32(0xdba43b9), XV32(0xa66bb0c2), XV32(0x5a19a54f), XV32(0xf1c85634),
|
||||||
|
XV32(0x1258fa5c), XV32(0xb9890927), XV32(0x45fb1caa), XV32(0xee2aefd1),
|
||||||
|
XV32(0x16cec4cb), XV32(0xbd1f37b0), XV32(0x416d223d), XV32(0xeabcd146),
|
||||||
|
XV32(0x1b748772), XV32(0xb0a57409), XV32(0x4cd76184), XV32(0xe70692ff),
|
||||||
|
XV32(0x1fe2b9e5), XV32(0xb4334a9e), XV32(0x48415f13), XV32(0xe390ac68),
|
||||||
|
XV32(0x24b1f4b8), XV32(0x8f6007c3), XV32(0x7312124e), XV32(0xd8c3e135),
|
||||||
|
XV32(0x2027ca2f), XV32(0x8bf63954), XV32(0x77842cd9), XV32(0xdc55dfa2),
|
||||||
|
XV32(0x2d9d8996), XV32(0x864c7aed), XV32(0x7a3e6f60), XV32(0xd1ef9c1b),
|
||||||
|
XV32(0x290bb701), XV32(0x82da447a), XV32(0x7ea851f7), XV32(0xd579a28c),
|
||||||
|
XV32(0x36e90ee4), XV32(0x9d38fd9f), XV32(0x614ae812), XV32(0xca9b1b69),
|
||||||
|
XV32(0x327f3073), XV32(0x99aec308), XV32(0x65dcd685), XV32(0xce0d25fe),
|
||||||
|
XV32(0x3fc573ca), XV32(0x941480b1), XV32(0x6866953c), XV32(0xc3b76647),
|
||||||
|
XV32(0x3b534d5d), XV32(0x9082be26), XV32(0x6cf0abab), XV32(0xc72158d0),
|
||||||
|
XV32(0x4963e970), XV32(0xe2b21a0b), XV32(0x1ec00f86), XV32(0xb511fcfd),
|
||||||
|
XV32(0x4df5d7e7), XV32(0xe624249c), XV32(0x1a563111), XV32(0xb187c26a),
|
||||||
|
XV32(0x404f945e), XV32(0xeb9e6725), XV32(0x17ec72a8), XV32(0xbc3d81d3),
|
||||||
|
XV32(0x44d9aac9), XV32(0xef0859b2), XV32(0x137a4c3f), XV32(0xb8abbf44),
|
||||||
|
XV32(0x5b3b132c), XV32(0xf0eae057), XV32(0xc98f5da), XV32(0xa74906a1),
|
||||||
|
XV32(0x5fad2dbb), XV32(0xf47cdec0), XV32(0x80ecb4d), XV32(0xa3df3836),
|
||||||
|
XV32(0x52176e02), XV32(0xf9c69d79), XV32(0x5b488f4), XV32(0xae657b8f),
|
||||||
|
XV32(0x56815095), XV32(0xfd50a3ee), XV32(0x122b663), XV32(0xaaf34518),
|
||||||
|
XV32(0x6dd21dc8), XV32(0xc603eeb3), XV32(0x3a71fb3e), XV32(0x91a00845),
|
||||||
|
XV32(0x6944235f), XV32(0xc295d024), XV32(0x3ee7c5a9), XV32(0x953636d2),
|
||||||
|
XV32(0x64fe60e6), XV32(0xcf2f939d), XV32(0x335d8610), XV32(0x988c756b),
|
||||||
|
XV32(0x60685e71), XV32(0xcbb9ad0a), XV32(0x37cbb887), XV32(0x9c1a4bfc),
|
||||||
|
XV32(0x7f8ae794), XV32(0xd45b14ef), XV32(0x28290162), XV32(0x83f8f219),
|
||||||
|
XV32(0x7b1cd903), XV32(0xd0cd2a78), XV32(0x2cbf3ff5), XV32(0x876ecc8e),
|
||||||
|
XV32(0x76a69aba), XV32(0xdd7769c1), XV32(0x21057c4c), XV32(0x8ad48f37),
|
||||||
|
XV32(0x7230a42d), XV32(0xd9e15756), XV32(0x259342db), XV32(0x8e42b1a0),
|
||||||
|
XV32(0x3916219b), XV32(0x92c7d2e0), XV32(0x6eb5c76d), XV32(0xc5643416),
|
||||||
|
XV32(0x3d801f0c), XV32(0x9651ec77), XV32(0x6a23f9fa), XV32(0xc1f20a81),
|
||||||
|
XV32(0x303a5cb5), XV32(0x9bebafce), XV32(0x6799ba43), XV32(0xcc484938),
|
||||||
|
XV32(0x34ac6222), XV32(0x9f7d9159), XV32(0x630f84d4), XV32(0xc8de77af),
|
||||||
|
XV32(0x2b4edbc7), XV32(0x809f28bc), XV32(0x7ced3d31), XV32(0xd73cce4a),
|
||||||
|
XV32(0x2fd8e550), XV32(0x8409162b), XV32(0x787b03a6), XV32(0xd3aaf0dd),
|
||||||
|
XV32(0x2262a6e9), XV32(0x89b35592), XV32(0x75c1401f), XV32(0xde10b364),
|
||||||
|
XV32(0x26f4987e), XV32(0x8d256b05), XV32(0x71577e88), XV32(0xda868df3),
|
||||||
|
XV32(0x1da7d523), XV32(0xb6762658), XV32(0x4a0433d5), XV32(0xe1d5c0ae),
|
||||||
|
XV32(0x1931ebb4), XV32(0xb2e018cf), XV32(0x4e920d42), XV32(0xe543fe39),
|
||||||
|
XV32(0x148ba80d), XV32(0xbf5a5b76), XV32(0x43284efb), XV32(0xe8f9bd80),
|
||||||
|
XV32(0x101d969a), XV32(0xbbcc65e1), XV32(0x47be706c), XV32(0xec6f8317),
|
||||||
|
XV32(0xfff2f7f), XV32(0xa42edc04), XV32(0x585cc989), XV32(0xf38d3af2),
|
||||||
|
XV32(0xb6911e8), XV32(0xa0b8e293), XV32(0x5ccaf71e), XV32(0xf71b0465),
|
||||||
|
XV32(0x6d35251), XV32(0xad02a12a), XV32(0x5170b4a7), XV32(0xfaa147dc),
|
||||||
|
XV32(0x2456cc6), XV32(0xa9949fbd), XV32(0x55e68a30), XV32(0xfe37794b),
|
||||||
|
XV32(0x7075c8eb), XV32(0xdba43b90), XV32(0x27d62e1d), XV32(0x8c07dd66),
|
||||||
|
XV32(0x74e3f67c), XV32(0xdf320507), XV32(0x2340108a), XV32(0x8891e3f1),
|
||||||
|
XV32(0x7959b5c5), XV32(0xd28846be), XV32(0x2efa5333), XV32(0x852ba048),
|
||||||
|
XV32(0x7dcf8b52), XV32(0xd61e7829), XV32(0x2a6c6da4), XV32(0x81bd9edf),
|
||||||
|
XV32(0x622d32b7), XV32(0xc9fcc1cc), XV32(0x358ed441), XV32(0x9e5f273a),
|
||||||
|
XV32(0x66bb0c20), XV32(0xcd6aff5b), XV32(0x3118ead6), XV32(0x9ac919ad),
|
||||||
|
XV32(0x6b014f99), XV32(0xc0d0bce2), XV32(0x3ca2a96f), XV32(0x97735a14),
|
||||||
|
XV32(0x6f97710e), XV32(0xc4468275), XV32(0x383497f8), XV32(0x93e56483),
|
||||||
|
XV32(0x54c43c53), XV32(0xff15cf28), XV32(0x367daa5), XV32(0xa8b629de),
|
||||||
|
XV32(0x505202c4), XV32(0xfb83f1bf), XV32(0x7f1e432), XV32(0xac201749),
|
||||||
|
XV32(0x5de8417d), XV32(0xf639b206), XV32(0xa4ba78b), XV32(0xa19a54f0),
|
||||||
|
XV32(0x597e7fea), XV32(0xf2af8c91), XV32(0xedd991c), XV32(0xa50c6a67),
|
||||||
|
XV32(0x469cc60f), XV32(0xed4d3574), XV32(0x113f20f9), XV32(0xbaeed382),
|
||||||
|
XV32(0x420af898), XV32(0xe9db0be3), XV32(0x15a91e6e), XV32(0xbe78ed15),
|
||||||
|
XV32(0x4fb0bb21), XV32(0xe461485a), XV32(0x18135dd7), XV32(0xb3c2aeac),
|
||||||
|
XV32(0x4b2685b6), XV32(0xe0f776cd), XV32(0x1c856340), XV32(0xb754903b)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const xply_word U[256] = {
|
||||||
|
XV32(0x0), XV32(0x5ce33923), XV32(0x1217813d), XV32(0x4ef4b81e),
|
||||||
|
XV32(0x242f027a), XV32(0x78cc3b59), XV32(0x36388347), XV32(0x6adbba64),
|
||||||
|
XV32(0x485e04f4), XV32(0x14bd3dd7), XV32(0x5a4985c9), XV32(0x6aabcea),
|
||||||
|
XV32(0x6c71068e), XV32(0x30923fad), XV32(0x7e6687b3), XV32(0x2285be90),
|
||||||
|
XV32(0x3b6dfa93), XV32(0x678ec3b0), XV32(0x297a7bae), XV32(0x7599428d),
|
||||||
|
XV32(0x1f42f8e9), XV32(0x43a1c1ca), XV32(0xd5579d4), XV32(0x51b640f7),
|
||||||
|
XV32(0x7333fe67), XV32(0x2fd0c744), XV32(0x61247f5a), XV32(0x3dc74679),
|
||||||
|
XV32(0x571cfc1d), XV32(0xbffc53e), XV32(0x450b7d20), XV32(0x19e84403),
|
||||||
|
XV32(0x76dbf526), XV32(0x2a38cc05), XV32(0x64cc741b), XV32(0x382f4d38),
|
||||||
|
XV32(0x52f4f75c), XV32(0xe17ce7f), XV32(0x40e37661), XV32(0x1c004f42),
|
||||||
|
XV32(0x3e85f1d2), XV32(0x6266c8f1), XV32(0x2c9270ef), XV32(0x707149cc),
|
||||||
|
XV32(0x1aaaf3a8), XV32(0x4649ca8b), XV32(0x8bd7295), XV32(0x545e4bb6),
|
||||||
|
XV32(0x4db60fb5), XV32(0x11553696), XV32(0x5fa18e88), XV32(0x342b7ab),
|
||||||
|
XV32(0x69990dcf), XV32(0x357a34ec), XV32(0x7b8e8cf2), XV32(0x276db5d1),
|
||||||
|
XV32(0x5e80b41), XV32(0x590b3262), XV32(0x17ff8a7c), XV32(0x4b1cb35f),
|
||||||
|
XV32(0x21c7093b), XV32(0x7d243018), XV32(0x33d08806), XV32(0x6f33b125),
|
||||||
|
XV32(0x46661937), XV32(0x1a852014), XV32(0x5471980a), XV32(0x892a129),
|
||||||
|
XV32(0x62491b4d), XV32(0x3eaa226e), XV32(0x705e9a70), XV32(0x2cbda353),
|
||||||
|
XV32(0xe381dc3), XV32(0x52db24e0), XV32(0x1c2f9cfe), XV32(0x40cca5dd),
|
||||||
|
XV32(0x2a171fb9), XV32(0x76f4269a), XV32(0x38009e84), XV32(0x64e3a7a7),
|
||||||
|
XV32(0x7d0be3a4), XV32(0x21e8da87), XV32(0x6f1c6299), XV32(0x33ff5bba),
|
||||||
|
XV32(0x5924e1de), XV32(0x5c7d8fd), XV32(0x4b3360e3), XV32(0x17d059c0),
|
||||||
|
XV32(0x3555e750), XV32(0x69b6de73), XV32(0x2742666d), XV32(0x7ba15f4e),
|
||||||
|
XV32(0x117ae52a), XV32(0x4d99dc09), XV32(0x36d6417), XV32(0x5f8e5d34),
|
||||||
|
XV32(0x30bdec11), XV32(0x6c5ed532), XV32(0x22aa6d2c), XV32(0x7e49540f),
|
||||||
|
XV32(0x1492ee6b), XV32(0x4871d748), XV32(0x6856f56), XV32(0x5a665675),
|
||||||
|
XV32(0x78e3e8e5), XV32(0x2400d1c6), XV32(0x6af469d8), XV32(0x361750fb),
|
||||||
|
XV32(0x5cccea9f), XV32(0x2fd3bc), XV32(0x4edb6ba2), XV32(0x12385281),
|
||||||
|
XV32(0xbd01682), XV32(0x57332fa1), XV32(0x19c797bf), XV32(0x4524ae9c),
|
||||||
|
XV32(0x2fff14f8), XV32(0x731c2ddb), XV32(0x3de895c5), XV32(0x610bace6),
|
||||||
|
XV32(0x438e1276), XV32(0x1f6d2b55), XV32(0x5199934b), XV32(0xd7aaa68),
|
||||||
|
XV32(0x67a1100c), XV32(0x3b42292f), XV32(0x75b69131), XV32(0x2955a812),
|
||||||
|
XV32(0x271dc115), XV32(0x7bfef836), XV32(0x350a4028), XV32(0x69e9790b),
|
||||||
|
XV32(0x332c36f), XV32(0x5fd1fa4c), XV32(0x11254252), XV32(0x4dc67b71),
|
||||||
|
XV32(0x6f43c5e1), XV32(0x33a0fcc2), XV32(0x7d5444dc), XV32(0x21b77dff),
|
||||||
|
XV32(0x4b6cc79b), XV32(0x178ffeb8), XV32(0x597b46a6), XV32(0x5987f85),
|
||||||
|
XV32(0x1c703b86), XV32(0x409302a5), XV32(0xe67babb), XV32(0x52848398),
|
||||||
|
XV32(0x385f39fc), XV32(0x64bc00df), XV32(0x2a48b8c1), XV32(0x76ab81e2),
|
||||||
|
XV32(0x542e3f72), XV32(0x8cd0651), XV32(0x4639be4f), XV32(0x1ada876c),
|
||||||
|
XV32(0x70013d08), XV32(0x2ce2042b), XV32(0x6216bc35), XV32(0x3ef58516),
|
||||||
|
XV32(0x51c63433), XV32(0xd250d10), XV32(0x43d1b50e), XV32(0x1f328c2d),
|
||||||
|
XV32(0x75e93649), XV32(0x290a0f6a), XV32(0x67feb774), XV32(0x3b1d8e57),
|
||||||
|
XV32(0x199830c7), XV32(0x457b09e4), XV32(0xb8fb1fa), XV32(0x576c88d9),
|
||||||
|
XV32(0x3db732bd), XV32(0x61540b9e), XV32(0x2fa0b380), XV32(0x73438aa3),
|
||||||
|
XV32(0x6aabcea0), XV32(0x3648f783), XV32(0x78bc4f9d), XV32(0x245f76be),
|
||||||
|
XV32(0x4e84ccda), XV32(0x1267f5f9), XV32(0x5c934de7), XV32(0x7074c4),
|
||||||
|
XV32(0x22f5ca54), XV32(0x7e16f377), XV32(0x30e24b69), XV32(0x6c01724a),
|
||||||
|
XV32(0x6dac82e), XV32(0x5a39f10d), XV32(0x14cd4913), XV32(0x482e7030),
|
||||||
|
XV32(0x617bd822), XV32(0x3d98e101), XV32(0x736c591f), XV32(0x2f8f603c),
|
||||||
|
XV32(0x4554da58), XV32(0x19b7e37b), XV32(0x57435b65), XV32(0xba06246),
|
||||||
|
XV32(0x2925dcd6), XV32(0x75c6e5f5), XV32(0x3b325deb), XV32(0x67d164c8),
|
||||||
|
XV32(0xd0adeac), XV32(0x51e9e78f), XV32(0x1f1d5f91), XV32(0x43fe66b2),
|
||||||
|
XV32(0x5a1622b1), XV32(0x6f51b92), XV32(0x4801a38c), XV32(0x14e29aaf),
|
||||||
|
XV32(0x7e3920cb), XV32(0x22da19e8), XV32(0x6c2ea1f6), XV32(0x30cd98d5),
|
||||||
|
XV32(0x12482645), XV32(0x4eab1f66), XV32(0x5fa778), XV32(0x5cbc9e5b),
|
||||||
|
XV32(0x3667243f), XV32(0x6a841d1c), XV32(0x2470a502), XV32(0x78939c21),
|
||||||
|
XV32(0x17a02d04), XV32(0x4b431427), XV32(0x5b7ac39), XV32(0x5954951a),
|
||||||
|
XV32(0x338f2f7e), XV32(0x6f6c165d), XV32(0x2198ae43), XV32(0x7d7b9760),
|
||||||
|
XV32(0x5ffe29f0), XV32(0x31d10d3), XV32(0x4de9a8cd), XV32(0x110a91ee),
|
||||||
|
XV32(0x7bd12b8a), XV32(0x273212a9), XV32(0x69c6aab7), XV32(0x35259394),
|
||||||
|
XV32(0x2ccdd797), XV32(0x702eeeb4), XV32(0x3eda56aa), XV32(0x62396f89),
|
||||||
|
XV32(0x8e2d5ed), XV32(0x5401ecce), XV32(0x1af554d0), XV32(0x46166df3),
|
||||||
|
XV32(0x6493d363), XV32(0x3870ea40), XV32(0x7684525e), XV32(0x2a676b7d),
|
||||||
|
XV32(0x40bcd119), XV32(0x1c5fe83a), XV32(0x52ab5024), XV32(0xe486907)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* if defined(XRABPLY_TYPE32) */
|
||||||
|
|
||||||
68
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xtypes.h
Normal file
68
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xtypes.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XTYPES_H)
|
||||||
|
#define XTYPES_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct s_chanode {
|
||||||
|
struct s_chanode *next;
|
||||||
|
long icurr;
|
||||||
|
} chanode_t;
|
||||||
|
|
||||||
|
typedef struct s_chastore {
|
||||||
|
chanode_t *head, *tail;
|
||||||
|
long isize, nsize;
|
||||||
|
chanode_t *ancur;
|
||||||
|
chanode_t *sncur;
|
||||||
|
long scurr;
|
||||||
|
} chastore_t;
|
||||||
|
|
||||||
|
typedef struct s_xrecord {
|
||||||
|
struct s_xrecord *next;
|
||||||
|
char const *ptr;
|
||||||
|
long size;
|
||||||
|
unsigned long ha;
|
||||||
|
} xrecord_t;
|
||||||
|
|
||||||
|
typedef struct s_xdfile {
|
||||||
|
chastore_t rcha;
|
||||||
|
long nrec;
|
||||||
|
unsigned int hbits;
|
||||||
|
xrecord_t **rhash;
|
||||||
|
long dstart, dend;
|
||||||
|
xrecord_t **recs;
|
||||||
|
char *rchg;
|
||||||
|
long *rindex;
|
||||||
|
long nreff;
|
||||||
|
unsigned long *ha;
|
||||||
|
} xdfile_t;
|
||||||
|
|
||||||
|
typedef struct s_xdfenv {
|
||||||
|
xdfile_t xdf1, xdf2;
|
||||||
|
} xdfenv_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XTYPES_H) */
|
||||||
|
|
||||||
580
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xutils.c
Normal file
580
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xutils.c
Normal file
@@ -0,0 +1,580 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define XDL_GUESS_NLINES 256
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_bogosqrt(long n) {
|
||||||
|
long i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Classical integer square root approximation using shifts.
|
||||||
|
*/
|
||||||
|
for (i = 1; n > 0; n >>= 2)
|
||||||
|
i <<= 1;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
|
||||||
|
xdemitcb_t *ecb) {
|
||||||
|
int i = 2;
|
||||||
|
mmbuffer_t mb[3];
|
||||||
|
|
||||||
|
mb[0].ptr = (char *) pre;
|
||||||
|
mb[0].size = psize;
|
||||||
|
mb[1].ptr = (char *) rec;
|
||||||
|
mb[1].size = size;
|
||||||
|
if (size > 0 && rec[size - 1] != '\n') {
|
||||||
|
mb[2].ptr = (char *) "\n\\ No newline at end of file\n";
|
||||||
|
mb[2].size = strlen(mb[2].ptr);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (ecb->outf(ecb->priv, mb, i) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_init_mmfile(mmfile_t *mmf, long bsize, unsigned long flags) {
|
||||||
|
|
||||||
|
mmf->flags = flags;
|
||||||
|
mmf->head = mmf->tail = NULL;
|
||||||
|
mmf->bsize = bsize;
|
||||||
|
mmf->fsize = 0;
|
||||||
|
mmf->rcur = mmf->wcur = NULL;
|
||||||
|
mmf->rpos = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xdl_free_mmfile(mmfile_t *mmf) {
|
||||||
|
mmblock_t *cur, *tmp;
|
||||||
|
|
||||||
|
for (cur = mmf->head; (tmp = cur) != NULL;) {
|
||||||
|
cur = cur->next;
|
||||||
|
xdl_free(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_mmfile_iscompact(mmfile_t *mmf) {
|
||||||
|
|
||||||
|
return mmf->head == mmf->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_seek_mmfile(mmfile_t *mmf, long off) {
|
||||||
|
long bsize;
|
||||||
|
|
||||||
|
if (xdl_mmfile_first(mmf, &bsize)) {
|
||||||
|
do {
|
||||||
|
if (off < bsize) {
|
||||||
|
mmf->rpos = off;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
off -= bsize;
|
||||||
|
} while (xdl_mmfile_next(mmf, &bsize));
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_read_mmfile(mmfile_t *mmf, void *data, long size) {
|
||||||
|
long rsize, csize;
|
||||||
|
char *ptr = data;
|
||||||
|
mmblock_t *rcur;
|
||||||
|
|
||||||
|
for (rsize = 0, rcur = mmf->rcur; rcur && rsize < size;) {
|
||||||
|
if (mmf->rpos >= rcur->size) {
|
||||||
|
if (!(mmf->rcur = rcur = rcur->next))
|
||||||
|
break;
|
||||||
|
mmf->rpos = 0;
|
||||||
|
}
|
||||||
|
csize = XDL_MIN(size - rsize, rcur->size - mmf->rpos);
|
||||||
|
memcpy(ptr, rcur->ptr + mmf->rpos, csize);
|
||||||
|
rsize += csize;
|
||||||
|
ptr += csize;
|
||||||
|
mmf->rpos += csize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_write_mmfile(mmfile_t *mmf, void const *data, long size) {
|
||||||
|
long wsize, bsize, csize;
|
||||||
|
mmblock_t *wcur;
|
||||||
|
|
||||||
|
for (wsize = 0; wsize < size;) {
|
||||||
|
wcur = mmf->wcur;
|
||||||
|
if (wcur && (wcur->flags & XDL_MMB_READONLY))
|
||||||
|
return wsize;
|
||||||
|
if (!wcur || wcur->size == wcur->bsize ||
|
||||||
|
(mmf->flags & XDL_MMF_ATOMIC && wcur->size + size > wcur->bsize)) {
|
||||||
|
bsize = XDL_MAX(mmf->bsize, size);
|
||||||
|
if (!(wcur = (mmblock_t *) xdl_malloc(sizeof(mmblock_t) + bsize))) {
|
||||||
|
|
||||||
|
return wsize;
|
||||||
|
}
|
||||||
|
wcur->flags = 0;
|
||||||
|
wcur->ptr = (char *) wcur + sizeof(mmblock_t);
|
||||||
|
wcur->size = 0;
|
||||||
|
wcur->bsize = bsize;
|
||||||
|
wcur->next = NULL;
|
||||||
|
if (!mmf->head)
|
||||||
|
mmf->head = wcur;
|
||||||
|
if (mmf->tail)
|
||||||
|
mmf->tail->next = wcur;
|
||||||
|
mmf->tail = wcur;
|
||||||
|
mmf->wcur = wcur;
|
||||||
|
}
|
||||||
|
csize = XDL_MIN(size - wsize, wcur->bsize - wcur->size);
|
||||||
|
memcpy(wcur->ptr + wcur->size, (char const *) data + wsize, csize);
|
||||||
|
wsize += csize;
|
||||||
|
wcur->size += csize;
|
||||||
|
mmf->fsize += csize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_writem_mmfile(mmfile_t *mmf, mmbuffer_t *mb, int nbuf) {
|
||||||
|
int i;
|
||||||
|
long size;
|
||||||
|
char *data;
|
||||||
|
|
||||||
|
for (i = 0, size = 0; i < nbuf; i++)
|
||||||
|
size += mb[i].size;
|
||||||
|
if (!(data = (char *) xdl_mmfile_writeallocate(mmf, size)))
|
||||||
|
return -1;
|
||||||
|
for (i = 0; i < nbuf; i++) {
|
||||||
|
memcpy(data, mb[i].ptr, mb[i].size);
|
||||||
|
data += mb[i].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_mmfile_writeallocate(mmfile_t *mmf, long size) {
|
||||||
|
long bsize;
|
||||||
|
mmblock_t *wcur;
|
||||||
|
char *blk;
|
||||||
|
|
||||||
|
if (!(wcur = mmf->wcur) || wcur->size + size > wcur->bsize) {
|
||||||
|
bsize = XDL_MAX(mmf->bsize, size);
|
||||||
|
if (!(wcur = (mmblock_t *) xdl_malloc(sizeof(mmblock_t) + bsize))) {
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wcur->flags = 0;
|
||||||
|
wcur->ptr = (char *) wcur + sizeof(mmblock_t);
|
||||||
|
wcur->size = 0;
|
||||||
|
wcur->bsize = bsize;
|
||||||
|
wcur->next = NULL;
|
||||||
|
if (!mmf->head)
|
||||||
|
mmf->head = wcur;
|
||||||
|
if (mmf->tail)
|
||||||
|
mmf->tail->next = wcur;
|
||||||
|
mmf->tail = wcur;
|
||||||
|
mmf->wcur = wcur;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk = wcur->ptr + wcur->size;
|
||||||
|
wcur->size += size;
|
||||||
|
mmf->fsize += size;
|
||||||
|
|
||||||
|
return blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_mmfile_ptradd(mmfile_t *mmf, char *ptr, long size, unsigned long flags) {
|
||||||
|
mmblock_t *wcur;
|
||||||
|
|
||||||
|
if (!(wcur = (mmblock_t *) xdl_malloc(sizeof(mmblock_t)))) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wcur->flags = flags;
|
||||||
|
wcur->ptr = ptr;
|
||||||
|
wcur->size = wcur->bsize = size;
|
||||||
|
wcur->next = NULL;
|
||||||
|
if (!mmf->head)
|
||||||
|
mmf->head = wcur;
|
||||||
|
if (mmf->tail)
|
||||||
|
mmf->tail->next = wcur;
|
||||||
|
mmf->tail = wcur;
|
||||||
|
mmf->wcur = wcur;
|
||||||
|
|
||||||
|
mmf->fsize += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_copy_mmfile(mmfile_t *mmf, long size, xdemitcb_t *ecb) {
|
||||||
|
long rsize, csize;
|
||||||
|
mmblock_t *rcur;
|
||||||
|
mmbuffer_t mb;
|
||||||
|
|
||||||
|
for (rsize = 0, rcur = mmf->rcur; rcur && rsize < size;) {
|
||||||
|
if (mmf->rpos >= rcur->size) {
|
||||||
|
if (!(mmf->rcur = rcur = rcur->next))
|
||||||
|
break;
|
||||||
|
mmf->rpos = 0;
|
||||||
|
}
|
||||||
|
csize = XDL_MIN(size - rsize, rcur->size - mmf->rpos);
|
||||||
|
mb.ptr = rcur->ptr + mmf->rpos;
|
||||||
|
mb.size = csize;
|
||||||
|
if (ecb->outf(ecb->priv, &mb, 1) < 0) {
|
||||||
|
|
||||||
|
return rsize;
|
||||||
|
}
|
||||||
|
rsize += csize;
|
||||||
|
mmf->rpos += csize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_mmfile_first(mmfile_t *mmf, long *size) {
|
||||||
|
|
||||||
|
if (!(mmf->rcur = mmf->head))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*size = mmf->rcur->size;
|
||||||
|
|
||||||
|
return mmf->rcur->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_mmfile_next(mmfile_t *mmf, long *size) {
|
||||||
|
|
||||||
|
if (!mmf->rcur || !(mmf->rcur = mmf->rcur->next))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*size = mmf->rcur->size;
|
||||||
|
|
||||||
|
return mmf->rcur->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_mmfile_size(mmfile_t *mmf) {
|
||||||
|
|
||||||
|
return mmf->fsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_mmfile_cmp(mmfile_t *mmf1, mmfile_t *mmf2) {
|
||||||
|
int cres;
|
||||||
|
long size, bsize1, bsize2, size1, size2;
|
||||||
|
char const *blk1, *cur1, *top1;
|
||||||
|
char const *blk2, *cur2, *top2;
|
||||||
|
|
||||||
|
if ((cur1 = blk1 = xdl_mmfile_first(mmf1, &bsize1)) != NULL)
|
||||||
|
top1 = blk1 + bsize1;
|
||||||
|
if ((cur2 = blk2 = xdl_mmfile_first(mmf2, &bsize2)) != NULL)
|
||||||
|
top2 = blk2 + bsize2;
|
||||||
|
if (!cur1) {
|
||||||
|
if (!cur2 || xdl_mmfile_size(mmf2) == 0)
|
||||||
|
return 0;
|
||||||
|
return -*cur2;
|
||||||
|
} else if (!cur2)
|
||||||
|
return xdl_mmfile_size(mmf1) ? *cur1: 0;
|
||||||
|
for (;;) {
|
||||||
|
if (cur1 >= top1) {
|
||||||
|
if ((cur1 = blk1 = xdl_mmfile_next(mmf1, &bsize1)) != NULL)
|
||||||
|
top1 = blk1 + bsize1;
|
||||||
|
}
|
||||||
|
if (cur2 >= top2) {
|
||||||
|
if ((cur2 = blk2 = xdl_mmfile_next(mmf2, &bsize2)) != NULL)
|
||||||
|
top2 = blk2 + bsize2;
|
||||||
|
}
|
||||||
|
if (!cur1) {
|
||||||
|
if (!cur2)
|
||||||
|
break;
|
||||||
|
return -*cur2;
|
||||||
|
} else if (!cur2)
|
||||||
|
return *cur1;
|
||||||
|
size1 = top1 - cur1;
|
||||||
|
size2 = top2 - cur2;
|
||||||
|
size = XDL_MIN(size1, size2);
|
||||||
|
if ((cres = memcmp(cur1, cur2, size)) != 0)
|
||||||
|
return cres;
|
||||||
|
cur1 += size;
|
||||||
|
cur2 += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_mmfile_compact(mmfile_t *mmfo, mmfile_t *mmfc, long bsize, unsigned long flags) {
|
||||||
|
long fsize = xdl_mmfile_size(mmfo), size;
|
||||||
|
char *data;
|
||||||
|
char const *blk;
|
||||||
|
|
||||||
|
if (xdl_init_mmfile(mmfc, bsize, flags) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(data = (char *) xdl_mmfile_writeallocate(mmfc, fsize))) {
|
||||||
|
|
||||||
|
xdl_free_mmfile(mmfc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((blk = (char const *) xdl_mmfile_first(mmfo, &size)) != NULL) {
|
||||||
|
do {
|
||||||
|
memcpy(data, blk, size);
|
||||||
|
data += size;
|
||||||
|
} while ((blk = (char const *) xdl_mmfile_next(mmfo, &size)) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_mmfile_outf(void *priv, mmbuffer_t *mb, int nbuf) {
|
||||||
|
mmfile_t *mmf = priv;
|
||||||
|
|
||||||
|
if (xdl_writem_mmfile(mmf, mb, nbuf) < 0) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_cha_init(chastore_t *cha, long isize, long icount) {
|
||||||
|
|
||||||
|
cha->head = cha->tail = NULL;
|
||||||
|
cha->isize = isize;
|
||||||
|
cha->nsize = icount * isize;
|
||||||
|
cha->ancur = cha->sncur = NULL;
|
||||||
|
cha->scurr = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xdl_cha_free(chastore_t *cha) {
|
||||||
|
chanode_t *cur, *tmp;
|
||||||
|
|
||||||
|
for (cur = cha->head; (tmp = cur) != NULL;) {
|
||||||
|
cur = cur->next;
|
||||||
|
xdl_free(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_cha_alloc(chastore_t *cha) {
|
||||||
|
chanode_t *ancur;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
if (!(ancur = cha->ancur) || ancur->icurr == cha->nsize) {
|
||||||
|
if (!(ancur = (chanode_t *) xdl_malloc(sizeof(chanode_t) + cha->nsize))) {
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ancur->icurr = 0;
|
||||||
|
ancur->next = NULL;
|
||||||
|
if (cha->tail)
|
||||||
|
cha->tail->next = ancur;
|
||||||
|
if (!cha->head)
|
||||||
|
cha->head = ancur;
|
||||||
|
cha->tail = ancur;
|
||||||
|
cha->ancur = ancur;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (char *) ancur + sizeof(chanode_t) + ancur->icurr;
|
||||||
|
ancur->icurr += cha->isize;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_cha_first(chastore_t *cha) {
|
||||||
|
chanode_t *sncur;
|
||||||
|
|
||||||
|
if (!(cha->sncur = sncur = cha->head))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cha->scurr = 0;
|
||||||
|
|
||||||
|
return (char *) sncur + sizeof(chanode_t) + cha->scurr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *xdl_cha_next(chastore_t *cha) {
|
||||||
|
chanode_t *sncur;
|
||||||
|
|
||||||
|
if (!(sncur = cha->sncur))
|
||||||
|
return NULL;
|
||||||
|
cha->scurr += cha->isize;
|
||||||
|
if (cha->scurr == sncur->icurr) {
|
||||||
|
if (!(sncur = cha->sncur = sncur->next))
|
||||||
|
return NULL;
|
||||||
|
cha->scurr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char *) sncur + sizeof(chanode_t) + cha->scurr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_guess_lines(mmfile_t *mf) {
|
||||||
|
long nl = 0, size, tsize = 0;
|
||||||
|
char const *data, *cur, *top;
|
||||||
|
|
||||||
|
if ((cur = data = xdl_mmfile_first(mf, &size)) != NULL) {
|
||||||
|
for (top = data + size; nl < XDL_GUESS_NLINES;) {
|
||||||
|
if (cur >= top) {
|
||||||
|
tsize += (long) (cur - data);
|
||||||
|
if (!(cur = data = xdl_mmfile_next(mf, &size)))
|
||||||
|
break;
|
||||||
|
top = data + size;
|
||||||
|
}
|
||||||
|
nl++;
|
||||||
|
if (!(cur = memchr(cur, '\n', top - cur)))
|
||||||
|
cur = top;
|
||||||
|
else
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
tsize += (long) (cur - data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nl && tsize)
|
||||||
|
nl = xdl_mmfile_size(mf) / (tsize / nl);
|
||||||
|
|
||||||
|
return nl + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long xdl_hash_record(char const **data, char const *top) {
|
||||||
|
unsigned long ha = 5381;
|
||||||
|
char const *ptr = *data;
|
||||||
|
|
||||||
|
for (; ptr < top && *ptr != '\n'; ptr++) {
|
||||||
|
ha += (ha << 5);
|
||||||
|
ha ^= (unsigned long) *ptr;
|
||||||
|
}
|
||||||
|
*data = ptr < top ? ptr + 1: ptr;
|
||||||
|
|
||||||
|
return ha;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int xdl_hashbits(unsigned int size) {
|
||||||
|
unsigned int val = 1, bits = 0;
|
||||||
|
|
||||||
|
for (; val < size && bits < CHAR_BIT * sizeof(unsigned int); val <<= 1, bits++);
|
||||||
|
return bits ? bits: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_num_out(char *out, long val) {
|
||||||
|
char *ptr, *str = out;
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
ptr = buf + sizeof(buf) - 1;
|
||||||
|
*ptr = '\0';
|
||||||
|
if (val < 0) {
|
||||||
|
*--ptr = '-';
|
||||||
|
val = -val;
|
||||||
|
}
|
||||||
|
for (; val && ptr > buf; val /= 10)
|
||||||
|
*--ptr = "0123456789"[val % 10];
|
||||||
|
if (*ptr)
|
||||||
|
for (; *ptr; ptr++, str++)
|
||||||
|
*str = *ptr;
|
||||||
|
else
|
||||||
|
*str++ = '0';
|
||||||
|
*str = '\0';
|
||||||
|
|
||||||
|
return str - out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_atol(char const *str, char const **next) {
|
||||||
|
long val, base;
|
||||||
|
char const *top;
|
||||||
|
|
||||||
|
for (top = str; XDL_ISDIGIT(*top); top++);
|
||||||
|
if (next)
|
||||||
|
*next = top;
|
||||||
|
for (val = 0, base = 1, top--; top >= str; top--, base *= 10)
|
||||||
|
val += base * (long)(*top - '0');
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb) {
|
||||||
|
int nb = 0;
|
||||||
|
mmbuffer_t mb;
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
memcpy(buf, "@@ -", 4);
|
||||||
|
nb += 4;
|
||||||
|
|
||||||
|
nb += xdl_num_out(buf + nb, c1 ? s1: s1 - 1);
|
||||||
|
|
||||||
|
memcpy(buf + nb, ",", 1);
|
||||||
|
nb += 1;
|
||||||
|
|
||||||
|
nb += xdl_num_out(buf + nb, c1);
|
||||||
|
|
||||||
|
memcpy(buf + nb, " +", 2);
|
||||||
|
nb += 2;
|
||||||
|
|
||||||
|
nb += xdl_num_out(buf + nb, c2 ? s2: s2 - 1);
|
||||||
|
|
||||||
|
memcpy(buf + nb, ",", 1);
|
||||||
|
nb += 1;
|
||||||
|
|
||||||
|
nb += xdl_num_out(buf + nb, c2);
|
||||||
|
|
||||||
|
memcpy(buf + nb, " @@\n", 4);
|
||||||
|
nb += 4;
|
||||||
|
|
||||||
|
mb.ptr = buf;
|
||||||
|
mb.size = nb;
|
||||||
|
if (ecb->outf(ecb->priv, &mb, 1) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
47
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xutils.h
Normal file
47
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xutils.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(XUTILS_H)
|
||||||
|
#define XUTILS_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
long xdl_bogosqrt(long n);
|
||||||
|
int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
|
||||||
|
xdemitcb_t *ecb);
|
||||||
|
int xdl_mmfile_outf(void *priv, mmbuffer_t *mb, int nbuf);
|
||||||
|
int xdl_cha_init(chastore_t *cha, long isize, long icount);
|
||||||
|
void xdl_cha_free(chastore_t *cha);
|
||||||
|
void *xdl_cha_alloc(chastore_t *cha);
|
||||||
|
void *xdl_cha_first(chastore_t *cha);
|
||||||
|
void *xdl_cha_next(chastore_t *cha);
|
||||||
|
long xdl_guess_lines(mmfile_t *mf);
|
||||||
|
unsigned long xdl_hash_record(char const **data, char const *top);
|
||||||
|
unsigned int xdl_hashbits(unsigned int size);
|
||||||
|
int xdl_num_out(char *out, long val);
|
||||||
|
long xdl_atol(char const *str, char const **next);
|
||||||
|
int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* #if !defined(XUTILS_H) */
|
||||||
|
|
||||||
27
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xversion.c
Normal file
27
gems/xdiff-rb/ext/xdiff/xdiff/xdiff/xversion.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* LibXDiff by Davide Libenzi ( File Differential Library )
|
||||||
|
* Copyright (C) 2003 Davide Libenzi
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xinclude.h"
|
||||||
|
|
||||||
|
|
||||||
|
char libxdiff_version[] = "LibXDiff v" PACKAGE_VERSION " by Davide Libenzi <davide@xmailserver.org>";
|
||||||
|
|
||||||
27
gems/xdiff-rb/lib/xdiff.rb
Normal file
27
gems/xdiff-rb/lib/xdiff.rb
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
module XDiff
|
||||||
|
VERSION = "0.0.1"
|
||||||
|
|
||||||
|
def self.validate_arg(method, name, arg)
|
||||||
|
raise ArgumentError.new(
|
||||||
|
"(#{method}) '#{name}' cannot be nil"
|
||||||
|
) if arg.nil?
|
||||||
|
raise ArgumentError.new(
|
||||||
|
"(#{method}) '#{name}' must be String (is #{arg.class})"
|
||||||
|
) unless arg.is_a?(String)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.diff(a, b)
|
||||||
|
validate_arg("diff", "a", a)
|
||||||
|
validate_arg("diff", "b", b)
|
||||||
|
Native.diff(a, b)
|
||||||
|
end
|
||||||
|
def self.patch(a, b)
|
||||||
|
validate_arg("patch", "a", a)
|
||||||
|
validate_arg("patch", "b", b)
|
||||||
|
Native.patch(a, b)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# XDiff::Native methods defined by extension.cc
|
||||||
|
require "xdiff/extension"
|
||||||
|
XDiff::Native.init
|
||||||
32
gems/xdiff-rb/test/xdiff_test.rb
Normal file
32
gems/xdiff-rb/test/xdiff_test.rb
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
require "minitest/autorun"
|
||||||
|
require "xdiff"
|
||||||
|
|
||||||
|
class TestXDiff < Minitest::Test
|
||||||
|
def assert_patches(a, b)
|
||||||
|
diff = XDiff.diff(a, b)
|
||||||
|
|
||||||
|
diff_hex = diff.unpack("H*").first
|
||||||
|
puts "diff (#{diff.size}): #{diff_hex}"
|
||||||
|
|
||||||
|
refute_equal "", diff
|
||||||
|
stitched = XDiff.patch(a, diff)
|
||||||
|
assert_equal b, stitched
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_raises
|
||||||
|
assert_raises(ArgumentError) { XDiff.patch(nil, "") }
|
||||||
|
assert_raises(ArgumentError) { XDiff.patch("", nil) }
|
||||||
|
assert_raises(ArgumentError) { XDiff.patch("", 123) }
|
||||||
|
assert_raises(ArgumentError) { XDiff.patch(123, "") }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_patch
|
||||||
|
assert_patches("foo bar", "foo bar")
|
||||||
|
assert_patches("", "")
|
||||||
|
assert_patches("foo", "")
|
||||||
|
assert_patches("", "foo")
|
||||||
|
assert_patches("abc\x00123", "123")
|
||||||
|
assert_patches("abc\x00123", "\x00")
|
||||||
|
assert_patches("\x00", "\x00")
|
||||||
|
end
|
||||||
|
end
|
||||||
23
gems/xdiff-rb/xdiff.gemspec
Normal file
23
gems/xdiff-rb/xdiff.gemspec
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
require "rake"
|
||||||
|
|
||||||
|
Gem::Specification.new do |s|
|
||||||
|
s.name = "xdiff"
|
||||||
|
s.version = "0.0.1"
|
||||||
|
s.summary = "libxdiff bindings"
|
||||||
|
s.description = "A simple hello world gem"
|
||||||
|
s.authors = ["Dylan Knutson"]
|
||||||
|
s.email = "dymk@dymk.co"
|
||||||
|
s.files = FileList[
|
||||||
|
"lib/xdiff.rb",
|
||||||
|
"ext/xdiff/extconf.rb",
|
||||||
|
"ext/xdiff/extension.cc",
|
||||||
|
"ext/xdiff/xdiff.tar.gz",
|
||||||
|
]
|
||||||
|
s.homepage =
|
||||||
|
"https://rubygems.org/gems/xdiff"
|
||||||
|
s.license = "MIT"
|
||||||
|
s.extensions = %w[ext/xdiff/extconf.rb]
|
||||||
|
s.add_development_dependency "rake", ">= 1.9.1"
|
||||||
|
s.add_development_dependency "rake-compiler", ">= 0.8.3"
|
||||||
|
s.add_development_dependency "minitest"
|
||||||
|
end
|
||||||
16
package.json
16
package.json
@@ -24,13 +24,7 @@
|
|||||||
"react_ujs": "^2.6.2",
|
"react_ujs": "^2.6.2",
|
||||||
"shakapacker": "6.6.0",
|
"shakapacker": "6.6.0",
|
||||||
"style-loader": "^3.3.2",
|
"style-loader": "^3.3.2",
|
||||||
"terser-webpack-plugin": "5",
|
"terser-webpack-plugin": "5"
|
||||||
"typescript": "^5.0.3",
|
|
||||||
"webpack": "5",
|
|
||||||
"webpack-assets-manifest": "5",
|
|
||||||
"webpack-cli": "4",
|
|
||||||
"webpack-dev-server": "^4.13.2",
|
|
||||||
"webpack-merge": "5"
|
|
||||||
},
|
},
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"babel": {
|
"babel": {
|
||||||
@@ -46,6 +40,12 @@
|
|||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
|
||||||
"@types/lodash": "^4.14.192",
|
"@types/lodash": "^4.14.192",
|
||||||
"@types/react": "^18.0.33",
|
"@types/react": "^18.0.33",
|
||||||
"react-refresh": "^0.14.0"
|
"react-refresh": "^0.14.0",
|
||||||
|
"typescript": "^5.0.3",
|
||||||
|
"webpack": "5",
|
||||||
|
"webpack-assets-manifest": "5",
|
||||||
|
"webpack-cli": "4",
|
||||||
|
"webpack-dev-server": "^4.13.2",
|
||||||
|
"webpack-merge": "5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user