2828#include <stdlib.h>
2929#include <string.h>
3030#include <stdio.h>
31+ #include <stdbool.h>
3132
3233typedef unsigned char byte ;
3334
35+ static uint16_t endswap16 (uint16_t value ) {
36+ uint16_t ret = 0 ;
37+ ret |= (value >> 8 ) & 0x00ff ;
38+ ret |= (value << 8 ) & 0xff00 ;
39+ return ret ;
40+ }
41+
42+ static uint32_t endswap32 (uint32_t value ) {
43+ uint32_t ret = 0 ;
44+ ret |= (value >> 24 ) & 0x000000ff ;
45+ ret |= (value >> 8 ) & 0x0000ff00 ;
46+ ret |= (value << 8 ) & 0x00ff0000 ;
47+ ret |= (value << 24 ) & 0xff000000 ;
48+ return ret ;
49+ }
50+
51+ static uint64_t endswap64 (uint64_t value ) {
52+ uint64_t ret = 0 ;
53+ ret |= (value >> 56 ) & 0x00000000000000ff ;
54+ ret |= (value >> 40 ) & 0x000000000000ff00 ;
55+ ret |= (value >> 24 ) & 0x0000000000ff0000 ;
56+ ret |= (value >> 8 ) & 0x00000000ff000000 ;
57+ ret |= (value << 8 ) & 0x000000ff00000000 ;
58+ ret |= (value << 24 ) & 0x0000ff0000000000 ;
59+ ret |= (value << 40 ) & 0x00ff000000000000 ;
60+ ret |= (value << 56 ) & 0xff00000000000000 ;
61+ return ret ;
62+ }
63+
64+ #ifdef __BYTE_ORDER__
65+
66+ #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
67+ #define bigendian true
68+ #else
69+ #define bigendian false
70+ #endif
71+
72+ #else /* !__BYTE_ORDER__ */
73+
74+ static bool bigendian = false;
75+
76+ #endif /* !__BYTE_ORDER__ */
77+
78+ #define ENDSWAP (VALUE ) (bigendian ? ( \
79+ sizeof(VALUE) == 1 ? (VALUE) : \
80+ sizeof(VALUE) == 2 ? endswap16(VALUE) : \
81+ sizeof(VALUE) == 4 ? endswap32(VALUE) : \
82+ sizeof(VALUE) == 8 ? endswap64(VALUE) : (abort(), 1) \
83+ ) : (VALUE))
84+
3485/* Higher -> better compression with exponentally dimnishing gains. */
3586#define LIMLZ_SA_NEIGHBORS 32
3687
37- struct sa_cmp_ctx { int * rank ; size_t n , k ; };
88+ struct sa_cmp_ctx { int32_t * rank ; size_t n , k ; };
3889static struct sa_cmp_ctx g_sa_ctx ;
3990
40- static int sa_cmp_idx (int i , int j ) {
41- int ri , rj ;
91+ static int32_t sa_cmp_idx (int32_t i , int32_t j ) {
92+ int32_t ri , rj ;
4293 if (g_sa_ctx .rank [i ] != g_sa_ctx .rank [j ])
4394 return g_sa_ctx .rank [i ] - g_sa_ctx .rank [j ];
44- ri = (i + (int )g_sa_ctx .k < (int )g_sa_ctx .n ) ? g_sa_ctx .rank [i + g_sa_ctx .k ] : -1 ;
45- rj = (j + (int )g_sa_ctx .k < (int )g_sa_ctx .n ) ? g_sa_ctx .rank [j + g_sa_ctx .k ] : -1 ;
95+ ri = (i + (int32_t )g_sa_ctx .k < (int32_t )g_sa_ctx .n ) ? g_sa_ctx .rank [i + g_sa_ctx .k ] : -1 ;
96+ rj = (j + (int32_t )g_sa_ctx .k < (int32_t )g_sa_ctx .n ) ? g_sa_ctx .rank [j + g_sa_ctx .k ] : -1 ;
4697 return ri - rj ;
4798}
4899
49100static int sa_qsort_cmp (const void * a , const void * b ) {
50- int i = * (const int * ) a , j = * (const int * ) b ;
51- return sa_cmp_idx ( i , j );
101+ int32_t d = sa_cmp_idx ( * (const int32_t * )a , * (const int32_t * )b ) ;
102+ return ( d > 0 ) - ( d < 0 );
52103}
53104
54- static int saca (const byte * s , size_t n , int * sa , int * rank , int * tmp ) {
105+ static int saca (const byte * s , size_t n , int32_t * sa , int32_t * rank , int32_t * tmp ) {
55106 size_t i ;
56107 if (!n )
57108 return 0 ;
58109 for (i = 0 ; i < n ; ++ i ) {
59- sa [i ] = (int )i ; rank [i ] = (int )s [i ];
110+ sa [i ] = (int32_t )i ; rank [i ] = (int32_t )s [i ];
60111 }
61112 for (g_sa_ctx .k = 1 ;; g_sa_ctx .k <<= 1 ) {
62113 g_sa_ctx .rank = rank ; g_sa_ctx .n = n ;
@@ -82,7 +133,7 @@ struct match_choice { uint32_t len; uint16_t off; };
82133struct parse_choice { uint32_t lit , mlen ; uint16_t off ; };
83134
84135static int longest_matches (const byte * src , size_t n , struct match_choice * mch ) {
85- int * sa , * rank , * tmp , * inv ;
136+ int32_t * sa , * rank , * tmp , * inv ;
86137 size_t i ;
87138 if (!n )
88139 return 0 ;
@@ -95,17 +146,18 @@ static int longest_matches(const byte * src, size_t n, struct match_choice * mch
95146 return -1 ;
96147 }
97148 for (i = 0 ; i < n ; ++ i )
98- inv [sa [i ]] = (int )i ;
149+ inv [sa [i ]] = (int32_t )i ;
99150 for (i = 0 ; i < n ; ++ i ) {
100- int r = inv [i ], d , rr ;
151+ int32_t r = inv [i ], rr ;
152+ int d ;
101153 size_t best_len = 0 ;
102154 uint16_t best_off = 0 ;
103155 for (d = - LIMLZ_SA_NEIGHBORS ; d <= LIMLZ_SA_NEIGHBORS ; ++ d ) {
104156 size_t j , l , off ;
105157 if (!d )
106158 continue ;
107159 rr = r + d ;
108- if (rr < 0 || rr >= (int )n )
160+ if (rr < 0 || rr >= (int32_t )n )
109161 continue ;
110162 j = (size_t )sa [rr ];
111163 if (j >= i )
@@ -218,6 +270,7 @@ static size_t limlzpack(void * dst, size_t dstcap, const void * srcv, size_t src
218270 dp [i ] = best_cost ; pick [i ].lit = best_lit ;
219271 pick [i ].mlen = best_len ; pick [i ].off = best_off ;
220272 }
273+ int terminated = 0 ;
221274 for (i = 0 ; i < srcsz ; ) {
222275 byte * tokenp ;
223276 size_t lit = pick [i ].lit , ml = pick [i ].mlen ;
@@ -241,6 +294,7 @@ static size_t limlzpack(void * dst, size_t dstcap, const void * srcv, size_t src
241294 i += lit ;
242295 if (i >= srcsz ) {
243296 * tokenp = (byte )(token_hi << 3 );
297+ terminated = 1 ;
244298 break ;
245299 }
246300 unsigned mode_bit = (off > 255 ) ? 1u : 0u ;
@@ -260,6 +314,14 @@ static size_t limlzpack(void * dst, size_t dstcap, const void * srcv, size_t src
260314 goto fail ;
261315 i += ml ;
262316 }
317+ /* A match-ended parse leaves no trailing token; the decompressor keys
318+ * termination off a zero-or-more-byte literal copy reaching ipe, so always
319+ * emit a final lit=0 token when the main loop didn't already. */
320+ if (!terminated ) {
321+ if (out >= out_end )
322+ goto fail ;
323+ * out ++ = 0 ;
324+ }
263325 free (mch ); free (pick ); free (bestm ); free (dp );
264326 return (size_t )(out - dstp );
265327fail :
@@ -285,6 +347,11 @@ static uint32_t crc32_nibble(const byte *data, size_t len) {
285347}
286348
287349int main (int argc , char * argv []) {
350+ #ifndef __BYTE_ORDER__
351+ uint32_t endcheck = 0x12345678 ;
352+ uint8_t endbyte = * ((uint8_t * )& endcheck );
353+ bigendian = endbyte == 0x12 ;
354+ #endif
288355 if (argc != 3 ) {
289356 fprintf (stderr , "? %s <input> <output>\n" , argv [0 ]); return 1 ;
290357 }
@@ -308,7 +375,7 @@ int main(int argc, char *argv[]) {
308375 if (!outsz ) {
309376 fprintf (stderr , "? limlzpack\n" ); return 1 ;
310377 }
311- uint32_t crc = crc32_nibble (inbuf , insz );
378+ uint32_t crc = ENDSWAP ( crc32_nibble (inbuf , insz ) );
312379 fwrite (& crc , sizeof (crc ), 1 , fout );
313380 fwrite (outbuf , 1 , outsz , fout );
314381 fclose (fout );
0 commit comments