packages feed

lzlib 1.0.7.4 → 1.0.7.5

raw patch · 19 files changed

+137/−221 lines, 19 filesdep +tastydep +tasty-hunitdep −directorydep −hspecPVP ok

version bump matches the API change (PVP)

Dependencies added: tasty, tasty-hunit

Dependencies removed: directory, hspec

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # lzlib +## 1.0.7.5++  * Bump C sources to lzlib 1.16+ ## 1.0.7.4    * Bump C sources to lzlib 1.15
README.md view
@@ -1,33 +1,9 @@ # lzlib -[![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/lzlib/badge)](https://matrix.hackage.haskell.org/package/lzlib)-[![Hackage](https://img.shields.io/hackage/v/lzlib.svg)](http://hackage.haskell.org/package/lzlib)--[![Dependencies of latest version on Hackage](https://img.shields.io/hackage-deps/v/lzlib.svg)](https://hackage.haskell.org/package/lzlib)- Haskell bindings to [lzlib](https://www.nongnu.org/lzip/lzlib.html). -This package includes a high-level interface to lzlib. It provides performance-comparable to the [lzip](https://www.nongnu.org/lzip/) command-line tool.--## Comparison--Compared to the [lzip](http://hackage.haskell.org/package/lzip) Haskell library:--  * Uses `c2hs` instead of `hsc2hs`-  * Provides a high-level (`ByteString`-based) API--### Performance--Performance should be comparable to the-[lzip](http://download.savannah.gnu.org/releases/lzip/) C++ program.--## Hacking--Run+This package includes a high-level interface to lzlib based on `ByteString`s. -```bash-make-```+## BUGS -to download a few tarballs before running the test suite.+The test suite segfaults when `-with-rtsopts=-N` is supplied.
cbits/cbuffer.c view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided
cbits/decoder.c view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided@@ -65,7 +65,7 @@       if( ( *state = St_set_char( *state ) ) < 4 )         LZd_put_byte( d, Rd_decode_tree8( rdec, bm ) );       else-        LZd_put_byte( d, Rd_decode_matched( rdec, bm, LZd_peek( d, d->rep0 ) ) );+        LZd_put_byte( d, Rd_decode_matched( rdec, bm, LZd_peek( d, d->dis0 ) ) );       continue;       }     /* match or repeated match */@@ -76,23 +76,23 @@         {         if( Rd_decode_bit( rdec, &d->bm_len[*state][pos_state] ) == 0 )	/* 4th bit */           { *state = St_set_shortrep( *state );-            LZd_put_byte( d, LZd_peek( d, d->rep0 ) ); continue; }+            LZd_put_byte( d, LZd_peek( d, d->dis0 ) ); continue; }         }       else         {         unsigned distance;         if( Rd_decode_bit( rdec, &d->bm_rep1[*state] ) == 0 )	/* 4th bit */-          distance = d->rep1;+          distance = d->dis1;         else           {           if( Rd_decode_bit( rdec, &d->bm_rep2[*state] ) == 0 )	/* 5th bit */-            distance = d->rep2;+            distance = d->dis2;           else-            { distance = d->rep3; d->rep3 = d->rep2; }-          d->rep2 = d->rep1;+            { distance = d->dis3; d->dis3 = d->dis2; }+          d->dis2 = d->dis1;           }-        d->rep1 = d->rep0;-        d->rep0 = distance;+        d->dis1 = d->dis0;+        d->dis0 = distance;         }       *state = St_set_rep( *state );       len = Rd_decode_len( rdec, &d->rep_len_model, pos_state );@@ -100,21 +100,20 @@     else					/* match */       {       len = Rd_decode_len( rdec, &d->match_len_model, pos_state );-      unsigned distance = Rd_decode_tree6( rdec, d->bm_dis_slot[get_len_state(len)] );-      if( distance >= start_dis_model )+      unsigned dis0 = Rd_decode_tree6( rdec, d->bm_dis_slot[get_len_state(len)] );+      if( dis0 >= start_dis_model )         {-        const unsigned dis_slot = distance;+        const unsigned dis_slot = dis0;         const int direct_bits = ( dis_slot >> 1 ) - 1;-        distance = ( 2 | ( dis_slot & 1 ) ) << direct_bits;+        dis0 = ( 2 | ( dis_slot & 1 ) ) << direct_bits;         if( dis_slot < end_dis_model )-          distance += Rd_decode_tree_reversed( rdec,-                      d->bm_dis + ( distance - dis_slot ), direct_bits );+          dis0 += Rd_decode_tree_reversed( rdec, d->bm_dis + ( dis0 - dis_slot ),+                                           direct_bits );         else           {-          distance +=-            Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits;-          distance += Rd_decode_tree_reversed4( rdec, d->bm_align );-          if( distance == 0xFFFFFFFFU )		/* marker found */+          dis0 += Rd_decode( rdec, direct_bits - dis_align_bits ) << dis_align_bits;+          dis0 += Rd_decode_tree_reversed4( rdec, d->bm_align );+          if( dis0 == 0xFFFFFFFFU )		/* marker found */             {             Rd_normalize( rdec );             const unsigned mpos = rdec->member_position;@@ -137,12 +136,12 @@             }           }         }-      d->rep3 = d->rep2; d->rep2 = d->rep1; d->rep1 = d->rep0; d->rep0 = distance;+      d->dis3 = d->dis2; d->dis2 = d->dis1; d->dis1 = d->dis0; d->dis0 = dis0;+      if( dis0 >= d->dictionary_size ||+          ( dis0 >= d->cb.put && !d->pos_wrapped ) ) return 1;       *state = St_set_match( *state );-      if( d->rep0 >= d->dictionary_size ||-          ( d->rep0 >= d->cb.put && !d->pos_wrapped ) ) return 1;       }-    LZd_copy_block( d, d->rep0, len );+    LZd_copy_block( d, d->dis0, len );     }   return 2;   }
cbits/decoder.h view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided@@ -17,7 +17,7 @@    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ -enum { rd_min_available_bytes = 10 };+enum { rd_min_available_bytes = 11 };  typedef struct Range_decoder   {@@ -155,13 +155,10 @@     { rdec->range <<= 8; rdec->code = (rdec->code << 8) | Rd_get_byte( rdec ); }   } -static inline unsigned Rd_decode( Range_decoder * const rdec,-                                  const int num_bits )+static inline unsigned Rd_decode( Range_decoder * const rdec, int num_bits )   {   unsigned symbol = 0;-  int i;-  for( i = num_bits; i > 0; --i )-    {+  do {     Rd_normalize( rdec );     rdec->range >>= 1; /*    symbol <<= 1; */@@ -169,7 +166,7 @@     const bool bit = rdec->code >= rdec->range;     symbol <<= 1; symbol += bit;     rdec->code -= rdec->range & ( 0U - bit );-    }+    } while( --num_bits > 0 );   return symbol;   } @@ -339,10 +336,10 @@   bool check_trailer_pending;   bool member_finished;   bool pos_wrapped;-  unsigned rep0;		/* rep[0-3] latest four distances */-  unsigned rep1;		/* used for efficient coding of */-  unsigned rep2;		/* repeated distances */-  unsigned rep3;+  unsigned dis0;		/* dis[0-3] latest four distances */+  unsigned dis1;		/* used for efficient coding of */+  unsigned dis2;		/* repeated distances */+  unsigned dis3;   State state;    Bit_model bm_literal[1<<literal_context_bits][0x300];@@ -385,16 +382,17 @@ static inline void LZd_copy_block( LZ_decoder * const d,                                    const unsigned distance, unsigned len )   {-  unsigned lpos = d->cb.put, i = lpos - distance - 1;+  unsigned lpos = d->cb.put, i;   bool fast, fast2;   if( lpos > distance )     {+    i = lpos - distance - 1;     fast = len < d->cb.buffer_size - lpos;     fast2 = fast && len <= lpos - i;     }   else     {-    i += d->cb.buffer_size;+    i = d->cb.buffer_size + lpos - distance - 1;     fast = len < d->cb.buffer_size - i;		/* (i == pos) may happen */     fast2 = fast && len <= i - lpos;     }@@ -427,12 +425,11 @@   d->check_trailer_pending = false;   d->member_finished = false;   d->pos_wrapped = false;-  /* prev_byte of first byte; also for LZd_peek( 0 ) on corrupt file */-  d->cb.buffer[d->cb.buffer_size-1] = 0;-  d->rep0 = 0;-  d->rep1 = 0;-  d->rep2 = 0;-  d->rep3 = 0;+  d->cb.buffer[d->cb.buffer_size-1] = 0;	/* prev_byte of first byte */+  d->dis0 = 0;+  d->dis1 = 0;+  d->dis2 = 0;+  d->dis3 = 0;   d->state = 0;    Bm_array_init( d->bm_literal[0], (1 << literal_context_bits) * 0x300 );
cbits/encoder.c view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided@@ -157,7 +157,7 @@  /* Return the number of bytes advanced (ahead).    trials[0]..trials[ahead-1] contain the steps to encode.-   ( trials[0].dis4 == -1 ) means literal.+   ( trials[0].cdis == -1 ) means literal.    A match/rep longer or equal than match_len_limit finishes the sequence. */ static int LZe_sequence_optimizer( LZ_encoder * const e,@@ -186,7 +186,7 @@   if( replens[rep_index] >= e->match_len_limit )     {     e->trials[0].price = replens[rep_index];-    e->trials[0].dis4 = rep_index;+    e->trials[0].cdis = rep_index;     if( !LZe_move_and_update( e, replens[rep_index] ) ) return 0;     return replens[rep_index];     }@@ -194,7 +194,7 @@   if( main_len >= e->match_len_limit )     {     e->trials[0].price = main_len;-    e->trials[0].dis4 = e->pairs[num_pairs-1].dis + num_rep_distances;+    e->trials[0].cdis = e->pairs[num_pairs-1].dis + num_rep_distances;     if( !LZe_move_and_update( e, main_len ) ) return 0;     return main_len;     }@@ -209,7 +209,7 @@     e->trials[1].price += LZeb_price_literal( &e->eb, prev_byte, cur_byte );   else     e->trials[1].price += LZeb_price_matched( &e->eb, prev_byte, cur_byte, match_byte );-  e->trials[1].dis4 = -1;				/* literal */+  e->trials[1].cdis = -1;				/* literal */    const int match_price = price1( e->eb.bm_match[state][pos_state] );   const int rep_match_price = match_price + price1( e->eb.bm_rep[state] );@@ -223,7 +223,7 @@   if( num_trials < min_match_len )     {     e->trials[0].price = 1;-    e->trials[0].dis4 = e->trials[1].dis4;+    e->trials[0].cdis = e->trials[1].cdis;     if( !Mb_move_pos( &e->eb.mb ) ) return 0;     return 1;     }@@ -282,7 +282,7 @@     Trial * cur_trial = &e->trials[cur];     State cur_state;     {-    const int dis4 = cur_trial->dis4;+    const int cdis = cur_trial->cdis;     int prev_index = cur_trial->prev_index;     const int prev_index2 = cur_trial->prev_index2; @@ -291,15 +291,15 @@       cur_state = e->trials[prev_index].state;       if( prev_index + 1 == cur )			/* len == 1 */         {-        if( dis4 == 0 ) cur_state = St_set_shortrep( cur_state );+        if( cdis == 0 ) cur_state = St_set_shortrep( cur_state );         else cur_state = St_set_char( cur_state );	/* literal */         }-      else if( dis4 < num_rep_distances ) cur_state = St_set_rep( cur_state );+      else if( cdis < num_rep_distances ) cur_state = St_set_rep( cur_state );       else cur_state = St_set_match( cur_state );       }     else       {-      if( prev_index2 == dual_step_trial )	/* dis4 == 0 (rep0) */+      if( prev_index2 == dual_step_trial )	/* cdis == 0 (rep0) */         --prev_index;       else					/* prev_index2 >= 0 */         prev_index = prev_index2;@@ -308,7 +308,7 @@     cur_trial->state = cur_state;     for( i = 0; i < num_rep_distances; ++i )       cur_trial->reps[i] = e->trials[prev_index].reps[i];-    mtf_reps( dis4, cur_trial->reps );		/* literal is ignored */+    mtf_reps( cdis, cur_trial->reps );		/* literal is ignored */     }      const int pos_state = Mb_data_position( &e->eb.mb ) & pos_state_mask;@@ -328,18 +328,19 @@      Tr_update( next_trial, next_price, -1, cur );	/* literal */ -    const int match_price = cur_trial->price + price1( e->eb.bm_match[cur_state][pos_state] );+    const int match_price =+      cur_trial->price + price1( e->eb.bm_match[cur_state][pos_state] );     const int rep_match_price = match_price + price1( e->eb.bm_rep[cur_state] ); -    if( match_byte == cur_byte && next_trial->dis4 != 0 &&+    if( match_byte == cur_byte && next_trial->cdis != 0 &&         next_trial->prev_index2 == single_step_trial )       {-      const int price = rep_match_price +-                        LZeb_price_shortrep( &e->eb, cur_state, pos_state );+      const int price =+        rep_match_price + LZeb_price_shortrep( &e->eb, cur_state, pos_state );       if( price <= next_trial->price )         {         next_trial->price = price;-        next_trial->dis4 = 0;				/* rep0 */+        next_trial->cdis = 0;				/* rep0 */         next_trial->prev_index = cur;         }       }@@ -520,7 +521,7 @@       const int pos_state =         ( Mb_data_position( &e->eb.mb ) - ahead ) & pos_state_mask;       const int len = e->trials[i].price;-      int dis = e->trials[i].dis4;+      int dis = e->trials[i].cdis;        bool bit = dis < 0;       Re_encode_bit( &e->eb.renc, &e->eb.bm_match[*state][pos_state], !bit );
cbits/encoder.h view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided@@ -100,19 +100,19 @@   {   State state;   int price;		/* dual use var; cumulative price, match length */-  int dis4;		/* -1 for literal, or rep, or match distance + 4 */+  int cdis;		/* -1 for literal, or rep, or match distance + 4 */   int prev_index;	/* index of prev trial in trials[] */   int prev_index2;	/*   -2  trial is single step */ 			/*   -1  literal + rep0 */ 			/* >= 0  ( rep or match ) + literal + rep0 */-  int reps[num_rep_distances];+  int reps[num_rep_distances];		/* latest four distances */   } Trial;  static inline void Tr_update( Trial * const trial, const int pr,-                              const int distance4, const int p_i )+                              const int cdi, const int p_i )   {   if( pr < trial->price )-    { trial->price = pr; trial->dis4 = distance4; trial->prev_index = p_i;+    { trial->price = pr; trial->cdis = cdi; trial->prev_index = p_i;       trial->prev_index2 = single_step_trial; }   } @@ -120,16 +120,16 @@                                const int p_i )   {   if( pr < trial->price )-    { trial->price = pr; trial->dis4 = 0; trial->prev_index = p_i;+    { trial->price = pr; trial->cdis = 0; trial->prev_index = p_i;       trial->prev_index2 = dual_step_trial; }   }  static inline void Tr_update3( Trial * const trial, const int pr,-                               const int distance4, const int p_i,+                               const int cdi, const int p_i,                                const int p_i2 )   {   if( pr < trial->price )-    { trial->price = pr; trial->dis4 = distance4; trial->prev_index = p_i;+    { trial->price = pr; trial->cdis = cdi; trial->prev_index = p_i;       trial->prev_index2 = p_i2; }   } @@ -166,18 +166,18 @@  static int LZe_get_match_pairs( LZ_encoder * const e, Pair * pairs ); -       /* move-to-front dis in/into reps; do nothing if( dis4 <= 0 ) */-static inline void mtf_reps( const int dis4, int reps[num_rep_distances] )+       /* move-to-front dis in/into reps; do nothing if( cdis <= 0 ) */+static inline void mtf_reps( const int cdis, int reps[num_rep_distances] )   {-  if( dis4 >= num_rep_distances )			/* match */+  if( cdis >= num_rep_distances )			/* match */     {     reps[3] = reps[2]; reps[2] = reps[1]; reps[1] = reps[0];-    reps[0] = dis4 - num_rep_distances;+    reps[0] = cdis - num_rep_distances;     }-  else if( dis4 > 0 )				/* repeated match */+  else if( cdis > 0 )				/* repeated match */     {-    const int distance = reps[dis4];-    int i; for( i = dis4; i > 0; --i ) reps[i] = reps[i-1];+    const int distance = reps[cdis];+    int i; for( i = cdis; i > 0; --i ) reps[i] = reps[i-1];     reps[0] = distance;     }   }@@ -252,7 +252,7 @@  static inline void LZe_backward( LZ_encoder * const e, int cur )   {-  int dis4 = e->trials[cur].dis4;+  int cdis = e->trials[cur].cdis;   while( cur > 0 )     {     const int prev_index = e->trials[cur].prev_index;@@ -260,19 +260,19 @@      if( e->trials[cur].prev_index2 != single_step_trial )       {-      prev_trial->dis4 = -1;					/* literal */+      prev_trial->cdis = -1;					/* literal */       prev_trial->prev_index = prev_index - 1;       prev_trial->prev_index2 = single_step_trial;       if( e->trials[cur].prev_index2 >= 0 )         {         Trial * const prev_trial2 = &e->trials[prev_index-1];-        prev_trial2->dis4 = dis4; dis4 = 0;			/* rep0 */+        prev_trial2->cdis = cdis; cdis = 0;			/* rep0 */         prev_trial2->prev_index = e->trials[cur].prev_index2;         prev_trial2->prev_index2 = single_step_trial;         }       }     prev_trial->price = cur - prev_index;			/* len */-    cur = dis4; dis4 = prev_trial->dis4; prev_trial->dis4 = cur;+    cur = cdis; cdis = prev_trial->cdis; prev_trial->cdis = cur;     cur = prev_index;     }   }
cbits/encoder_base.c view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided@@ -123,7 +123,7 @@   }  -/* End Of Stream marker => (dis == 0xFFFFFFFFU, len == min_match_len) */+/* End Of Stream marker => (dis == 0xFFFF_FFFF, len == min_match_len) */ static void LZeb_try_full_flush( LZ_encoder_base * const eb )   {   if( eb->member_finished || Cb_free_bytes( &eb->renc.cb ) <@@ -143,7 +143,7 @@   }  -/* Sync Flush marker => (dis == 0xFFFFFFFFU, len == min_match_len + 1) */+/* Sync Flush marker => (dis == 0xFFFF_FFFF, len == min_match_len + 1) */ static void LZeb_try_sync_flush( LZ_encoder_base * const eb )   {   const unsigned min_size = eb->renc.ff_count + max_marker_size;@@ -167,7 +167,7 @@                         const unsigned long long member_size )   {   const unsigned long long min_member_size = min_dictionary_size;-  const unsigned long long max_member_size = 0x0008000000000000ULL; /* 2 PiB */+  const unsigned long long max_member_size = 1ULL << 51;	/* 2 PiB */   Mb_reset( &eb->mb );   eb->member_size_limit = min( max( min_member_size, member_size ),                           max_member_size ) - Lt_size - max_marker_size;
cbits/encoder_base.h view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided@@ -509,7 +509,7 @@   }  -enum { max_marker_size = 16,+enum { max_marker_size = 16,		/* rd_min_available_bytes + 5 */        num_rep_distances = 4 };		/* must be 4 */  typedef struct LZ_encoder_base@@ -531,7 +531,7 @@   Len_model match_len_model;   Len_model rep_len_model;   Range_encoder renc;-  int reps[num_rep_distances];+  int reps[num_rep_distances];		/* latest four distances */   State state;   bool member_finished;   } LZ_encoder_base;
cbits/fast_encoder.c view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided
cbits/fast_encoder.h view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided
cbits/lzip.h view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided
cbits/lzlib.c view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided
cbits/lzlib.h view
@@ -1,5 +1,5 @@ /* Lzlib - Compression library for the lzip format-   Copyright (C) 2009-2025 Antonio Diaz Diaz.+   Copyright (C) 2009-2026 Antonio Diaz Diaz.     This library is free software. Redistribution and use in source and    binary forms, with or without modification, are permitted provided@@ -24,9 +24,9 @@ /* LZ_API_VERSION was first defined in lzlib 1.8 to 1.    Since lzlib 1.12, LZ_API_VERSION is defined as (major * 1000 + minor). */ -#define LZ_API_VERSION 1015+#define LZ_API_VERSION 1016 -static const char * const LZ_version_string = "1.15";+static const char * const LZ_version_string = "1.16";  typedef enum LZ_Errno   { LZ_ok = 0,         LZ_bad_argument, LZ_mem_error,
lzlib.cabal view
@@ -1,6 +1,6 @@ cabal-version:      1.18 name:               lzlib-version:            1.0.7.4+version:            1.0.7.5 license:            BSD3 license-file:       LICENSE copyright:          Copyright: (c) 2019-2021 Vanessa McHale@@ -70,17 +70,17 @@  test-suite lzlib-test     type:             exitcode-stdio-1.0-    main-is:          Spec.hs+    main-is:          Z.hs     hs-source-dirs:   test     default-language: Haskell2010-    ghc-options:      -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall+    -- ghc-options:      -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall+    ghc-options:      -threaded -rtsopts "-with-rtsopts=-K1K" -Wall     build-depends:         base,         lzlib,-        hspec,-        bytestring,-        directory,-        pathological-bytestrings+        pathological-bytestrings,+        tasty,+        tasty-hunit      if impl(ghc >=8.0)         ghc-options:
src/Codec/Lzip.hs view
@@ -54,22 +54,9 @@ import           System.IO                    (IOMode (ReadMode), hFileSize,                                                withFile) -data CompressionLevel = Zero-    | One-    | Two-    | Three-    | Four-    | Five-    | Six-    | Seven-    | Eight-    | Nine-    deriving (Enum, Bounded)+data CompressionLevel = Zero | One | Two | Three | Four | Five | Six | Seven | Eight | Nine deriving (Enum, Bounded) -data LzOptions = LzOptions-    { dictionarySize :: !Int-    , matchLenLimit  :: !Int-    }+data LzOptions = LzOptions { dictionarySize :: !Int, matchLenLimit  :: !Int }  encoderOptions :: CompressionLevel -> LzOptions encoderOptions Zero  = LzOptions 65535 16@@ -107,7 +94,10 @@     where          -- TODO: not a fan of this loop!-        step :: LZDecoderPtr -> [BS.ByteString] -> (ForeignPtr UInt8, CInt) -> LazyST.ST s (Maybe BS.ByteString, [BS.ByteString])+        step :: LZDecoderPtr+             -> [BS.ByteString]+             -> (ForeignPtr UInt8, CInt)+             -> LazyST.ST s (Maybe BS.ByteString, [BS.ByteString])         step decoder bss (buf, bufSz) = LazyST.unsafeIOToST $ do             maxSz <- fromIntegral <$> lZDecompressWriteSize decoder             bss' <- case bss of@@ -123,6 +113,7 @@                 (bs':bss') -> if BS.length bs' > maxSz                     then                         let (bs'', rest) = BS.splitAt maxSz bs' in+                        -- TODO: this should be safe I think?                         BS.unsafeUseAsCStringLen bs'' $ \(bytes, sz) ->                             lZDecompressWrite decoder (castPtr bytes) (fromIntegral sz) $> rest:bss'                     else@@ -164,16 +155,16 @@ -- -- @since 1.0.2.0 compressSzBest :: BSL.ByteString-           -> Int -- ^ Size of input data, in bytes-           -> BSL.ByteString+               -> Int -- ^ Size of input data, in bytes+               -> BSL.ByteString compressSzBest = compressWithSz maxBound  -- | Alias for @'compressWithSz' 'minBound'@ -- -- @since 1.0.2.0 compressSzFast :: BSL.ByteString-           -> Int -- ^ Size of input data, in bytes-           -> BSL.ByteString+               -> Int -- ^ Size of input data, in bytes+               -> BSL.ByteString compressSzFast = compressWithSz minBound  -- | Alias for @'compressWith' 'maxBound'@@@ -240,7 +231,10 @@     BSL.fromChunks <$> loop (castForeignPtr enc) bss buf      where-        step :: LZEncoderPtr -> [BS.ByteString] -> ForeignPtr UInt8 -> LazyST.ST s (Bool, BS.ByteString, [BS.ByteString])+        step :: LZEncoderPtr+             -> [BS.ByteString]+             -> ForeignPtr UInt8+             -> LazyST.ST s (Bool, BS.ByteString, [BS.ByteString])         step encoder bss buf = LazyST.unsafeIOToST $ do             maxSz <- fromIntegral <$> lZCompressWriteSize encoder             bss' <- case bss of
src/Codec/Lzip/Raw.chs view
@@ -72,7 +72,7 @@  {# pointer *LZ_Encoder as LZEncoderPtr foreign finalizer LZ_compress_close as ^ -> LZEncoder #} -{# fun LZ_compress_open as ^ { `CInt', `CInt', id `CULLong' } -> `Ptr LZEncoder' id #}+{# fun LZ_compress_open as ^ { `CInt', `CInt', `CULLong' } -> `Ptr LZEncoder' id #} {# fun LZ_compress_finish as ^ { `LZEncoderPtr' } -> `CInt' #} {# fun LZ_compress_read as ^ { `LZEncoderPtr', `Ptr UInt8', `CInt' } -> `CInt' #} {# fun LZ_compress_write as ^ { `LZEncoderPtr', `Ptr UInt8', `CInt' } -> `CInt' #}
− test/Spec.hs
@@ -1,71 +0,0 @@-module Main ( main ) where--import           Codec.Lzip                   (compress, compressBest,-                                               decompress)-import           Control.Applicative-import           Control.Concurrent           (forkIO, newEmptyMVar, putMVar,-                                               readMVar)-import           Control.Monad                (filterM)-import qualified Data.ByteString              as BS-import qualified Data.ByteString.Lazy         as BSL-import           Data.ByteString.Pathological (nonstandardRead)-import           Data.Foldable                (traverse_)-import           System.Directory             (doesFileExist)-import           Test.Hspec--forceHead :: BSL.ByteString -> IO ()-forceHead bsl = BS.length (head $ BSL.toChunks bsl) `seq` pure ()--forceBSL :: BSL.ByteString -> IO ()-forceBSL bsl = BS.length (last $ BSL.toChunks bsl) `seq` pure ()--decompressMultithreaded :: FilePath -> IO ()-decompressMultithreaded fp = do-    bsl <- decompress <$> BSL.readFile fp-    forceHead bsl-    done <- newEmptyMVar-    _ <- forkIO (forceBSL bsl *> putMVar done ())-    _ <- forkIO (forceBSL bsl *> putMVar done ())-    readMVar done--compressFileGeneral :: (FilePath -> IO BSL.ByteString) -> FilePath -> Spec-compressFileGeneral f fp = parallel $-    it ("decompress . compress should be identity (" ++ fp ++ ")") $ do-        str <- f fp-        decompress (compress str) `shouldBe` str--compressFileFreaky :: FilePath -> Spec-compressFileFreaky = compressFileGeneral nonstandardRead--compressFile :: FilePath -> Spec-compressFile = compressFileGeneral BSL.readFile--decompressFileGeneral :: (FilePath -> IO BSL.ByteString) -> FilePath -> Spec-decompressFileGeneral f fp = parallel $-    it ("compress . decompress should be identity (" ++ fp ++ ")") $ do-        str <- f fp-        compressBest (decompress str) `shouldBe` str--decompressFileFreaky :: FilePath -> Spec-decompressFileFreaky = decompressFileGeneral nonstandardRead--decompressFile :: FilePath -> Spec-decompressFile = decompressFileGeneral BSL.readFile--main :: IO ()-main = do-    ex' <- filterM doesFileExist ["gmp-6.1.2.tar.lz", "lzlib-1.10.tar.lz"]-    ex <- ("cbits/encoder.c" :)-            <$> filterM doesFileExist ["gmp-6.1.2.tar", "lzlib-1.10.tar"]-    hspec $ do-        describe "roundtrip" $-            traverse_ compressFile ex-        describe "roundtrip" $-            traverse_ decompressFile ex'-        describe "roundtrip (sketchy)" $-            traverse_ compressFileFreaky ex-        describe "roundtrip (sketchy)" $-            traverse_ decompressFileFreaky ex'-        describe "decompress (multithreaded)" $-            it "should not fail" $-                traverse_ decompressMultithreaded ex'
+ test/Z.hs view
@@ -0,0 +1,16 @@+module Main ( main ) where++import           Codec.Lzip                   (compressBest, decompress)+import           Data.ByteString.Pathological (nonstandardRead)+import           Test.Tasty                   (TestTree, defaultMain, testGroup)+import           Test.Tasty.HUnit             (testCase, (@?=))++compressFile :: FilePath -> TestTree+compressFile fp = testCase fp $ do+    d <- nonstandardRead fp+    decompress (compressBest d) @?= d++main :: IO ()+main = defaultMain $+    testGroup "roundtrip"+        [ compressFile "test/data/7341e7190c2219dbc2641707c5c0e41e038f8a44.jpg" ]