ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Compress-LZF/LZF.xs
Revision: 1.23
Committed: Fri Feb 16 22:11:17 2007 UTC (17 years, 3 months ago) by root
Branch: MAIN
CVS Tags: rel-1_71
Changes since 1.22: +11 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5     /* try to be compatible with older perls */
6     /* SvPV_nolen() macro first defined in 5.005_55 */
7     /* this is slow, not threadsafe, but works */
8     #include "patchlevel.h"
9     #if (PATCHLEVEL == 4) || ((PATCHLEVEL == 5) && (SUBVERSION < 55))
10     static STRLEN nolen_na;
11     # define SvPV_nolen(sv) SvPV ((sv), nolen_na)
12     #endif
13 root 1.2 #if PATCHLEVEL < 6
14     # define call_sv perl_call_sv
15     #endif
16 root 1.1
17 root 1.23 #define LZF_STANDALONE 1
18     #define LZF_STATE_ARG 1
19    
20 root 1.1 #include "lzf_c.c"
21     #include "lzf_d.c"
22    
23     /* we re-use the storable header for our purposes */
24     #define MAGIC_LO 0
25     #define MAGIC_U 0 /* uncompressed data follows */
26     #define MAGIC_C 1 /* compressed data follows */
27 root 1.4 #define MAGIC_undef 2 /* the special value undef */
28     #define MAGIC_CR 3 /* storable (reference, freeze), compressed */
29 root 1.1 #define MAGIC_R 4 /* storable (reference, freeze) */
30 root 1.9 #define MAGIC_CR_deref 5 /* storable (NO reference, freeze), compressed */
31 root 1.10 #define MAGIC_R_deref 6 /* storable (NO reference, freeze) */
32 root 1.1 #define MAGIC_HI 7 /* room for one higher storable major */
33 root 1.20 /* for historical reasons, MAGIC_undef + MAGIC_R and MAGIC_undef + MAGIC_R_deref are used, too */
34 root 1.1
35     #define IN_RANGE(v,l,h) ((unsigned int)((unsigned)(v) - (unsigned)(l)) <= (unsigned)(h) - (unsigned)(l))
36    
37 root 1.14 static SV *serializer_package, *serializer_mstore, *serializer_mretrieve;
38 root 1.1 static CV *storable_mstore, *storable_mretrieve;
39    
40 root 1.20 #if Size_t_size > 4
41     # define MAX_LENGTH ((Size_t)0x80000000L)
42     #else
43     # define MAX_LENGTH ((Size_t) 0x8000000L)
44     #endif
45    
46 root 1.1 static SV *
47 root 1.10 compress_sv (SV *data, char cprepend, int uprepend)
48 root 1.1 {
49 root 1.23 LZF_STATE *state;
50 root 1.1 STRLEN usize, csize;
51     char *src = (char *)SvPV (data, usize);
52    
53     if (usize)
54     {
55     SV *ret = NEWSV (0, usize + 1);
56     unsigned char *dst;
57     int skip = 0;
58    
59     SvPOK_only (ret);
60     dst = (unsigned char *)SvPVX (ret);
61    
62     if (cprepend)
63     dst[skip++] = cprepend;
64    
65 root 1.20 if (usize <= 0x7f)
66 root 1.1 {
67     dst[skip++] = usize;
68     }
69 root 1.20 else if (usize <= 0x7ff)
70 root 1.1 {
71     dst[skip++] = (( usize >> 6) | 0xc0);
72     dst[skip++] = (( usize & 0x3f) | 0x80);
73     }
74 root 1.20 else if (usize <= 0xffff)
75 root 1.1 {
76     dst[skip++] = (( usize >> 12) | 0xe0);
77     dst[skip++] = (((usize >> 6) & 0x3f) | 0x80);
78     dst[skip++] = (( usize & 0x3f) | 0x80);
79     }
80 root 1.20 else if (usize <= 0x1fffff)
81 root 1.1 {
82     dst[skip++] = (( usize >> 18) | 0xf0);
83     dst[skip++] = (((usize >> 12) & 0x3f) | 0x80);
84     dst[skip++] = (((usize >> 6) & 0x3f) | 0x80);
85     dst[skip++] = (( usize & 0x3f) | 0x80);
86     }
87 root 1.20 else if (usize <= 0x3ffffff)
88 root 1.1 {
89     dst[skip++] = (( usize >> 24) | 0xf8);
90     dst[skip++] = (((usize >> 18) & 0x3f) | 0x80);
91     dst[skip++] = (((usize >> 12) & 0x3f) | 0x80);
92     dst[skip++] = (((usize >> 6) & 0x3f) | 0x80);
93     dst[skip++] = (( usize & 0x3f) | 0x80);
94     }
95 root 1.20 else if (usize <= 0x7fffffff)
96     {
97     dst[skip++] = (( usize >> 30) | 0xfc);
98     dst[skip++] = (((usize >> 24) & 0x3f) | 0x80);
99     dst[skip++] = (((usize >> 18) & 0x3f) | 0x80);
100     dst[skip++] = (((usize >> 12) & 0x3f) | 0x80);
101     dst[skip++] = (((usize >> 6) & 0x3f) | 0x80);
102     dst[skip++] = (( usize & 0x3f) | 0x80);
103     }
104 root 1.1 else
105 root 1.20 croak ("compress can only compress up to %ld bytes", 0x7fffffffL);
106 root 1.1
107 root 1.23 New (0, state, 1, LZF_STATE);
108     if (!state)
109     croak ("Compress::LZF unable to allocate memory for compression state");
110    
111 root 1.1 /* 11 bytes is the smallest compressible string */
112     csize = usize < 11 ? 0 :
113 root 1.23 lzf_compress (src, usize, dst + skip, usize - skip, *state);
114    
115     Safefree (state);
116 root 1.1
117     if (csize)
118     {
119     SvCUR_set (ret, csize + skip);
120     }
121 root 1.10 else if (uprepend < 0)
122 root 1.1 {
123     SvREFCNT_dec (ret);
124     ret = SvREFCNT_inc (data);
125     }
126     else
127     {
128 root 1.10 *dst++ = uprepend;
129 root 1.1
130     Move ((void *)src, (void *)dst, usize, unsigned char);
131    
132     SvCUR_set (ret, usize + 1);
133     }
134    
135     return ret;
136     }
137     else
138     return newSVpv ("", 0);
139     }
140    
141     static SV *
142     decompress_sv (SV *data, int skip)
143     {
144     STRLEN usize, csize;
145     unsigned char *src = (unsigned char *)SvPV (data, csize) + skip;
146    
147     if (csize)
148     {
149     void *dst;
150     SV *ret;
151    
152     csize -= skip;
153    
154     if (src[0])
155     {
156 root 1.21 if (!(src[0] & 0x80) && csize >= 1)
157 root 1.1 {
158     csize -= 1;
159     usize = *src++ & 0xff;
160     }
161 root 1.21 else if (!(src[0] & 0x20) && csize >= 2)
162 root 1.1 {
163     csize -= 2;
164     usize = *src++ & 0x1f;
165     usize = (usize << 6) | (*src++ & 0x3f);
166     }
167 root 1.21 else if (!(src[0] & 0x10) && csize >= 3)
168 root 1.1 {
169     csize -= 3;
170     usize = *src++ & 0x0f;
171     usize = (usize << 6) | (*src++ & 0x3f);
172     usize = (usize << 6) | (*src++ & 0x3f);
173     }
174 root 1.21 else if (!(src[0] & 0x08) && csize >= 4)
175 root 1.1 {
176     csize -= 4;
177     usize = *src++ & 0x07;
178     usize = (usize << 6) | (*src++ & 0x3f);
179     usize = (usize << 6) | (*src++ & 0x3f);
180     usize = (usize << 6) | (*src++ & 0x3f);
181     }
182 root 1.21 else if (!(src[0] & 0x04) && csize >= 5)
183 root 1.1 {
184     csize -= 5;
185     usize = *src++ & 0x03;
186     usize = (usize << 6) | (*src++ & 0x3f);
187     usize = (usize << 6) | (*src++ & 0x3f);
188     usize = (usize << 6) | (*src++ & 0x3f);
189     usize = (usize << 6) | (*src++ & 0x3f);
190     }
191 root 1.21 else if (!(src[0] & 0x02) && csize >= 6)
192 root 1.20 {
193     csize -= 6;
194     usize = *src++ & 0x01;
195     usize = (usize << 6) | (*src++ & 0x3f);
196     usize = (usize << 6) | (*src++ & 0x3f);
197     usize = (usize << 6) | (*src++ & 0x3f);
198     usize = (usize << 6) | (*src++ & 0x3f);
199     usize = (usize << 6) | (*src++ & 0x3f);
200     }
201 root 1.1 else
202 root 1.13 croak ("compressed data corrupted (invalid length)");
203 root 1.21
204     if (!usize)
205     croak ("compressed data corrupted (invalid length)");
206 root 1.1
207     ret = NEWSV (0, usize);
208     SvPOK_only (ret);
209     dst = SvPVX (ret);
210    
211     if (lzf_decompress (src, csize, dst, usize) != usize)
212 root 1.22 {
213     SvREFCNT_dec (ret);
214     croak ("compressed data corrupted (size mismatch)", csize, skip, usize);
215     }
216 root 1.1 }
217     else
218     {
219     usize = csize - 1;
220 root 1.21 ret = NEWSV (0, usize | 1);
221 root 1.1 SvPOK_only (ret);
222    
223     Move ((void *)(src + 1), (void *)SvPVX (ret), usize, unsigned char);
224     }
225    
226     SvCUR_set (ret, usize);
227    
228     return ret;
229     }
230     else
231     return newSVpvn ("", 0);
232     }
233    
234     static void
235     need_storable(void)
236     {
237 root 1.2 #if PATCHLEVEL < 6
238 root 1.14 char req[8192];
239     sprintf (req, "require %s;", SvPV_nolen (serializer_package));
240     perl_eval_pv (req, 1);
241 root 1.2 #else
242 root 1.14 load_module (PERL_LOADMOD_NOIMPORT, serializer_package, Nullsv);
243 root 1.2 #endif
244 root 1.1
245 root 1.14 storable_mstore = GvCV (gv_fetchpv (SvPV_nolen (serializer_mstore ), TRUE, SVt_PVCV));
246     storable_mretrieve = GvCV (gv_fetchpv (SvPV_nolen (serializer_mretrieve), TRUE, SVt_PVCV));
247 root 1.1 }
248    
249     MODULE = Compress::LZF PACKAGE = Compress::LZF
250 root 1.14
251     BOOT:
252     serializer_package = newSVpv ("Storable", 0);
253 root 1.20 serializer_mstore = newSVpv ("Storable::net_mstore", 0);
254 root 1.14 serializer_mretrieve = newSVpv ("Storable::mretrieve", 0);
255    
256     void
257     set_serializer(package, mstore, mretrieve)
258     SV * package
259     SV * mstore
260     SV * mretrieve
261     PROTOTYPE: $$$
262     PPCODE:
263     SvSetSV (serializer_package , package );
264     SvSetSV (serializer_mstore , mstore );
265     SvSetSV (serializer_mretrieve, mretrieve);
266     storable_mstore =
267     storable_mretrieve = 0;
268 root 1.1
269     void
270     compress(data)
271     SV * data
272     PROTOTYPE: $
273     PPCODE:
274 root 1.10 XPUSHs (sv_2mortal (compress_sv (data, 0, MAGIC_U)));
275 root 1.1
276     void
277     decompress(data)
278     SV * data
279     PROTOTYPE: $
280     PPCODE:
281     XPUSHs (sv_2mortal (decompress_sv (data, 0)));
282    
283     void
284     sfreeze(sv)
285     SV * sv
286     ALIAS:
287     sfreeze_cr = 1
288     sfreeze_c = 2
289     PROTOTYPE: $
290     PPCODE:
291    
292 root 1.10 SvGETMAGIC (sv);
293    
294 root 1.4 if (!SvOK (sv))
295     XPUSHs (sv_2mortal (newSVpvn ("\02", 1))); /* 02 == MAGIC_undef */
296 root 1.12 else if (SvROK (sv)
297     || (SvTYPE(sv) != SVt_IV
298     && SvTYPE(sv) != SVt_NV
299     && SvTYPE(sv) != SVt_PV
300 root 1.15 && SvTYPE(sv) != SVt_PVIV
301     && SvTYPE(sv) != SVt_PVNV
302 root 1.12 && SvTYPE(sv) != SVt_PVMG)) /* mstore */
303 root 1.1 {
304 root 1.9 int deref = !SvROK (sv);
305    
306 root 1.1 if (!storable_mstore)
307     need_storable ();
308    
309 root 1.9 if (deref)
310     sv = newRV_noinc (sv);
311    
312 root 1.1 PUSHMARK (SP);
313     XPUSHs (sv);
314     PUTBACK;
315    
316     if (1 != call_sv ((SV *)storable_mstore, G_SCALAR))
317     croak ("Storable::mstore didn't return a single scalar");
318    
319     SPAGAIN;
320    
321     sv = POPs;
322    
323 root 1.20 if (SvPVX (sv)[0] == MAGIC_R)
324     {
325     if (deref)
326     SvPVX (sv)[0] = MAGIC_R_deref;
327     }
328     else
329     {
330     char pfx[2];
331    
332     pfx[0] = MAGIC_undef;
333     pfx[1] = deref ? MAGIC_R_deref : MAGIC_R;
334 root 1.1
335 root 1.20 sv_insert (sv, 0, 0, pfx, 2);
336     }
337 root 1.10
338 root 1.1 if (ix) /* compress */
339 root 1.10 sv = sv_2mortal (compress_sv (sv, deref ? MAGIC_CR_deref : MAGIC_CR, -1));
340 root 1.9
341 root 1.10 XPUSHs (sv);
342 root 1.1 }
343 root 1.13 else if (SvPOKp (sv) && IN_RANGE (SvPVX (sv)[0], MAGIC_LO, MAGIC_HI))
344 root 1.10 XPUSHs (sv_2mortal (compress_sv (sv, MAGIC_C, MAGIC_U))); /* need to prefix only */
345 root 1.1 else if (ix == 2) /* compress always */
346 root 1.10 XPUSHs (sv_2mortal (compress_sv (sv, MAGIC_C, -1)));
347 root 1.15 else if (SvNIOK (sv)) /* don't compress */
348     {
349     STRLEN len;
350     char *s = SvPV (sv, len);
351     XPUSHs (sv_2mortal (newSVpvn (s, len)));
352     }
353 root 1.1 else /* don't compress */
354 root 1.15 XPUSHs (sv_2mortal (newSVsv (sv)));
355 root 1.1
356     void
357     sthaw(sv)
358     SV * sv
359     PROTOTYPE: $
360     PPCODE:
361 root 1.20 {
362     STRLEN svlen;
363 root 1.9 int deref = 0;
364    
365 root 1.7 SvGETMAGIC (sv);
366 root 1.20 if (SvPOK (sv) && IN_RANGE (SvPV (sv, svlen)[0], MAGIC_LO, MAGIC_HI))
367 root 1.1 {
368 root 1.20 redo:
369    
370 root 1.1 switch (SvPVX (sv)[0])
371     {
372 root 1.4 case MAGIC_undef:
373 root 1.20 if (svlen <= 1)
374     XPUSHs (sv_2mortal (NEWSV (0, 0)));
375     else
376     {
377     if (SvPVX (sv)[1] == MAGIC_R_deref)
378     deref = 1;
379     else if (SvPVX (sv)[1] != MAGIC_R)
380     croak ("Compress::LZF::sthaw(): invalid data, maybe you need a newer version of Compress::LZF?");
381    
382     sv_chop (sv, SvPVX (sv) + 2);
383    
384     if (!storable_mstore)
385     need_storable ();
386    
387     PUSHMARK (SP);
388     XPUSHs (sv);
389     PUTBACK;
390    
391     if (1 != call_sv ((SV *)storable_mretrieve, G_SCALAR))
392     croak ("Storable::mstore didn't return a single scalar");
393    
394     SPAGAIN;
395    
396     if (deref)
397     SETs (sv_2mortal (SvREFCNT_inc (SvRV (TOPs))));
398     else
399     SETs (sv_2mortal (newSVsv (TOPs)));
400     }
401 root 1.4 break;
402    
403 root 1.1 case MAGIC_U:
404     XPUSHs (sv_2mortal (decompress_sv (sv, 0)));
405     break;
406    
407     case MAGIC_C:
408     XPUSHs (sv_2mortal (decompress_sv (sv, 1)));
409     break;
410    
411 root 1.10 case MAGIC_R_deref:
412     deref = 1;
413     SvPVX (sv)[0] = MAGIC_R;
414     goto handle_MAGIC_R;
415    
416 root 1.9 case MAGIC_CR_deref:
417     deref = 1;
418 root 1.1 case MAGIC_CR:
419     sv = sv_2mortal (decompress_sv (sv, 1)); /* mortal could be optimized */
420 root 1.10 if (deref)
421     if (SvPVX (sv)[0] == MAGIC_R_deref)
422 root 1.9 SvPVX (sv)[0] = MAGIC_R;
423 root 1.20
424     goto redo;
425 root 1.10
426 root 1.1 case MAGIC_R:
427 root 1.10 handle_MAGIC_R:
428 root 1.1 if (!storable_mstore)
429     need_storable ();
430    
431     PUSHMARK (SP);
432     XPUSHs (sv);
433     PUTBACK;
434    
435     if (1 != call_sv ((SV *)storable_mretrieve, G_SCALAR))
436     croak ("Storable::mstore didn't return a single scalar");
437    
438     SPAGAIN;
439    
440 root 1.9 if (deref)
441     {
442 root 1.10 SETs (sv_2mortal (SvREFCNT_inc (SvRV (TOPs))));
443 root 1.9
444     if (SvPVX (sv)[0] == MAGIC_R)
445 root 1.10 SvPVX (sv)[0] = MAGIC_R_deref;
446 root 1.9 }
447 root 1.10 else
448 pcg 1.17 SETs (sv_2mortal (newSVsv (TOPs)));
449 root 1.1
450     break;
451    
452     default:
453     croak ("Compress::LZF::sthaw(): invalid data, maybe you need a newer version of Compress::LZF?");
454     }
455     }
456     else
457 root 1.11 XPUSHs (sv_2mortal (newSVsv (sv)));
458 root 1.20 }
459 pcg 1.16