mirror of
https://github.com/xorgy/mediafire-fuse
synced 2026-01-13 13:14:29 -08:00
add 3rdparty/xdelta3-3.0.8
This commit is contained in:
340
3rdparty/xdelta3-3.0.8/COPYING
vendored
Normal file
340
3rdparty/xdelta3-3.0.8/COPYING
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 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.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, 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 or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
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 give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
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 Program or any portion
|
||||
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
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 Program, 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 Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) 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; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, 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 executable. However, as a
|
||||
special exception, the source code 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.
|
||||
|
||||
If distribution of executable or 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 counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program 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.
|
||||
|
||||
5. 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 Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program 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 to
|
||||
this License.
|
||||
|
||||
7. 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 Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program 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 Program.
|
||||
|
||||
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.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program 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.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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 Program
|
||||
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 Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, 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
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), 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 Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
34
3rdparty/xdelta3-3.0.8/README
vendored
Normal file
34
3rdparty/xdelta3-3.0.8/README
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
Xdelta 3.x readme.txt
|
||||
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
<josh.macdonald@gmail.com>
|
||||
|
||||
|
||||
Thanks for downloading Xdelta!
|
||||
|
||||
This directory contains the Xdelta3 command-line interface (CLI) and source
|
||||
distribution for VCDIFF differential compression, a.k.a. delta
|
||||
compression. The latest information and downloads are available here:
|
||||
|
||||
http://xdelta.org/
|
||||
http://code.google.com/p/xdelta/
|
||||
|
||||
The command-line syntax:
|
||||
|
||||
http://code.google.com/p/xdelta/wiki/CommandLineSyntax
|
||||
|
||||
Run 'xdelta3 -h' for brief help. Run 'xdelta3 test' for built-in tests.
|
||||
|
||||
Sample commands (like gzip, -e means encode, -d means decode)
|
||||
|
||||
xdelta3 -9 -S djw -e -vfs OLD_FILE NEW_FILE DELTA_FILE
|
||||
xdelta3 -d -vfs OLD_FILE DELTA_FILE DECODED_FILE
|
||||
|
||||
File bug reports and browse open support issues here:
|
||||
|
||||
http://code.google.com/p/xdelta/issues/list
|
||||
|
||||
The source distribution contains the C/C++/Python APIs, Unix, Microsoft VC++
|
||||
and Cygwin builds. Xdelta3 is covered under the terms of the GPL, see
|
||||
COPYING.
|
||||
|
||||
Commercial inquiries welcome, please contact <josh.macdonald@gmail.com>
|
||||
569
3rdparty/xdelta3-3.0.8/xdelta3-blkcache.h
vendored
Normal file
569
3rdparty/xdelta3-3.0.8/xdelta3-blkcache.h
vendored
Normal file
@@ -0,0 +1,569 @@
|
||||
/* xdelta 3 - delta compression tools and library
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
* 2008, 2009, 2010
|
||||
* Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* TODO: This code is heavily revised from 3.0z but still needs major
|
||||
* refactoring. */
|
||||
|
||||
#include "xdelta3-internal.h"
|
||||
|
||||
typedef struct _main_blklru main_blklru;
|
||||
typedef struct _main_blklru_list main_blklru_list;
|
||||
|
||||
struct _main_blklru_list
|
||||
{
|
||||
main_blklru_list *next;
|
||||
main_blklru_list *prev;
|
||||
};
|
||||
|
||||
struct _main_blklru
|
||||
{
|
||||
uint8_t *blk;
|
||||
xoff_t blkno;
|
||||
usize_t size;
|
||||
main_blklru_list link;
|
||||
};
|
||||
|
||||
#define MAX_LRU_SIZE 32U
|
||||
#define XD3_MINSRCWINSZ (XD3_ALLOCSIZE * MAX_LRU_SIZE)
|
||||
#define XD3_MAXSRCWINSZ (1ULL << 31)
|
||||
|
||||
XD3_MAKELIST(main_blklru_list,main_blklru,link);
|
||||
|
||||
static usize_t lru_size = 0;
|
||||
static main_blklru *lru = NULL; /* array of lru_size elts */
|
||||
static main_blklru_list lru_list;
|
||||
static int do_src_fifo = 0; /* set to avoid lru */
|
||||
|
||||
static int lru_hits = 0;
|
||||
static int lru_misses = 0;
|
||||
static int lru_filled = 0;
|
||||
|
||||
static void main_lru_reset (void)
|
||||
{
|
||||
lru_size = 0;
|
||||
lru = NULL;
|
||||
do_src_fifo = 0;
|
||||
lru_hits = 0;
|
||||
lru_misses = 0;
|
||||
lru_filled = 0;
|
||||
}
|
||||
|
||||
static void main_lru_cleanup (void)
|
||||
{
|
||||
if (lru != NULL)
|
||||
{
|
||||
main_buffree (lru[0].blk);
|
||||
}
|
||||
|
||||
main_free (lru);
|
||||
lru = NULL;
|
||||
|
||||
lru_hits = 0;
|
||||
lru_misses = 0;
|
||||
lru_filled = 0;
|
||||
}
|
||||
|
||||
/* This is called at different times for encoding and decoding. The
|
||||
* encoder calls it immediately, the decoder delays until the
|
||||
* application header is received. */
|
||||
static int
|
||||
main_set_source (xd3_stream *stream, xd3_cmd cmd,
|
||||
main_file *sfile, xd3_source *source)
|
||||
{
|
||||
int ret = 0;
|
||||
usize_t i;
|
||||
xoff_t source_size = 0;
|
||||
usize_t blksize;
|
||||
|
||||
XD3_ASSERT (lru == NULL);
|
||||
XD3_ASSERT (stream->src == NULL);
|
||||
XD3_ASSERT (option_srcwinsz >= XD3_MINSRCWINSZ);
|
||||
|
||||
/* TODO: this code needs refactoring into FIFO, LRU, FAKE. Yuck!
|
||||
* This is simplified from 3.0z which had issues with sizing the
|
||||
* source buffer memory allocation and the source blocksize. */
|
||||
|
||||
/* LRU-specific */
|
||||
main_blklru_list_init (& lru_list);
|
||||
|
||||
if (allow_fake_source)
|
||||
{
|
||||
/* TODO: refactor
|
||||
* TOOLS/recode-specific: Check "allow_fake_source" mode looks
|
||||
* broken now. */
|
||||
sfile->mode = XO_READ;
|
||||
sfile->realname = sfile->filename;
|
||||
sfile->nread = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Either a regular file (possibly compressed) or a FIFO
|
||||
* (possibly compressed). */
|
||||
if ((ret = main_file_open (sfile, sfile->filename, XO_READ)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If the file is regular we know it's size. If the file turns
|
||||
* out to be externally compressed, size_known may change. */
|
||||
sfile->size_known = (main_file_stat (sfile, &source_size) == 0);
|
||||
}
|
||||
|
||||
/* Note: The API requires a power-of-two blocksize and srcwinsz
|
||||
* (-B). The logic here will use a single block if the entire file
|
||||
* is known to fit into srcwinsz. */
|
||||
option_srcwinsz = xd3_pow2_roundup (option_srcwinsz);
|
||||
|
||||
/* Though called "lru", it is not LRU-specific. We always allocate
|
||||
* a maximum number of source block buffers. If the entire file
|
||||
* fits into srcwinsz, this buffer will stay as the only
|
||||
* (lru_size==1) source block. Otherwise, we know that at least
|
||||
* option_srcwinsz bytes are available. Split the source window
|
||||
* into buffers. */
|
||||
if ((lru = (main_blklru*) main_malloc (MAX_LRU_SIZE *
|
||||
sizeof (main_blklru))) == NULL)
|
||||
{
|
||||
ret = ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset (lru, 0, sizeof(lru[0]) * MAX_LRU_SIZE);
|
||||
|
||||
/* Allocate the entire buffer. */
|
||||
if ((lru[0].blk = (uint8_t*) main_bufalloc (option_srcwinsz)) == NULL)
|
||||
{
|
||||
ret = ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Main calls main_getblk_func() once before xd3_set_source(). This
|
||||
* is the point at which external decompression may begin. Set the
|
||||
* system for a single block. */
|
||||
lru_size = 1;
|
||||
lru[0].blkno = (xoff_t) -1;
|
||||
blksize = option_srcwinsz;
|
||||
main_blklru_list_push_back (& lru_list, & lru[0]);
|
||||
XD3_ASSERT (blksize != 0);
|
||||
|
||||
/* Initialize xd3_source. */
|
||||
source->blksize = blksize;
|
||||
source->name = sfile->filename;
|
||||
source->ioh = sfile;
|
||||
source->curblkno = (xoff_t) -1;
|
||||
source->curblk = NULL;
|
||||
source->max_winsize = option_srcwinsz;
|
||||
|
||||
if ((ret = main_getblk_func (stream, source, 0)) != 0)
|
||||
{
|
||||
XPR(NT "error reading source: %s: %s\n",
|
||||
sfile->filename,
|
||||
xd3_mainerror (ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
source->onblk = lru[0].size; /* xd3 sets onblk */
|
||||
|
||||
/* If the file is smaller than a block, size is known. */
|
||||
if (!sfile->size_known && source->onblk < blksize)
|
||||
{
|
||||
source_size = source->onblk;
|
||||
sfile->size_known = 1;
|
||||
}
|
||||
|
||||
/* If the size is not known or is greater than the buffer size, we
|
||||
* split the buffer across MAX_LRU_SIZE blocks (already allocated in
|
||||
* "lru"). */
|
||||
if (!sfile->size_known || source_size > option_srcwinsz)
|
||||
{
|
||||
/* Modify block 0, change blocksize. */
|
||||
blksize = option_srcwinsz / MAX_LRU_SIZE;
|
||||
source->blksize = blksize;
|
||||
source->onblk = blksize; /* xd3 sets onblk */
|
||||
/* Note: source->max_winsize is unchanged. */
|
||||
lru[0].size = blksize;
|
||||
lru_size = MAX_LRU_SIZE;
|
||||
|
||||
/* Setup rest of blocks. */
|
||||
for (i = 1; i < lru_size; i += 1)
|
||||
{
|
||||
lru[i].blk = lru[0].blk + (blksize * i);
|
||||
lru[i].blkno = i;
|
||||
lru[i].size = blksize;
|
||||
main_blklru_list_push_back (& lru_list, & lru[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! sfile->size_known)
|
||||
{
|
||||
/* If the size is not know, we must use FIFO discipline. */
|
||||
do_src_fifo = 1;
|
||||
}
|
||||
|
||||
/* Call the appropriate set_source method, handle errors, print
|
||||
* verbose message, etc. */
|
||||
if (sfile->size_known)
|
||||
{
|
||||
ret = xd3_set_source_and_size (stream, source, source_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = xd3_set_source (stream, source);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
XPR(NT XD3_LIB_ERRMSG (stream, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
XD3_ASSERT (stream->src == source);
|
||||
XD3_ASSERT (source->blksize == blksize);
|
||||
|
||||
if (option_verbose)
|
||||
{
|
||||
static shortbuf srcszbuf;
|
||||
static shortbuf srccntbuf;
|
||||
static shortbuf winszbuf;
|
||||
static shortbuf blkszbuf;
|
||||
static shortbuf nbufs;
|
||||
|
||||
if (sfile->size_known)
|
||||
{
|
||||
short_sprintf (srcszbuf, "source size %s [%"Q"u]",
|
||||
main_format_bcnt (source_size, &srccntbuf),
|
||||
source_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
short_sprintf (srcszbuf, "%s", "source size unknown");
|
||||
}
|
||||
|
||||
nbufs.buf[0] = 0;
|
||||
|
||||
if (option_verbose > 1)
|
||||
{
|
||||
short_sprintf (nbufs, " #bufs %u", lru_size);
|
||||
}
|
||||
|
||||
XPR(NT "source %s %s blksize %s window %s%s%s\n",
|
||||
sfile->filename,
|
||||
srcszbuf.buf,
|
||||
main_format_bcnt (blksize, &blkszbuf),
|
||||
main_format_bcnt (option_srcwinsz, &winszbuf),
|
||||
nbufs.buf,
|
||||
do_src_fifo ? " (FIFO)" : "");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
main_getblk_lru (xd3_source *source, xoff_t blkno,
|
||||
main_blklru** blrup, int *is_new)
|
||||
{
|
||||
main_blklru *blru = NULL;
|
||||
usize_t i;
|
||||
|
||||
(*is_new) = 0;
|
||||
|
||||
if (do_src_fifo)
|
||||
{
|
||||
/* Direct lookup assumes sequential scan w/o skipping blocks. */
|
||||
int idx = blkno % lru_size;
|
||||
blru = & lru[idx];
|
||||
if (blru->blkno == blkno)
|
||||
{
|
||||
(*blrup) = blru;
|
||||
return 0;
|
||||
}
|
||||
/* No going backwards in a sequential scan. */
|
||||
if (blru->blkno != (xoff_t) -1 && blru->blkno > blkno)
|
||||
{
|
||||
return XD3_TOOFARBACK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sequential search through LRU. */
|
||||
for (i = 0; i < lru_size; i += 1)
|
||||
{
|
||||
blru = & lru[i];
|
||||
if (blru->blkno == blkno)
|
||||
{
|
||||
main_blklru_list_remove (blru);
|
||||
main_blklru_list_push_back (& lru_list, blru);
|
||||
(*blrup) = blru;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_src_fifo)
|
||||
{
|
||||
int idx = blkno % lru_size;
|
||||
blru = & lru[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
XD3_ASSERT (! main_blklru_list_empty (& lru_list));
|
||||
blru = main_blklru_list_pop_front (& lru_list);
|
||||
main_blklru_list_push_back (& lru_list, blru);
|
||||
}
|
||||
|
||||
lru_filled += 1;
|
||||
(*is_new) = 1;
|
||||
(*blrup) = blru;
|
||||
blru->blkno = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
main_read_seek_source (xd3_stream *stream,
|
||||
xd3_source *source,
|
||||
xoff_t blkno) {
|
||||
xoff_t pos = blkno * source->blksize;
|
||||
main_file *sfile = (main_file*) source->ioh;
|
||||
main_blklru *blru;
|
||||
int is_new;
|
||||
size_t nread = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!sfile->seek_failed)
|
||||
{
|
||||
ret = main_file_seek (sfile, pos);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
sfile->source_position = pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (sfile->seek_failed || ret != 0)
|
||||
{
|
||||
/* For an unseekable file (or other seek error, does it
|
||||
* matter?) */
|
||||
if (sfile->source_position > pos)
|
||||
{
|
||||
/* Could assert !IS_ENCODE(), this shouldn't happen
|
||||
* because of do_src_fifo during encode. */
|
||||
if (!option_quiet)
|
||||
{
|
||||
XPR(NT "source can't seek backwards; requested block offset "
|
||||
"%"Q"u source position is %"Q"u\n",
|
||||
pos, sfile->source_position);
|
||||
}
|
||||
|
||||
sfile->seek_failed = 1;
|
||||
stream->msg = "non-seekable source: "
|
||||
"copy is too far back (try raising -B)";
|
||||
return XD3_TOOFARBACK;
|
||||
}
|
||||
|
||||
/* There's a chance here, that an genuine lseek error will cause
|
||||
* xdelta3 to shift into non-seekable mode, entering a degraded
|
||||
* condition. */
|
||||
if (!sfile->seek_failed && option_verbose)
|
||||
{
|
||||
XPR(NT "source can't seek, will use FIFO for %s\n",
|
||||
sfile->filename);
|
||||
|
||||
if (option_verbose > 1)
|
||||
{
|
||||
XPR(NT "seek error at offset %"Q"u: %s\n",
|
||||
pos, xd3_mainerror (ret));
|
||||
}
|
||||
}
|
||||
|
||||
sfile->seek_failed = 1;
|
||||
|
||||
if (option_verbose > 1 && pos != sfile->source_position)
|
||||
{
|
||||
XPR(NT "non-seekable source skipping %"Q"u bytes @ %"Q"u\n",
|
||||
pos - sfile->source_position,
|
||||
sfile->source_position);
|
||||
}
|
||||
|
||||
while (sfile->source_position < pos)
|
||||
{
|
||||
xoff_t skip_blkno;
|
||||
usize_t skip_offset;
|
||||
|
||||
xd3_blksize_div (sfile->source_position, source,
|
||||
&skip_blkno, &skip_offset);
|
||||
|
||||
/* Read past unused data */
|
||||
XD3_ASSERT (pos - sfile->source_position >= source->blksize);
|
||||
XD3_ASSERT (skip_offset == 0);
|
||||
|
||||
if ((ret = main_getblk_lru (source, skip_blkno,
|
||||
& blru, & is_new)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
XD3_ASSERT (is_new);
|
||||
blru->blkno = skip_blkno;
|
||||
|
||||
if ((ret = main_read_primary_input (sfile,
|
||||
(uint8_t*) blru->blk,
|
||||
source->blksize,
|
||||
& nread)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (nread != source->blksize)
|
||||
{
|
||||
IF_DEBUG1 (DP(RINT "[getblk] short skip block nread = %zu\n",
|
||||
nread));
|
||||
stream->msg = "non-seekable input is short";
|
||||
return XD3_INVALID_INPUT;
|
||||
}
|
||||
|
||||
sfile->source_position += nread;
|
||||
blru->size = nread;
|
||||
|
||||
IF_DEBUG1 (DP(RINT "[getblk] skip blkno %"Q"u size %u\n",
|
||||
skip_blkno, blru->size));
|
||||
|
||||
XD3_ASSERT (sfile->source_position <= pos);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the callback for reading a block of source. This function
|
||||
* is blocking and it implements a small LRU.
|
||||
*
|
||||
* Note that it is possible for main_input() to handle getblk requests
|
||||
* in a non-blocking manner. If the callback is NULL then the caller
|
||||
* of xd3_*_input() must handle the XD3_GETSRCBLK return value and
|
||||
* fill the source in the same way. See xd3_getblk for details. To
|
||||
* see an example of non-blocking getblk, see xdelta-test.h. */
|
||||
static int
|
||||
main_getblk_func (xd3_stream *stream,
|
||||
xd3_source *source,
|
||||
xoff_t blkno)
|
||||
{
|
||||
int ret = 0;
|
||||
xoff_t pos = blkno * source->blksize;
|
||||
main_file *sfile = (main_file*) source->ioh;
|
||||
main_blklru *blru;
|
||||
int is_new;
|
||||
int did_seek = 0;
|
||||
size_t nread = 0;
|
||||
|
||||
if (allow_fake_source)
|
||||
{
|
||||
source->curblkno = blkno;
|
||||
source->onblk = 0;
|
||||
source->curblk = lru[0].blk;
|
||||
lru[0].size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ret = main_getblk_lru (source, blkno, & blru, & is_new)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!is_new)
|
||||
{
|
||||
source->curblkno = blkno;
|
||||
source->onblk = blru->size;
|
||||
source->curblk = blru->blk;
|
||||
lru_hits++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lru_misses += 1;
|
||||
|
||||
if (pos != sfile->source_position)
|
||||
{
|
||||
/* Only try to seek when the position is wrong. This means the
|
||||
* decoder will fail when the source buffer is too small, but
|
||||
* only when the input is non-seekable. */
|
||||
if ((ret = main_read_seek_source (stream, source, blkno)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Indicates that another call to main_getblk_lru() may be
|
||||
* needed */
|
||||
did_seek = 1;
|
||||
}
|
||||
|
||||
XD3_ASSERT (sfile->source_position == pos);
|
||||
|
||||
if (did_seek &&
|
||||
(ret = main_getblk_lru (source, blkno, & blru, & is_new)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = main_read_primary_input (sfile,
|
||||
(uint8_t*) blru->blk,
|
||||
source->blksize,
|
||||
& nread)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Save the last block read, used to handle non-seekable files. */
|
||||
sfile->source_position = pos + nread;
|
||||
|
||||
if (option_verbose > 3)
|
||||
{
|
||||
if (blru->blkno != (xoff_t)-1)
|
||||
{
|
||||
if (blru->blkno != blkno)
|
||||
{
|
||||
XPR(NT "source block %"Q"u read %zu ejects %"Q"u (lru_hits=%u, "
|
||||
"lru_misses=%u, lru_filled=%u)\n",
|
||||
blkno, nread, blru->blkno, lru_hits, lru_misses, lru_filled);
|
||||
}
|
||||
else
|
||||
{
|
||||
XPR(NT "source block %"Q"u read %zu (lru_hits=%u, "
|
||||
"lru_misses=%u, lru_filled=%u)\n",
|
||||
blkno, nread, lru_hits, lru_misses, lru_filled);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XPR(NT "source block %"Q"u read %zu (lru_hits=%u, lru_misses=%u, "
|
||||
"lru_filled=%u)\n", blkno, nread,
|
||||
lru_hits, lru_misses, lru_filled);
|
||||
}
|
||||
}
|
||||
|
||||
source->curblk = blru->blk;
|
||||
source->curblkno = blkno;
|
||||
source->onblk = nread;
|
||||
blru->size = nread;
|
||||
blru->blkno = blkno;
|
||||
|
||||
IF_DEBUG1 (DP(RINT "[main_getblk] blkno %"Q"u onblk %zu pos %"Q"u "
|
||||
"srcpos %"Q"u\n",
|
||||
blkno, nread, pos, sfile->source_position));
|
||||
|
||||
return 0;
|
||||
}
|
||||
173
3rdparty/xdelta3-3.0.8/xdelta3-cfgs.h
vendored
Normal file
173
3rdparty/xdelta3-3.0.8/xdelta3-cfgs.h
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
/* xdelta 3 - delta compression tools and library
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/******************************************************************
|
||||
SOFT string matcher
|
||||
******************************************************************/
|
||||
|
||||
#if XD3_BUILD_SOFT
|
||||
|
||||
#define TEMPLATE soft
|
||||
#define LLOOK stream->smatcher.large_look
|
||||
#define LSTEP stream->smatcher.large_step
|
||||
#define SLOOK stream->smatcher.small_look
|
||||
#define SCHAIN stream->smatcher.small_chain
|
||||
#define SLCHAIN stream->smatcher.small_lchain
|
||||
#define MAXLAZY stream->smatcher.max_lazy
|
||||
#define LONGENOUGH stream->smatcher.long_enough
|
||||
|
||||
#define SOFTCFG 1
|
||||
#include "xdelta3.c"
|
||||
#undef SOFTCFG
|
||||
|
||||
#undef TEMPLATE
|
||||
#undef LLOOK
|
||||
#undef SLOOK
|
||||
#undef LSTEP
|
||||
#undef SCHAIN
|
||||
#undef SLCHAIN
|
||||
#undef MAXLAZY
|
||||
#undef LONGENOUGH
|
||||
#endif
|
||||
|
||||
#define SOFTCFG 0
|
||||
|
||||
/************************************************************
|
||||
FASTEST string matcher
|
||||
**********************************************************/
|
||||
#if XD3_BUILD_FASTEST
|
||||
#define TEMPLATE fastest
|
||||
#define LLOOK 9
|
||||
#define LSTEP 26
|
||||
#define SLOOK 4U
|
||||
#define SCHAIN 1
|
||||
#define SLCHAIN 1
|
||||
#define MAXLAZY 6
|
||||
#define LONGENOUGH 6
|
||||
|
||||
#include "xdelta3.c"
|
||||
|
||||
#undef TEMPLATE
|
||||
#undef LLOOK
|
||||
#undef SLOOK
|
||||
#undef LSTEP
|
||||
#undef SCHAIN
|
||||
#undef SLCHAIN
|
||||
#undef MAXLAZY
|
||||
#undef LONGENOUGH
|
||||
#endif
|
||||
|
||||
/************************************************************
|
||||
FASTER string matcher
|
||||
**********************************************************/
|
||||
#if XD3_BUILD_FASTER
|
||||
#define TEMPLATE faster
|
||||
#define LLOOK 9
|
||||
#define LSTEP 15
|
||||
#define SLOOK 4U
|
||||
#define SCHAIN 1
|
||||
#define SLCHAIN 1
|
||||
#define MAXLAZY 18
|
||||
#define LONGENOUGH 18
|
||||
|
||||
#include "xdelta3.c"
|
||||
|
||||
#undef TEMPLATE
|
||||
#undef LLOOK
|
||||
#undef SLOOK
|
||||
#undef LSTEP
|
||||
#undef SCHAIN
|
||||
#undef SLCHAIN
|
||||
#undef MAXLAZY
|
||||
#undef LONGENOUGH
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
FAST string matcher
|
||||
********************************************************/
|
||||
#if XD3_BUILD_FAST
|
||||
#define TEMPLATE fast
|
||||
#define LLOOK 9
|
||||
#define LSTEP 8
|
||||
#define SLOOK 4U
|
||||
#define SCHAIN 4
|
||||
#define SLCHAIN 1
|
||||
#define MAXLAZY 18
|
||||
#define LONGENOUGH 35
|
||||
|
||||
#include "xdelta3.c"
|
||||
|
||||
#undef TEMPLATE
|
||||
#undef LLOOK
|
||||
#undef SLOOK
|
||||
#undef LSTEP
|
||||
#undef SCHAIN
|
||||
#undef SLCHAIN
|
||||
#undef MAXLAZY
|
||||
#undef LONGENOUGH
|
||||
#endif
|
||||
|
||||
/**************************************************
|
||||
SLOW string matcher
|
||||
**************************************************************/
|
||||
#if XD3_BUILD_SLOW
|
||||
#define TEMPLATE slow
|
||||
#define LLOOK 9
|
||||
#define LSTEP 2
|
||||
#define SLOOK 4U
|
||||
#define SCHAIN 44
|
||||
#define SLCHAIN 13
|
||||
#define MAXLAZY 90
|
||||
#define LONGENOUGH 70
|
||||
|
||||
#include "xdelta3.c"
|
||||
|
||||
#undef TEMPLATE
|
||||
#undef LLOOK
|
||||
#undef SLOOK
|
||||
#undef LSTEP
|
||||
#undef SCHAIN
|
||||
#undef SLCHAIN
|
||||
#undef MAXLAZY
|
||||
#undef LONGENOUGH
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
DEFAULT string matcher
|
||||
************************************************************/
|
||||
#if XD3_BUILD_DEFAULT
|
||||
#define TEMPLATE default
|
||||
#define LLOOK 9
|
||||
#define LSTEP 3
|
||||
#define SLOOK 4U
|
||||
#define SCHAIN 8
|
||||
#define SLCHAIN 2
|
||||
#define MAXLAZY 36
|
||||
#define LONGENOUGH 70
|
||||
|
||||
#include "xdelta3.c"
|
||||
|
||||
#undef TEMPLATE
|
||||
#undef LLOOK
|
||||
#undef SLOOK
|
||||
#undef LSTEP
|
||||
#undef SCHAIN
|
||||
#undef SLCHAIN
|
||||
#undef MAXLAZY
|
||||
#undef LONGENOUGH
|
||||
#endif
|
||||
1148
3rdparty/xdelta3-3.0.8/xdelta3-decode.h
vendored
Normal file
1148
3rdparty/xdelta3-3.0.8/xdelta3-decode.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1837
3rdparty/xdelta3-3.0.8/xdelta3-djw.h
vendored
Normal file
1837
3rdparty/xdelta3-3.0.8/xdelta3-djw.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
860
3rdparty/xdelta3-3.0.8/xdelta3-fgk.h
vendored
Normal file
860
3rdparty/xdelta3-3.0.8/xdelta3-fgk.h
vendored
Normal file
@@ -0,0 +1,860 @@
|
||||
/* xdelta 3 - delta compression tools and library
|
||||
* Copyright (C) 2002, 2006, 2007. Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* For demonstration purposes only.
|
||||
*/
|
||||
|
||||
#ifndef _XDELTA3_FGK_h_
|
||||
#define _XDELTA3_FGK_h_
|
||||
|
||||
/* An implementation of the FGK algorithm described by D.E. Knuth in
|
||||
* "Dynamic Huffman Coding" in Journal of Algorithms 6. */
|
||||
|
||||
/* A 32bit counter (fgk_weight) is used as the frequency counter for
|
||||
* nodes in the huffman tree. TODO: Need oto test for overflow and/or
|
||||
* reset stats. */
|
||||
|
||||
typedef struct _fgk_stream fgk_stream;
|
||||
typedef struct _fgk_node fgk_node;
|
||||
typedef struct _fgk_block fgk_block;
|
||||
typedef unsigned int fgk_bit;
|
||||
typedef uint32_t fgk_weight;
|
||||
|
||||
struct _fgk_block {
|
||||
union {
|
||||
fgk_node *un_leader;
|
||||
fgk_block *un_freeptr;
|
||||
} un;
|
||||
};
|
||||
|
||||
#define block_leader un.un_leader
|
||||
#define block_freeptr un.un_freeptr
|
||||
|
||||
/* The code can also support fixed huffman encoding/decoding. */
|
||||
#define IS_ADAPTIVE 1
|
||||
|
||||
/* weight is a count of the number of times this element has been seen
|
||||
* in the current encoding/decoding. parent, right_child, and
|
||||
* left_child are pointers defining the tree structure. right and
|
||||
* left point to neighbors in an ordered sequence of weights. The
|
||||
* left child of a node is always guaranteed to have weight not
|
||||
* greater than its sibling. fgk_blockLeader points to the element
|
||||
* with the same weight as itself which is closest to the next
|
||||
* increasing weight block. */
|
||||
struct _fgk_node
|
||||
{
|
||||
fgk_weight weight;
|
||||
fgk_node *parent;
|
||||
fgk_node *left_child;
|
||||
fgk_node *right_child;
|
||||
fgk_node *left;
|
||||
fgk_node *right;
|
||||
fgk_block *my_block;
|
||||
};
|
||||
|
||||
/* alphabet_size is the a count of the number of possible leaves in
|
||||
* the huffman tree. The number of total nodes counting internal
|
||||
* nodes is ((2 * alphabet_size) - 1). zero_freq_count is the number
|
||||
* of elements remaining which have zero frequency. zero_freq_exp and
|
||||
* zero_freq_rem satisfy the equation zero_freq_count =
|
||||
* 2^zero_freq_exp + zero_freq_rem. root_node is the root of the
|
||||
* tree, which is initialized to a node with zero frequency and
|
||||
* contains the 0th such element. free_node contains a pointer to the
|
||||
* next available fgk_node space. alphabet contains all the elements
|
||||
* and is indexed by N. remaining_zeros points to the head of the
|
||||
* list of zeros. */
|
||||
struct _fgk_stream
|
||||
{
|
||||
usize_t alphabet_size;
|
||||
usize_t zero_freq_count;
|
||||
usize_t zero_freq_exp;
|
||||
usize_t zero_freq_rem;
|
||||
usize_t coded_depth;
|
||||
|
||||
usize_t total_nodes;
|
||||
usize_t total_blocks;
|
||||
|
||||
fgk_bit *coded_bits;
|
||||
|
||||
fgk_block *block_array;
|
||||
fgk_block *free_block;
|
||||
|
||||
fgk_node *decode_ptr;
|
||||
fgk_node *remaining_zeros;
|
||||
fgk_node *alphabet;
|
||||
fgk_node *root_node;
|
||||
fgk_node *free_node;
|
||||
};
|
||||
|
||||
/*********************************************************************/
|
||||
/* Encoder */
|
||||
/*********************************************************************/
|
||||
|
||||
static fgk_stream* fgk_alloc (xd3_stream *stream /*, usize_t alphabet_size */);
|
||||
static int fgk_init (xd3_stream *stream,
|
||||
fgk_stream *h,
|
||||
int is_encode);
|
||||
static int fgk_encode_data (fgk_stream *h,
|
||||
usize_t n);
|
||||
static inline fgk_bit fgk_get_encoded_bit (fgk_stream *h);
|
||||
|
||||
static int xd3_encode_fgk (xd3_stream *stream,
|
||||
fgk_stream *sec_stream,
|
||||
xd3_output *input,
|
||||
xd3_output *output,
|
||||
xd3_sec_cfg *cfg);
|
||||
|
||||
/*********************************************************************/
|
||||
/* Decoder */
|
||||
/*********************************************************************/
|
||||
|
||||
static inline int fgk_decode_bit (fgk_stream *h,
|
||||
fgk_bit b);
|
||||
static int fgk_decode_data (fgk_stream *h);
|
||||
static void fgk_destroy (xd3_stream *stream,
|
||||
fgk_stream *h);
|
||||
|
||||
static int xd3_decode_fgk (xd3_stream *stream,
|
||||
fgk_stream *sec_stream,
|
||||
const uint8_t **input,
|
||||
const uint8_t *const input_end,
|
||||
uint8_t **output,
|
||||
const uint8_t *const output_end);
|
||||
|
||||
/*********************************************************************/
|
||||
/* Private */
|
||||
/*********************************************************************/
|
||||
|
||||
static unsigned int fgk_find_nth_zero (fgk_stream *h, usize_t n);
|
||||
static usize_t fgk_nth_zero (fgk_stream *h, usize_t n);
|
||||
static void fgk_update_tree (fgk_stream *h, usize_t n);
|
||||
static fgk_node* fgk_increase_zero_weight (fgk_stream *h, usize_t n);
|
||||
static void fgk_eliminate_zero (fgk_stream* h, fgk_node *node);
|
||||
static void fgk_move_right (fgk_stream *h, fgk_node *node);
|
||||
static void fgk_promote (fgk_stream *h, fgk_node *node);
|
||||
static void fgk_init_node (fgk_node *node, usize_t i, usize_t size);
|
||||
static fgk_block* fgk_make_block (fgk_stream *h, fgk_node *l);
|
||||
static void fgk_free_block (fgk_stream *h, fgk_block *b);
|
||||
static void fgk_factor_remaining (fgk_stream *h);
|
||||
static inline void fgk_swap_ptrs (fgk_node **one, fgk_node **two);
|
||||
|
||||
/*********************************************************************/
|
||||
/* Basic Routines */
|
||||
/*********************************************************************/
|
||||
|
||||
/* returns an initialized huffman encoder for an alphabet with the
|
||||
* given size. returns NULL if enough memory cannot be allocated */
|
||||
static fgk_stream* fgk_alloc (xd3_stream *stream /*, int alphabet_size0 */)
|
||||
{
|
||||
usize_t alphabet_size0 = ALPHABET_SIZE;
|
||||
fgk_stream *h;
|
||||
|
||||
if ((h = (fgk_stream*) xd3_alloc (stream, 1, sizeof (fgk_stream))) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h->total_nodes = (2 * alphabet_size0) - 1;
|
||||
h->total_blocks = (2 * h->total_nodes);
|
||||
h->alphabet = (fgk_node*) xd3_alloc (stream, h->total_nodes, sizeof (fgk_node));
|
||||
h->block_array = (fgk_block*) xd3_alloc (stream, h->total_blocks, sizeof (fgk_block));
|
||||
h->coded_bits = (fgk_bit*) xd3_alloc (stream, alphabet_size0, sizeof (fgk_bit));
|
||||
|
||||
if (h->coded_bits == NULL ||
|
||||
h->alphabet == NULL ||
|
||||
h->block_array == NULL)
|
||||
{
|
||||
fgk_destroy (stream, h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h->alphabet_size = alphabet_size0;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static int fgk_init (xd3_stream *stream, fgk_stream *h, int is_encode)
|
||||
{
|
||||
usize_t ui;
|
||||
ssize_t si;
|
||||
|
||||
h->root_node = h->alphabet;
|
||||
h->decode_ptr = h->root_node;
|
||||
h->free_node = h->alphabet + h->alphabet_size;
|
||||
h->remaining_zeros = h->alphabet;
|
||||
h->coded_depth = 0;
|
||||
h->zero_freq_count = h->alphabet_size + 2;
|
||||
|
||||
/* after two calls to factor_remaining, zero_freq_count == alphabet_size */
|
||||
fgk_factor_remaining(h); /* set ZFE and ZFR */
|
||||
fgk_factor_remaining(h); /* set ZFDB according to prev state */
|
||||
|
||||
IF_DEBUG (memset (h->alphabet, 0, sizeof (h->alphabet[0]) * h->total_nodes));
|
||||
|
||||
for (ui = 0; ui < h->total_blocks-1; ui += 1)
|
||||
{
|
||||
h->block_array[ui].block_freeptr = &h->block_array[ui + 1];
|
||||
}
|
||||
|
||||
h->block_array[h->total_blocks - 1].block_freeptr = NULL;
|
||||
h->free_block = h->block_array;
|
||||
|
||||
/* Zero frequency nodes are inserted in the first alphabet_size
|
||||
* positions, with Value, weight, and a pointer to the next zero
|
||||
* frequency node. */
|
||||
for (si = h->alphabet_size - 1; si >= 0; si -= 1)
|
||||
{
|
||||
fgk_init_node (h->alphabet + si, (usize_t) si, h->alphabet_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fgk_swap_ptrs(fgk_node **one, fgk_node **two)
|
||||
{
|
||||
fgk_node *tmp = *one;
|
||||
*one = *two;
|
||||
*two = tmp;
|
||||
}
|
||||
|
||||
/* Takes huffman transmitter h and n, the nth elt in the alphabet, and
|
||||
* returns the number of required to encode n. */
|
||||
static int fgk_encode_data (fgk_stream* h, usize_t n)
|
||||
{
|
||||
fgk_node *target_ptr = h->alphabet + n;
|
||||
|
||||
XD3_ASSERT (n < h->alphabet_size);
|
||||
|
||||
h->coded_depth = 0;
|
||||
|
||||
/* First encode the binary representation of the nth remaining
|
||||
* zero frequency element in reverse such that bit, which will be
|
||||
* encoded from h->coded_depth down to 0 will arrive in increasing
|
||||
* order following the tree path. If there is only one left, it
|
||||
* is not neccesary to encode these bits. */
|
||||
if (IS_ADAPTIVE && target_ptr->weight == 0)
|
||||
{
|
||||
unsigned int where, shift;
|
||||
int bits;
|
||||
|
||||
where = fgk_find_nth_zero(h, n);
|
||||
shift = 1;
|
||||
|
||||
if (h->zero_freq_rem == 0)
|
||||
{
|
||||
bits = h->zero_freq_exp;
|
||||
}
|
||||
else
|
||||
{
|
||||
bits = h->zero_freq_exp + 1;
|
||||
}
|
||||
|
||||
while (bits > 0)
|
||||
{
|
||||
h->coded_bits[h->coded_depth++] = (shift & where) && 1;
|
||||
|
||||
bits -= 1;
|
||||
shift <<= 1;
|
||||
};
|
||||
|
||||
target_ptr = h->remaining_zeros;
|
||||
}
|
||||
|
||||
/* The path from root to node is filled into coded_bits in reverse so
|
||||
* that it is encoded in the right order */
|
||||
while (target_ptr != h->root_node)
|
||||
{
|
||||
h->coded_bits[h->coded_depth++] = (target_ptr->parent->right_child == target_ptr);
|
||||
|
||||
target_ptr = target_ptr->parent;
|
||||
}
|
||||
|
||||
if (IS_ADAPTIVE)
|
||||
{
|
||||
fgk_update_tree(h, n);
|
||||
}
|
||||
|
||||
return h->coded_depth;
|
||||
}
|
||||
|
||||
/* Should be called as many times as fgk_encode_data returns.
|
||||
*/
|
||||
static inline fgk_bit fgk_get_encoded_bit (fgk_stream *h)
|
||||
{
|
||||
XD3_ASSERT (h->coded_depth > 0);
|
||||
|
||||
return h->coded_bits[--h->coded_depth];
|
||||
}
|
||||
|
||||
/* This procedure updates the tree after alphabet[n] has been encoded
|
||||
* or decoded.
|
||||
*/
|
||||
static void fgk_update_tree (fgk_stream *h, usize_t n)
|
||||
{
|
||||
fgk_node *incr_node;
|
||||
|
||||
if (h->alphabet[n].weight == 0)
|
||||
{
|
||||
incr_node = fgk_increase_zero_weight (h, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
incr_node = h->alphabet + n;
|
||||
}
|
||||
|
||||
while (incr_node != h->root_node)
|
||||
{
|
||||
fgk_move_right (h, incr_node);
|
||||
fgk_promote (h, incr_node);
|
||||
incr_node->weight += 1; /* incr the parent */
|
||||
incr_node = incr_node->parent; /* repeat */
|
||||
}
|
||||
|
||||
h->root_node->weight += 1;
|
||||
}
|
||||
|
||||
static void fgk_move_right (fgk_stream *h, fgk_node *move_fwd)
|
||||
{
|
||||
fgk_node **fwd_par_ptr, **back_par_ptr;
|
||||
fgk_node *move_back, *tmp;
|
||||
|
||||
move_back = move_fwd->my_block->block_leader;
|
||||
|
||||
if (move_fwd == move_back ||
|
||||
move_fwd->parent == move_back ||
|
||||
move_fwd->weight == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
move_back->right->left = move_fwd;
|
||||
|
||||
if (move_fwd->left)
|
||||
{
|
||||
move_fwd->left->right = move_back;
|
||||
}
|
||||
|
||||
tmp = move_fwd->right;
|
||||
move_fwd->right = move_back->right;
|
||||
|
||||
if (tmp == move_back)
|
||||
{
|
||||
move_back->right = move_fwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp->left = move_back;
|
||||
move_back->right = tmp;
|
||||
}
|
||||
|
||||
tmp = move_back->left;
|
||||
move_back->left = move_fwd->left;
|
||||
|
||||
if (tmp == move_fwd)
|
||||
{
|
||||
move_fwd->left = move_back;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp->right = move_fwd;
|
||||
move_fwd->left = tmp;
|
||||
}
|
||||
|
||||
if (move_fwd->parent->right_child == move_fwd)
|
||||
{
|
||||
fwd_par_ptr = &move_fwd->parent->right_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
fwd_par_ptr = &move_fwd->parent->left_child;
|
||||
}
|
||||
|
||||
if (move_back->parent->right_child == move_back)
|
||||
{
|
||||
back_par_ptr = &move_back->parent->right_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
back_par_ptr = &move_back->parent->left_child;
|
||||
}
|
||||
|
||||
fgk_swap_ptrs (&move_fwd->parent, &move_back->parent);
|
||||
fgk_swap_ptrs (fwd_par_ptr, back_par_ptr);
|
||||
|
||||
move_fwd->my_block->block_leader = move_fwd;
|
||||
}
|
||||
|
||||
/* Shifts node, the leader of its block, into the next block. */
|
||||
static void fgk_promote (fgk_stream *h, fgk_node *node)
|
||||
{
|
||||
fgk_node *my_left, *my_right;
|
||||
fgk_block *cur_block;
|
||||
|
||||
my_right = node->right;
|
||||
my_left = node->left;
|
||||
cur_block = node->my_block;
|
||||
|
||||
if (node->weight == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* if left is right child, parent of remaining zeros case (?), means parent
|
||||
* has same weight as right child. */
|
||||
if (my_left == node->right_child &&
|
||||
node->left_child &&
|
||||
node->left_child->weight == 0)
|
||||
{
|
||||
XD3_ASSERT (node->left_child == h->remaining_zeros);
|
||||
XD3_ASSERT (node->right_child->weight == (node->weight+1)); /* child weight was already incremented */
|
||||
|
||||
if (node->weight == (my_right->weight - 1) && my_right != h->root_node)
|
||||
{
|
||||
fgk_free_block (h, cur_block);
|
||||
node->my_block = my_right->my_block;
|
||||
my_left->my_block = my_right->my_block;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (my_left == h->remaining_zeros)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* true if not the leftmost node */
|
||||
if (my_left->my_block == cur_block)
|
||||
{
|
||||
my_left->my_block->block_leader = my_left;
|
||||
}
|
||||
else
|
||||
{
|
||||
fgk_free_block (h, cur_block);
|
||||
}
|
||||
|
||||
/* node->parent != my_right */
|
||||
if ((node->weight == (my_right->weight - 1)) && (my_right != h->root_node))
|
||||
{
|
||||
node->my_block = my_right->my_block;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->my_block = fgk_make_block (h, node);
|
||||
}
|
||||
}
|
||||
|
||||
/* When an element is seen the first time this is called to remove it from the list of
|
||||
* zero weight elements and introduce a new internal node to the tree. */
|
||||
static fgk_node* fgk_increase_zero_weight (fgk_stream *h, usize_t n)
|
||||
{
|
||||
fgk_node *this_zero, *new_internal, *zero_ptr;
|
||||
|
||||
this_zero = h->alphabet + n;
|
||||
|
||||
if (h->zero_freq_count == 1)
|
||||
{
|
||||
/* this is the last one */
|
||||
this_zero->right_child = NULL;
|
||||
|
||||
if (this_zero->right->weight == 1)
|
||||
{
|
||||
this_zero->my_block = this_zero->right->my_block;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_zero->my_block = fgk_make_block (h, this_zero);
|
||||
}
|
||||
|
||||
h->remaining_zeros = NULL;
|
||||
|
||||
return this_zero;
|
||||
}
|
||||
|
||||
zero_ptr = h->remaining_zeros;
|
||||
|
||||
new_internal = h->free_node++;
|
||||
|
||||
new_internal->parent = zero_ptr->parent;
|
||||
new_internal->right = zero_ptr->right;
|
||||
new_internal->weight = 0;
|
||||
new_internal->right_child = this_zero;
|
||||
new_internal->left = this_zero;
|
||||
|
||||
if (h->remaining_zeros == h->root_node)
|
||||
{
|
||||
/* This is the first element to be coded */
|
||||
h->root_node = new_internal;
|
||||
this_zero->my_block = fgk_make_block (h, this_zero);
|
||||
new_internal->my_block = fgk_make_block (h, new_internal);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_internal->right->left = new_internal;
|
||||
|
||||
if (zero_ptr->parent->right_child == zero_ptr)
|
||||
{
|
||||
zero_ptr->parent->right_child = new_internal;
|
||||
}
|
||||
else
|
||||
{
|
||||
zero_ptr->parent->left_child = new_internal;
|
||||
}
|
||||
|
||||
if (new_internal->right->weight == 1)
|
||||
{
|
||||
new_internal->my_block = new_internal->right->my_block;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_internal->my_block = fgk_make_block (h, new_internal);
|
||||
}
|
||||
|
||||
this_zero->my_block = new_internal->my_block;
|
||||
}
|
||||
|
||||
fgk_eliminate_zero (h, this_zero);
|
||||
|
||||
new_internal->left_child = h->remaining_zeros;
|
||||
|
||||
this_zero->right = new_internal;
|
||||
this_zero->left = h->remaining_zeros;
|
||||
this_zero->parent = new_internal;
|
||||
this_zero->left_child = NULL;
|
||||
this_zero->right_child = NULL;
|
||||
|
||||
h->remaining_zeros->parent = new_internal;
|
||||
h->remaining_zeros->right = this_zero;
|
||||
|
||||
return this_zero;
|
||||
}
|
||||
|
||||
/* When a zero frequency element is encoded, it is followed by the
|
||||
* binary representation of the index into the remaining elements.
|
||||
* Sets a cache to the element before it so that it can be removed
|
||||
* without calling this procedure again. */
|
||||
static unsigned int fgk_find_nth_zero (fgk_stream* h, usize_t n)
|
||||
{
|
||||
fgk_node *target_ptr = h->alphabet + n;
|
||||
fgk_node *head_ptr = h->remaining_zeros;
|
||||
unsigned int idx = 0;
|
||||
|
||||
while (target_ptr != head_ptr)
|
||||
{
|
||||
head_ptr = head_ptr->right_child;
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/* Splices node out of the list of zeros. */
|
||||
static void fgk_eliminate_zero (fgk_stream* h, fgk_node *node)
|
||||
{
|
||||
if (h->zero_freq_count == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fgk_factor_remaining(h);
|
||||
|
||||
if (node->left_child == NULL)
|
||||
{
|
||||
h->remaining_zeros = h->remaining_zeros->right_child;
|
||||
h->remaining_zeros->left_child = NULL;
|
||||
}
|
||||
else if (node->right_child == NULL)
|
||||
{
|
||||
node->left_child->right_child = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->right_child->left_child = node->left_child;
|
||||
node->left_child->right_child = node->right_child;
|
||||
}
|
||||
}
|
||||
|
||||
static void fgk_init_node (fgk_node *node, usize_t i, usize_t size)
|
||||
{
|
||||
if (i < size - 1)
|
||||
{
|
||||
node->right_child = node + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->right_child = NULL;
|
||||
}
|
||||
|
||||
if (i >= 1)
|
||||
{
|
||||
node->left_child = node - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->left_child = NULL;
|
||||
}
|
||||
|
||||
node->weight = 0;
|
||||
node->parent = NULL;
|
||||
node->right = NULL;
|
||||
node->left = NULL;
|
||||
node->my_block = NULL;
|
||||
}
|
||||
|
||||
/* The data structure used is an array of blocks, which are unions of
|
||||
* free pointers and huffnode pointers. free blocks are a linked list
|
||||
* of free blocks, the front of which is h->free_block. The used
|
||||
* blocks are pointers to the head of each block. */
|
||||
static fgk_block* fgk_make_block (fgk_stream *h, fgk_node* lead)
|
||||
{
|
||||
fgk_block *ret = h->free_block;
|
||||
|
||||
XD3_ASSERT (h->free_block != NULL);
|
||||
|
||||
h->free_block = h->free_block->block_freeptr;
|
||||
|
||||
ret->block_leader = lead;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Restores the block to the front of the free list. */
|
||||
static void fgk_free_block (fgk_stream *h, fgk_block *b)
|
||||
{
|
||||
b->block_freeptr = h->free_block;
|
||||
h->free_block = b;
|
||||
}
|
||||
|
||||
/* sets zero_freq_count, zero_freq_rem, and zero_freq_exp to satsity
|
||||
* the equation given above. */
|
||||
static void fgk_factor_remaining (fgk_stream *h)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
i = (--h->zero_freq_count);
|
||||
h->zero_freq_exp = 0;
|
||||
|
||||
while (i > 1)
|
||||
{
|
||||
h->zero_freq_exp += 1;
|
||||
i >>= 1;
|
||||
}
|
||||
|
||||
i = 1 << h->zero_freq_exp;
|
||||
|
||||
h->zero_freq_rem = h->zero_freq_count - i;
|
||||
}
|
||||
|
||||
/* receives a bit at a time and returns true when a complete code has
|
||||
* been received.
|
||||
*/
|
||||
static inline int fgk_decode_bit (fgk_stream* h, fgk_bit b)
|
||||
{
|
||||
XD3_ASSERT (b == 1 || b == 0);
|
||||
|
||||
if (IS_ADAPTIVE && h->decode_ptr->weight == 0)
|
||||
{
|
||||
usize_t bitsreq;
|
||||
|
||||
if (h->zero_freq_rem == 0)
|
||||
{
|
||||
bitsreq = h->zero_freq_exp;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitsreq = h->zero_freq_exp + 1;
|
||||
}
|
||||
|
||||
h->coded_bits[h->coded_depth] = b;
|
||||
h->coded_depth += 1;
|
||||
|
||||
return h->coded_depth >= bitsreq;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
h->decode_ptr = h->decode_ptr->right_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
h->decode_ptr = h->decode_ptr->left_child;
|
||||
}
|
||||
|
||||
if (h->decode_ptr->left_child == NULL)
|
||||
{
|
||||
/* If the weight is non-zero, finished. */
|
||||
if (h->decode_ptr->weight != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* zero_freq_count is dropping to 0, finished. */
|
||||
return h->zero_freq_count == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static usize_t fgk_nth_zero (fgk_stream* h, usize_t n)
|
||||
{
|
||||
fgk_node *ret = h->remaining_zeros;
|
||||
|
||||
/* ERROR: if during this loop (ret->right_child == NULL) then the
|
||||
* encoder's zero count is too high. Could return an error code
|
||||
* now, but is probably unnecessary overhead, since the caller
|
||||
* should check integrity anyway. */
|
||||
for (; n != 0 && ret->right_child != NULL; n -= 1)
|
||||
{
|
||||
ret = ret->right_child;
|
||||
}
|
||||
|
||||
return (usize_t)(ret - h->alphabet);
|
||||
}
|
||||
|
||||
/* once fgk_decode_bit returns 1, this retrieves an index into the
|
||||
* alphabet otherwise this returns 0, indicating more bits are
|
||||
* required.
|
||||
*/
|
||||
static int fgk_decode_data (fgk_stream* h)
|
||||
{
|
||||
usize_t elt = (usize_t)(h->decode_ptr - h->alphabet);
|
||||
|
||||
if (IS_ADAPTIVE && h->decode_ptr->weight == 0) {
|
||||
usize_t i = 0;
|
||||
usize_t n = 0;
|
||||
|
||||
if (h->coded_depth > 0)
|
||||
{
|
||||
for (; i < h->coded_depth - 1; i += 1)
|
||||
{
|
||||
n |= h->coded_bits[i];
|
||||
n <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
n |= h->coded_bits[i];
|
||||
elt = fgk_nth_zero(h, n);
|
||||
}
|
||||
|
||||
h->coded_depth = 0;
|
||||
|
||||
if (IS_ADAPTIVE)
|
||||
{
|
||||
fgk_update_tree(h, elt);
|
||||
}
|
||||
|
||||
h->decode_ptr = h->root_node;
|
||||
|
||||
return elt;
|
||||
}
|
||||
|
||||
static void fgk_destroy (xd3_stream *stream,
|
||||
fgk_stream *h)
|
||||
{
|
||||
if (h != NULL)
|
||||
{
|
||||
xd3_free (stream, h->alphabet);
|
||||
xd3_free (stream, h->coded_bits);
|
||||
xd3_free (stream, h->block_array);
|
||||
xd3_free (stream, h);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* Xdelta */
|
||||
/*********************************************************************/
|
||||
|
||||
static int
|
||||
xd3_encode_fgk (xd3_stream *stream, fgk_stream *sec_stream, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg)
|
||||
{
|
||||
bit_state bstate = BIT_STATE_ENCODE_INIT;
|
||||
xd3_output *cur_page;
|
||||
int ret;
|
||||
|
||||
/* OPT: quit compression early if it looks bad */
|
||||
for (cur_page = input; cur_page; cur_page = cur_page->next_page)
|
||||
{
|
||||
const uint8_t *inp = cur_page->base;
|
||||
const uint8_t *inp_max = inp + cur_page->next;
|
||||
|
||||
while (inp < inp_max)
|
||||
{
|
||||
usize_t bits = fgk_encode_data (sec_stream, *inp++);
|
||||
|
||||
while (bits--)
|
||||
{
|
||||
if ((ret = xd3_encode_bit (stream, & output, & bstate, fgk_get_encoded_bit (sec_stream)))) { return ret; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xd3_flush_bits (stream, & output, & bstate);
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_decode_fgk (xd3_stream *stream,
|
||||
fgk_stream *sec_stream,
|
||||
const uint8_t **input_pos,
|
||||
const uint8_t *const input_max,
|
||||
uint8_t **output_pos,
|
||||
const uint8_t *const output_max)
|
||||
{
|
||||
bit_state bstate;
|
||||
uint8_t *output = *output_pos;
|
||||
const uint8_t *input = *input_pos;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (input == input_max)
|
||||
{
|
||||
stream->msg = "secondary decoder end of input";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
|
||||
bstate.cur_byte = *input++;
|
||||
|
||||
for (bstate.cur_mask = 1; bstate.cur_mask != 0x100; bstate.cur_mask <<= 1)
|
||||
{
|
||||
int done = fgk_decode_bit (sec_stream, (bstate.cur_byte & bstate.cur_mask) ? 1U : 0U);
|
||||
|
||||
if (! done) { continue; }
|
||||
|
||||
*output++ = fgk_decode_data (sec_stream);
|
||||
|
||||
if (output == output_max)
|
||||
{
|
||||
/* During regression testing: */
|
||||
IF_REGRESSION ({
|
||||
int ret;
|
||||
bstate.cur_mask <<= 1;
|
||||
if ((ret = xd3_test_clean_bits (stream, & bstate))) { return ret; }
|
||||
});
|
||||
|
||||
(*output_pos) = output;
|
||||
(*input_pos) = input;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _XDELTA3_FGK_ */
|
||||
170
3rdparty/xdelta3-3.0.8/xdelta3-hash.h
vendored
Normal file
170
3rdparty/xdelta3-3.0.8/xdelta3-hash.h
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
/* xdelta 3 - delta compression tools and library
|
||||
* Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _XDELTA3_HASH_H_
|
||||
#define _XDELTA3_HASH_H_
|
||||
|
||||
#if XD3_DEBUG
|
||||
#define SMALL_HASH_DEBUG1(s,inp) \
|
||||
uint32_t debug_state; \
|
||||
uint32_t debug_hval = xd3_checksum_hash (& (s)->small_hash, \
|
||||
xd3_scksum (&debug_state, (inp), (s)->smatcher.small_look))
|
||||
#define SMALL_HASH_DEBUG2(s,inp) \
|
||||
XD3_ASSERT (debug_hval == xd3_checksum_hash (& (s)->small_hash, \
|
||||
xd3_scksum (&debug_state, (inp), (s)->smatcher.small_look)))
|
||||
#else
|
||||
#define SMALL_HASH_DEBUG1(s,inp)
|
||||
#define SMALL_HASH_DEBUG2(s,inp)
|
||||
#endif /* XD3_DEBUG */
|
||||
|
||||
/* This is a good hash multiplier for 32-bit LCGs: see "linear
|
||||
* congruential generators of different sizes and good lattice
|
||||
* structure" */
|
||||
static const uint32_t hash_multiplier = 1597334677U;
|
||||
|
||||
/***********************************************************************
|
||||
Permute stuff
|
||||
***********************************************************************/
|
||||
|
||||
#if HASH_PERMUTE == 0
|
||||
#define PERMUTE(x) (x)
|
||||
#else
|
||||
#define PERMUTE(x) (__single_hash[(uint32_t)x])
|
||||
|
||||
extern const uint16_t __single_hash[256];
|
||||
#endif
|
||||
|
||||
/* Update the checksum state. */
|
||||
#if ADLER_LARGE_CKSUM
|
||||
inline uint32_t
|
||||
xd3_large_cksum_update (uint32_t cksum,
|
||||
const uint8_t *base,
|
||||
usize_t look) {
|
||||
uint32_t old_c = PERMUTE(base[0]);
|
||||
uint32_t new_c = PERMUTE(base[look]);
|
||||
uint32_t low = ((cksum & 0xffff) - old_c + new_c) & 0xffff;
|
||||
uint32_t high = ((cksum >> 16) - (old_c * look) + low) & 0xffff;
|
||||
return (high << 16) | low;
|
||||
}
|
||||
#else
|
||||
/* TODO: revisit this topic */
|
||||
#endif
|
||||
|
||||
#if UNALIGNED_OK
|
||||
#define UNALIGNED_READ32(dest,src) (*(dest)) = (*(uint32_t*)(src))
|
||||
#else
|
||||
#define UNALIGNED_READ32(dest,src) memcpy((dest), (src), 4);
|
||||
#endif
|
||||
|
||||
/* TODO: small cksum is hard-coded for 4 bytes (i.e., "look" is unused) */
|
||||
static inline uint32_t
|
||||
xd3_scksum (uint32_t *state,
|
||||
const uint8_t *base,
|
||||
const usize_t look)
|
||||
{
|
||||
UNALIGNED_READ32(state, base);
|
||||
return (*state) * hash_multiplier;
|
||||
}
|
||||
static inline uint32_t
|
||||
xd3_small_cksum_update (uint32_t *state,
|
||||
const uint8_t *base,
|
||||
usize_t look)
|
||||
{
|
||||
UNALIGNED_READ32(state, base+1);
|
||||
return (*state) * hash_multiplier;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Ctable stuff
|
||||
***********************************************************************/
|
||||
|
||||
static inline usize_t
|
||||
xd3_checksum_hash (const xd3_hash_cfg *cfg, const usize_t cksum)
|
||||
{
|
||||
return (cksum >> cfg->shift) ^ (cksum & cfg->mask);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Cksum function
|
||||
***********************************************************************/
|
||||
|
||||
#if ADLER_LARGE_CKSUM
|
||||
static inline uint32_t
|
||||
xd3_lcksum (const uint8_t *seg, const usize_t ln)
|
||||
{
|
||||
usize_t i = 0;
|
||||
uint32_t low = 0;
|
||||
uint32_t high = 0;
|
||||
|
||||
for (; i < ln; i += 1)
|
||||
{
|
||||
low += PERMUTE(*seg++);
|
||||
high += low;
|
||||
}
|
||||
|
||||
return ((high & 0xffff) << 16) | (low & 0xffff);
|
||||
}
|
||||
#else
|
||||
static inline uint32_t
|
||||
xd3_lcksum (const uint8_t *seg, const usize_t ln)
|
||||
{
|
||||
usize_t i, j;
|
||||
uint32_t h = 0;
|
||||
for (i = 0, j = ln - 1; i < ln; ++i, --j) {
|
||||
h += PERMUTE(seg[i]) * hash_multiplier_powers[j];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if XD3_ENCODER
|
||||
static usize_t
|
||||
xd3_size_log2 (usize_t slots)
|
||||
{
|
||||
int bits = 28; /* This should not be an unreasonable limit. */
|
||||
int i;
|
||||
|
||||
for (i = 3; i <= bits; i += 1)
|
||||
{
|
||||
if (slots < (1U << i))
|
||||
{
|
||||
/* TODO: this is compaction=1 in checksum_test.cc and maybe should
|
||||
* not be fixed at -1. */
|
||||
bits = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void
|
||||
xd3_size_hashtable (xd3_stream *stream,
|
||||
usize_t slots,
|
||||
xd3_hash_cfg *cfg)
|
||||
{
|
||||
int bits = xd3_size_log2 (slots);
|
||||
|
||||
/* TODO: there's a 32-bit assumption here */
|
||||
cfg->size = (1 << bits);
|
||||
cfg->mask = (cfg->size - 1);
|
||||
cfg->shift = 32 - bits;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
145
3rdparty/xdelta3-3.0.8/xdelta3-internal.h
vendored
Normal file
145
3rdparty/xdelta3-3.0.8/xdelta3-internal.h
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/* xdelta3 - delta compression tools and library
|
||||
* Copyright (C) 2011, 2012 Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#ifndef XDELTA3_INTERNAL_H__
|
||||
#define XDELTA3_INTERNAL_H__
|
||||
|
||||
#include "xdelta3.h"
|
||||
|
||||
typedef struct _main_file main_file;
|
||||
typedef struct _main_extcomp main_extcomp;
|
||||
|
||||
void main_buffree (void *ptr);
|
||||
void* main_bufalloc (size_t size);
|
||||
void main_file_init (main_file *xfile);
|
||||
int main_file_close (main_file *xfile);
|
||||
void main_file_cleanup (main_file *xfile);
|
||||
int main_file_isopen (main_file *xfile);
|
||||
int main_file_open (main_file *xfile, const char* name, int mode);
|
||||
int main_file_exists (main_file *xfile);
|
||||
int xd3_whole_append_window (xd3_stream *stream);
|
||||
int xd3_main_cmdline (int argc, char **argv);
|
||||
int main_file_read (main_file *ifile,
|
||||
uint8_t *buf,
|
||||
size_t size,
|
||||
size_t *nread,
|
||||
const char *msg);
|
||||
int main_file_write (main_file *ofile, uint8_t *buf,
|
||||
usize_t size, const char *msg);
|
||||
int test_compare_files (const char* f0, const char* f1);
|
||||
usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno);
|
||||
xoff_t xd3_source_eof(const xd3_source *src);
|
||||
uint32_t xd3_large_cksum_update (uint32_t cksum,
|
||||
const uint8_t *base,
|
||||
usize_t look);
|
||||
int xd3_encode_init_full (xd3_stream *stream);
|
||||
#if PYTHON_MODULE || SWIG_MODULE || NOT_MAIN
|
||||
int xd3_main_cmdline (int argc, char **argv);
|
||||
#endif
|
||||
|
||||
/* main_file->mode values */
|
||||
typedef enum
|
||||
{
|
||||
XO_READ = 0,
|
||||
XO_WRITE = 1
|
||||
} main_file_modes;
|
||||
|
||||
struct _main_file
|
||||
{
|
||||
#if XD3_STDIO
|
||||
FILE *file;
|
||||
#elif XD3_POSIX
|
||||
int file;
|
||||
#elif XD3_WIN32
|
||||
HANDLE file;
|
||||
#endif
|
||||
|
||||
int mode; /* XO_READ and XO_WRITE */
|
||||
const char *filename; /* File name or /dev/stdin,
|
||||
* /dev/stdout, /dev/stderr. */
|
||||
char *filename_copy; /* File name or /dev/stdin,
|
||||
* /dev/stdout, /dev/stderr. */
|
||||
const char *realname; /* File name or /dev/stdin,
|
||||
* /dev/stdout, /dev/stderr. */
|
||||
const main_extcomp *compressor; /* External compression struct. */
|
||||
int flags; /* RD_FIRST, RD_NONEXTERNAL, ... */
|
||||
xoff_t nread; /* for input position */
|
||||
xoff_t nwrite; /* for output position */
|
||||
uint8_t *snprintf_buf; /* internal snprintf() use */
|
||||
int size_known; /* Set by main_set_souze */
|
||||
xoff_t source_position; /* for avoiding seek in getblk_func */
|
||||
int seek_failed; /* after seek fails once, try FIFO */
|
||||
};
|
||||
|
||||
/* According to the internet, Windows vsnprintf() differs from most
|
||||
* Unix implementations regarding the terminating 0 when the boundary
|
||||
* condition is met. It doesn't matter here, we don't rely on the
|
||||
* trailing 0. Besides, both Windows and DJGPP vsnprintf return -1
|
||||
* upon truncation, which isn't C99 compliant. To overcome this,
|
||||
* recent MinGW runtimes provided their own vsnprintf (notice the
|
||||
* absence of the '_' prefix) but they were initially buggy. So,
|
||||
* always use the native '_'-prefixed version with Win32. */
|
||||
#ifdef _WIN32
|
||||
#define vsnprintf_func(str,size,fmt,args) \
|
||||
_vsnprintf_s(str,size,size-1,fmt,args)
|
||||
#define snprintf_func(str,size,fmt,...) \
|
||||
_snprintf_s(str,size,size-1,fmt,__VA_ARGS__)
|
||||
#else
|
||||
#define vsnprintf_func vsnprintf
|
||||
#define snprintf_func snprintf
|
||||
#endif
|
||||
#define short_sprintf(sb,fmt,...) \
|
||||
snprintf_func((sb).buf,sizeof((sb).buf),fmt,__VA_ARGS__)
|
||||
|
||||
/* Type used for short snprintf calls. */
|
||||
typedef struct {
|
||||
char buf[48];
|
||||
} shortbuf;
|
||||
|
||||
/* Prior to SVN 303 this function was only defined in DJGPP and WIN32
|
||||
* environments and other platforms would use the builtin snprintf()
|
||||
* with an arrangement of macros below. In OS X 10.6, Apply made
|
||||
* snprintf() a macro, which defeated those macros (since snprintf
|
||||
* would be evaluated before its argument macros were expanded,
|
||||
* therefore always define xsnprintf_func. */
|
||||
#undef PRINTF_ATTRIBUTE
|
||||
#ifdef __GNUC__
|
||||
/* Let's just assume no one uses gcc 2.x! */
|
||||
#define PRINTF_ATTRIBUTE(x,y) __attribute__ ((__format__ (__printf__, x, y)))
|
||||
#else
|
||||
#define PRINTF_ATTRIBUTE(x,y)
|
||||
#endif
|
||||
|
||||
/* Underlying xprintf() */
|
||||
int xsnprintf_func (char *str, int n, const char *fmt, ...)
|
||||
PRINTF_ATTRIBUTE(3,4);
|
||||
|
||||
/* XPR(NT "", ...) (used by main) prefixes an "xdelta3: " to the output. */
|
||||
void xprintf(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
|
||||
#define XPR xprintf
|
||||
#define NT "xdelta3: "
|
||||
#define NTR ""
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX 4294967295U
|
||||
#endif
|
||||
|
||||
#ifndef UINT64_MAX
|
||||
#define UINT64_MAX 18446744073709551615ULL
|
||||
#endif
|
||||
|
||||
#endif // XDELTA3_INTERNAL_H__
|
||||
130
3rdparty/xdelta3-3.0.8/xdelta3-list.h
vendored
Normal file
130
3rdparty/xdelta3-3.0.8/xdelta3-list.h
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
/* xdelta 3 - delta compression tools and library
|
||||
* Copyright (C) 2002, 2006, 2007. Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __XDELTA3_LIST__
|
||||
#define __XDELTA3_LIST__
|
||||
|
||||
#define XD3_MAKELIST(LTYPE,ETYPE,LNAME) \
|
||||
\
|
||||
static inline ETYPE* \
|
||||
LTYPE ## _entry (LTYPE* l) \
|
||||
{ \
|
||||
return (ETYPE*) ((char*) l - (ptrdiff_t) &((ETYPE*) 0)->LNAME); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
LTYPE ## _init (LTYPE *l) \
|
||||
{ \
|
||||
l->next = l; \
|
||||
l->prev = l; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
LTYPE ## _add (LTYPE *prev, LTYPE *next, LTYPE *ins) \
|
||||
{ \
|
||||
next->prev = ins; \
|
||||
prev->next = ins; \
|
||||
ins->next = next; \
|
||||
ins->prev = prev; \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
LTYPE ## _push_back (LTYPE *l, ETYPE *i) \
|
||||
{ \
|
||||
LTYPE ## _add (l->prev, l, & i->LNAME); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
LTYPE ## _del (LTYPE *next, \
|
||||
LTYPE *prev) \
|
||||
{ \
|
||||
next->prev = prev; \
|
||||
prev->next = next; \
|
||||
} \
|
||||
\
|
||||
static inline ETYPE* \
|
||||
LTYPE ## _remove (ETYPE *f) \
|
||||
{ \
|
||||
LTYPE *i = f->LNAME.next; \
|
||||
LTYPE ## _del (f->LNAME.next, f->LNAME.prev); \
|
||||
return LTYPE ## _entry (i); \
|
||||
} \
|
||||
\
|
||||
static inline ETYPE* \
|
||||
LTYPE ## _pop_back (LTYPE *l) \
|
||||
{ \
|
||||
LTYPE *i = l->prev; \
|
||||
LTYPE ## _del (i->next, i->prev); \
|
||||
return LTYPE ## _entry (i); \
|
||||
} \
|
||||
\
|
||||
static inline ETYPE* \
|
||||
LTYPE ## _pop_front (LTYPE *l) \
|
||||
{ \
|
||||
LTYPE *i = l->next; \
|
||||
LTYPE ## _del (i->next, i->prev); \
|
||||
return LTYPE ## _entry (i); \
|
||||
} \
|
||||
\
|
||||
static inline int \
|
||||
LTYPE ## _empty (LTYPE *l) \
|
||||
{ \
|
||||
return l == l->next; \
|
||||
} \
|
||||
\
|
||||
static inline ETYPE* \
|
||||
LTYPE ## _front (LTYPE *f) \
|
||||
{ \
|
||||
return LTYPE ## _entry (f->next); \
|
||||
} \
|
||||
\
|
||||
static inline ETYPE* \
|
||||
LTYPE ## _back (LTYPE *f) \
|
||||
{ \
|
||||
return LTYPE ## _entry (f->prev); \
|
||||
} \
|
||||
\
|
||||
static inline int \
|
||||
LTYPE ## _end (LTYPE *f, ETYPE *i) \
|
||||
{ \
|
||||
return f == & i->LNAME; \
|
||||
} \
|
||||
\
|
||||
static inline ETYPE* \
|
||||
LTYPE ## _next (ETYPE *f) \
|
||||
{ \
|
||||
return LTYPE ## _entry (f->LNAME.next); \
|
||||
} \
|
||||
\
|
||||
static inline usize_t \
|
||||
LTYPE ## _length (LTYPE *l) \
|
||||
{ \
|
||||
LTYPE *p; \
|
||||
int c = 0; \
|
||||
\
|
||||
for (p = l->next; p != l; p = p->next) \
|
||||
{ \
|
||||
c += 1; \
|
||||
} \
|
||||
\
|
||||
return c; \
|
||||
} \
|
||||
\
|
||||
typedef int unused_ ## LTYPE
|
||||
|
||||
#endif
|
||||
196
3rdparty/xdelta3-3.0.8/xdelta3-lzma.h
vendored
Normal file
196
3rdparty/xdelta3-3.0.8/xdelta3-lzma.h
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
/* xdelta 3 - delta compression tools and library
|
||||
* Copyright (C) 2012, 2013. Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Note: The use of the _easy_ decoder means we're not calling the
|
||||
* xd3_stream malloc hooks. TODO(jmacd) Fix if anyone cares. */
|
||||
|
||||
#ifndef _XDELTA3_LZMA_H_
|
||||
#define _XDELTA3_LZMA_H_
|
||||
|
||||
#include <lzma.h>
|
||||
|
||||
typedef struct _xd3_lzma_stream xd3_lzma_stream;
|
||||
|
||||
struct _xd3_lzma_stream {
|
||||
lzma_stream lzma;
|
||||
lzma_options_lzma options;
|
||||
lzma_filter filters[2];
|
||||
};
|
||||
|
||||
xd3_sec_stream*
|
||||
xd3_lzma_alloc (xd3_stream *stream)
|
||||
{
|
||||
return (xd3_sec_stream*) xd3_alloc (stream, sizeof (xd3_lzma_stream), 1);
|
||||
}
|
||||
|
||||
void
|
||||
xd3_lzma_destroy (xd3_stream *stream, xd3_sec_stream *sec_stream)
|
||||
{
|
||||
xd3_lzma_stream *ls = (xd3_lzma_stream*) sec_stream;
|
||||
lzma_end (&ls->lzma);
|
||||
xd3_free (stream, ls);
|
||||
}
|
||||
|
||||
int
|
||||
xd3_lzma_init (xd3_stream *stream, xd3_lzma_stream *sec, int is_encode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset (&sec->lzma, 0, sizeof(sec->lzma));
|
||||
|
||||
if (is_encode)
|
||||
{
|
||||
int preset = (stream->flags & XD3_COMPLEVEL_MASK) >> XD3_COMPLEVEL_SHIFT;
|
||||
|
||||
if (lzma_lzma_preset(&sec->options, preset))
|
||||
{
|
||||
stream->msg = "invalid lzma preset";
|
||||
return XD3_INVALID;
|
||||
}
|
||||
|
||||
sec->filters[0].id = LZMA_FILTER_LZMA2;
|
||||
sec->filters[0].options = &sec->options;
|
||||
sec->filters[1].id = LZMA_VLI_UNKNOWN;
|
||||
|
||||
ret = lzma_stream_encoder (&sec->lzma, &sec->filters[0], LZMA_CHECK_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = lzma_stream_decoder (&sec->lzma, UINT64_MAX, LZMA_TELL_NO_CHECK);
|
||||
}
|
||||
|
||||
if (ret != LZMA_OK)
|
||||
{
|
||||
stream->msg = "lzma stream init failed";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xd3_decode_lzma (xd3_stream *stream, xd3_lzma_stream *sec,
|
||||
const uint8_t **input_pos,
|
||||
const uint8_t *const input_end,
|
||||
uint8_t **output_pos,
|
||||
const uint8_t *const output_end)
|
||||
{
|
||||
uint8_t *output = *output_pos;
|
||||
const uint8_t *input = *input_pos;
|
||||
size_t avail_in = input_end - input;
|
||||
size_t avail_out = output_end - output;
|
||||
|
||||
sec->lzma.avail_in = avail_in;
|
||||
sec->lzma.next_in = input;
|
||||
sec->lzma.avail_out = avail_out;
|
||||
sec->lzma.next_out = output;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int lret = lzma_code (&sec->lzma, LZMA_RUN);
|
||||
|
||||
switch (lret)
|
||||
{
|
||||
case LZMA_NO_CHECK:
|
||||
case LZMA_OK:
|
||||
if (sec->lzma.avail_out == 0)
|
||||
{
|
||||
(*output_pos) = sec->lzma.next_out;
|
||||
(*input_pos) = sec->lzma.next_in;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
stream->msg = "lzma decoding error";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if XD3_ENCODER
|
||||
|
||||
int xd3_encode_lzma (xd3_stream *stream,
|
||||
xd3_lzma_stream *sec,
|
||||
xd3_output *input,
|
||||
xd3_output *output,
|
||||
xd3_sec_cfg *cfg)
|
||||
|
||||
{
|
||||
lzma_action action = LZMA_RUN;
|
||||
|
||||
cfg->inefficient = 1; /* Can't skip windows */
|
||||
sec->lzma.next_in = NULL;
|
||||
sec->lzma.avail_in = 0;
|
||||
sec->lzma.next_out = (output->base + output->next);
|
||||
sec->lzma.avail_out = (output->avail - output->next);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int lret;
|
||||
size_t nwrite;
|
||||
if (sec->lzma.avail_in == 0 && input != NULL)
|
||||
{
|
||||
sec->lzma.avail_in = input->next;
|
||||
sec->lzma.next_in = input->base;
|
||||
|
||||
if ((input = input->next_page) == NULL)
|
||||
{
|
||||
action = LZMA_SYNC_FLUSH;
|
||||
}
|
||||
}
|
||||
|
||||
lret = lzma_code (&sec->lzma, action);
|
||||
|
||||
nwrite = (output->avail - output->next) - sec->lzma.avail_out;
|
||||
|
||||
if (nwrite != 0)
|
||||
{
|
||||
output->next += nwrite;
|
||||
|
||||
if (output->next == output->avail)
|
||||
{
|
||||
if ((output = xd3_alloc_output (stream, output)) == NULL)
|
||||
{
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
sec->lzma.next_out = output->base;
|
||||
sec->lzma.avail_out = output->avail;
|
||||
}
|
||||
}
|
||||
|
||||
switch (lret)
|
||||
{
|
||||
case LZMA_OK:
|
||||
break;
|
||||
|
||||
case LZMA_STREAM_END:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
stream->msg = "lzma encoding error";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* XD3_ENCODER */
|
||||
|
||||
#endif /* _XDELTA3_LZMA_H_ */
|
||||
4048
3rdparty/xdelta3-3.0.8/xdelta3-main.h
vendored
Normal file
4048
3rdparty/xdelta3-3.0.8/xdelta3-main.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
579
3rdparty/xdelta3-3.0.8/xdelta3-merge.h
vendored
Normal file
579
3rdparty/xdelta3-3.0.8/xdelta3-merge.h
vendored
Normal file
@@ -0,0 +1,579 @@
|
||||
/* xdelta 3 - delta compression tools and library
|
||||
* Copyright (C) 2007. Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _XDELTA3_MERGE_H_
|
||||
#define _XDELTA3_MERGE_H_
|
||||
|
||||
int xd3_merge_inputs (xd3_stream *stream,
|
||||
xd3_whole_state *source,
|
||||
xd3_whole_state *input);
|
||||
|
||||
static int
|
||||
xd3_whole_state_init (xd3_stream *stream)
|
||||
{
|
||||
XD3_ASSERT (stream->whole_target.adds == NULL);
|
||||
XD3_ASSERT (stream->whole_target.inst == NULL);
|
||||
XD3_ASSERT (stream->whole_target.wininfo == NULL);
|
||||
XD3_ASSERT (stream->whole_target.length == 0);
|
||||
|
||||
stream->whole_target.adds_alloc = XD3_ALLOCSIZE;
|
||||
stream->whole_target.inst_alloc = XD3_ALLOCSIZE;
|
||||
stream->whole_target.wininfo_alloc = XD3_ALLOCSIZE;
|
||||
|
||||
if ((stream->whole_target.adds = (uint8_t*)
|
||||
xd3_alloc (stream, stream->whole_target.adds_alloc, 1)) == NULL ||
|
||||
(stream->whole_target.inst = (xd3_winst*)
|
||||
xd3_alloc (stream, stream->whole_target.inst_alloc, 1)) == NULL ||
|
||||
(stream->whole_target.wininfo = (xd3_wininfo*)
|
||||
xd3_alloc (stream, stream->whole_target.wininfo_alloc, 1)) == NULL)
|
||||
{
|
||||
return ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
xd3_swap_whole_state (xd3_whole_state *a,
|
||||
xd3_whole_state *b)
|
||||
{
|
||||
xd3_whole_state tmp;
|
||||
XD3_ASSERT (a->inst != NULL && a->adds != NULL);
|
||||
XD3_ASSERT (b->inst != NULL && b->adds != NULL);
|
||||
XD3_ASSERT (b->wininfo != NULL && b->wininfo != NULL);
|
||||
memcpy (&tmp, a, sizeof (xd3_whole_state));
|
||||
memcpy (a, b, sizeof (xd3_whole_state));
|
||||
memcpy (b, &tmp, sizeof (xd3_whole_state));
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_realloc_buffer (xd3_stream *stream,
|
||||
usize_t current_units,
|
||||
usize_t unit_size,
|
||||
usize_t new_units,
|
||||
usize_t *alloc_size,
|
||||
void **alloc_ptr)
|
||||
{
|
||||
usize_t needed;
|
||||
usize_t new_alloc;
|
||||
usize_t cur_size;
|
||||
uint8_t *new_buf;
|
||||
|
||||
needed = (current_units + new_units) * unit_size;
|
||||
|
||||
if (needed <= *alloc_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur_size = current_units * unit_size;
|
||||
new_alloc = xd3_round_blksize (needed * 2, XD3_ALLOCSIZE);
|
||||
|
||||
if ((new_buf = (uint8_t*) xd3_alloc (stream, new_alloc, 1)) == NULL)
|
||||
{
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (cur_size != 0)
|
||||
{
|
||||
memcpy (new_buf, *alloc_ptr, cur_size);
|
||||
}
|
||||
|
||||
if (*alloc_ptr != NULL)
|
||||
{
|
||||
xd3_free (stream, *alloc_ptr);
|
||||
}
|
||||
|
||||
*alloc_size = new_alloc;
|
||||
*alloc_ptr = new_buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* allocate one new output instruction */
|
||||
static int
|
||||
xd3_whole_alloc_winst (xd3_stream *stream,
|
||||
xd3_winst **winstp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = xd3_realloc_buffer (stream,
|
||||
stream->whole_target.instlen,
|
||||
sizeof (xd3_winst),
|
||||
1,
|
||||
& stream->whole_target.inst_alloc,
|
||||
(void**) & stream->whole_target.inst)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
*winstp = &stream->whole_target.inst[stream->whole_target.instlen++];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_whole_alloc_adds (xd3_stream *stream,
|
||||
usize_t count)
|
||||
{
|
||||
return xd3_realloc_buffer (stream,
|
||||
stream->whole_target.addslen,
|
||||
1,
|
||||
count,
|
||||
& stream->whole_target.adds_alloc,
|
||||
(void**) & stream->whole_target.adds);
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_whole_alloc_wininfo (xd3_stream *stream,
|
||||
xd3_wininfo **wininfop)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = xd3_realloc_buffer (stream,
|
||||
stream->whole_target.wininfolen,
|
||||
sizeof (xd3_wininfo),
|
||||
1,
|
||||
& stream->whole_target.wininfo_alloc,
|
||||
(void**) & stream->whole_target.wininfo)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
*wininfop = &stream->whole_target.wininfo[stream->whole_target.wininfolen++];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_whole_append_inst (xd3_stream *stream,
|
||||
xd3_hinst *inst)
|
||||
{
|
||||
int ret;
|
||||
xd3_winst *winst;
|
||||
|
||||
if ((ret = xd3_whole_alloc_winst (stream, &winst)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
winst->type = inst->type;
|
||||
winst->mode = 0;
|
||||
winst->size = inst->size;
|
||||
winst->position = stream->whole_target.length;
|
||||
stream->whole_target.length += inst->size;
|
||||
|
||||
if (((inst->type == XD3_ADD) || (inst->type == XD3_RUN)) &&
|
||||
(ret = xd3_whole_alloc_adds (stream,
|
||||
(inst->type == XD3_RUN ? 1 : inst->size))))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (inst->type)
|
||||
{
|
||||
case XD3_RUN:
|
||||
winst->addr = stream->whole_target.addslen;
|
||||
stream->whole_target.adds[stream->whole_target.addslen++] =
|
||||
*stream->data_sect.buf++;
|
||||
break;
|
||||
|
||||
case XD3_ADD:
|
||||
winst->addr = stream->whole_target.addslen;
|
||||
memcpy (stream->whole_target.adds + stream->whole_target.addslen,
|
||||
stream->data_sect.buf,
|
||||
inst->size);
|
||||
stream->data_sect.buf += inst->size;
|
||||
stream->whole_target.addslen += inst->size;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (inst->addr < stream->dec_cpylen)
|
||||
{
|
||||
winst->mode = SRCORTGT (stream->dec_win_ind);
|
||||
winst->addr = stream->dec_cpyoff + inst->addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
winst->addr = (stream->dec_winstart +
|
||||
inst->addr -
|
||||
stream->dec_cpylen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xd3_whole_append_window (xd3_stream *stream)
|
||||
{
|
||||
int ret;
|
||||
xd3_wininfo *wininfo;
|
||||
|
||||
if ((ret = xd3_whole_alloc_wininfo (stream, &wininfo))) { return ret; }
|
||||
|
||||
wininfo->length = stream->dec_tgtlen;
|
||||
wininfo->offset = stream->dec_winstart;
|
||||
wininfo->adler32 = stream->dec_adler32;
|
||||
|
||||
while (stream->inst_sect.buf < stream->inst_sect.buf_max)
|
||||
{
|
||||
if ((ret = xd3_decode_instruction (stream)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((stream->dec_current1.type != XD3_NOOP) &&
|
||||
(ret = xd3_whole_append_inst (stream,
|
||||
& stream->dec_current1)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((stream->dec_current2.type != XD3_NOOP) &&
|
||||
(ret = xd3_whole_append_inst (stream,
|
||||
& stream->dec_current2)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* xd3_merge_input_output applies *source to *stream, returns the
|
||||
* result in stream. */
|
||||
int xd3_merge_input_output (xd3_stream *stream,
|
||||
xd3_whole_state *source)
|
||||
{
|
||||
int ret;
|
||||
xd3_stream tmp_stream;
|
||||
memset (& tmp_stream, 0, sizeof (tmp_stream));
|
||||
if ((ret = xd3_config_stream (& tmp_stream, NULL)) ||
|
||||
(ret = xd3_whole_state_init (& tmp_stream)) ||
|
||||
(ret = xd3_merge_inputs (& tmp_stream,
|
||||
source,
|
||||
& stream->whole_target)))
|
||||
{
|
||||
XPR(NT XD3_LIB_ERRMSG (&tmp_stream, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* the output is in tmp_stream.whole_state, swap into input */
|
||||
xd3_swap_whole_state (& stream->whole_target,
|
||||
& tmp_stream.whole_target);
|
||||
/* total allocation counts are preserved */
|
||||
xd3_free_stream (& tmp_stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_merge_run (xd3_stream *stream,
|
||||
xd3_whole_state *target,
|
||||
xd3_winst *iinst)
|
||||
{
|
||||
int ret;
|
||||
xd3_winst *oinst;
|
||||
|
||||
if ((ret = xd3_whole_alloc_winst (stream, &oinst)) ||
|
||||
(ret = xd3_whole_alloc_adds (stream, 1)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
oinst->type = iinst->type;
|
||||
oinst->mode = iinst->mode;
|
||||
oinst->size = iinst->size;
|
||||
oinst->addr = stream->whole_target.addslen;
|
||||
|
||||
XD3_ASSERT (stream->whole_target.length == iinst->position);
|
||||
oinst->position = stream->whole_target.length;
|
||||
stream->whole_target.length += iinst->size;
|
||||
|
||||
stream->whole_target.adds[stream->whole_target.addslen++] =
|
||||
target->adds[iinst->addr];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_merge_add (xd3_stream *stream,
|
||||
xd3_whole_state *target,
|
||||
xd3_winst *iinst)
|
||||
{
|
||||
int ret;
|
||||
xd3_winst *oinst;
|
||||
|
||||
if ((ret = xd3_whole_alloc_winst (stream, &oinst)) ||
|
||||
(ret = xd3_whole_alloc_adds (stream, iinst->size)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
oinst->type = iinst->type;
|
||||
oinst->mode = iinst->mode;
|
||||
oinst->size = iinst->size;
|
||||
oinst->addr = stream->whole_target.addslen;
|
||||
|
||||
XD3_ASSERT (stream->whole_target.length == iinst->position);
|
||||
oinst->position = stream->whole_target.length;
|
||||
stream->whole_target.length += iinst->size;
|
||||
|
||||
memcpy(stream->whole_target.adds + stream->whole_target.addslen,
|
||||
target->adds + iinst->addr,
|
||||
iinst->size);
|
||||
|
||||
stream->whole_target.addslen += iinst->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_merge_target_copy (xd3_stream *stream,
|
||||
xd3_winst *iinst)
|
||||
{
|
||||
int ret;
|
||||
xd3_winst *oinst;
|
||||
|
||||
if ((ret = xd3_whole_alloc_winst (stream, &oinst)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
XD3_ASSERT (stream->whole_target.length == iinst->position);
|
||||
|
||||
memcpy (oinst, iinst, sizeof (*oinst));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_merge_find_position (xd3_stream *stream,
|
||||
xd3_whole_state *source,
|
||||
xoff_t address,
|
||||
usize_t *inst_num)
|
||||
{
|
||||
usize_t low;
|
||||
usize_t high;
|
||||
|
||||
if (address >= source->length)
|
||||
{
|
||||
stream->msg = "Invalid copy offset in merge";
|
||||
return XD3_INVALID_INPUT;
|
||||
}
|
||||
|
||||
low = 0;
|
||||
high = source->instlen;
|
||||
|
||||
while (low != high)
|
||||
{
|
||||
xoff_t mid_lpos;
|
||||
xoff_t mid_hpos;
|
||||
usize_t mid = low + (high - low) / 2;
|
||||
mid_lpos = source->inst[mid].position;
|
||||
|
||||
if (address < mid_lpos)
|
||||
{
|
||||
high = mid;
|
||||
continue;
|
||||
}
|
||||
|
||||
mid_hpos = mid_lpos + source->inst[mid].size;
|
||||
|
||||
if (address >= mid_hpos)
|
||||
{
|
||||
low = mid + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
*inst_num = mid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream->msg = "Internal error in merge";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_merge_source_copy (xd3_stream *stream,
|
||||
xd3_whole_state *source,
|
||||
const xd3_winst *iinst_orig)
|
||||
{
|
||||
int ret;
|
||||
xd3_winst iinst;
|
||||
usize_t sinst_num;
|
||||
|
||||
memcpy (& iinst, iinst_orig, sizeof (iinst));
|
||||
|
||||
XD3_ASSERT (iinst.mode == VCD_SOURCE);
|
||||
|
||||
if ((ret = xd3_merge_find_position (stream, source,
|
||||
iinst.addr, &sinst_num)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (iinst.size > 0)
|
||||
{
|
||||
xd3_winst *sinst;
|
||||
xd3_winst *minst;
|
||||
usize_t sinst_offset;
|
||||
usize_t sinst_left;
|
||||
usize_t this_take;
|
||||
|
||||
XD3_ASSERT (sinst_num < source->instlen);
|
||||
|
||||
sinst = &source->inst[sinst_num];
|
||||
|
||||
XD3_ASSERT (iinst.addr >= sinst->position);
|
||||
|
||||
sinst_offset = (usize_t)(iinst.addr - sinst->position);
|
||||
|
||||
XD3_ASSERT (sinst->size > sinst_offset);
|
||||
|
||||
sinst_left = sinst->size - sinst_offset;
|
||||
this_take = min (iinst.size, sinst_left);
|
||||
|
||||
XD3_ASSERT (this_take > 0);
|
||||
|
||||
if ((ret = xd3_whole_alloc_winst (stream, &minst)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
minst->size = this_take;
|
||||
minst->type = sinst->type;
|
||||
minst->position = iinst.position;
|
||||
minst->mode = 0;
|
||||
|
||||
switch (sinst->type)
|
||||
{
|
||||
case XD3_RUN:
|
||||
if ((ret = xd3_whole_alloc_adds (stream, 1)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
minst->addr = stream->whole_target.addslen;
|
||||
stream->whole_target.adds[stream->whole_target.addslen++] =
|
||||
source->adds[sinst->addr];
|
||||
break;
|
||||
case XD3_ADD:
|
||||
if ((ret = xd3_whole_alloc_adds (stream, this_take)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
minst->addr = stream->whole_target.addslen;
|
||||
memcpy(stream->whole_target.adds + stream->whole_target.addslen,
|
||||
source->adds + sinst->addr + sinst_offset,
|
||||
this_take);
|
||||
stream->whole_target.addslen += this_take;
|
||||
break;
|
||||
default:
|
||||
if (sinst->mode != 0)
|
||||
{
|
||||
minst->mode = sinst->mode;
|
||||
minst->addr = sinst->addr + sinst_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: this is slow because of the recursion, which
|
||||
// could reach a depth equal to the number of target
|
||||
// copies, and this is compression-inefficient because
|
||||
// it can produce duplicate adds.
|
||||
xd3_winst tinst;
|
||||
tinst.type = XD3_CPY;
|
||||
tinst.mode = iinst.mode;
|
||||
tinst.addr = sinst->addr + sinst_offset;
|
||||
tinst.size = this_take;
|
||||
tinst.position = iinst.position;
|
||||
|
||||
// The instruction allocated in this frame will not be used.
|
||||
stream->whole_target.instlen -= 1;
|
||||
|
||||
if ((ret = xd3_merge_source_copy (stream, source, &tinst)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
iinst.position += this_take;
|
||||
iinst.addr += this_take;
|
||||
iinst.size -= this_take;
|
||||
sinst_num += 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* xd3_merge_inputs() applies *input to *source, returns its result in
|
||||
* stream. */
|
||||
int xd3_merge_inputs (xd3_stream *stream,
|
||||
xd3_whole_state *source,
|
||||
xd3_whole_state *input)
|
||||
{
|
||||
int ret = 0;
|
||||
usize_t i;
|
||||
size_t input_i;
|
||||
|
||||
for (i = 0; i < input->wininfolen; ++i) {
|
||||
xd3_wininfo *copyinfo;
|
||||
|
||||
if ((ret = xd3_whole_alloc_wininfo (stream, ©info))) { return ret; }
|
||||
|
||||
*copyinfo = input->wininfo[i];
|
||||
}
|
||||
|
||||
/* iterate over each instruction. */
|
||||
for (input_i = 0; ret == 0 && input_i < input->instlen; ++input_i)
|
||||
{
|
||||
xd3_winst *iinst = &input->inst[input_i];
|
||||
|
||||
switch (iinst->type)
|
||||
{
|
||||
case XD3_RUN:
|
||||
ret = xd3_merge_run (stream, input, iinst);
|
||||
break;
|
||||
case XD3_ADD:
|
||||
ret = xd3_merge_add (stream, input, iinst);
|
||||
break;
|
||||
default:
|
||||
/* TODO: VCD_TARGET support is completely untested all
|
||||
* throughout. */
|
||||
if (iinst->mode == 0 || iinst->mode == VCD_TARGET)
|
||||
{
|
||||
ret = xd3_merge_target_copy (stream, iinst);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = xd3_merge_source_copy (stream, source, iinst);
|
||||
}
|
||||
|
||||
/* The whole_target.length is not updated in the xd3_merge*copy
|
||||
* routine because of recursion in xd3_merge_source_copy. */
|
||||
stream->whole_target.length += iinst->size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
315
3rdparty/xdelta3-3.0.8/xdelta3-second.h
vendored
Normal file
315
3rdparty/xdelta3-3.0.8/xdelta3-second.h
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
/* xdelta 3 - delta compression tools and library
|
||||
* Copyright (C) 2002, 2003, 2006, 2007, 2013. Joshua P. MacDonald
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _XDELTA3_SECOND_H_
|
||||
#define _XDELTA3_SECOND_H_
|
||||
|
||||
static inline void xd3_bit_state_encode_init (bit_state *bits)
|
||||
{
|
||||
bits->cur_byte = 0;
|
||||
bits->cur_mask = 1;
|
||||
}
|
||||
|
||||
static inline int xd3_decode_bits (xd3_stream *stream,
|
||||
bit_state *bits,
|
||||
const uint8_t **input,
|
||||
const uint8_t *input_max,
|
||||
usize_t nbits,
|
||||
usize_t *valuep)
|
||||
{
|
||||
usize_t value = 0;
|
||||
usize_t vmask = 1 << nbits;
|
||||
|
||||
if (bits->cur_mask == 0x100) { goto next_byte; }
|
||||
|
||||
for (;;)
|
||||
{
|
||||
do
|
||||
{
|
||||
vmask >>= 1;
|
||||
|
||||
if (bits->cur_byte & bits->cur_mask)
|
||||
{
|
||||
value |= vmask;
|
||||
}
|
||||
|
||||
bits->cur_mask <<= 1;
|
||||
|
||||
if (vmask == 1) { goto done; }
|
||||
}
|
||||
while (bits->cur_mask != 0x100);
|
||||
|
||||
next_byte:
|
||||
|
||||
if (*input == input_max)
|
||||
{
|
||||
stream->msg = "secondary decoder end of input";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
|
||||
bits->cur_byte = *(*input)++;
|
||||
bits->cur_mask = 1;
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
IF_DEBUG2 (DP(RINT "(d) %u ", value));
|
||||
|
||||
(*valuep) = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if REGRESSION_TEST
|
||||
/* There may be extra bits at the end of secondary decompression, this macro
|
||||
* checks for non-zero bits. This is overly strict, but helps pass the
|
||||
* single-bit-error regression test. */
|
||||
static int
|
||||
xd3_test_clean_bits (xd3_stream *stream, bit_state *bits)
|
||||
{
|
||||
for (; bits->cur_mask != 0x100; bits->cur_mask <<= 1)
|
||||
{
|
||||
if (bits->cur_byte & bits->cur_mask)
|
||||
{
|
||||
stream->msg = "secondary decoder garbage";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
xd3_get_secondary (xd3_stream *stream, xd3_sec_stream **sec_streamp,
|
||||
int is_encode)
|
||||
{
|
||||
if (*sec_streamp == NULL)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((*sec_streamp = stream->sec_type->alloc (stream)) == NULL)
|
||||
{
|
||||
stream->msg = "error initializing secondary stream";
|
||||
return XD3_INVALID;
|
||||
}
|
||||
|
||||
if ((ret = stream->sec_type->init (stream, *sec_streamp, is_encode)) != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_decode_secondary (xd3_stream *stream,
|
||||
xd3_desect *sect,
|
||||
xd3_sec_stream **sec_streamp)
|
||||
{
|
||||
uint32_t dec_size;
|
||||
uint8_t *out_used;
|
||||
int ret;
|
||||
|
||||
if ((ret = xd3_get_secondary (stream, sec_streamp, 0)) != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Decode the size, allocate the buffer. */
|
||||
if ((ret = xd3_read_size (stream, & sect->buf,
|
||||
sect->buf_max, & dec_size)) ||
|
||||
(ret = xd3_decode_allocate (stream, dec_size,
|
||||
& sect->copied2, & sect->alloc2)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
out_used = sect->copied2;
|
||||
|
||||
if ((ret = stream->sec_type->decode (stream, *sec_streamp,
|
||||
& sect->buf, sect->buf_max,
|
||||
& out_used, out_used + dec_size)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sect->buf != sect->buf_max)
|
||||
{
|
||||
stream->msg = "secondary decoder finished with unused input";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
|
||||
if (out_used != sect->copied2 + dec_size)
|
||||
{
|
||||
stream->msg = "secondary decoder short output";
|
||||
return XD3_INTERNAL;
|
||||
}
|
||||
|
||||
sect->buf = sect->copied2;
|
||||
sect->buf_max = sect->copied2 + dec_size;
|
||||
sect->size = dec_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if XD3_ENCODER
|
||||
static inline int xd3_encode_bit (xd3_stream *stream,
|
||||
xd3_output **output,
|
||||
bit_state *bits,
|
||||
usize_t bit)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bit)
|
||||
{
|
||||
bits->cur_byte |= bits->cur_mask;
|
||||
}
|
||||
|
||||
/* OPT: Might help to buffer more than 8 bits at once. */
|
||||
if (bits->cur_mask == 0x80)
|
||||
{
|
||||
if ((ret = xd3_emit_byte (stream, output, bits->cur_byte)) != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
bits->cur_mask = 1;
|
||||
bits->cur_byte = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bits->cur_mask <<= 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int xd3_flush_bits (xd3_stream *stream,
|
||||
xd3_output **output,
|
||||
bit_state *bits)
|
||||
{
|
||||
return (bits->cur_mask == 1) ? 0 :
|
||||
xd3_emit_byte (stream, output, bits->cur_byte);
|
||||
}
|
||||
|
||||
static inline int xd3_encode_bits (xd3_stream *stream,
|
||||
xd3_output **output,
|
||||
bit_state *bits,
|
||||
usize_t nbits,
|
||||
usize_t value)
|
||||
{
|
||||
int ret;
|
||||
usize_t mask = 1 << nbits;
|
||||
|
||||
XD3_ASSERT (nbits > 0);
|
||||
XD3_ASSERT (nbits < sizeof (usize_t) * 8);
|
||||
XD3_ASSERT (value < mask);
|
||||
|
||||
do
|
||||
{
|
||||
mask >>= 1;
|
||||
|
||||
if ((ret = xd3_encode_bit (stream, output, bits, value & mask)))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
while (mask != 1);
|
||||
|
||||
IF_DEBUG2 (DP(RINT "(e) %u ", value));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xd3_encode_secondary (xd3_stream *stream,
|
||||
xd3_output **head,
|
||||
xd3_output **tail,
|
||||
xd3_sec_stream **sec_streamp,
|
||||
xd3_sec_cfg *cfg,
|
||||
int *did_it)
|
||||
{
|
||||
xd3_output *tmp_head;
|
||||
xd3_output *tmp_tail;
|
||||
|
||||
usize_t comp_size;
|
||||
usize_t orig_size;
|
||||
|
||||
int ret;
|
||||
|
||||
orig_size = xd3_sizeof_output (*head);
|
||||
|
||||
if (orig_size < SECONDARY_MIN_INPUT) { return 0; }
|
||||
|
||||
if ((ret = xd3_get_secondary (stream, sec_streamp, 1)) != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
tmp_head = xd3_alloc_output (stream, NULL);
|
||||
|
||||
/* Encode the size, encode the data. Encoding the size makes it
|
||||
* simpler, but is a little gross. Should not need the entire
|
||||
* section in contiguous memory, but it is much easier this way. */
|
||||
if ((ret = xd3_emit_size (stream, & tmp_head, orig_size)) ||
|
||||
(ret = stream->sec_type->encode (stream, *sec_streamp, *head,
|
||||
tmp_head, cfg)))
|
||||
{
|
||||
goto getout;
|
||||
}
|
||||
|
||||
/* If the secondary compressor determines it's no good, it returns
|
||||
* XD3_NOSECOND. */
|
||||
|
||||
/* Setup tmp_tail, comp_size */
|
||||
tmp_tail = tmp_head;
|
||||
comp_size = tmp_head->next;
|
||||
|
||||
while (tmp_tail->next_page != NULL)
|
||||
{
|
||||
tmp_tail = tmp_tail->next_page;
|
||||
comp_size += tmp_tail->next;
|
||||
}
|
||||
|
||||
XD3_ASSERT (comp_size == xd3_sizeof_output (tmp_head));
|
||||
XD3_ASSERT (tmp_tail != NULL);
|
||||
|
||||
if (comp_size < (orig_size - SECONDARY_MIN_SAVINGS) || cfg->inefficient)
|
||||
{
|
||||
IF_DEBUG1(DP(RINT "secondary saved %u bytes: %u -> %u (%0.2f%%)\n",
|
||||
orig_size - comp_size, orig_size, comp_size,
|
||||
100.0 * (double) comp_size / (double) orig_size));
|
||||
|
||||
xd3_free_output (stream, *head);
|
||||
|
||||
*head = tmp_head;
|
||||
*tail = tmp_tail;
|
||||
*did_it = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
getout:
|
||||
if (ret == XD3_NOSECOND) { ret = 0; }
|
||||
xd3_free_output (stream, tmp_head);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* XD3_ENCODER */
|
||||
#endif /* _XDELTA3_SECOND_H_ */
|
||||
2872
3rdparty/xdelta3-3.0.8/xdelta3-test.h
vendored
Normal file
2872
3rdparty/xdelta3-3.0.8/xdelta3-test.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5497
3rdparty/xdelta3-3.0.8/xdelta3.c
vendored
Normal file
5497
3rdparty/xdelta3-3.0.8/xdelta3.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1373
3rdparty/xdelta3-3.0.8/xdelta3.h
vendored
Normal file
1373
3rdparty/xdelta3-3.0.8/xdelta3.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user