]> wimlib.net Git - wimlib/blobdiff - src/xpress-compress.c
portability and compression cleanups
[wimlib] / src / xpress-compress.c
index f39d54758969f2884f37ee2e8d50b3164152b7c4..fdcc2fca49e61a10b935e4ed3decf65479da9514 100644 (file)
@@ -8,31 +8,31 @@
 /*
  * Copyright (C) 2012, 2013, 2014 Eric Biggers
  *
- * This file is part of wimlib, a library for working with WIM files.
+ * This file is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option) any
+ * later version.
  *
- * wimlib is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at your option)
- * any later version.
- *
- * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * This file is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  * details.
  *
- * You should have received a copy of the GNU General Public License
- * along with wimlib; if not, see http://www.gnu.org/licenses/.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file; if not, see http://www.gnu.org/licenses/.
  */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
 
+#include "wimlib/bitops.h"
 #include "wimlib/compress_common.h"
 #include "wimlib/compressor_ops.h"
 #include "wimlib/endianness.h"
 #include "wimlib/error.h"
 #include "wimlib/lz_mf.h"
+#include "wimlib/unaligned.h"
 #include "wimlib/util.h"
 #include "wimlib/xpress.h"
 
@@ -136,7 +136,7 @@ struct xpress_mc_pos_data {
         */
        u32 mc_item_data;
 #define MC_OFFSET_SHIFT 16
-#define MC_LEN_MASK ((1 << MC_OFFSET_SHIFT) - 1)
+#define MC_LEN_MASK (((u32)1 << MC_OFFSET_SHIFT) - 1)
 };
 
 
