1 | #include "EXTERN.h" |
1 | #include "EXTERN.h" |
2 | #include "perl.h" |
2 | #include "perl.h" |
3 | #include "XSUB.h" |
3 | #include "XSUB.h" |
|
|
4 | |
|
|
5 | #include "perlmulticore.h" |
4 | |
6 | |
5 | #define LZF_STANDALONE 1 |
7 | #define LZF_STANDALONE 1 |
6 | #define LZF_STATE_ARG 1 |
8 | #define LZF_STATE_ARG 1 |
7 | |
9 | |
8 | #include "lzf_c.c" |
10 | #include "lzf_c.c" |
… | |
… | |
33 | #endif |
35 | #endif |
34 | |
36 | |
35 | static SV * |
37 | static SV * |
36 | compress_sv (SV *data, char cprepend, int uprepend, int best) |
38 | compress_sv (SV *data, char cprepend, int uprepend, int best) |
37 | { |
39 | { |
38 | LZF_STATE *state; |
40 | void *state; |
39 | STRLEN usize, csize; |
41 | STRLEN usize, csize; |
40 | char *src = (char *)SvPVbyte (data, usize); |
42 | char *src = (char *)SvPVbyte (data, usize); |
41 | |
43 | |
42 | if (usize) |
44 | if (usize) |
43 | { |
45 | { |
… | |
… | |
58 | else if (usize <= 0x7ff) |
60 | else if (usize <= 0x7ff) |
59 | { |
61 | { |
60 | dst[skip++] = (( usize >> 6) | 0xc0); |
62 | dst[skip++] = (( usize >> 6) | 0xc0); |
61 | dst[skip++] = (( usize & 0x3f) | 0x80); |
63 | dst[skip++] = (( usize & 0x3f) | 0x80); |
62 | } |
64 | } |
63 | else if (usize <= 0xffff) |
65 | else if (usize <= 0xffff) |
64 | { |
66 | { |
65 | dst[skip++] = (( usize >> 12) | 0xe0); |
67 | dst[skip++] = (( usize >> 12) | 0xe0); |
66 | dst[skip++] = (((usize >> 6) & 0x3f) | 0x80); |
68 | dst[skip++] = (((usize >> 6) & 0x3f) | 0x80); |
67 | dst[skip++] = (( usize & 0x3f) | 0x80); |
69 | dst[skip++] = (( usize & 0x3f) | 0x80); |
68 | } |
70 | } |
69 | else if (usize <= 0x1fffff) |
71 | else if (usize <= 0x1fffff) |
70 | { |
72 | { |
71 | dst[skip++] = (( usize >> 18) | 0xf0); |
73 | dst[skip++] = (( usize >> 18) | 0xf0); |
72 | dst[skip++] = (((usize >> 12) & 0x3f) | 0x80); |
74 | dst[skip++] = (((usize >> 12) & 0x3f) | 0x80); |
73 | dst[skip++] = (((usize >> 6) & 0x3f) | 0x80); |
75 | dst[skip++] = (((usize >> 6) & 0x3f) | 0x80); |
74 | dst[skip++] = (( usize & 0x3f) | 0x80); |
76 | dst[skip++] = (( usize & 0x3f) | 0x80); |
75 | } |
77 | } |
76 | else if (usize <= 0x3ffffff) |
78 | else if (usize <= 0x3ffffff) |
77 | { |
79 | { |
78 | dst[skip++] = (( usize >> 24) | 0xf8); |
80 | dst[skip++] = (( usize >> 24) | 0xf8); |
79 | dst[skip++] = (((usize >> 18) & 0x3f) | 0x80); |
81 | dst[skip++] = (((usize >> 18) & 0x3f) | 0x80); |
80 | dst[skip++] = (((usize >> 12) & 0x3f) | 0x80); |
82 | dst[skip++] = (((usize >> 12) & 0x3f) | 0x80); |
81 | dst[skip++] = (((usize >> 6) & 0x3f) | 0x80); |
83 | dst[skip++] = (((usize >> 6) & 0x3f) | 0x80); |
82 | dst[skip++] = (( usize & 0x3f) | 0x80); |
84 | dst[skip++] = (( usize & 0x3f) | 0x80); |
83 | } |
85 | } |
84 | else if (usize <= 0x7fffffff) |
86 | else if (usize <= 0x7fffffff) |
85 | { |
87 | { |
86 | dst[skip++] = (( usize >> 30) | 0xfc); |
88 | dst[skip++] = (( usize >> 30) | 0xfc); |
87 | dst[skip++] = (((usize >> 24) & 0x3f) | 0x80); |
89 | dst[skip++] = (((usize >> 24) & 0x3f) | 0x80); |
88 | dst[skip++] = (((usize >> 18) & 0x3f) | 0x80); |
90 | dst[skip++] = (((usize >> 18) & 0x3f) | 0x80); |
89 | dst[skip++] = (((usize >> 12) & 0x3f) | 0x80); |
91 | dst[skip++] = (((usize >> 12) & 0x3f) | 0x80); |
… | |
… | |
91 | dst[skip++] = (( usize & 0x3f) | 0x80); |
93 | dst[skip++] = (( usize & 0x3f) | 0x80); |
92 | } |
94 | } |
93 | else |
95 | else |
94 | croak ("compress can only compress up to %ld bytes", 0x7fffffffL); |
96 | croak ("compress can only compress up to %ld bytes", 0x7fffffffL); |
95 | |
97 | |
96 | New (0, state, 1, LZF_STATE); |
98 | if (usize > 2000) perlinterp_release (); |
|
|
99 | |
|
|
100 | state = malloc (best ? sizeof (LZF_STATE_BEST) : sizeof (LZF_STATE)); |
97 | if (!state) |
101 | if (!state) |
|
|
102 | { |
|
|
103 | if (usize > 2000) perlinterp_acquire (); |
98 | croak ("Compress::LZF unable to allocate memory for compression state"); |
104 | croak ("Compress::LZF unable to allocate memory for compression state"); |
|
|
105 | } |
99 | |
106 | |
100 | /* 11 bytes is the smallest compressible string */ |
107 | /* 11 bytes is the smallest compressible string */ |
101 | csize = usize < 11 ? 0 : |
108 | csize = usize < 11 ? 0 : |
102 | (best ? lzf_compress_best (src, usize, dst + skip, usize - skip) |
109 | (best ? lzf_compress_best (src, usize, dst + skip, usize - skip, *(LZF_STATE_BEST *)state) |
103 | : lzf_compress (src, usize, dst + skip, usize - skip, *state)); |
110 | : lzf_compress (src, usize, dst + skip, usize - skip, *(LZF_STATE *)state)); |
104 | |
111 | |
105 | Safefree (state); |
112 | free (state); |
|
|
113 | |
|
|
114 | if (usize > 2000) perlinterp_acquire (); |
106 | |
115 | |
107 | if (csize) |
116 | if (csize) |
108 | { |
117 | { |
109 | SvCUR_set (ret, csize + skip); |
118 | SvCUR_set (ret, csize + skip); |
110 | } |
119 | } |
… | |
… | |
136 | |
145 | |
137 | if (csize) |
146 | if (csize) |
138 | { |
147 | { |
139 | void *dst; |
148 | void *dst; |
140 | SV *ret; |
149 | SV *ret; |
|
|
150 | int res; |
141 | |
151 | |
142 | csize -= skip; |
152 | csize -= skip; |
143 | |
153 | |
144 | if (src[0]) |
154 | if (src[0]) |
145 | { |
155 | { |
… | |
… | |
191 | else |
201 | else |
192 | croak ("compressed data corrupted (invalid length)"); |
202 | croak ("compressed data corrupted (invalid length)"); |
193 | |
203 | |
194 | if (!usize) |
204 | if (!usize) |
195 | croak ("compressed data corrupted (invalid length)"); |
205 | croak ("compressed data corrupted (invalid length)"); |
196 | |
206 | |
197 | ret = NEWSV (0, usize); |
207 | ret = NEWSV (0, usize); |
198 | SvPOK_only (ret); |
208 | SvPOK_only (ret); |
199 | dst = SvPVX (ret); |
209 | dst = SvPVX (ret); |
200 | |
210 | |
|
|
211 | if (usize > 4000) perlinterp_release (); |
201 | if (lzf_decompress (src, csize, dst, usize) != usize) |
212 | res = lzf_decompress (src, csize, dst, usize) != usize; |
|
|
213 | if (usize > 4000) perlinterp_acquire (); |
|
|
214 | |
|
|
215 | if (res) |
202 | { |
216 | { |
203 | SvREFCNT_dec (ret); |
217 | SvREFCNT_dec (ret); |
204 | croak ("compressed data corrupted (size mismatch)", csize, skip, usize); |
218 | croak ("compressed data corrupted (size mismatch)", csize, skip, usize); |
205 | } |
219 | } |
206 | } |
220 | } |
… | |
… | |
454 | SvPVX (sv)[0] = MAGIC_R_deref; |
468 | SvPVX (sv)[0] = MAGIC_R_deref; |
455 | } |
469 | } |
456 | else |
470 | else |
457 | SETs (sv_2mortal (newSVsv (TOPs))); |
471 | SETs (sv_2mortal (newSVsv (TOPs))); |
458 | |
472 | |
459 | break; |
473 | break; |
460 | |
474 | |
461 | default: |
475 | default: |
462 | croak ("Compress::LZF::sthaw(): invalid data, maybe you need a newer version of Compress::LZF?"); |
476 | croak ("Compress::LZF::sthaw(): invalid data, maybe you need a newer version of Compress::LZF?"); |
463 | } |
477 | } |
464 | } |
478 | } |