diff options
author | josh.macdonald <jmacd@users.noreply.github.com> | 2010-02-07 03:00:42 +0000 |
---|---|---|
committer | josh.macdonald <jmacd@users.noreply.github.com> | 2010-02-07 03:00:42 +0000 |
commit | 3dbebbe46096e17c0298f1cbe315d10b35b4f9ee (patch) | |
tree | c2ae665c490d2a4e4cd4365721f4cf807fa1e44b /xdelta3 | |
parent | e7a0eda2519593950a1a0dff77e42d4da9189c3e (diff) |
Implement srcwin_maxsz in xd3_source_match_setup(), which prevents
the encoder from seeking backwards further than this parameter. This
was supposed to be implemented long ago, but was especially problematic
in the recent release, which implements source-from-FIFO.
Diffstat (limited to 'xdelta3')
-rwxr-xr-x | xdelta3/testing/Makefile | 5 | ||||
-rw-r--r-- | xdelta3/testing/file.h | 28 | ||||
-rw-r--r-- | xdelta3/testing/modify.h | 107 | ||||
-rw-r--r-- | xdelta3/testing/regtest.cc | 128 | ||||
-rw-r--r-- | xdelta3/testing/segment.h | 10 | ||||
-rw-r--r-- | xdelta3/xdelta3-main.h | 111 | ||||
-rw-r--r-- | xdelta3/xdelta3.c | 164 | ||||
-rw-r--r-- | xdelta3/xdelta3.h | 20 |
8 files changed, 346 insertions, 227 deletions
diff --git a/xdelta3/testing/Makefile b/xdelta3/testing/Makefile index 2cfeee3..c1621f2 100755 --- a/xdelta3/testing/Makefile +++ b/xdelta3/testing/Makefile | |||
@@ -1,11 +1,10 @@ | |||
1 | CFLAGS = -O2 -Wall -Wconversion -Wsign-compare -Wextra -Wno-unused-parameter -I.. \ | 1 | CFLAGS = -g -Wall -Wconversion -Wsign-compare -Wextra \ |
2 | -Wno-unused-parameter -I.. \ | ||
2 | -DGENERIC_ENCODE_TABLES=1 \ | 3 | -DGENERIC_ENCODE_TABLES=1 \ |
3 | -DSECONDARY_DJW=1 \ | 4 | -DSECONDARY_DJW=1 \ |
4 | -DSECONDARY_FGK=1 \ | 5 | -DSECONDARY_FGK=1 \ |
5 | -DXD3_USE_LARGEFILE64=1 | 6 | -DXD3_USE_LARGEFILE64=1 |
6 | 7 | ||
7 | #CFLAGS = -O2 -Wall -I.. -DXD3_DEBUG=1 -DNDEBUG=1 | ||
8 | |||
9 | DEPS = ../*.h ../*.c *.cc *.h | 8 | DEPS = ../*.h ../*.c *.cc *.h |
10 | 9 | ||
11 | TARGETS = xdelta3-regtest xdelta3-regtest2 | 10 | TARGETS = xdelta3-regtest xdelta3-regtest2 |
diff --git a/xdelta3/testing/file.h b/xdelta3/testing/file.h index 9bfbf4c..b46717f 100644 --- a/xdelta3/testing/file.h +++ b/xdelta3/testing/file.h | |||
@@ -7,7 +7,7 @@ class Block { | |||
7 | public: | 7 | public: |
8 | Block() | 8 | Block() |
9 | : data_(NULL), | 9 | : data_(NULL), |
10 | data_size_(0), | 10 | data_size_(0), |
11 | size_(0) { } | 11 | size_(0) { } |
12 | 12 | ||
13 | ~Block() { | 13 | ~Block() { |
@@ -15,7 +15,7 @@ public: | |||
15 | delete [] data_; | 15 | delete [] data_; |
16 | } | 16 | } |
17 | } | 17 | } |
18 | 18 | ||
19 | size_t Size() const { | 19 | size_t Size() const { |
20 | return size_; | 20 | return size_; |
21 | } | 21 | } |
@@ -27,7 +27,7 @@ public: | |||
27 | 27 | ||
28 | uint8_t* Data() const { | 28 | uint8_t* Data() const { |
29 | if (data_ == NULL) { | 29 | if (data_ == NULL) { |
30 | CHECK_EQ(0, size_); | 30 | CHECK_EQ(0, size_); |
31 | data_size_ = 1; | 31 | data_size_ = 1; |
32 | data_ = new uint8_t[1]; | 32 | data_ = new uint8_t[1]; |
33 | } | 33 | } |
@@ -42,9 +42,9 @@ public: | |||
42 | data_ = new uint8_t[Constants::BLOCK_SIZE]; | 42 | data_ = new uint8_t[Constants::BLOCK_SIZE]; |
43 | data_size_ = Constants::BLOCK_SIZE; | 43 | data_size_ = Constants::BLOCK_SIZE; |
44 | } | 44 | } |
45 | 45 | ||
46 | if (size_ + size > data_size_) { | 46 | if (size_ + size > data_size_) { |
47 | uint8_t *tmp = data_; | 47 | uint8_t *tmp = data_; |
48 | while (size_ + size > data_size_) { | 48 | while (size_ + size > data_size_) { |
49 | data_size_ *= 2; | 49 | data_size_ *= 2; |
50 | } | 50 | } |
@@ -109,7 +109,7 @@ class FileSpec { | |||
109 | // Generates a file with a known size | 109 | // Generates a file with a known size |
110 | void GenerateFixedSize(xoff_t size) { | 110 | void GenerateFixedSize(xoff_t size) { |
111 | Reset(); | 111 | Reset(); |
112 | 112 | ||
113 | for (xoff_t p = 0; p < size; ) { | 113 | for (xoff_t p = 0; p < size; ) { |
114 | xoff_t t = min(Constants::BLOCK_SIZE, size - p); | 114 | xoff_t t = min(Constants::BLOCK_SIZE, size - p); |
115 | table_.insert(make_pair(p, Segment(t, rand_))); | 115 | table_.insert(make_pair(p, Segment(t, rand_))); |
@@ -172,7 +172,8 @@ class FileSpec { | |||
172 | iter != table_.end(); | 172 | iter != table_.end(); |
173 | ++iter) { | 173 | ++iter) { |
174 | const Segment &seg = iter->second; | 174 | const Segment &seg = iter->second; |
175 | cerr << "Segment at " << iter->first << " (" << seg.ToString() << ")" << endl; | 175 | cerr << "Segment at " << iter->first |
176 | << " (" << seg.ToString() << ")" << endl; | ||
176 | } | 177 | } |
177 | } | 178 | } |
178 | 179 | ||
@@ -210,7 +211,7 @@ class FileSpec { | |||
210 | const Segment &seg = pos->second; | 211 | const Segment &seg = pos->second; |
211 | 212 | ||
212 | // The position of this segment may start before this block starts, | 213 | // The position of this segment may start before this block starts, |
213 | // and then the position of the data may be offset from the seeding | 214 | // and then the position of the data may be offset from the seeding |
214 | // position. | 215 | // position. |
215 | size_t seg_offset = offset - pos->first; | 216 | size_t seg_offset = offset - pos->first; |
216 | size_t advance = min(seg.Size() - seg_offset, | 217 | size_t advance = min(seg.Size() - seg_offset, |
@@ -330,10 +331,12 @@ public: | |||
330 | iter.Get(&sblock); | 331 | iter.Get(&sblock); |
331 | tblock.SetSize(sblock.Size()); | 332 | tblock.SetSize(sblock.Size()); |
332 | usize_t tread; | 333 | usize_t tread; |
333 | CHECK_EQ(0, main_file_read(&t, tblock.Data(), tblock.Size(), &tread, "read failed")); | 334 | CHECK_EQ(0, main_file_read(&t, |
335 | tblock.Data(), | ||
336 | tblock.Size(), &tread, "read failed")); | ||
334 | CHECK_EQ(0, CmpDifferentBlockBytes(tblock, sblock)); | 337 | CHECK_EQ(0, CmpDifferentBlockBytes(tblock, sblock)); |
335 | } | 338 | } |
336 | 339 | ||
337 | CHECK_EQ(0, main_file_close(&t)); | 340 | CHECK_EQ(0, main_file_close(&t)); |
338 | main_file_cleanup(&t); | 341 | main_file_cleanup(&t); |
339 | return true; | 342 | return true; |
@@ -345,7 +348,6 @@ protected: | |||
345 | 348 | ||
346 | class TmpFile : public ExtFile { | 349 | class TmpFile : public ExtFile { |
347 | public: | 350 | public: |
348 | // TODO this is a little unportable! | ||
349 | TmpFile() { | 351 | TmpFile() { |
350 | main_file_init(&file_); | 352 | main_file_init(&file_); |
351 | CHECK_EQ(0, main_file_open(&file_, Name(), XO_WRITE)); | 353 | CHECK_EQ(0, main_file_open(&file_, Name(), XO_WRITE)); |
@@ -356,8 +358,8 @@ public: | |||
356 | } | 358 | } |
357 | 359 | ||
358 | void Append(const Block *block) { | 360 | void Append(const Block *block) { |
359 | CHECK_EQ(0, main_file_write(&file_, | 361 | CHECK_EQ(0, main_file_write(&file_, |
360 | block->Data(), block->Size(), | 362 | block->Data(), block->Size(), |
361 | "tmpfile write failed")); | 363 | "tmpfile write failed")); |
362 | } | 364 | } |
363 | 365 | ||
diff --git a/xdelta3/testing/modify.h b/xdelta3/testing/modify.h index 7f27992..4a6edd3 100644 --- a/xdelta3/testing/modify.h +++ b/xdelta3/testing/modify.h | |||
@@ -2,20 +2,23 @@ | |||
2 | class Mutator { | 2 | class Mutator { |
3 | public: | 3 | public: |
4 | virtual ~Mutator() { } | 4 | virtual ~Mutator() { } |
5 | virtual void Mutate(SegmentMap *table, | 5 | virtual void Mutate(SegmentMap *table, |
6 | const SegmentMap *source_table, | 6 | const SegmentMap *source_table, |
7 | MTRandom *rand) const = 0; | 7 | MTRandom *rand) const = 0; |
8 | }; | 8 | }; |
9 | 9 | ||
10 | class Change { | 10 | class Change { |
11 | public: | 11 | public: |
12 | enum Kind { | 12 | enum Kind { |
13 | MODIFY = 1, | 13 | MODIFY = 1, // Mutate a certain range w/ random or supplied data |
14 | ADD = 2, | 14 | ADD = 2, // Insert random or supplied data |
15 | DELETE = 3, | 15 | DELETE = 3, // Delete a specified range of data |
16 | MOVE = 4, | 16 | COPY = 4, // Copy from one region, inserting elsewhere |
17 | COPY = 5, | 17 | MOVE = 5, // Copy then delete copied-from range |
18 | OVERWRITE = 6, | 18 | OVERWRITE = 6, // Copy then delete copied-to range |
19 | |||
20 | // ADD, DELETE, and COPY change the file size | ||
21 | // MODIFY, MOVE, OVERWRITE preserve the file size | ||
19 | }; | 22 | }; |
20 | 23 | ||
21 | // Constructor for modify, add, delete. | 24 | // Constructor for modify, add, delete. |
@@ -24,7 +27,7 @@ public: | |||
24 | size(size), | 27 | size(size), |
25 | addr1(addr1), | 28 | addr1(addr1), |
26 | addr2(0), | 29 | addr2(0), |
27 | insert(NULL) { | 30 | insert(NULL) { |
28 | CHECK(kind != MOVE && kind != COPY && kind != OVERWRITE); | 31 | CHECK(kind != MOVE && kind != COPY && kind != OVERWRITE); |
29 | } | 32 | } |
30 | 33 | ||
@@ -34,17 +37,17 @@ public: | |||
34 | size(size), | 37 | size(size), |
35 | addr1(addr1), | 38 | addr1(addr1), |
36 | addr2(0), | 39 | addr2(0), |
37 | insert(insert) { | 40 | insert(insert) { |
38 | CHECK(kind != MOVE && kind != COPY && kind != OVERWRITE); | 41 | CHECK(kind != MOVE && kind != COPY && kind != OVERWRITE); |
39 | } | 42 | } |
40 | 43 | ||
41 | // Constructor for move | 44 | // Constructor for move, copy, overwrite |
42 | Change(Kind kind, xoff_t size, xoff_t addr1, xoff_t addr2) | 45 | Change(Kind kind, xoff_t size, xoff_t addr1, xoff_t addr2) |
43 | : kind(kind), | 46 | : kind(kind), |
44 | size(size), | 47 | size(size), |
45 | addr1(addr1), | 48 | addr1(addr1), |
46 | addr2(addr2), | 49 | addr2(addr2), |
47 | insert(NULL) { | 50 | insert(NULL) { |
48 | CHECK(kind == MOVE || kind == COPY || kind == OVERWRITE); | 51 | CHECK(kind == MOVE || kind == COPY || kind == OVERWRITE); |
49 | } | 52 | } |
50 | 53 | ||
@@ -72,8 +75,9 @@ public: | |||
72 | // The speed of processing gigabytes of data is so slow compared with | 75 | // The speed of processing gigabytes of data is so slow compared with |
73 | // these table-copy operations, no attempt to make this fast. | 76 | // these table-copy operations, no attempt to make this fast. |
74 | SegmentMap tmp; | 77 | SegmentMap tmp; |
75 | 78 | ||
76 | for (ConstChangeListIterator iter(cl_.begin()); iter != cl_.end(); ++iter) { | 79 | for (ConstChangeListIterator iter(cl_.begin()); |
80 | iter != cl_.end(); ++iter) { | ||
77 | const Change &ch = *iter; | 81 | const Change &ch = *iter; |
78 | tmp.clear(); | 82 | tmp.clear(); |
79 | Mutate(ch, &tmp, source_table, rand); | 83 | Mutate(ch, &tmp, source_table, rand); |
@@ -81,8 +85,8 @@ public: | |||
81 | source_table = table; | 85 | source_table = table; |
82 | } | 86 | } |
83 | } | 87 | } |
84 | 88 | ||
85 | static void Mutate(const Change &ch, | 89 | static void Mutate(const Change &ch, |
86 | SegmentMap *table, | 90 | SegmentMap *table, |
87 | const SegmentMap *source_table, | 91 | const SegmentMap *source_table, |
88 | MTRandom *rand) { | 92 | MTRandom *rand) { |
@@ -108,7 +112,7 @@ public: | |||
108 | } | 112 | } |
109 | } | 113 | } |
110 | 114 | ||
111 | static void ModifyChange(const Change &ch, | 115 | static void ModifyChange(const Change &ch, |
112 | SegmentMap *table, | 116 | SegmentMap *table, |
113 | const SegmentMap *source_table, | 117 | const SegmentMap *source_table, |
114 | MTRandom *rand) { | 118 | MTRandom *rand) { |
@@ -117,7 +121,7 @@ public: | |||
117 | xoff_t i_start = 0; | 121 | xoff_t i_start = 0; |
118 | xoff_t i_end = 0; | 122 | xoff_t i_end = 0; |
119 | 123 | ||
120 | for (ConstSegmentMapIterator iter(source_table->begin()); | 124 | for (ConstSegmentMapIterator iter(source_table->begin()); |
121 | iter != source_table->end(); | 125 | iter != source_table->end(); |
122 | ++iter) { | 126 | ++iter) { |
123 | const Segment &seg = iter->second; | 127 | const Segment &seg = iter->second; |
@@ -130,8 +134,8 @@ public: | |||
130 | } | 134 | } |
131 | 135 | ||
132 | if (i_start < m_start) { | 136 | if (i_start < m_start) { |
133 | table->insert(table->end(), | 137 | table->insert(table->end(), |
134 | make_pair(i_start, | 138 | make_pair(i_start, |
135 | seg.Subseg(0, m_start - i_start))); | 139 | seg.Subseg(0, m_start - i_start))); |
136 | } | 140 | } |
137 | 141 | ||
@@ -148,8 +152,8 @@ public: | |||
148 | } | 152 | } |
149 | 153 | ||
150 | if (i_end > m_end) { | 154 | if (i_end > m_end) { |
151 | table->insert(table->end(), | 155 | table->insert(table->end(), |
152 | make_pair(m_end, | 156 | make_pair(m_end, |
153 | seg.Subseg(m_end - i_start, i_end - m_end))); | 157 | seg.Subseg(m_end - i_start, i_end - m_end))); |
154 | } | 158 | } |
155 | } | 159 | } |
@@ -159,7 +163,7 @@ public: | |||
159 | CHECK_LE(m_end, i_end); | 163 | CHECK_LE(m_end, i_end); |
160 | } | 164 | } |
161 | 165 | ||
162 | static void AddChange(const Change &ch, | 166 | static void AddChange(const Change &ch, |
163 | SegmentMap *table, | 167 | SegmentMap *table, |
164 | const SegmentMap *source_table, | 168 | const SegmentMap *source_table, |
165 | MTRandom *rand) { | 169 | MTRandom *rand) { |
@@ -167,7 +171,7 @@ public: | |||
167 | xoff_t i_start = 0; | 171 | xoff_t i_start = 0; |
168 | xoff_t i_end = 0; | 172 | xoff_t i_end = 0; |
169 | 173 | ||
170 | for (ConstSegmentMapIterator iter(source_table->begin()); | 174 | for (ConstSegmentMapIterator iter(source_table->begin()); |
171 | iter != source_table->end(); | 175 | iter != source_table->end(); |
172 | ++iter) { | 176 | ++iter) { |
173 | const Segment &seg = iter->second; | 177 | const Segment &seg = iter->second; |
@@ -185,8 +189,8 @@ public: | |||
185 | } | 189 | } |
186 | 190 | ||
187 | if (i_start < m_start) { | 191 | if (i_start < m_start) { |
188 | table->insert(table->end(), | 192 | table->insert(table->end(), |
189 | make_pair(i_start, | 193 | make_pair(i_start, |
190 | seg.Subseg(0, m_start - i_start))); | 194 | seg.Subseg(0, m_start - i_start))); |
191 | } | 195 | } |
192 | 196 | ||
@@ -198,9 +202,10 @@ public: | |||
198 | } | 202 | } |
199 | 203 | ||
200 | if (m_start < i_end) { | 204 | if (m_start < i_end) { |
201 | table->insert(table->end(), | 205 | table->insert(table->end(), |
202 | make_pair(m_start + ch.size, | 206 | make_pair(m_start + ch.size, |
203 | seg.Subseg(m_start - i_start, i_end - m_start))); | 207 | seg.Subseg(m_start - i_start, |
208 | i_end - m_start))); | ||
204 | } | 209 | } |
205 | } | 210 | } |
206 | 211 | ||
@@ -213,7 +218,7 @@ public: | |||
213 | } | 218 | } |
214 | } | 219 | } |
215 | 220 | ||
216 | static void DeleteChange(const Change &ch, | 221 | static void DeleteChange(const Change &ch, |
217 | SegmentMap *table, | 222 | SegmentMap *table, |
218 | const SegmentMap *source_table, | 223 | const SegmentMap *source_table, |
219 | MTRandom *rand) { | 224 | MTRandom *rand) { |
@@ -222,7 +227,7 @@ public: | |||
222 | xoff_t i_start = 0; | 227 | xoff_t i_start = 0; |
223 | xoff_t i_end = 0; | 228 | xoff_t i_end = 0; |
224 | 229 | ||
225 | for (ConstSegmentMapIterator iter(source_table->begin()); | 230 | for (ConstSegmentMapIterator iter(source_table->begin()); |
226 | iter != source_table->end(); | 231 | iter != source_table->end(); |
227 | ++iter) { | 232 | ++iter) { |
228 | const Segment &seg = iter->second; | 233 | const Segment &seg = iter->second; |
@@ -240,14 +245,14 @@ public: | |||
240 | } | 245 | } |
241 | 246 | ||
242 | if (i_start < m_start) { | 247 | if (i_start < m_start) { |
243 | table->insert(table->end(), | 248 | table->insert(table->end(), |
244 | make_pair(i_start, | 249 | make_pair(i_start, |
245 | seg.Subseg(0, m_start - i_start))); | 250 | seg.Subseg(0, m_start - i_start))); |
246 | } | 251 | } |
247 | 252 | ||
248 | if (i_end > m_end) { | 253 | if (i_end > m_end) { |
249 | table->insert(table->end(), | 254 | table->insert(table->end(), |
250 | make_pair(m_end - ch.size, | 255 | make_pair(m_end - ch.size, |
251 | seg.Subseg(m_end - i_start, i_end - m_end))); | 256 | seg.Subseg(m_end - i_start, i_end - m_end))); |
252 | } | 257 | } |
253 | } | 258 | } |
@@ -256,19 +261,21 @@ public: | |||
256 | CHECK_LE(m_end, i_end); | 261 | CHECK_LE(m_end, i_end); |
257 | } | 262 | } |
258 | 263 | ||
259 | static void MoveChange(const Change &ch, | 264 | // A move is a copy followed by delete of the copied-from range. |
265 | static void MoveChange(const Change &ch, | ||
260 | SegmentMap *table, | 266 | SegmentMap *table, |
261 | const SegmentMap *source_table, | 267 | const SegmentMap *source_table, |
262 | MTRandom *rand) { | 268 | MTRandom *rand) { |
263 | SegmentMap tmp; | 269 | SegmentMap tmp; |
264 | CHECK_NE(ch.addr1, ch.addr2); | 270 | CHECK_NE(ch.addr1, ch.addr2); |
265 | CopyChange(ch, &tmp, source_table, rand); | 271 | CopyChange(ch, &tmp, source_table, rand); |
266 | Change d(Change::DELETE, ch.size, | 272 | Change d(Change::DELETE, ch.size, |
267 | ch.addr1 < ch.addr2 ? ch.addr1 : ch.addr1 + ch.size); | 273 | ch.addr1 < ch.addr2 ? ch.addr1 : ch.addr1 + ch.size); |
268 | DeleteChange(d, table, &tmp, rand); | 274 | DeleteChange(d, table, &tmp, rand); |
269 | } | 275 | } |
270 | 276 | ||
271 | static void OverwriteChange(const Change &ch, | 277 | // An overwrite is a copy followed by a delete of the copied-to range. |
278 | static void OverwriteChange(const Change &ch, | ||
272 | SegmentMap *table, | 279 | SegmentMap *table, |
273 | const SegmentMap *source_table, | 280 | const SegmentMap *source_table, |
274 | MTRandom *rand) { | 281 | MTRandom *rand) { |
@@ -279,7 +286,7 @@ public: | |||
279 | DeleteChange(d, table, &tmp, rand); | 286 | DeleteChange(d, table, &tmp, rand); |
280 | } | 287 | } |
281 | 288 | ||
282 | static void CopyChange(const Change &ch, | 289 | static void CopyChange(const Change &ch, |
283 | SegmentMap *table, | 290 | SegmentMap *table, |
284 | const SegmentMap *source_table, | 291 | const SegmentMap *source_table, |
285 | MTRandom *ignore) { | 292 | MTRandom *ignore) { |
@@ -289,7 +296,7 @@ public: | |||
289 | xoff_t i_end = 0; | 296 | xoff_t i_end = 0; |
290 | 297 | ||
291 | // Like AddChange() with AppendCopy instead of a random segment. | 298 | // Like AddChange() with AppendCopy instead of a random segment. |
292 | for (ConstSegmentMapIterator iter(source_table->begin()); | 299 | for (ConstSegmentMapIterator iter(source_table->begin()); |
293 | iter != source_table->end(); | 300 | iter != source_table->end(); |
294 | ++iter) { | 301 | ++iter) { |
295 | const Segment &seg = iter->second; | 302 | const Segment &seg = iter->second; |
@@ -307,16 +314,16 @@ public: | |||
307 | } | 314 | } |
308 | 315 | ||
309 | if (i_start < m_start) { | 316 | if (i_start < m_start) { |
310 | table->insert(table->end(), | 317 | table->insert(table->end(), |
311 | make_pair(i_start, | 318 | make_pair(i_start, |
312 | seg.Subseg(0, m_start - i_start))); | 319 | seg.Subseg(0, m_start - i_start))); |
313 | } | 320 | } |
314 | 321 | ||
315 | AppendCopy(table, source_table, c_start, m_start, ch.size); | 322 | AppendCopy(table, source_table, c_start, m_start, ch.size); |
316 | 323 | ||
317 | if (m_start < i_end) { | 324 | if (m_start < i_end) { |
318 | table->insert(table->end(), | 325 | table->insert(table->end(), |
319 | make_pair(m_start + ch.size, | 326 | make_pair(m_start + ch.size, |
320 | seg.Subseg(m_start - i_start, i_end - m_start))); | 327 | seg.Subseg(m_start - i_start, i_end - m_start))); |
321 | } | 328 | } |
322 | } | 329 | } |
@@ -331,7 +338,7 @@ public: | |||
331 | 338 | ||
332 | static void AppendCopy(SegmentMap *table, | 339 | static void AppendCopy(SegmentMap *table, |
333 | const SegmentMap *source_table, | 340 | const SegmentMap *source_table, |
334 | xoff_t copy_offset, | 341 | xoff_t copy_offset, |
335 | xoff_t append_offset, | 342 | xoff_t append_offset, |
336 | xoff_t length) { | 343 | xoff_t length) { |
337 | ConstSegmentMapIterator pos(source_table->upper_bound(copy_offset)); | 344 | ConstSegmentMapIterator pos(source_table->upper_bound(copy_offset)); |
@@ -340,10 +347,10 @@ public: | |||
340 | 347 | ||
341 | while (got < length) { | 348 | while (got < length) { |
342 | size_t seg_offset = copy_offset - pos->first; | 349 | size_t seg_offset = copy_offset - pos->first; |
343 | size_t advance = min(pos->second.Size() - seg_offset, | 350 | size_t advance = min(pos->second.Size() - seg_offset, |
344 | (size_t)(length - got)); | 351 | (size_t)(length - got)); |
345 | 352 | ||
346 | table->insert(table->end(), | 353 | table->insert(table->end(), |
347 | make_pair(append_offset, | 354 | make_pair(append_offset, |
348 | pos->second.Subseg(seg_offset, | 355 | pos->second.Subseg(seg_offset, |
349 | advance))); | 356 | advance))); |
@@ -354,7 +361,7 @@ public: | |||
354 | ++pos; | 361 | ++pos; |
355 | } | 362 | } |
356 | } | 363 | } |
357 | 364 | ||
358 | ChangeList* Changes() { | 365 | ChangeList* Changes() { |
359 | return &cl_; | 366 | return &cl_; |
360 | } | 367 | } |
@@ -369,8 +376,8 @@ private: | |||
369 | 376 | ||
370 | class Modify1stByte : public Mutator { | 377 | class Modify1stByte : public Mutator { |
371 | public: | 378 | public: |
372 | void Mutate(SegmentMap *table, | 379 | void Mutate(SegmentMap *table, |
373 | const SegmentMap *source_table, | 380 | const SegmentMap *source_table, |
374 | MTRandom *rand) const { | 381 | MTRandom *rand) const { |
375 | ChangeListMutator::Mutate(Change(Change::MODIFY, 1, 0), | 382 | ChangeListMutator::Mutate(Change(Change::MODIFY, 1, 0), |
376 | table, source_table, rand); | 383 | table, source_table, rand); |
diff --git a/xdelta3/testing/regtest.cc b/xdelta3/testing/regtest.cc index 4ac458b..f0b7a42 100644 --- a/xdelta3/testing/regtest.cc +++ b/xdelta3/testing/regtest.cc | |||
@@ -8,15 +8,20 @@ class Regtest { | |||
8 | public: | 8 | public: |
9 | typedef typename Constants::Sizes Sizes; | 9 | typedef typename Constants::Sizes Sizes; |
10 | 10 | ||
11 | struct Options { | ||
12 | size_t encode_srcwin_maxsz; | ||
13 | }; | ||
14 | |||
11 | #include "segment.h" | 15 | #include "segment.h" |
12 | #include "modify.h" | 16 | #include "modify.h" |
13 | #include "file.h" | 17 | #include "file.h" |
14 | #include "cmp.h" | 18 | #include "cmp.h" |
15 | #include "delta.h" | 19 | #include "delta.h" |
16 | 20 | ||
17 | void InMemoryEncodeDecode(const FileSpec &source_file, | 21 | void InMemoryEncodeDecode(const FileSpec &source_file, |
18 | const FileSpec &target_file, | 22 | const FileSpec &target_file, |
19 | Block *coded_data) { | 23 | Block *coded_data, |
24 | const Options &options = Options()) { | ||
20 | xd3_stream encode_stream; | 25 | xd3_stream encode_stream; |
21 | xd3_config encode_config; | 26 | xd3_config encode_config; |
22 | xd3_source encode_source; | 27 | xd3_source encode_source; |
@@ -41,8 +46,9 @@ void InMemoryEncodeDecode(const FileSpec &source_file, | |||
41 | xd3_init_config(&decode_config, XD3_ADLER32); | 46 | xd3_init_config(&decode_config, XD3_ADLER32); |
42 | 47 | ||
43 | encode_config.winsize = Constants::WINDOW_SIZE; | 48 | encode_config.winsize = Constants::WINDOW_SIZE; |
49 | encode_config.srcwin_maxsz = options.encode_srcwin_maxsz; | ||
44 | 50 | ||
45 | // TODO! the smatcher setup isn't working, | 51 | // TODO! the smatcher setup isn't working, |
46 | // if (options.large_cksum_step) { | 52 | // if (options.large_cksum_step) { |
47 | // encode_config.smatch_cfg = XD3_SMATCH_SOFT; | 53 | // encode_config.smatch_cfg = XD3_SMATCH_SOFT; |
48 | // encode_config.smatcher_soft.large_step = options.large_cksum_step; | 54 | // encode_config.smatcher_soft.large_step = options.large_cksum_step; |
@@ -81,7 +87,8 @@ void InMemoryEncodeDecode(const FileSpec &source_file, | |||
81 | 87 | ||
82 | IF_DEBUG2(DP(RINT "target in %s: %llu..%llu %"Q"u(%"Q"u) verified %"Q"u\n", | 88 | IF_DEBUG2(DP(RINT "target in %s: %llu..%llu %"Q"u(%"Q"u) verified %"Q"u\n", |
83 | encoding ? "encoding" : "decoding", | 89 | encoding ? "encoding" : "decoding", |
84 | target_iterator.Offset(), target_iterator.Offset() + target_block.Size(), | 90 | target_iterator.Offset(), |
91 | target_iterator.Offset() + target_block.Size(), | ||
85 | target_iterator.Blkno(), blks, verified_bytes)); | 92 | target_iterator.Blkno(), blks, verified_bytes)); |
86 | 93 | ||
87 | if (blks == 0 || target_iterator.Blkno() == (blks - 1)) { | 94 | if (blks == 0 || target_iterator.Blkno() == (blks - 1)) { |
@@ -102,7 +109,7 @@ void InMemoryEncodeDecode(const FileSpec &source_file, | |||
102 | msg = decode_stream.msg; | 109 | msg = decode_stream.msg; |
103 | } | 110 | } |
104 | 111 | ||
105 | IF_DEBUG2(DP(RINT "%s = %s %s\n", encoding ? "E " : " D", | 112 | IF_DEBUG1(DP(RINT "%s = %s %s\n", encoding ? "E " : " D", |
106 | xd3_strerror(ret), | 113 | xd3_strerror(ret), |
107 | msg == NULL ? "" : msg)); | 114 | msg == NULL ? "" : msg)); |
108 | 115 | ||
@@ -111,12 +118,12 @@ void InMemoryEncodeDecode(const FileSpec &source_file, | |||
111 | if (encoding) { | 118 | if (encoding) { |
112 | if (coded_data != NULL) { | 119 | if (coded_data != NULL) { |
113 | // Optional encoded-output to the caller | 120 | // Optional encoded-output to the caller |
114 | coded_data->Append(encode_stream.next_out, | 121 | coded_data->Append(encode_stream.next_out, |
115 | encode_stream.avail_out); | 122 | encode_stream.avail_out); |
116 | } | 123 | } |
117 | // Feed this data to the decoder. | 124 | // Feed this data to the decoder. |
118 | xd3_avail_input(&decode_stream, | 125 | xd3_avail_input(&decode_stream, |
119 | encode_stream.next_out, | 126 | encode_stream.next_out, |
120 | encode_stream.avail_out); | 127 | encode_stream.avail_out); |
121 | xd3_consume_output(&encode_stream); | 128 | xd3_consume_output(&encode_stream); |
122 | encoding = false; | 129 | encoding = false; |
@@ -131,12 +138,13 @@ void InMemoryEncodeDecode(const FileSpec &source_file, | |||
131 | xd3_source *src = (encoding ? &encode_source : &decode_source); | 138 | xd3_source *src = (encoding ? &encode_source : &decode_source); |
132 | Block *block = (encoding ? &encode_source_block : &decode_source_block); | 139 | Block *block = (encoding ? &encode_source_block : &decode_source_block); |
133 | if (encoding) { | 140 | if (encoding) { |
134 | IF_DEBUG2(DP(RINT "block %"Q"u last srcpos %"Q"u encodepos %u\n", | 141 | IF_DEBUG1(DP(RINT "[srcblock] %"Q"u last srcpos %"Q"u " |
142 | "encodepos %"Q"u\n", | ||
135 | encode_source.getblkno, | 143 | encode_source.getblkno, |
136 | encode_stream.match_last_srcpos, | 144 | encode_stream.match_last_srcpos, |
137 | encode_stream.input_position)); | 145 | encode_stream.input_position + encode_stream.total_in)); |
138 | } | 146 | } |
139 | 147 | ||
140 | source_iterator.SetBlock(src->getblkno); | 148 | source_iterator.SetBlock(src->getblkno); |
141 | source_iterator.Get(block); | 149 | source_iterator.Get(block); |
142 | src->curblkno = src->getblkno; | 150 | src->curblkno = src->getblkno; |
@@ -171,8 +179,8 @@ void InMemoryEncodeDecode(const FileSpec &source_file, | |||
171 | } | 179 | } |
172 | encoding = false; | 180 | encoding = false; |
173 | } else { | 181 | } else { |
174 | CHECK_EQ(0, CmpDifferentBlockBytesAtOffset(decoded_block, | 182 | CHECK_EQ(0, CmpDifferentBlockBytesAtOffset(decoded_block, |
175 | target_file, | 183 | target_file, |
176 | verified_bytes)); | 184 | verified_bytes)); |
177 | verified_bytes += decoded_block.Size(); | 185 | verified_bytes += decoded_block.Size(); |
178 | decoded_block.Reset(); | 186 | decoded_block.Reset(); |
@@ -210,7 +218,7 @@ void TestRandomNumbers() { | |||
210 | usum += rand.Rand32(); | 218 | usum += rand.Rand32(); |
211 | esum += rand.ExpRand32(1024); | 219 | esum += rand.ExpRand32(1024); |
212 | } | 220 | } |
213 | 221 | ||
214 | double allowed_error = 0.01; | 222 | double allowed_error = 0.01; |
215 | 223 | ||
216 | uint32_t umean = usum / rounds; | 224 | uint32_t umean = usum / rounds; |
@@ -331,10 +339,11 @@ void TestModifyMutator() { | |||
331 | 339 | ||
332 | for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { | 340 | for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { |
333 | ChangeList cl1; | 341 | ChangeList cl1; |
334 | cl1.push_back(Change(Change::MODIFY, test_cases[i].size, test_cases[i].addr)); | 342 | cl1.push_back(Change(Change::MODIFY, test_cases[i].size, |
343 | test_cases[i].addr)); | ||
335 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | 344 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); |
336 | CHECK_EQ(spec0.Size(), spec1.Size()); | 345 | CHECK_EQ(spec0.Size(), spec1.Size()); |
337 | 346 | ||
338 | size_t diff = CmpDifferentBytes(spec0, spec1); | 347 | size_t diff = CmpDifferentBytes(spec0, spec1); |
339 | CHECK_LE(diff, test_cases[i].size); | 348 | CHECK_LE(diff, test_cases[i].size); |
340 | 349 | ||
@@ -407,7 +416,8 @@ void TestDeleteMutator() { | |||
407 | 416 | ||
408 | for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { | 417 | for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { |
409 | ChangeList cl1; | 418 | ChangeList cl1; |
410 | cl1.push_back(Change(Change::DELETE, test_cases[i].size, test_cases[i].addr)); | 419 | cl1.push_back(Change(Change::DELETE, test_cases[i].size, |
420 | test_cases[i].addr)); | ||
411 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | 421 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); |
412 | CHECK_EQ(spec0.Size() - test_cases[i].size, spec1.Size()); | 422 | CHECK_EQ(spec0.Size() - test_cases[i].size, spec1.Size()); |
413 | 423 | ||
@@ -435,12 +445,13 @@ void TestCopyMutator() { | |||
435 | // copies, it does not enter checksums. So these tests copy data from | 445 | // copies, it does not enter checksums. So these tests copy data from |
436 | // later to earlier so that checksumming will start. | 446 | // later to earlier so that checksumming will start. |
437 | { Constants::BLOCK_SIZE / 2, Constants::BLOCK_SIZE / 2, 0 }, | 447 | { Constants::BLOCK_SIZE / 2, Constants::BLOCK_SIZE / 2, 0 }, |
438 | { Constants::BLOCK_SIZE, 2 * Constants::BLOCK_SIZE, Constants::BLOCK_SIZE, }, | 448 | { Constants::BLOCK_SIZE, 2 * Constants::BLOCK_SIZE, |
449 | Constants::BLOCK_SIZE, }, | ||
439 | }; | 450 | }; |
440 | 451 | ||
441 | for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { | 452 | for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { |
442 | ChangeList cl1; | 453 | ChangeList cl1; |
443 | cl1.push_back(Change(Change::COPY, test_cases[i].size, | 454 | cl1.push_back(Change(Change::COPY, test_cases[i].size, |
444 | test_cases[i].from, test_cases[i].to)); | 455 | test_cases[i].from, test_cases[i].to)); |
445 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | 456 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); |
446 | CHECK_EQ(spec0.Size() + test_cases[i].size, spec1.Size()); | 457 | CHECK_EQ(spec0.Size() + test_cases[i].size, spec1.Size()); |
@@ -468,17 +479,21 @@ void TestMoveMutator() { | |||
468 | // This is easier to test than Copy but has the same trouble as Delete. | 479 | // This is easier to test than Copy but has the same trouble as Delete. |
469 | { Constants::BLOCK_SIZE / 2, Constants::BLOCK_SIZE / 2, 0 }, | 480 | { Constants::BLOCK_SIZE / 2, Constants::BLOCK_SIZE / 2, 0 }, |
470 | { Constants::BLOCK_SIZE / 2, 0, Constants::BLOCK_SIZE / 2 }, | 481 | { Constants::BLOCK_SIZE / 2, 0, Constants::BLOCK_SIZE / 2 }, |
471 | { Constants::BLOCK_SIZE, Constants::BLOCK_SIZE, 2 * Constants::BLOCK_SIZE }, | 482 | { Constants::BLOCK_SIZE, Constants::BLOCK_SIZE, 2 * |
472 | { Constants::BLOCK_SIZE, 2 * Constants::BLOCK_SIZE, Constants::BLOCK_SIZE }, | 483 | Constants::BLOCK_SIZE }, |
473 | { Constants::BLOCK_SIZE * 3 / 2, Constants::BLOCK_SIZE, Constants::BLOCK_SIZE * 3 / 2 }, | 484 | { Constants::BLOCK_SIZE, 2 * Constants::BLOCK_SIZE, |
485 | Constants::BLOCK_SIZE }, | ||
486 | { Constants::BLOCK_SIZE * 3 / 2, Constants::BLOCK_SIZE, | ||
487 | Constants::BLOCK_SIZE * 3 / 2 }, | ||
474 | 488 | ||
475 | // This is a no-op | 489 | // This is a no-op |
476 | { Constants::BLOCK_SIZE, Constants::BLOCK_SIZE * 2, 3 * Constants::BLOCK_SIZE }, | 490 | { Constants::BLOCK_SIZE, Constants::BLOCK_SIZE * 2, |
491 | 3 * Constants::BLOCK_SIZE }, | ||
477 | }; | 492 | }; |
478 | 493 | ||
479 | for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { | 494 | for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { |
480 | ChangeList cl1; | 495 | ChangeList cl1; |
481 | cl1.push_back(Change(Change::MOVE, test_cases[i].size, | 496 | cl1.push_back(Change(Change::MOVE, test_cases[i].size, |
482 | test_cases[i].from, test_cases[i].to)); | 497 | test_cases[i].from, test_cases[i].to)); |
483 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | 498 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); |
484 | CHECK_EQ(spec0.Size(), spec1.Size()); | 499 | CHECK_EQ(spec0.Size(), spec1.Size()); |
@@ -506,10 +521,11 @@ void TestOverwriteMutator() { | |||
506 | Block b0, b1; | 521 | Block b0, b1; |
507 | BlockIterator(spec0).Get(&b0); | 522 | BlockIterator(spec0).Get(&b0); |
508 | BlockIterator(spec1).Get(&b1); | 523 | BlockIterator(spec1).Get(&b1); |
509 | 524 | ||
510 | CHECK(memcmp(b0.Data(), b1.Data() + 20, 10) == 0); | 525 | CHECK(memcmp(b0.Data(), b1.Data() + 20, 10) == 0); |
511 | CHECK(memcmp(b0.Data(), b1.Data(), 20) == 0); | 526 | CHECK(memcmp(b0.Data(), b1.Data(), 20) == 0); |
512 | CHECK(memcmp(b0.Data() + 30, b1.Data() + 30, Constants::BLOCK_SIZE - 30) == 0); | 527 | CHECK(memcmp(b0.Data() + 30, b1.Data() + 30, |
528 | Constants::BLOCK_SIZE - 30) == 0); | ||
513 | 529 | ||
514 | cl1.clear(); | 530 | cl1.clear(); |
515 | cl1.push_back(Change(Change::OVERWRITE, 10, 20, (xoff_t)0)); | 531 | cl1.push_back(Change(Change::OVERWRITE, 10, 20, (xoff_t)0)); |
@@ -518,9 +534,10 @@ void TestOverwriteMutator() { | |||
518 | 534 | ||
519 | BlockIterator(spec0).Get(&b0); | 535 | BlockIterator(spec0).Get(&b0); |
520 | BlockIterator(spec1).Get(&b1); | 536 | BlockIterator(spec1).Get(&b1); |
521 | 537 | ||
522 | CHECK(memcmp(b0.Data() + 20, b1.Data(), 10) == 0); | 538 | CHECK(memcmp(b0.Data() + 20, b1.Data(), 10) == 0); |
523 | CHECK(memcmp(b0.Data() + 10, b1.Data() + 10, Constants::BLOCK_SIZE - 10) == 0); | 539 | CHECK(memcmp(b0.Data() + 10, b1.Data() + 10, |
540 | Constants::BLOCK_SIZE - 10) == 0); | ||
524 | } | 541 | } |
525 | 542 | ||
526 | // Note: this test is written to expose a problem, but the problem was | 543 | // Note: this test is written to expose a problem, but the problem was |
@@ -534,7 +551,7 @@ void TestNonBlockingProgress() { | |||
534 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 3); | 551 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 3); |
535 | 552 | ||
536 | // This is a lazy target match | 553 | // This is a lazy target match |
537 | Change ct(Change::OVERWRITE, 22, | 554 | Change ct(Change::OVERWRITE, 22, |
538 | Constants::BLOCK_SIZE + 50, | 555 | Constants::BLOCK_SIZE + 50, |
539 | Constants::BLOCK_SIZE + 20); | 556 | Constants::BLOCK_SIZE + 20); |
540 | 557 | ||
@@ -598,6 +615,44 @@ void TestBlockInMemory() { | |||
598 | CHECK_EQ(spec1.Blocks(Constants::WINDOW_SIZE), delta.Windows()); | 615 | CHECK_EQ(spec1.Blocks(Constants::WINDOW_SIZE), delta.Windows()); |
599 | } | 616 | } |
600 | 617 | ||
618 | void TestFifoCopyDiscipline() { | ||
619 | MTRandom rand; | ||
620 | FileSpec spec0(&rand); | ||
621 | FileSpec spec1(&rand); | ||
622 | |||
623 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 4); | ||
624 | |||
625 | // Create a half-block copy, 2.5 blocks apart. With 64-byte blocks, | ||
626 | // the file in spec0 copies @ 384 from spec1 @ 64. | ||
627 | ChangeList cl1; | ||
628 | cl1.push_back(Change(Change::MODIFY, | ||
629 | Constants::BLOCK_SIZE / 2, | ||
630 | 0)); | ||
631 | cl1.push_back(Change(Change::OVERWRITE, | ||
632 | Constants::BLOCK_SIZE / 2, | ||
633 | Constants::BLOCK_SIZE * 3, | ||
634 | Constants::BLOCK_SIZE / 2)); | ||
635 | cl1.push_back(Change(Change::MODIFY, | ||
636 | Constants::BLOCK_SIZE * 3, | ||
637 | Constants::BLOCK_SIZE)); | ||
638 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | ||
639 | |||
640 | Options options1; | ||
641 | options1.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 4; | ||
642 | Block block1; | ||
643 | InMemoryEncodeDecode(spec1, spec0, &block1, options1); | ||
644 | Delta delta1(block1); | ||
645 | CHECK_EQ(4 * Constants::BLOCK_SIZE - | ||
646 | Constants::BLOCK_SIZE / 2, delta1.AddedBytes()); | ||
647 | |||
648 | Options options2; | ||
649 | options2.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 3; | ||
650 | Block block2; | ||
651 | InMemoryEncodeDecode(spec1, spec0, &block2, options2); | ||
652 | Delta delta2(block2); | ||
653 | CHECK_EQ(4 * Constants::BLOCK_SIZE, delta2.AddedBytes()); | ||
654 | } | ||
655 | |||
601 | void FourWayMergeTest(const FileSpec &spec0, | 656 | void FourWayMergeTest(const FileSpec &spec0, |
602 | const FileSpec &spec1, | 657 | const FileSpec &spec1, |
603 | const FileSpec &spec2, | 658 | const FileSpec &spec2, |
@@ -631,7 +686,7 @@ void FourWayMergeTest(const FileSpec &spec0, | |||
631 | mcmd.push_back(NULL); | 686 | mcmd.push_back(NULL); |
632 | 687 | ||
633 | //DP(RINT "Running one merge: %s\n", CommandToString(mcmd).c_str()); | 688 | //DP(RINT "Running one merge: %s\n", CommandToString(mcmd).c_str()); |
634 | CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, | 689 | CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, |
635 | const_cast<char**>(&mcmd[0]))); | 690 | const_cast<char**>(&mcmd[0]))); |
636 | 691 | ||
637 | ExtFile recon; | 692 | ExtFile recon; |
@@ -645,7 +700,7 @@ void FourWayMergeTest(const FileSpec &spec0, | |||
645 | tcmd.push_back(NULL); | 700 | tcmd.push_back(NULL); |
646 | 701 | ||
647 | //DP(RINT "Running one recon! %s\n", CommandToString(tcmd).c_str()); | 702 | //DP(RINT "Running one recon! %s\n", CommandToString(tcmd).c_str()); |
648 | CHECK_EQ(0, xd3_main_cmdline(tcmd.size() - 1, | 703 | CHECK_EQ(0, xd3_main_cmdline(tcmd.size() - 1, |
649 | const_cast<char**>(&tcmd[0]))); | 704 | const_cast<char**>(&tcmd[0]))); |
650 | //DP(RINT "Should equal! %s\n", f2.Name()); | 705 | //DP(RINT "Should equal! %s\n", f2.Name()); |
651 | 706 | ||
@@ -675,7 +730,7 @@ void TestMergeCommand1() { | |||
675 | if (change1 == 0) { | 730 | if (change1 == 0) { |
676 | continue; | 731 | continue; |
677 | } | 732 | } |
678 | 733 | ||
679 | DP(RINT "S0 = %lu\n", size0); | 734 | DP(RINT "S0 = %lu\n", size0); |
680 | DP(RINT "C1 = %lu\n", change1); | 735 | DP(RINT "C1 = %lu\n", change1); |
681 | 736 | ||
@@ -685,7 +740,7 @@ void TestMergeCommand1() { | |||
685 | spec0.GenerateFixedSize(size0); | 740 | spec0.GenerateFixedSize(size0); |
686 | 741 | ||
687 | ChangeList cl1, cl2, cl3; | 742 | ChangeList cl1, cl2, cl3; |
688 | 743 | ||
689 | size_t change3 = change1; | 744 | size_t change3 = change1; |
690 | size_t change3_pos; | 745 | size_t change3_pos; |
691 | 746 | ||
@@ -735,7 +790,7 @@ void TestMergeCommand2() { | |||
735 | SizeIterator<size_t, Sizes> si3(&rand, 10); | 790 | SizeIterator<size_t, Sizes> si3(&rand, 10); |
736 | for (; !si3.Done(); si3.Next()) { | 791 | for (; !si3.Done(); si3.Next()) { |
737 | size_t size3 = si3.Get(); | 792 | size_t size3 = si3.Get(); |
738 | 793 | ||
739 | // We're only interested in three sizes, strictly decreasing. */ | 794 | // We're only interested in three sizes, strictly decreasing. */ |
740 | if (size3 >= size2 || size2 >= size1 || size1 >= size0) { | 795 | if (size3 >= size2 || size2 >= size1 || size1 >= size0) { |
741 | continue; | 796 | continue; |
@@ -749,7 +804,7 @@ void TestMergeCommand2() { | |||
749 | spec0.GenerateFixedSize(size0); | 804 | spec0.GenerateFixedSize(size0); |
750 | 805 | ||
751 | ChangeList cl1, cl2, cl3; | 806 | ChangeList cl1, cl2, cl3; |
752 | 807 | ||
753 | cl1.push_back(Change(Change::DELETE, size0 - size1, 0)); | 808 | cl1.push_back(Change(Change::DELETE, size0 - size1, 0)); |
754 | cl2.push_back(Change(Change::DELETE, size0 - size2, 0)); | 809 | cl2.push_back(Change(Change::DELETE, size0 - size2, 0)); |
755 | cl3.push_back(Change(Change::DELETE, size0 - size3, 0)); | 810 | cl3.push_back(Change(Change::DELETE, size0 - size3, 0)); |
@@ -790,6 +845,7 @@ void MainTest() { | |||
790 | TEST(TestEmptyInMemory); | 845 | TEST(TestEmptyInMemory); |
791 | TEST(TestBlockInMemory); | 846 | TEST(TestBlockInMemory); |
792 | TEST(TestNonBlockingProgress); | 847 | TEST(TestNonBlockingProgress); |
848 | TEST(TestFifoCopyDiscipline); | ||
793 | TEST(TestMergeCommand1); | 849 | TEST(TestMergeCommand1); |
794 | TEST(TestMergeCommand2); | 850 | TEST(TestMergeCommand2); |
795 | } | 851 | } |
diff --git a/xdelta3/testing/segment.h b/xdelta3/testing/segment.h index a743bfd..ea3dcee 100644 --- a/xdelta3/testing/segment.h +++ b/xdelta3/testing/segment.h | |||
@@ -6,7 +6,7 @@ class Segment { | |||
6 | : size_(size), | 6 | : size_(size), |
7 | seed_(rand->Rand32()), | 7 | seed_(rand->Rand32()), |
8 | seed_offset_(0), | 8 | seed_offset_(0), |
9 | data_(NULL) { | 9 | data_(NULL) { |
10 | CHECK_GT(size_, 0); | 10 | CHECK_GT(size_, 0); |
11 | } | 11 | } |
12 | 12 | ||
@@ -14,7 +14,7 @@ class Segment { | |||
14 | : size_(size), | 14 | : size_(size), |
15 | seed_(seed), | 15 | seed_(seed), |
16 | seed_offset_(0), | 16 | seed_offset_(0), |
17 | data_(NULL) { | 17 | data_(NULL) { |
18 | CHECK_GT(size_, 0); | 18 | CHECK_GT(size_, 0); |
19 | } | 19 | } |
20 | 20 | ||
@@ -22,12 +22,12 @@ class Segment { | |||
22 | : size_(size), | 22 | : size_(size), |
23 | seed_(0), | 23 | seed_(0), |
24 | seed_offset_(0), | 24 | seed_offset_(0), |
25 | data_(data) { | 25 | data_(data) { |
26 | CHECK_GT(size_, 0); | 26 | CHECK_GT(size_, 0); |
27 | } | 27 | } |
28 | 28 | ||
29 | size_t Size() const { | 29 | size_t Size() const { |
30 | return size_; | 30 | return size_; |
31 | } | 31 | } |
32 | 32 | ||
33 | Segment Subseg(size_t start, size_t size) const { | 33 | Segment Subseg(size_t start, size_t size) const { |
@@ -66,7 +66,7 @@ class Segment { | |||
66 | } | 66 | } |
67 | } else { | 67 | } else { |
68 | char buf[256]; | 68 | char buf[256]; |
69 | sprintf(buf, "size=%ld,seed=%ld,skip=%ld", size_, seed_, seed_offset_); | 69 | sprintf(buf, "size=%ld,seed=%ud,skip=%ld", size_, seed_, seed_offset_); |
70 | r.append(buf); | 70 | r.append(buf); |
71 | } | 71 | } |
72 | return r; | 72 | return r; |
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h index 167343a..7fa0901 100644 --- a/xdelta3/xdelta3-main.h +++ b/xdelta3/xdelta3-main.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* xdelta 3 - delta compression tools and library | 1 | /* xdelta 3 - delta compression tools and library |
2 | * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, | 2 | * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, |
3 | * 2008, 2009 | 3 | * 2008, 2009, 2010 |
4 | * Joshua P. MacDonald | 4 | * Joshua P. MacDonald |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -323,7 +323,7 @@ static int option_recompress_outputs = 1; | |||
323 | /* This is for comparing "printdelta" output without attention to | 323 | /* This is for comparing "printdelta" output without attention to |
324 | * copy-instruction modes. */ | 324 | * copy-instruction modes. */ |
325 | #if VCDIFF_TOOLS | 325 | #if VCDIFF_TOOLS |
326 | static int option_print_cpymode = 1; /* Note: see reset_defaults(). */ | 326 | static int option_print_cpymode = 1; /* Note: see reset_defaults(). */ |
327 | #endif | 327 | #endif |
328 | 328 | ||
329 | /* Static variables */ | 329 | /* Static variables */ |
@@ -1111,7 +1111,7 @@ main_file_seek (main_file *xfile, xoff_t pos) | |||
1111 | 1111 | ||
1112 | if (ret) | 1112 | if (ret) |
1113 | { | 1113 | { |
1114 | XPR(NT "seek to %"Q"u failed: %s: %s\n", | 1114 | XPR(NT "seek to %"Q"u failed: %s: %s\n", |
1115 | pos, xfile->filename, xd3_mainerror (ret)); | 1115 | pos, xfile->filename, xd3_mainerror (ret)); |
1116 | } | 1116 | } |
1117 | 1117 | ||
@@ -1266,7 +1266,7 @@ xsnprintf_func (char *str, int n, const char *fmt, ...) | |||
1266 | return ret; | 1266 | return ret; |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | /* The following macros let VCDIFF print using main_file_write(), | 1269 | /* The following macros let VCDIFF print using main_file_write(), |
1270 | * for example: | 1270 | * for example: |
1271 | * | 1271 | * |
1272 | * VC(UT "trying to be portable: %d\n", x)VE; | 1272 | * VC(UT "trying to be portable: %d\n", x)VE; |
@@ -1315,23 +1315,24 @@ main_print_window (xd3_stream* stream, main_file *xfile) | |||
1315 | addr_bytes = stream->addr_sect.buf - addr_before; | 1315 | addr_bytes = stream->addr_sect.buf - addr_before; |
1316 | inst_bytes = stream->inst_sect.buf - inst_before; | 1316 | inst_bytes = stream->inst_sect.buf - inst_before; |
1317 | 1317 | ||
1318 | VC(UT " %06"Q"u %03u %s %6u", stream->dec_winstart + size, | 1318 | VC(UT " %06"Q"u %03u %s %6u", stream->dec_winstart + size, |
1319 | option_print_cpymode ? code : 0, | 1319 | option_print_cpymode ? code : 0, |
1320 | xd3_rtype_to_string ((xd3_rtype) stream->dec_current1.type, option_print_cpymode), | 1320 | xd3_rtype_to_string ((xd3_rtype) stream->dec_current1.type, |
1321 | option_print_cpymode), | ||
1321 | (usize_t) stream->dec_current1.size)VE; | 1322 | (usize_t) stream->dec_current1.size)VE; |
1322 | 1323 | ||
1323 | if (stream->dec_current1.type != XD3_NOOP) | 1324 | if (stream->dec_current1.type != XD3_NOOP) |
1324 | { | 1325 | { |
1325 | if (stream->dec_current1.type >= XD3_CPY) | 1326 | if (stream->dec_current1.type >= XD3_CPY) |
1326 | { | 1327 | { |
1327 | if (stream->dec_current1.addr >= stream->dec_cpylen) | 1328 | if (stream->dec_current1.addr >= stream->dec_cpylen) |
1328 | { | 1329 | { |
1329 | VC(UT " T@%-6u", | 1330 | VC(UT " T@%-6u", |
1330 | stream->dec_current1.addr - stream->dec_cpylen)VE; | 1331 | stream->dec_current1.addr - stream->dec_cpylen)VE; |
1331 | } | 1332 | } |
1332 | else | 1333 | else |
1333 | { | 1334 | { |
1334 | VC(UT " S@%-6"Q"u", | 1335 | VC(UT " S@%-6"Q"u", |
1335 | stream->dec_cpyoff + stream->dec_current1.addr)VE; | 1336 | stream->dec_cpyoff + stream->dec_current1.addr)VE; |
1336 | } | 1337 | } |
1337 | } | 1338 | } |
@@ -1352,14 +1353,14 @@ main_print_window (xd3_stream* stream, main_file *xfile) | |||
1352 | 1353 | ||
1353 | if (stream->dec_current2.type >= XD3_CPY) | 1354 | if (stream->dec_current2.type >= XD3_CPY) |
1354 | { | 1355 | { |
1355 | if (stream->dec_current2.addr >= stream->dec_cpylen) | 1356 | if (stream->dec_current2.addr >= stream->dec_cpylen) |
1356 | { | 1357 | { |
1357 | VC(UT " T@%-6u", | 1358 | VC(UT " T@%-6u", |
1358 | stream->dec_current2.addr - stream->dec_cpylen)VE; | 1359 | stream->dec_current2.addr - stream->dec_cpylen)VE; |
1359 | } | 1360 | } |
1360 | else | 1361 | else |
1361 | { | 1362 | { |
1362 | VC(UT " S@%-6"Q"u", | 1363 | VC(UT " S@%-6"Q"u", |
1363 | stream->dec_cpyoff + stream->dec_current2.addr)VE; | 1364 | stream->dec_cpyoff + stream->dec_current2.addr)VE; |
1364 | } | 1365 | } |
1365 | } | 1366 | } |
@@ -1432,7 +1433,8 @@ main_print_func (xd3_stream* stream, main_file *xfile) | |||
1432 | 1433 | ||
1433 | if (xfile->snprintf_buf == NULL) | 1434 | if (xfile->snprintf_buf == NULL) |
1434 | { | 1435 | { |
1435 | if ((xfile->snprintf_buf = (uint8_t*)main_malloc(SNPRINTF_BUFSIZE)) == NULL) | 1436 | if ((xfile->snprintf_buf = |
1437 | (uint8_t*)main_malloc(SNPRINTF_BUFSIZE)) == NULL) | ||
1436 | { | 1438 | { |
1437 | return ENOMEM; | 1439 | return ENOMEM; |
1438 | } | 1440 | } |
@@ -1742,7 +1744,7 @@ main_merge_arguments (main_merge_list* merges) | |||
1742 | } | 1744 | } |
1743 | 1745 | ||
1744 | if ((ret = xd3_config_stream (& merge_input, NULL)) || | 1746 | if ((ret = xd3_config_stream (& merge_input, NULL)) || |
1745 | (ret = xd3_whole_state_init (& merge_input))) | 1747 | (ret = xd3_whole_state_init (& merge_input))) |
1746 | { | 1748 | { |
1747 | XPR(NT XD3_LIB_ERRMSG (& merge_input, ret)); | 1749 | XPR(NT XD3_LIB_ERRMSG (& merge_input, ret)); |
1748 | return ret; | 1750 | return ret; |
@@ -1768,7 +1770,7 @@ main_merge_arguments (main_merge_list* merges) | |||
1768 | if (count++ == 0) | 1770 | if (count++ == 0) |
1769 | { | 1771 | { |
1770 | /* The first merge source is the next merge input. */ | 1772 | /* The first merge source is the next merge input. */ |
1771 | xd3_swap_whole_state (& recode_stream->whole_target, | 1773 | xd3_swap_whole_state (& recode_stream->whole_target, |
1772 | & merge_input.whole_target); | 1774 | & merge_input.whole_target); |
1773 | } | 1775 | } |
1774 | else | 1776 | else |
@@ -1822,7 +1824,7 @@ main_merge_arguments (main_merge_list* merges) | |||
1822 | goto error; | 1824 | goto error; |
1823 | } | 1825 | } |
1824 | 1826 | ||
1825 | xd3_swap_whole_state (& merge_stream->whole_target, | 1827 | xd3_swap_whole_state (& merge_stream->whole_target, |
1826 | & merge_input.whole_target); | 1828 | & merge_input.whole_target); |
1827 | ret = 0; | 1829 | ret = 0; |
1828 | error: | 1830 | error: |
@@ -1861,7 +1863,7 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1861 | /* merge_stream is set if there were arguments. this stream's input | 1863 | /* merge_stream is set if there were arguments. this stream's input |
1862 | * needs to be applied to the merge_stream source. */ | 1864 | * needs to be applied to the merge_stream source. */ |
1863 | if ((merge_stream != NULL) && | 1865 | if ((merge_stream != NULL) && |
1864 | (ret = xd3_merge_input_output (stream, | 1866 | (ret = xd3_merge_input_output (stream, |
1865 | & merge_stream->whole_target))) | 1867 | & merge_stream->whole_target))) |
1866 | { | 1868 | { |
1867 | XPR(NT XD3_LIB_ERRMSG (stream, ret)); | 1869 | XPR(NT XD3_LIB_ERRMSG (stream, ret)); |
@@ -1918,7 +1920,7 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1918 | } | 1920 | } |
1919 | 1921 | ||
1920 | if (option_use_checksum && | 1922 | if (option_use_checksum && |
1921 | (stream->dec_win_ind & VCD_ADLER32) != 0) | 1923 | (stream->dec_win_ind & VCD_ADLER32) != 0) |
1922 | { | 1924 | { |
1923 | recode_stream->flags |= XD3_ADLER32_RECODE; | 1925 | recode_stream->flags |= XD3_ADLER32_RECODE; |
1924 | recode_stream->recode_adler32 = stream->whole_target.wininfo[window_num].adler32; | 1926 | recode_stream->recode_adler32 = stream->whole_target.wininfo[window_num].adler32; |
@@ -1931,7 +1933,7 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1931 | main_free (main_bdata); | 1933 | main_free (main_bdata); |
1932 | main_bdata = NULL; | 1934 | main_bdata = NULL; |
1933 | main_bsize = 0; | 1935 | main_bsize = 0; |
1934 | if ((main_bdata = (uint8_t*) | 1936 | if ((main_bdata = (uint8_t*) |
1935 | main_malloc (window_size)) == NULL) | 1937 | main_malloc (window_size)) == NULL) |
1936 | { | 1938 | { |
1937 | return ENOMEM; | 1939 | return ENOMEM; |
@@ -1959,7 +1961,7 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1959 | 1961 | ||
1960 | case XD3_ADD: | 1962 | case XD3_ADD: |
1961 | /* Adds are implicit, put them into the input buffer. */ | 1963 | /* Adds are implicit, put them into the input buffer. */ |
1962 | memcpy (main_bdata + window_pos, | 1964 | memcpy (main_bdata + window_pos, |
1963 | stream->whole_target.adds + inst->addr, take); | 1965 | stream->whole_target.adds + inst->addr, take); |
1964 | break; | 1966 | break; |
1965 | 1967 | ||
@@ -1976,14 +1978,14 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1976 | } | 1978 | } |
1977 | addr = inst->addr; | 1979 | addr = inst->addr; |
1978 | } | 1980 | } |
1979 | else | 1981 | else |
1980 | { | 1982 | { |
1981 | XD3_ASSERT (inst->addr >= window_start); | 1983 | XD3_ASSERT (inst->addr >= window_start); |
1982 | addr = inst->addr - window_start; | 1984 | addr = inst->addr - window_start; |
1983 | } | 1985 | } |
1984 | IF_DEBUG2 (DP(RINT "[merge copy] winpos %u take %u addr %"Q"u mode %u\n", | 1986 | IF_DEBUG2 (DP(RINT "[merge copy] winpos %u take %u addr %"Q"u mode %u\n", |
1985 | window_pos, take, addr, inst->mode)); | 1987 | window_pos, take, addr, inst->mode)); |
1986 | if ((ret = xd3_found_match (recode_stream, window_pos, take, | 1988 | if ((ret = xd3_found_match (recode_stream, window_pos, take, |
1987 | addr, inst->mode != 0))) | 1989 | addr, inst->mode != 0))) |
1988 | { | 1990 | { |
1989 | return ret; | 1991 | return ret; |
@@ -2381,9 +2383,9 @@ main_secondary_decompress_check (main_file *file, | |||
2381 | 2383 | ||
2382 | if (check_nread == try_read) | 2384 | if (check_nread == try_read) |
2383 | { | 2385 | { |
2384 | ret = main_file_read (file, | 2386 | ret = main_file_read (file, |
2385 | input_buf + try_read, | 2387 | input_buf + try_read, |
2386 | input_size - try_read, | 2388 | input_size - try_read, |
2387 | nread, | 2389 | nread, |
2388 | "input read failed"); | 2390 | "input read failed"); |
2389 | } | 2391 | } |
@@ -2732,7 +2734,7 @@ main_read_primary_input (main_file *file, | |||
2732 | { | 2734 | { |
2733 | /* Application header overrides magic number. */ | 2735 | /* Application header overrides magic number. */ |
2734 | } | 2736 | } |
2735 | else | 2737 | else |
2736 | { | 2738 | { |
2737 | return main_secondary_decompress_check (file, buf, size, nread); | 2739 | return main_secondary_decompress_check (file, buf, size, nread); |
2738 | } | 2740 | } |
@@ -2844,7 +2846,7 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2844 | } | 2846 | } |
2845 | 2847 | ||
2846 | if (sfile->size_known && source_size < option_srcwinsz) | 2848 | if (sfile->size_known && source_size < option_srcwinsz) |
2847 | { | 2849 | { |
2848 | blksize = (source_size / MIN_LRU_SIZE); | 2850 | blksize = (source_size / MIN_LRU_SIZE); |
2849 | } | 2851 | } |
2850 | else | 2852 | else |
@@ -2885,12 +2887,12 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2885 | main_blklru_list_remove (& lru[0]); | 2887 | main_blklru_list_remove (& lru[0]); |
2886 | lru = NULL; | 2888 | lru = NULL; |
2887 | 2889 | ||
2888 | if (ret != 0) | 2890 | if (ret != 0) |
2889 | { | 2891 | { |
2890 | main_free (block0.blk); | 2892 | main_free (block0.blk); |
2891 | 2893 | ||
2892 | XPR(NT "error reading source %s: %s\n", | 2894 | XPR(NT "error reading source %s: %s\n", |
2893 | sfile->filename, | 2895 | sfile->filename, |
2894 | xd3_mainerror (ret)); | 2896 | xd3_mainerror (ret)); |
2895 | 2897 | ||
2896 | return ret; | 2898 | return ret; |
@@ -2931,7 +2933,7 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2931 | lru[0].blkno = 0; | 2933 | lru[0].blkno = 0; |
2932 | lru[0].size = source->onblk; | 2934 | lru[0].size = source->onblk; |
2933 | 2935 | ||
2934 | if (! sfile->size_known) | 2936 | if (! sfile->size_known) |
2935 | { | 2937 | { |
2936 | do_not_lru = 1; | 2938 | do_not_lru = 1; |
2937 | } | 2939 | } |
@@ -2949,14 +2951,14 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2949 | ret = ENOMEM; | 2951 | ret = ENOMEM; |
2950 | return ret; | 2952 | return ret; |
2951 | } | 2953 | } |
2952 | 2954 | ||
2953 | if (do_not_lru == 0) | 2955 | if (do_not_lru == 0) |
2954 | { | 2956 | { |
2955 | main_blklru_list_push_back (& lru_free, & lru[i]); | 2957 | main_blklru_list_push_back (& lru_free, & lru[i]); |
2956 | } | 2958 | } |
2957 | } | 2959 | } |
2958 | 2960 | ||
2959 | if (sfile->size_known) | 2961 | if (sfile->size_known) |
2960 | { | 2962 | { |
2961 | ret = xd3_set_source_and_size (stream, source, source_size); | 2963 | ret = xd3_set_source_and_size (stream, source, source_size); |
2962 | } | 2964 | } |
@@ -2984,7 +2986,7 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2984 | 2986 | ||
2985 | if (sfile->size_known) | 2987 | if (sfile->size_known) |
2986 | { | 2988 | { |
2987 | sprintf (srcszbuf, "source size %s [%"Q"u]", | 2989 | sprintf (srcszbuf, "source size %s [%"Q"u]", |
2988 | main_format_bcnt (source_size, srccntbuf), | 2990 | main_format_bcnt (source_size, srccntbuf), |
2989 | source_size); | 2991 | source_size); |
2990 | } | 2992 | } |
@@ -2994,7 +2996,7 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2994 | } | 2996 | } |
2995 | 2997 | ||
2996 | nbufs[0] = 0; | 2998 | nbufs[0] = 0; |
2997 | 2999 | ||
2998 | if (option_verbose > 1) | 3000 | if (option_verbose > 1) |
2999 | { | 3001 | { |
3000 | sprintf(nbufs, " #bufs %u", lru_size); | 3002 | sprintf(nbufs, " #bufs %u", lru_size); |
@@ -3027,8 +3029,8 @@ main_get_winsize (main_file *ifile) { | |||
3027 | 3029 | ||
3028 | if (option_verbose > 1) | 3030 | if (option_verbose > 1) |
3029 | { | 3031 | { |
3030 | XPR(NT "input %s window size %s\n", | 3032 | XPR(NT "input %s window size %s\n", |
3031 | ifile->filename, | 3033 | ifile->filename, |
3032 | main_format_bcnt (size, iszbuf)); | 3034 | main_format_bcnt (size, iszbuf)); |
3033 | } | 3035 | } |
3034 | 3036 | ||
@@ -3080,12 +3082,12 @@ main_getblk_lru (xd3_source *source, xoff_t blkno, main_blklru** blrup, int *is_ | |||
3080 | } | 3082 | } |
3081 | } | 3083 | } |
3082 | 3084 | ||
3083 | if (do_not_lru) | 3085 | if (do_not_lru) |
3084 | { | 3086 | { |
3085 | int idx = blkno % lru_size; | 3087 | int idx = blkno % lru_size; |
3086 | blru = & lru[idx]; | 3088 | blru = & lru[idx]; |
3087 | } | 3089 | } |
3088 | else | 3090 | else |
3089 | { | 3091 | { |
3090 | if (! main_blklru_list_empty (& lru_free)) | 3092 | if (! main_blklru_list_empty (& lru_free)) |
3091 | { | 3093 | { |
@@ -3140,7 +3142,7 @@ main_getblk_func (xd3_stream *stream, | |||
3140 | return ret; | 3142 | return ret; |
3141 | } | 3143 | } |
3142 | 3144 | ||
3143 | if (!is_new) | 3145 | if (!is_new) |
3144 | { | 3146 | { |
3145 | source->curblkno = blkno; | 3147 | source->curblkno = blkno; |
3146 | source->onblk = blru->size; | 3148 | source->onblk = blru->size; |
@@ -3180,18 +3182,19 @@ main_getblk_func (xd3_stream *stream, | |||
3180 | if (option_verbose) | 3182 | if (option_verbose) |
3181 | { | 3183 | { |
3182 | XPR(NT "source can't seek backwards; requested block offset " | 3184 | XPR(NT "source can't seek backwards; requested block offset " |
3183 | "%"Q"u source position is %"Q"u\n", | 3185 | "%"Q"u source position is %"Q"u\n", |
3184 | pos, sfile->source_position); | 3186 | pos, sfile->source_position); |
3185 | } | 3187 | } |
3186 | 3188 | ||
3187 | sfile->seek_failed = 1; | 3189 | sfile->seek_failed = 1; |
3188 | stream->msg = "non-seekable source: copy is too far back (try raising -B)"; | 3190 | stream->msg = "non-seekable source: " |
3191 | "copy is too far back (try raising -B)"; | ||
3189 | return XD3_TOOFARBACK; | 3192 | return XD3_TOOFARBACK; |
3190 | } | 3193 | } |
3191 | 3194 | ||
3192 | if (option_verbose > 2 || (option_verbose > 1 && !sfile->seek_failed)) | 3195 | if (option_verbose > 2 || (option_verbose > 1 && !sfile->seek_failed)) |
3193 | { | 3196 | { |
3194 | XPR(NT "non-seekable source skipping %"Q"u bytes @ %"Q"u\n", | 3197 | XPR(NT "non-seekable source skipping %"Q"u bytes @ %"Q"u\n", |
3195 | pos - sfile->source_position, | 3198 | pos - sfile->source_position, |
3196 | sfile->source_position); | 3199 | sfile->source_position); |
3197 | } | 3200 | } |
@@ -3218,8 +3221,8 @@ main_getblk_func (xd3_stream *stream, | |||
3218 | 3221 | ||
3219 | if ((ret = main_read_primary_input (sfile, | 3222 | if ((ret = main_read_primary_input (sfile, |
3220 | (uint8_t*) blru->blk, | 3223 | (uint8_t*) blru->blk, |
3221 | source->blksize, | 3224 | source->blksize, |
3222 | & nread, | 3225 | & nread, |
3223 | 1 /* source */))) | 3226 | 1 /* source */))) |
3224 | { | 3227 | { |
3225 | return ret; | 3228 | return ret; |
@@ -3235,7 +3238,7 @@ main_getblk_func (xd3_stream *stream, | |||
3235 | sfile->source_position += nread; | 3238 | sfile->source_position += nread; |
3236 | blru->size = nread; | 3239 | blru->size = nread; |
3237 | 3240 | ||
3238 | IF_DEBUG1 (DP(RINT "[getblk] skip blkno %"Q"u {%"Q"u} size %u\n", | 3241 | IF_DEBUG1 (DP(RINT "[getblk] skip blkno %"Q"u {%"Q"u} size %u\n", |
3239 | skip_blkno, blru->blkno, blru->size)); | 3242 | skip_blkno, blru->blkno, blru->size)); |
3240 | 3243 | ||
3241 | XD3_ASSERT (sfile->source_position <= pos); | 3244 | XD3_ASSERT (sfile->source_position <= pos); |
@@ -3250,9 +3253,9 @@ main_getblk_func (xd3_stream *stream, | |||
3250 | return ret; | 3253 | return ret; |
3251 | } | 3254 | } |
3252 | 3255 | ||
3253 | if ((ret = main_read_primary_input (sfile, | 3256 | if ((ret = main_read_primary_input (sfile, |
3254 | (uint8_t*) blru->blk, | 3257 | (uint8_t*) blru->blk, |
3255 | source->blksize, | 3258 | source->blksize, |
3256 | & nread, | 3259 | & nread, |
3257 | 1 /* source */))) | 3260 | 1 /* source */))) |
3258 | { | 3261 | { |
@@ -3461,7 +3464,7 @@ main_input (xd3_cmd cmd, | |||
3461 | } | 3464 | } |
3462 | 3465 | ||
3463 | #if VCDIFF_TOOLS | 3466 | #if VCDIFF_TOOLS |
3464 | if ((cmd == CMD_MERGE || cmd == CMD_MERGE_ARG) && | 3467 | if ((cmd == CMD_MERGE || cmd == CMD_MERGE_ARG) && |
3465 | (ret = xd3_whole_state_init (& stream))) | 3468 | (ret = xd3_whole_state_init (& stream))) |
3466 | { | 3469 | { |
3467 | XPR(NT XD3_LIB_ERRMSG (& stream, ret)); | 3470 | XPR(NT XD3_LIB_ERRMSG (& stream, ret)); |
@@ -3473,7 +3476,7 @@ main_input (xd3_cmd cmd, | |||
3473 | { | 3476 | { |
3474 | /* When not decoding, set source now. The decoder delays this | 3477 | /* When not decoding, set source now. The decoder delays this |
3475 | * step until XD3_GOTHEADER. */ | 3478 | * step until XD3_GOTHEADER. */ |
3476 | if (sfile && sfile->filename != NULL) | 3479 | if (sfile && sfile->filename != NULL) |
3477 | { | 3480 | { |
3478 | if ((ret = main_set_source (& stream, cmd, sfile, & source))) | 3481 | if ((ret = main_set_source (& stream, cmd, sfile, & source))) |
3479 | { | 3482 | { |
@@ -3483,7 +3486,7 @@ main_input (xd3_cmd cmd, | |||
3483 | XD3_ASSERT(stream.src != NULL); | 3486 | XD3_ASSERT(stream.src != NULL); |
3484 | } | 3487 | } |
3485 | } | 3488 | } |
3486 | 3489 | ||
3487 | if (cmd == CMD_PRINTHDR || | 3490 | if (cmd == CMD_PRINTHDR || |
3488 | cmd == CMD_PRINTHDRS || | 3491 | cmd == CMD_PRINTHDRS || |
3489 | cmd == CMD_PRINTDELTA || | 3492 | cmd == CMD_PRINTDELTA || |
@@ -3593,7 +3596,7 @@ main_input (xd3_cmd cmd, | |||
3593 | { | 3596 | { |
3594 | return EXIT_FAILURE; | 3597 | return EXIT_FAILURE; |
3595 | } | 3598 | } |
3596 | 3599 | ||
3597 | if ((ret = output_func (& stream, ofile)) && | 3600 | if ((ret = output_func (& stream, ofile)) && |
3598 | (ret != PRINTHDR_SPECIAL)) | 3601 | (ret != PRINTHDR_SPECIAL)) |
3599 | { | 3602 | { |
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c index 3a053ed..98c0e57 100644 --- a/xdelta3/xdelta3.c +++ b/xdelta3/xdelta3.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* xdelta 3 - delta compression tools and library | 1 | /* xdelta 3 - delta compression tools and library |
2 | * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, | 2 | * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, |
3 | * 2008, 2009. Joshua P. MacDonald | 3 | * 2008, 2009, 2010. Joshua P. MacDonald |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -540,7 +540,8 @@ static usize_t xd3_smatch (xd3_stream *stream, | |||
540 | usize_t scksum, | 540 | usize_t scksum, |
541 | usize_t *match_offset); | 541 | usize_t *match_offset); |
542 | static int xd3_string_match_init (xd3_stream *stream); | 542 | static int xd3_string_match_init (xd3_stream *stream); |
543 | static uint32_t xd3_scksum (uint32_t *state, const uint8_t *seg, const usize_t ln); | 543 | static uint32_t xd3_scksum (uint32_t *state, const uint8_t *seg, |
544 | const usize_t ln); | ||
544 | static usize_t xd3_comprun (const uint8_t *seg, usize_t slook, uint8_t *run_cp); | 545 | static usize_t xd3_comprun (const uint8_t *seg, usize_t slook, uint8_t *run_cp); |
545 | static int xd3_srcwin_move_point (xd3_stream *stream, | 546 | static int xd3_srcwin_move_point (xd3_stream *stream, |
546 | usize_t *next_move_point); | 547 | usize_t *next_move_point); |
@@ -764,9 +765,9 @@ const xd3_sec_type fgk_sec_type = | |||
764 | (xd3_sec_stream* (*)(xd3_stream*)) fgk_alloc, | 765 | (xd3_sec_stream* (*)(xd3_stream*)) fgk_alloc, |
765 | (void (*)(xd3_stream*, xd3_sec_stream*)) fgk_destroy, | 766 | (void (*)(xd3_stream*, xd3_sec_stream*)) fgk_destroy, |
766 | (void (*)(xd3_sec_stream*)) fgk_init, | 767 | (void (*)(xd3_sec_stream*)) fgk_init, |
767 | (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, | 768 | (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, |
768 | uint8_t**, const uint8_t*)) xd3_decode_fgk, | 769 | uint8_t**, const uint8_t*)) xd3_decode_fgk, |
769 | IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, | 770 | IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, |
770 | xd3_output*, xd3_sec_cfg*)) xd3_encode_fgk) | 771 | xd3_output*, xd3_sec_cfg*)) xd3_encode_fgk) |
771 | }; | 772 | }; |
772 | #endif | 773 | #endif |
@@ -781,9 +782,9 @@ const xd3_sec_type djw_sec_type = | |||
781 | (xd3_sec_stream* (*)(xd3_stream*)) djw_alloc, | 782 | (xd3_sec_stream* (*)(xd3_stream*)) djw_alloc, |
782 | (void (*)(xd3_stream*, xd3_sec_stream*)) djw_destroy, | 783 | (void (*)(xd3_stream*, xd3_sec_stream*)) djw_destroy, |
783 | (void (*)(xd3_sec_stream*)) djw_init, | 784 | (void (*)(xd3_sec_stream*)) djw_init, |
784 | (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, | 785 | (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, |
785 | uint8_t**, const uint8_t*)) xd3_decode_huff, | 786 | uint8_t**, const uint8_t*)) xd3_decode_huff, |
786 | IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, | 787 | IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, |
787 | xd3_output*, xd3_sec_cfg*)) xd3_encode_huff) | 788 | xd3_output*, xd3_sec_cfg*)) xd3_encode_huff) |
788 | }; | 789 | }; |
789 | #endif | 790 | #endif |
@@ -1251,7 +1252,7 @@ static usize_t __alternate_code_table_compressed_size; | |||
1251 | /* This function generates a delta describing the code table for | 1252 | /* This function generates a delta describing the code table for |
1252 | * encoding within a VCDIFF file. This function is NOT thread safe | 1253 | * encoding within a VCDIFF file. This function is NOT thread safe |
1253 | * because it is only intended that this function is used to generate | 1254 | * because it is only intended that this function is used to generate |
1254 | * statically-compiled strings. "comp_string" must be sized | 1255 | * statically-compiled strings. "comp_string" must be sized |
1255 | * CODE_TABLE_VCDIFF_SIZE. */ | 1256 | * CODE_TABLE_VCDIFF_SIZE. */ |
1256 | int xd3_compute_code_table_encoding (xd3_stream *in_stream, | 1257 | int xd3_compute_code_table_encoding (xd3_stream *in_stream, |
1257 | const xd3_dinst *code_table, | 1258 | const xd3_dinst *code_table, |
@@ -1451,7 +1452,7 @@ xd3_apply_table_encoding (xd3_stream *in_stream, const uint8_t *data, usize_t si | |||
1451 | 1452 | ||
1452 | xd3_compute_code_table_string (xd3_rfc3284_code_table (), dflt_string); | 1453 | xd3_compute_code_table_string (xd3_rfc3284_code_table (), dflt_string); |
1453 | 1454 | ||
1454 | if ((ret = xd3_decode_memory (data, size, | 1455 | if ((ret = xd3_decode_memory (data, size, |
1455 | dflt_string, CODE_TABLE_STRING_SIZE, | 1456 | dflt_string, CODE_TABLE_STRING_SIZE, |
1456 | code_string, &code_size, | 1457 | code_string, &code_size, |
1457 | CODE_TABLE_STRING_SIZE, | 1458 | CODE_TABLE_STRING_SIZE, |
@@ -1623,9 +1624,9 @@ xd3_decode_bytes (xd3_stream *stream, uint8_t *buf, usize_t *pos, usize_t size) | |||
1623 | usize_t want; | 1624 | usize_t want; |
1624 | usize_t take; | 1625 | usize_t take; |
1625 | 1626 | ||
1626 | /* Note: The case where (*pos == size) happens when a zero-length appheader or code | 1627 | /* Note: The case where (*pos == size) happens when a zero-length |
1627 | * table is transmitted, but there is nothing in the standard against that. */ | 1628 | * appheader or code table is transmitted, but there is nothing in |
1628 | 1629 | * the standard against that. */ | |
1629 | while (*pos < size) | 1630 | while (*pos < size) |
1630 | { | 1631 | { |
1631 | if (stream->avail_in == 0) | 1632 | if (stream->avail_in == 0) |
@@ -1918,7 +1919,10 @@ xd3_update_cache (xd3_addr_cache* acache, usize_t addr) | |||
1918 | #if XD3_ENCODER | 1919 | #if XD3_ENCODER |
1919 | /* OPT: this gets called a lot, can it be optimized? */ | 1920 | /* OPT: this gets called a lot, can it be optimized? */ |
1920 | static int | 1921 | static int |
1921 | xd3_encode_address (xd3_stream *stream, usize_t addr, usize_t here, uint8_t* mode) | 1922 | xd3_encode_address (xd3_stream *stream, |
1923 | usize_t addr, | ||
1924 | usize_t here, | ||
1925 | uint8_t* mode) | ||
1922 | { | 1926 | { |
1923 | usize_t d, bestd; | 1927 | usize_t d, bestd; |
1924 | usize_t i, bestm, ret; | 1928 | usize_t i, bestm, ret; |
@@ -1948,7 +1952,7 @@ xd3_encode_address (xd3_stream *stream, usize_t addr, usize_t here, uint8_t* mod | |||
1948 | { | 1952 | { |
1949 | /* Note: If we used signed computation here, we'd could compte d | 1953 | /* Note: If we used signed computation here, we'd could compte d |
1950 | * and then check (d >= 0 && d < bestd). */ | 1954 | * and then check (d >= 0 && d < bestd). */ |
1951 | if (addr >= acache->near_array[i]) | 1955 | if (addr >= acache->near_array[i]) |
1952 | { | 1956 | { |
1953 | d = addr - acache->near_array[i]; | 1957 | d = addr - acache->near_array[i]; |
1954 | 1958 | ||
@@ -1962,18 +1966,26 @@ xd3_encode_address (xd3_stream *stream, usize_t addr, usize_t here, uint8_t* mod | |||
1962 | } | 1966 | } |
1963 | } | 1967 | } |
1964 | 1968 | ||
1965 | if (acache->s_same > 0 && acache->same_array[d = addr%(acache->s_same*256)] == addr) | 1969 | if (acache->s_same > 0 && |
1970 | acache->same_array[d = addr%(acache->s_same*256)] == addr) | ||
1966 | { | 1971 | { |
1967 | bestd = d%256; | 1972 | bestd = d%256; |
1968 | bestm = acache->s_near + 2 + d/256; /* 2 + s_near offsets past the VCD_NEAR modes */ | 1973 | /* 2 + s_near offsets past the VCD_NEAR modes */ |
1974 | bestm = acache->s_near + 2 + d/256; | ||
1969 | 1975 | ||
1970 | if ((ret = xd3_emit_byte (stream, & ADDR_TAIL (stream), bestd))) { return ret; } | 1976 | if ((ret = xd3_emit_byte (stream, & ADDR_TAIL (stream), bestd))) |
1977 | { | ||
1978 | return ret; | ||
1979 | } | ||
1971 | } | 1980 | } |
1972 | else | 1981 | else |
1973 | { | 1982 | { |
1974 | good: | 1983 | good: |
1975 | 1984 | ||
1976 | if ((ret = xd3_emit_size (stream, & ADDR_TAIL (stream), bestd))) { return ret; } | 1985 | if ((ret = xd3_emit_size (stream, & ADDR_TAIL (stream), bestd))) |
1986 | { | ||
1987 | return ret; | ||
1988 | } | ||
1977 | } | 1989 | } |
1978 | 1990 | ||
1979 | xd3_update_cache (acache, addr); | 1991 | xd3_update_cache (acache, addr); |
@@ -2054,7 +2066,7 @@ xd3_alloc (xd3_stream *stream, | |||
2054 | if (a != NULL) | 2066 | if (a != NULL) |
2055 | { | 2067 | { |
2056 | IF_DEBUG (stream->alloc_cnt += 1); | 2068 | IF_DEBUG (stream->alloc_cnt += 1); |
2057 | IF_DEBUG2 (DP(RINT "[stream %p malloc] size %u ptr %p\n", | 2069 | IF_DEBUG2 (DP(RINT "[stream %p malloc] size %u ptr %p\n", |
2058 | stream, elts * size, a)); | 2070 | stream, elts * size, a)); |
2059 | } | 2071 | } |
2060 | else | 2072 | else |
@@ -2073,7 +2085,7 @@ xd3_free (xd3_stream *stream, | |||
2073 | { | 2085 | { |
2074 | IF_DEBUG (stream->free_cnt += 1); | 2086 | IF_DEBUG (stream->free_cnt += 1); |
2075 | XD3_ASSERT (stream->free_cnt <= stream->alloc_cnt); | 2087 | XD3_ASSERT (stream->free_cnt <= stream->alloc_cnt); |
2076 | IF_DEBUG2 (DP(RINT "[stream %p free] %p\n", | 2088 | IF_DEBUG2 (DP(RINT "[stream %p free] %p\n", |
2077 | stream, ptr)); | 2089 | stream, ptr)); |
2078 | stream->free (stream->opaque, ptr); | 2090 | stream->free (stream->opaque, ptr); |
2079 | } | 2091 | } |
@@ -2109,12 +2121,14 @@ xd3_alloc_output (xd3_stream *stream, | |||
2109 | } | 2121 | } |
2110 | else | 2122 | else |
2111 | { | 2123 | { |
2112 | if ((output = (xd3_output*) xd3_alloc (stream, 1, sizeof (xd3_output))) == NULL) | 2124 | if ((output = (xd3_output*) xd3_alloc (stream, 1, |
2125 | sizeof (xd3_output))) == NULL) | ||
2113 | { | 2126 | { |
2114 | return NULL; | 2127 | return NULL; |
2115 | } | 2128 | } |
2116 | 2129 | ||
2117 | if ((base = (uint8_t*) xd3_alloc (stream, XD3_ALLOCSIZE, sizeof (uint8_t))) == NULL) | 2130 | if ((base = (uint8_t*) xd3_alloc (stream, XD3_ALLOCSIZE, |
2131 | sizeof (uint8_t))) == NULL) | ||
2118 | { | 2132 | { |
2119 | xd3_free (stream, output); | 2133 | xd3_free (stream, output); |
2120 | return NULL; | 2134 | return NULL; |
@@ -2448,7 +2462,7 @@ xd3_config_stream(xd3_stream *stream, | |||
2448 | 2462 | ||
2449 | switch (level) | 2463 | switch (level) |
2450 | { | 2464 | { |
2451 | case 1: | 2465 | case 1: |
2452 | IF_BUILD_FASTEST(*smatcher = __smatcher_fastest; | 2466 | IF_BUILD_FASTEST(*smatcher = __smatcher_fastest; |
2453 | break;) | 2467 | break;) |
2454 | case 2: | 2468 | case 2: |
@@ -2478,7 +2492,7 @@ xd3_config_stream(xd3_stream *stream, | |||
2478 | return 0; | 2492 | return 0; |
2479 | } | 2493 | } |
2480 | 2494 | ||
2481 | /***************************************************************** | 2495 | /*********************************************************** |
2482 | Getblk interface | 2496 | Getblk interface |
2483 | ***********************************************************/ | 2497 | ***********************************************************/ |
2484 | 2498 | ||
@@ -2492,7 +2506,7 @@ xoff_t xd3_source_eof(const xd3_source *src) | |||
2492 | inline | 2506 | inline |
2493 | usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno) | 2507 | usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno) |
2494 | { | 2508 | { |
2495 | usize_t r = (blkno == src->max_blkno ? | 2509 | usize_t r = (blkno == src->max_blkno ? |
2496 | src->onlastblk : | 2510 | src->onlastblk : |
2497 | src->blksize); | 2511 | src->blksize); |
2498 | return r; | 2512 | return r; |
@@ -2515,15 +2529,15 @@ xd3_getblk (xd3_stream *stream, xoff_t blkno) | |||
2515 | stream->msg = "getblk source input"; | 2529 | stream->msg = "getblk source input"; |
2516 | return XD3_GETSRCBLK; | 2530 | return XD3_GETSRCBLK; |
2517 | } | 2531 | } |
2518 | 2532 | ||
2519 | ret = stream->getblk (stream, source, blkno); | 2533 | ret = stream->getblk (stream, source, blkno); |
2520 | if (ret != 0) | 2534 | if (ret != 0) |
2521 | { | 2535 | { |
2522 | IF_DEBUG1 (DP(RINT "[getblk] app error: %s\n", xd3_strerror (ret))); | 2536 | IF_DEBUG1 (DP(RINT "[getblk] app error: %s\n", xd3_strerror (ret))); |
2523 | return ret; | 2537 | return ret; |
2524 | } | 2538 | } |
2525 | } | 2539 | } |
2526 | 2540 | ||
2527 | if (blkno >= source->frontier_blkno) | 2541 | if (blkno >= source->frontier_blkno) |
2528 | { | 2542 | { |
2529 | source->max_blkno = blkno; | 2543 | source->max_blkno = blkno; |
@@ -2533,13 +2547,13 @@ xd3_getblk (xd3_stream *stream, xoff_t blkno) | |||
2533 | { | 2547 | { |
2534 | source->frontier_blkno = blkno + 1; | 2548 | source->frontier_blkno = blkno + 1; |
2535 | 2549 | ||
2536 | IF_DEBUG2 (DP(RINT "[getblk] full source blkno %"Q"u: source length unknown %"Q"u\n", | 2550 | IF_DEBUG2 (DP(RINT "[getblk] full source blkno %"Q"u: source length unknown %"Q"u\n", |
2537 | blkno, | 2551 | blkno, |
2538 | xd3_source_eof (source))); | 2552 | xd3_source_eof (source))); |
2539 | } | 2553 | } |
2540 | else | 2554 | else |
2541 | { | 2555 | { |
2542 | if (!source->eof_known) | 2556 | if (!source->eof_known) |
2543 | { | 2557 | { |
2544 | IF_DEBUG2 (DP(RINT "[getblk] eof block has %d bytes; source length known %"Q"u\n", | 2558 | IF_DEBUG2 (DP(RINT "[getblk] eof block has %d bytes; source length known %"Q"u\n", |
2545 | xd3_bytes_on_srcblk (source, blkno), | 2559 | xd3_bytes_on_srcblk (source, blkno), |
@@ -2552,7 +2566,7 @@ xd3_getblk (xd3_stream *stream, xoff_t blkno) | |||
2552 | } | 2566 | } |
2553 | 2567 | ||
2554 | XD3_ASSERT (source->curblk != NULL); | 2568 | XD3_ASSERT (source->curblk != NULL); |
2555 | IF_DEBUG2 (DP(RINT "[getblk] read source block %"Q"u onblk %u blksize %u\n", | 2569 | IF_DEBUG2 (DP(RINT "[getblk] read source block %"Q"u onblk %u blksize %u\n", |
2556 | blkno, source->onblk, source->blksize)); | 2570 | blkno, source->onblk, source->blksize)); |
2557 | 2571 | ||
2558 | if (blkno == source->max_blkno) | 2572 | if (blkno == source->max_blkno) |
@@ -2609,7 +2623,7 @@ xd3_set_source_and_size (xd3_stream *stream, xd3_source *user_source, xoff_t sou | |||
2609 | source_size)); | 2623 | source_size)); |
2610 | 2624 | ||
2611 | xd3_blksize_div(source_size, | 2625 | xd3_blksize_div(source_size, |
2612 | stream->src, | 2626 | stream->src, |
2613 | &stream->src->max_blkno, | 2627 | &stream->src->max_blkno, |
2614 | &stream->src->onlastblk); | 2628 | &stream->src->onlastblk); |
2615 | } | 2629 | } |
@@ -2773,7 +2787,7 @@ xd3_iopt_finish_encoding (xd3_stream *stream, xd3_rinst *inst) | |||
2773 | } | 2787 | } |
2774 | else | 2788 | else |
2775 | { | 2789 | { |
2776 | stream->srcwin_decided_early = (!stream->src->eof_known || | 2790 | stream->srcwin_decided_early = (!stream->src->eof_known || |
2777 | (stream->srcwin_cksum_pos < xd3_source_eof (stream->src))); | 2791 | (stream->srcwin_cksum_pos < xd3_source_eof (stream->src))); |
2778 | } | 2792 | } |
2779 | 2793 | ||
@@ -2804,7 +2818,7 @@ xd3_iopt_finish_encoding (xd3_stream *stream, xd3_rinst *inst) | |||
2804 | /* Note: used to assert inst->size >= MIN_MATCH, but not true | 2818 | /* Note: used to assert inst->size >= MIN_MATCH, but not true |
2805 | * for merge operations & identical match heuristics. */ | 2819 | * for merge operations & identical match heuristics. */ |
2806 | /* the "here" position is always offset by taroff */ | 2820 | /* the "here" position is always offset by taroff */ |
2807 | if ((ret = xd3_encode_address (stream, addr, inst->pos + stream->taroff, | 2821 | if ((ret = xd3_encode_address (stream, addr, inst->pos + stream->taroff, |
2808 | & inst->type))) | 2822 | & inst->type))) |
2809 | { | 2823 | { |
2810 | return ret; | 2824 | return ret; |
@@ -3609,7 +3623,8 @@ xd3_encode_init (xd3_stream *stream, int full_init) | |||
3609 | * identical or short inputs require no table allocation. */ | 3623 | * identical or short inputs require no table allocation. */ |
3610 | if (large_comp) | 3624 | if (large_comp) |
3611 | { | 3625 | { |
3612 | usize_t hash_values = (stream->srcwin_maxsz / stream->smatcher.large_step); | 3626 | usize_t hash_values = (stream->srcwin_maxsz / |
3627 | stream->smatcher.large_step); | ||
3613 | 3628 | ||
3614 | xd3_size_hashtable (stream, | 3629 | xd3_size_hashtable (stream, |
3615 | hash_values, | 3630 | hash_values, |
@@ -3780,7 +3795,7 @@ xd3_encode_input (xd3_stream *stream) | |||
3780 | return XD3_WINSTART; | 3795 | return XD3_WINSTART; |
3781 | 3796 | ||
3782 | case ENC_SEARCH: | 3797 | case ENC_SEARCH: |
3783 | IF_DEBUG2 (DP(RINT "[SEARCH] match_state %d avail_in %u %s\n", | 3798 | IF_DEBUG2 (DP(RINT "[SEARCH] match_state %d avail_in %u %s\n", |
3784 | stream->match_state, stream->avail_in, stream->src ? "source" : "no source")); | 3799 | stream->match_state, stream->avail_in, stream->src ? "source" : "no source")); |
3785 | 3800 | ||
3786 | /* Reentrant matching. */ | 3801 | /* Reentrant matching. */ |
@@ -3795,7 +3810,7 @@ xd3_encode_input (xd3_stream *stream) | |||
3795 | * that extends to the end of the previous window. The | 3810 | * that extends to the end of the previous window. The |
3796 | * match_srcpos field is initially zero and later set | 3811 | * match_srcpos field is initially zero and later set |
3797 | * during xd3_source_extend_match. */ | 3812 | * during xd3_source_extend_match. */ |
3798 | 3813 | ||
3799 | if (stream->avail_in > 0) | 3814 | if (stream->avail_in > 0) |
3800 | { | 3815 | { |
3801 | /* This call can't fail because the source window is | 3816 | /* This call can't fail because the source window is |
@@ -3824,7 +3839,7 @@ xd3_encode_input (xd3_stream *stream) | |||
3824 | * or else it can get stuck in a match-backward | 3839 | * or else it can get stuck in a match-backward |
3825 | * (getsrcblk) then match-forward (getsrcblk), | 3840 | * (getsrcblk) then match-forward (getsrcblk), |
3826 | * find insufficient match length, then repeat | 3841 | * find insufficient match length, then repeat |
3827 | * exactly the same search. | 3842 | * exactly the same search. |
3828 | */ | 3843 | */ |
3829 | stream->input_position += stream->match_fwd; | 3844 | stream->input_position += stream->match_fwd; |
3830 | } | 3845 | } |
@@ -3962,7 +3977,7 @@ xd3_process_stream (int is_encode, | |||
3962 | 3977 | ||
3963 | (*output_size) = 0; | 3978 | (*output_size) = 0; |
3964 | 3979 | ||
3965 | stream->flags |= XD3_FLUSH; | 3980 | stream->flags |= XD3_FLUSH; |
3966 | 3981 | ||
3967 | xd3_avail_input (stream, input + ipos, n); | 3982 | xd3_avail_input (stream, input + ipos, n); |
3968 | ipos += n; | 3983 | ipos += n; |
@@ -4085,7 +4100,7 @@ xd3_process_memory (int is_encode, | |||
4085 | } | 4100 | } |
4086 | 4101 | ||
4087 | exit: | 4102 | exit: |
4088 | if (ret != 0) | 4103 | if (ret != 0) |
4089 | { | 4104 | { |
4090 | IF_DEBUG2 (DP(RINT "process_memory: %d: %s\n", ret, stream.msg)); | 4105 | IF_DEBUG2 (DP(RINT "process_memory: %d: %s\n", ret, stream.msg)); |
4091 | } | 4106 | } |
@@ -4303,7 +4318,8 @@ xd3_srcwin_setup (xd3_stream *stream) | |||
4303 | * issued, but we have to decide the source window base and length | 4318 | * issued, but we have to decide the source window base and length |
4304 | * now. */ | 4319 | * now. */ |
4305 | src->srcbase = stream->match_minaddr; | 4320 | src->srcbase = stream->match_minaddr; |
4306 | src->srclen = max ((usize_t) length, stream->avail_in + (stream->avail_in >> 2)); | 4321 | src->srclen = max ((usize_t) length, |
4322 | stream->avail_in + (stream->avail_in >> 2)); | ||
4307 | 4323 | ||
4308 | /* OPT: If we know the source size, it might be possible to reduce | 4324 | /* OPT: If we know the source size, it might be possible to reduce |
4309 | * srclen. */ | 4325 | * srclen. */ |
@@ -4346,6 +4362,17 @@ xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos) | |||
4346 | goto bad; | 4362 | goto bad; |
4347 | } | 4363 | } |
4348 | 4364 | ||
4365 | /* Implement srcwin_maxsz, which prevents the encoder from seeking | ||
4366 | * back further than the LRU cache maintaining FIFO discipline, | ||
4367 | * which causes terrible performance. */ | ||
4368 | if (xd3_source_eof (stream->src) - srcpos > stream->srcwin_maxsz) { | ||
4369 | IF_DEBUG1(DP(RINT "[match_setup] rejected due to srcwin_maxsz " | ||
4370 | "distance eof=%"Q"u srcpos=%"Q"u maxsz=%u\n", | ||
4371 | xd3_source_eof (stream->src), | ||
4372 | srcpos, stream->srcwin_maxsz)); | ||
4373 | goto bad; | ||
4374 | } | ||
4375 | |||
4349 | /* Going backwards, the 1.5-pass algorithm allows some | 4376 | /* Going backwards, the 1.5-pass algorithm allows some |
4350 | * already-matched input may be covered by a longer source match. | 4377 | * already-matched input may be covered by a longer source match. |
4351 | * The greedy algorithm does not allow this. */ | 4378 | * The greedy algorithm does not allow this. */ |
@@ -4396,8 +4423,11 @@ xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos) | |||
4396 | } | 4423 | } |
4397 | } | 4424 | } |
4398 | 4425 | ||
4399 | IF_DEBUG2(DP(RINT "[match_setup] srcpos %"Q"u unrestricted back %u fwd %u\n", | 4426 | IF_DEBUG1(DP(RINT |
4427 | "[match_setup] srcpos %"Q"u (tgtpos %"Q"u) " | ||
4428 | "unrestricted maxback %u maxfwd %u\n", | ||
4400 | srcpos, | 4429 | srcpos, |
4430 | stream->total_in + stream->input_position, | ||
4401 | stream->match_maxback, | 4431 | stream->match_maxback, |
4402 | stream->match_maxfwd)); | 4432 | stream->match_maxfwd)); |
4403 | goto good; | 4433 | goto good; |
@@ -4407,9 +4437,10 @@ xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos) | |||
4407 | XD3_ASSERT (src->srclen > 0); | 4437 | XD3_ASSERT (src->srclen > 0); |
4408 | 4438 | ||
4409 | /* Restricted case: fail if the srcpos lies outside the source window */ | 4439 | /* Restricted case: fail if the srcpos lies outside the source window */ |
4410 | if ((srcpos < src->srcbase) || (srcpos > (src->srcbase + (xoff_t) src->srclen))) | 4440 | if ((srcpos < src->srcbase) || |
4441 | (srcpos > (src->srcbase + (xoff_t) src->srclen))) | ||
4411 | { | 4442 | { |
4412 | IF_DEBUG2(DP(RINT "[match_setup] restricted source window failure\n")); | 4443 | IF_DEBUG1(DP(RINT "[match_setup] restricted source window failure\n")); |
4413 | goto bad; | 4444 | goto bad; |
4414 | } | 4445 | } |
4415 | else | 4446 | else |
@@ -4428,8 +4459,11 @@ xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos) | |||
4428 | stream->match_maxfwd = srcavail; | 4459 | stream->match_maxfwd = srcavail; |
4429 | } | 4460 | } |
4430 | 4461 | ||
4431 | IF_DEBUG2(DP(RINT "[match_setup] srcpos %"Q"u restricted back %u fwd %u\n", | 4462 | IF_DEBUG1(DP(RINT |
4463 | "[match_setup] srcpos %"Q"u (tgtpos %"Q"u) " | ||
4464 | "restricted maxback %u maxfwd %u\n", | ||
4432 | srcpos, | 4465 | srcpos, |
4466 | stream->total_in + stream->input_position, | ||
4433 | stream->match_maxback, | 4467 | stream->match_maxback, |
4434 | stream->match_maxfwd)); | 4468 | stream->match_maxfwd)); |
4435 | goto good; | 4469 | goto good; |
@@ -4468,7 +4502,7 @@ xd3_forward_match(const uint8_t *s1c, const uint8_t *s2c, size_t n) | |||
4468 | s1[i++] == s2[j++] && | 4502 | s1[i++] == s2[j++] && |
4469 | s1[i++] == s2[j++] && | 4503 | s1[i++] == s2[j++] && |
4470 | s1[i++] == s2[j++] && | 4504 | s1[i++] == s2[j++] && |
4471 | s1[i++] == s2[j++] && | 4505 | s1[i++] == s2[j++] && |
4472 | s1[i++] == s2[j++]) { } | 4506 | s1[i++] == s2[j++]) { } |
4473 | 4507 | ||
4474 | i = (i - 1) * sizeof(int); | 4508 | i = (i - 1) * sizeof(int); |
@@ -4519,7 +4553,7 @@ xd3_source_extend_match (xd3_stream *stream) | |||
4519 | usize_t tryrem; /* tryrem is the number of matchable bytes */ | 4553 | usize_t tryrem; /* tryrem is the number of matchable bytes */ |
4520 | usize_t matched; | 4554 | usize_t matched; |
4521 | 4555 | ||
4522 | IF_DEBUG2(DP(RINT "[extend match] srcpos %"Q"u\n", | 4556 | IF_DEBUG2(DP(RINT "[extend match] srcpos %"Q"u\n", |
4523 | stream->match_srcpos)); | 4557 | stream->match_srcpos)); |
4524 | 4558 | ||
4525 | XD3_ASSERT (src != NULL); | 4559 | XD3_ASSERT (src != NULL); |
@@ -4556,7 +4590,7 @@ xd3_source_extend_match (xd3_stream *stream) | |||
4556 | } | 4590 | } |
4557 | 4591 | ||
4558 | tryrem = min (tryoff, stream->match_maxback - stream->match_back); | 4592 | tryrem = min (tryoff, stream->match_maxback - stream->match_back); |
4559 | 4593 | ||
4560 | IF_DEBUG2(DP(RINT "[maxback] maxback %u trysrc %"Q"u/%u tgt %u tryrem %u\n", | 4594 | IF_DEBUG2(DP(RINT "[maxback] maxback %u trysrc %"Q"u/%u tgt %u tryrem %u\n", |
4561 | stream->match_maxback, tryblk, tryoff, streamoff, tryrem)); | 4595 | stream->match_maxback, tryblk, tryoff, streamoff, tryrem)); |
4562 | 4596 | ||
@@ -4988,12 +5022,6 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point) | |||
4988 | */ | 5022 | */ |
4989 | logical_input_cksum_pos += stream->src->blksize; | 5023 | logical_input_cksum_pos += stream->src->blksize; |
4990 | 5024 | ||
4991 | IF_DEBUG1 (DP(RINT "[srcwin_move_point] T=%"Q"u{%"Q"u} S=%"Q"u EOF=%"Q"u %s\n", | ||
4992 | stream->total_in + stream->input_position, | ||
4993 | logical_input_cksum_pos, | ||
4994 | stream->srcwin_cksum_pos, | ||
4995 | xd3_source_eof (stream->src), | ||
4996 | stream->src->eof_known ? "known" : "unknown")); | ||
4997 | while (stream->srcwin_cksum_pos < logical_input_cksum_pos && | 5025 | while (stream->srcwin_cksum_pos < logical_input_cksum_pos && |
4998 | (!stream->src->eof_known || | 5026 | (!stream->src->eof_known || |
4999 | stream->srcwin_cksum_pos < xd3_source_eof (stream->src))) | 5027 | stream->srcwin_cksum_pos < xd3_source_eof (stream->src))) |
@@ -5016,14 +5044,26 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point) | |||
5016 | { | 5044 | { |
5017 | ret = XD3_INTERNAL; | 5045 | ret = XD3_INTERNAL; |
5018 | } | 5046 | } |
5047 | IF_DEBUG1 (DP(RINT | ||
5048 | "[srcwin_move_point] async getblk return for %"Q"u\n", | ||
5049 | blkno)); | ||
5019 | return ret; | 5050 | return ret; |
5020 | } | 5051 | } |
5021 | 5052 | ||
5053 | IF_DEBUG1 (DP(RINT | ||
5054 | "[srcwin_move_point] T=%"Q"u{%"Q"u} S=%"Q"u EOF=%"Q"u %s\n", | ||
5055 | stream->total_in + stream->input_position, | ||
5056 | logical_input_cksum_pos, | ||
5057 | stream->srcwin_cksum_pos, | ||
5058 | xd3_source_eof (stream->src), | ||
5059 | stream->src->eof_known ? "known" : "unknown")); | ||
5060 | |||
5022 | blkpos = xd3_bytes_on_srcblk (stream->src, blkno); | 5061 | blkpos = xd3_bytes_on_srcblk (stream->src, blkno); |
5023 | 5062 | ||
5024 | if (blkpos < (ssize_t) stream->smatcher.large_look) | 5063 | if (blkpos < (ssize_t) stream->smatcher.large_look) |
5025 | { | 5064 | { |
5026 | stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; | 5065 | stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; |
5066 | IF_DEBUG1 (DP(RINT "[srcwin_move_point] continue (end-of-block)\n")); | ||
5027 | continue; | 5067 | continue; |
5028 | } | 5068 | } |
5029 | 5069 | ||
@@ -5058,15 +5098,25 @@ xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point) | |||
5058 | stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; | 5098 | stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; |
5059 | } | 5099 | } |
5060 | 5100 | ||
5101 | IF_DEBUG1 (DP(RINT | ||
5102 | "[srcwin_move_point] exited loop T=%"Q"u{%"Q"u} S=%"Q"u EOF=%"Q"u %s\n", | ||
5103 | stream->total_in + stream->input_position, | ||
5104 | logical_input_cksum_pos, | ||
5105 | stream->srcwin_cksum_pos, | ||
5106 | xd3_source_eof (stream->src), | ||
5107 | stream->src->eof_known ? "known" : "unknown")); | ||
5108 | |||
5061 | if (stream->src->eof_known) | 5109 | if (stream->src->eof_known) |
5062 | { | 5110 | { |
5063 | source_size = xd3_source_eof (stream->src); | 5111 | source_size = xd3_source_eof (stream->src); |
5064 | 5112 | ||
5065 | if (stream->srcwin_cksum_pos >= source_size) | 5113 | if (stream->srcwin_cksum_pos >= source_size) |
5066 | { | 5114 | { |
5067 | /* This invariant is needed for xd3_source_cksum_offset() */ | 5115 | /* This invariant is needed for xd3_source_cksum_offset() */ |
5068 | stream->srcwin_cksum_pos = source_size; | 5116 | stream->srcwin_cksum_pos = source_size; |
5069 | *next_move_point = USIZE_T_MAX; | 5117 | *next_move_point = USIZE_T_MAX; |
5118 | IF_DEBUG1 (DP(RINT | ||
5119 | "[srcwin_move_point] finished with source input\n")); | ||
5070 | return 0; | 5120 | return 0; |
5071 | } | 5121 | } |
5072 | } | 5122 | } |
@@ -5260,7 +5310,7 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
5260 | if (stream->large_table[linx] != 0) | 5310 | if (stream->large_table[linx] != 0) |
5261 | { | 5311 | { |
5262 | /* the match_setup will fail if the source window has | 5312 | /* the match_setup will fail if the source window has |
5263 | * been decided and the match lies outside it. | 5313 | * been decided and the match lies outside it. |
5264 | * OPT: Consider forcing a window at this point to | 5314 | * OPT: Consider forcing a window at this point to |
5265 | * permit a new source window. */ | 5315 | * permit a new source window. */ |
5266 | xoff_t adj_offset = | 5316 | xoff_t adj_offset = |
@@ -5357,7 +5407,7 @@ XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) | |||
5357 | } | 5407 | } |
5358 | 5408 | ||
5359 | /* Compute next RUN, CKSUM */ | 5409 | /* Compute next RUN, CKSUM */ |
5360 | if (DO_RUN) | 5410 | if (DO_RUN) |
5361 | { | 5411 | { |
5362 | NEXTRUN (inp[SLOOK]); | 5412 | NEXTRUN (inp[SLOOK]); |
5363 | } | 5413 | } |
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h index 5b99a72..f417dcf 100644 --- a/xdelta3/xdelta3.h +++ b/xdelta3/xdelta3.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* xdelta 3 - delta compression tools and library | 1 | /* xdelta 3 - delta compression tools and library |
2 | * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald | 2 | * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, |
3 | * 2008, 2009, 2010. Joshua P. MacDonald | ||
3 | * | 4 | * |
4 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -694,7 +695,8 @@ struct _xd3_config | |||
694 | buffer */ | 695 | buffer */ |
695 | usize_t srcwin_maxsz; /* srcwin_size grows by a factor | 696 | usize_t srcwin_maxsz; /* srcwin_size grows by a factor |
696 | of 2 when no matches are | 697 | of 2 when no matches are |
697 | found */ | 698 | found. encoder will not seek |
699 | back further than this. */ | ||
698 | 700 | ||
699 | xd3_getblk_func *getblk; /* The three callbacks. */ | 701 | xd3_getblk_func *getblk; /* The three callbacks. */ |
700 | xd3_alloc_func *alloc; | 702 | xd3_alloc_func *alloc; |
@@ -743,7 +745,7 @@ struct _xd3_source | |||
743 | xoff_t srcbase; /* offset of this source window | 745 | xoff_t srcbase; /* offset of this source window |
744 | in the source itself */ | 746 | in the source itself */ |
745 | int shiftby; /* for power-of-two blocksizes */ | 747 | int shiftby; /* for power-of-two blocksizes */ |
746 | int maskby; /* for power-of-two blocksizes */ | 748 | int maskby; /* for power-of-two blocksizes */ |
747 | xoff_t cpyoff_blocks; /* offset of dec_cpyoff in blocks */ | 749 | xoff_t cpyoff_blocks; /* offset of dec_cpyoff in blocks */ |
748 | usize_t cpyoff_blkoff; /* offset of copy window in | 750 | usize_t cpyoff_blkoff; /* offset of copy window in |
749 | blocks, remainder */ | 751 | blocks, remainder */ |
@@ -799,7 +801,7 @@ struct _xd3_stream | |||
799 | void* opaque; /* private data object passed to | 801 | void* opaque; /* private data object passed to |
800 | alloc, free, and getblk */ | 802 | alloc, free, and getblk */ |
801 | int flags; /* various options */ | 803 | int flags; /* various options */ |
802 | 804 | ||
803 | /* secondary compressor configuration */ | 805 | /* secondary compressor configuration */ |
804 | xd3_sec_cfg sec_data; /* Secondary compressor config: data */ | 806 | xd3_sec_cfg sec_data; /* Secondary compressor config: data */ |
805 | xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ | 807 | xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ |
@@ -1046,7 +1048,7 @@ int xd3_decode_memory (const uint8_t *input, | |||
1046 | * xd3_stream stream; | 1048 | * xd3_stream stream; |
1047 | * xd3_config config; | 1049 | * xd3_config config; |
1048 | * xd3_source src; | 1050 | * xd3_source src; |
1049 | * | 1051 | * |
1050 | * memset (& src, 0, sizeof (src)); | 1052 | * memset (& src, 0, sizeof (src)); |
1051 | * memset (& stream, 0, sizeof (stream)); | 1053 | * memset (& stream, 0, sizeof (stream)); |
1052 | * memset (& config, 0, sizeof (config)); | 1054 | * memset (& config, 0, sizeof (config)); |
@@ -1119,7 +1121,7 @@ int xd3_decode_stream (xd3_stream *stream, | |||
1119 | * assert(stream->current_window == 0); | 1121 | * assert(stream->current_window == 0); |
1120 | * stuff; | 1122 | * stuff; |
1121 | * } | 1123 | * } |
1122 | * // fallthrough | 1124 | * // fallthrough |
1123 | * case XD3_WINSTART: { | 1125 | * case XD3_WINSTART: { |
1124 | * something(stream->current_window); | 1126 | * something(stream->current_window); |
1125 | * goto again; | 1127 | * goto again; |
@@ -1171,7 +1173,7 @@ void xd3_free_stream (xd3_stream *stream); | |||
1171 | int xd3_set_source (xd3_stream *stream, | 1173 | int xd3_set_source (xd3_stream *stream, |
1172 | xd3_source *source); | 1174 | xd3_source *source); |
1173 | 1175 | ||
1174 | /* If the source size is known, call this instead of xd3_set_source(). | 1176 | /* If the source size is known, call this instead of xd3_set_source(). |
1175 | * to avoid having stream->getblk called (and/or to avoid XD3_GETSRCBLK). | 1177 | * to avoid having stream->getblk called (and/or to avoid XD3_GETSRCBLK). |
1176 | * | 1178 | * |
1177 | * Follow these steps: | 1179 | * Follow these steps: |
@@ -1231,7 +1233,7 @@ void xd3_init_config (xd3_config *config, | |||
1231 | config->flags = flags; | 1233 | config->flags = flags; |
1232 | } | 1234 | } |
1233 | 1235 | ||
1234 | /* This supplies some input to the stream. | 1236 | /* This supplies some input to the stream. |
1235 | * | 1237 | * |
1236 | * For encoding, if the input is larger than the configured window | 1238 | * For encoding, if the input is larger than the configured window |
1237 | * size (xd3_config.winsize), the entire input will be consumed and | 1239 | * size (xd3_config.winsize), the entire input will be consumed and |
@@ -1330,7 +1332,7 @@ void xd3_blksize_add (xoff_t *blkno, | |||
1330 | *blkoff += add; | 1332 | *blkoff += add; |
1331 | blkdiff = *blkoff >> source->shiftby; | 1333 | blkdiff = *blkoff >> source->shiftby; |
1332 | 1334 | ||
1333 | if (blkdiff) | 1335 | if (blkdiff) |
1334 | { | 1336 | { |
1335 | *blkno += blkdiff; | 1337 | *blkno += blkdiff; |
1336 | *blkoff &= source->maskby; | 1338 | *blkoff &= source->maskby; |