@@ -218,7 +218,7 @@ xpress_write_bits(struct xpress_output_bitstream *os,
        if (os->bitcount > 16) {
                os->bitcount -= 16;
                if (os->end - os->next_byte >= 2) {
-                       *(le16 *)os->next_bits = cpu_to_le16(os->bitbuf >> os->bitcount);
+                       put_unaligned_u16_le(os->bitbuf >> os->bitcount, os->next_bits);
                        os->next_bits = os->next_bits2;
                        os->next_bits2 = os->next_byte;
                        os->next_byte += 2;
@@ -246,8 +246,8 @@ xpress_flush_output(struct xpress_output_bitstream *os)
        if (unlikely(os->end - os->next_byte < 2))
                return 0;
 
-       *(le16 *)os->next_bits = cpu_to_le16(os->bitbuf << (16 - os->bitcount));
-       *(le16 *)os->next_bits2 = cpu_to_le16(0);
+       put_unaligned_u16_le(os->bitbuf << (16 - os->bitcount), os->next_bits);
+       put_unaligned_u16_le(0, os->next_bits2);
 
        return os->next_byte - os->start;
 }
@@ -334,8 +334,8 @@ xpress_declare_match(struct xpress_compressor *c,
 {
        unsigned adjusted_len = len - XPRESS_MIN_MATCH_LEN;
        unsigned len_hdr = min(adjusted_len, 0xf);
-       unsigned offset_bsr = bsr32(offset);
-       unsigned sym = XPRESS_NUM_CHARS + ((offset_bsr << 4) | len_hdr);
+       unsigned offset_high_bit = fls32(offset);
+       unsigned sym = XPRESS_NUM_CHARS + ((offset_high_bit << 4) | len_hdr);
 
        c->freqs[sym]++;
 
@@ -343,8 +343,8 @@ xpress_declare_match(struct xpress_compressor *c,
                *(*next_chosen_item)++ = (struct xpress_item) {
                        .data = (u64)sym |
                                ((u64)adjusted_len << 9) |
-                               ((u64)offset_bsr << 25) |
-                               ((u64)(offset ^ (1U << offset_bsr)) << 29),
+                               ((u64)offset_high_bit << 25) |
+                               ((u64)(offset ^ (1U << offset_high_bit)) << 29),
                };
        }
 }
@@ -589,7 +589,7 @@ xpress_set_costs(u8 costs[], const u8 lens[])
  * @matches must be sorted by strictly increasing length and strictly
  * increasing offset.  This is guaranteed by the match-finder.
  *
- * We consider each length from the minimum (2) to the longest
+ * We consider each length from the minimum (3) to the longest
  * (matches[num_matches - 1].len).  For each length, we consider only
  * the smallest offset for which that length is available.  Although
  * this is not guaranteed to be optimal due to the possibility of a
@@ -607,7 +607,7 @@ xpress_consider_matches(struct xpress_compressor *c,
        u32 cost;
        u32 position_cost;
        unsigned offset;
-       unsigned offset_bsr;
+       unsigned offset_high_bit;
        unsigned adjusted_len;
        unsigned len_hdr;
        unsigned sym;
@@ -616,11 +616,11 @@ xpress_consider_matches(struct xpress_compressor *c,
                /* All lengths are small.  Optimize accordingly.  */
                do {
                        offset = matches[i].offset;
-                       offset_bsr = bsr32(offset);
+                       offset_high_bit = fls32(offset);
                        len_hdr = len - XPRESS_MIN_MATCH_LEN;
-                       sym = XPRESS_NUM_CHARS + ((offset_bsr << 4) | len_hdr);
+                       sym = XPRESS_NUM_CHARS + ((offset_high_bit << 4) | len_hdr);
 
-                       position_cost = cur_optimum_ptr->cost + offset_bsr;
+                       position_cost = cur_optimum_ptr->cost + offset_high_bit;
                        do {
                                cost = position_cost + c->costs[sym];
                                if (cost < (cur_optimum_ptr + len)->cost) {
@@ -635,12 +635,12 @@ xpress_consider_matches(struct xpress_compressor *c,
                /* Some lengths are big.  */
                do {
                        offset = matches[i].offset;
-                       offset_bsr = bsr32(offset);
-                       position_cost = cur_optimum_ptr->cost + offset_bsr;
+                       offset_high_bit = fls32(offset);
+                       position_cost = cur_optimum_ptr->cost + offset_high_bit;
                        do {
                                adjusted_len = len - XPRESS_MIN_MATCH_LEN;
                                len_hdr = min(adjusted_len, 0xf);
-                               sym = XPRESS_NUM_CHARS + ((offset_bsr << 4) | len_hdr);
+                               sym = XPRESS_NUM_CHARS + ((offset_high_bit << 4) | len_hdr);
 
                                cost = position_cost + c->costs[sym];
                                if (adjusted_len >= 0xf) {
@@ -793,8 +793,8 @@ begin:
                 *      XPRESS_OPTIM_ARRAY_LENGTH is high enough that on most
                 *      inputs this limit is never reached.
                 *
-                * Note: no check for end-of-block is needed because
-                * end-of-block will trigger condition (1).
+                * Note: no check for end-of-window is needed because
+                * end-of-window will trigger condition (1).
                 */
                if (cur_optimum_ptr == end_optimum_ptr ||
                    cur_optimum_ptr == &c->optimum[XPRESS_OPTIM_ARRAY_LENGTH])
@@ -1208,14 +1208,16 @@ xpress_compress(const void *uncompressed_data, size_t uncompressed_size,
        c->cur_window_size = uncompressed_size;
        lz_mf_load_window(c->mf, c->cur_window, c->cur_window_size);
        memset(c->freqs, 0, sizeof(c->freqs));
+
        num_chosen_items = xpress_choose_items(c);
+
        c->freqs[XPRESS_END_OF_DATA]++;
        xpress_make_huffman_code(c);
 
        /* Output the Huffman code as a series of 512 4-bit lengths.  */
        cptr = compressed_data;
        for (unsigned i = 0; i < XPRESS_NUM_SYMBOLS; i += 2)
-               *cptr++ = (c->lens[i] & 0xf) | (c->lens[i + 1] << 4);
+               *cptr++ = (c->lens[i + 1] << 4) | c->lens[i];
 
        /* Output the encoded matches/literals.  */
        xpress_init_output(&os, cptr,
@@ -1239,8 +1241,8 @@ xpress_free_compressor(void *_c)
 
        if (c) {
                lz_mf_free(c->mf);
-               FREE(c->cached_matches);
                FREE(c->optimum);
+               FREE(c->cached_matches);
                FREE(c->chosen_items);
                FREE(c);
        }