/src/zlib-ng/deflate_rle.c
Line | Count | Source |
1 | | /* deflate_rle.c -- compress data using RLE strategy of deflation algorithm |
2 | | * |
3 | | * Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler |
4 | | * For conditions of distribution and use, see copyright notice in zlib.h |
5 | | */ |
6 | | |
7 | | #include "zbuild.h" |
8 | | #include "deflate.h" |
9 | | #include "deflate_p.h" |
10 | | #include "functable.h" |
11 | | #include "compare256_rle.h" |
12 | | |
13 | | #if OPTIMAL_CMP == 8 |
14 | | # define compare256_rle compare256_rle_8 |
15 | | #else |
16 | 0 | # define compare256_rle compare256_rle_64 |
17 | | #endif |
18 | | |
19 | | /* =========================================================================== |
20 | | * For Z_RLE, simply look for runs of bytes, generate matches only of distance |
21 | | * one. Do not maintain a hash table. (It will be regenerated if this run of |
22 | | * deflate switches away from Z_RLE.) |
23 | | */ |
24 | 0 | Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { |
25 | 0 | int bflush = 0; /* set if current block must be flushed */ |
26 | 0 | unsigned char *scan; /* scan goes up to strend for length of run */ |
27 | 0 | uint32_t match_len = 0; |
28 | |
|
29 | 0 | for (;;) { |
30 | | /* Make sure that we always have enough lookahead, except |
31 | | * at the end of the input file. We need STD_MAX_MATCH bytes |
32 | | * for the longest run, plus one for the unrolled loop. |
33 | | */ |
34 | 0 | if (s->lookahead <= STD_MAX_MATCH) { |
35 | 0 | PREFIX(fill_window)(s); |
36 | 0 | if (s->lookahead <= STD_MAX_MATCH && flush == Z_NO_FLUSH) |
37 | 0 | return need_more; |
38 | 0 | if (s->lookahead == 0) |
39 | 0 | break; /* flush the current block */ |
40 | 0 | } |
41 | | |
42 | | /* See how many times the previous byte repeats */ |
43 | 0 | if (s->lookahead >= STD_MIN_MATCH && s->strstart > 0) { |
44 | 0 | scan = s->window + s->strstart - 1; |
45 | 0 | if (scan[0] == scan[1] && scan[1] == scan[2]) { |
46 | 0 | match_len = compare256_rle(scan, scan+3)+2; |
47 | 0 | match_len = MIN(match_len, s->lookahead); |
48 | 0 | match_len = MIN(match_len, STD_MAX_MATCH); |
49 | 0 | } |
50 | 0 | Assert(scan+match_len <= s->window + s->window_size - 1, "wild scan"); |
51 | 0 | } |
52 | | |
53 | | /* Emit match if have run of STD_MIN_MATCH or longer, else emit literal */ |
54 | 0 | if (match_len >= STD_MIN_MATCH) { |
55 | 0 | Assert(s->strstart <= UINT16_MAX, "strstart should fit in uint16_t"); |
56 | 0 | check_match(s, s->strstart, s->strstart - 1, match_len); |
57 | |
|
58 | 0 | bflush = zng_tr_tally_dist(s, 1, match_len - STD_MIN_MATCH); |
59 | |
|
60 | 0 | s->lookahead -= match_len; |
61 | 0 | s->strstart += match_len; |
62 | 0 | match_len = 0; |
63 | 0 | } else { |
64 | | /* No match, output a literal byte */ |
65 | 0 | bflush = zng_tr_tally_lit(s, s->window[s->strstart]); |
66 | 0 | s->lookahead--; |
67 | 0 | s->strstart++; |
68 | 0 | } |
69 | 0 | if (bflush) |
70 | 0 | FLUSH_BLOCK(s, 0); |
71 | 0 | } |
72 | 0 | s->insert = 0; |
73 | 0 | if (flush == Z_FINISH) { |
74 | 0 | FLUSH_BLOCK(s, 1); |
75 | 0 | return finish_done; |
76 | 0 | } |
77 | 0 | if (s->sym_next) |
78 | 0 | FLUSH_BLOCK(s, 0); |
79 | 0 | return block_done; |
80 | 0 | } |