Mercurial > libavcodec.hg
annotate lzo.c @ 3198:6b9f0c4fbdbe libavcodec
First part of a series of speed-enchancing patches.
This one sets up a snow.h and makes snow use the dsputil function pointer
framework to access the three functions that will be implemented in asm
in the other parts of the patchset.
Patch by Robert Edele < yartrebo AH earthlink POIS net>
Original thread:
Subject: [Ffmpeg-devel] [PATCH] Snow mmx+sse2 asm optimizations
Date: Sun, 05 Feb 2006 12:47:14 -0500
author | gpoirier |
---|---|
date | Thu, 16 Mar 2006 19:18:18 +0000 |
parents | a2f611d6c34d |
children | c8c591fe26f8 |
rev | line source |
---|---|
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
1 /* |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
2 * LZO 1x decompression |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
3 * Copyright (c) 2006 Reimar Doeffinger |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
4 * |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
5 * This library is free software; you can redistribute it and/or |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
6 * modify it under the terms of the GNU Lesser General Public |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
7 * License as published by the Free Software Foundation; either |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
8 * version 2 of the License, or (at your option) any later version. |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
9 * |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
10 * This library is distributed in the hope that it will be useful, |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
13 * Lesser General Public License for more details. |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
14 * |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
15 * You should have received a copy of the GNU Lesser General Public |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
16 * License along with this library; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
3034
diff
changeset
|
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
18 */ |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
19 #include "common.h" |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
20 //! avoid e.g. MPlayers fast_memcpy, it slows things down here |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
21 #undef memcpy |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
22 #include <string.h> |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
23 #include "lzo.h" |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
24 |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
25 //! define if we may write up to 12 bytes beyond the output buffer |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
26 #define OUTBUF_PADDED 1 |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
27 //! define if we may read up to 4 bytes beyond the input buffer |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
28 #define INBUF_PADDED 1 |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
29 typedef struct LZOContext { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
30 uint8_t *in, *in_end; |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
31 uint8_t *out_start, *out, *out_end; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
32 int error; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
33 } LZOContext; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
34 |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
35 /** |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
36 * \brief read one byte from input buffer, avoiding overrun |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
37 * \return byte read |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
38 */ |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
39 static inline int get_byte(LZOContext *c) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
40 if (c->in < c->in_end) |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
41 return *c->in++; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
42 c->error |= LZO_INPUT_DEPLETED; |
3049
9f85c9cf6034
10l, get_byte returning 0 on error can cause a hang. So let's try with 1 instead...
reimar
parents:
3042
diff
changeset
|
43 return 1; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
44 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
45 |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
46 /** |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
47 * \brief decode a length value in the coding used by lzo |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
48 * \param x previous byte value |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
49 * \param mask bits used from x |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
50 * \return decoded length value |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
51 */ |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
52 static inline int get_len(LZOContext *c, int x, int mask) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
53 int cnt = x & mask; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
54 if (!cnt) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
55 while (!(x = get_byte(c))) cnt += 255; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
56 cnt += mask + x; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
57 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
58 return cnt; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
59 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
60 |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
61 /** |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
62 * \brief copy bytes from input to output buffer with checking |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
63 * \param cnt number of bytes to copy, must be > 0 |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
64 */ |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
65 static inline void copy(LZOContext *c, int cnt) { |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
66 register uint8_t *src = c->in; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
67 register uint8_t *dst = c->out; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
68 if (src + cnt > c->in_end) { |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
69 cnt = c->in_end - src; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
70 c->error |= LZO_INPUT_DEPLETED; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
71 } |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
72 if (dst + cnt > c->out_end) { |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
73 cnt = c->out_end - dst; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
74 c->error |= LZO_OUTPUT_FULL; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
75 } |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
76 #if defined(INBUF_PADDED) && defined(OUTBUF_PADDED) |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
77 dst[0] = src[0]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
78 dst[1] = src[1]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
79 dst[2] = src[2]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
80 dst[3] = src[3]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
81 src += 4; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
82 dst += 4; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
83 cnt -= 4; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
84 if (cnt > 0) |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
85 #endif |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
86 memcpy(dst, src, cnt); |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
87 c->in = src + cnt; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
88 c->out = dst + cnt; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
89 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
90 |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
91 /** |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
92 * \brief copy previously decoded bytes to current position |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
93 * \param back how many bytes back we start |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
94 * \param cnt number of bytes to copy, must be > 0 |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
95 * |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
96 * cnt > back is valid, this will copy the bytes we just copied, |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
97 * thus creating a repeating pattern with a period length of back. |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
98 */ |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
99 static inline void copy_backptr(LZOContext *c, int back, int cnt) { |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
100 register uint8_t *src = &c->out[-back]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
101 register uint8_t *dst = c->out; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
102 if (src < c->out_start) { |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
103 c->error |= LZO_INVALID_BACKPTR; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
104 return; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
105 } |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
106 if (dst + cnt > c->out_end) { |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
107 cnt = c->out_end - dst; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
108 c->error |= LZO_OUTPUT_FULL; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
109 } |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
110 if (back == 1) { |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
111 memset(dst, *src, cnt); |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
112 dst += cnt; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
113 } else { |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
114 #ifdef OUTBUF_PADDED |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
115 dst[0] = src[0]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
116 dst[1] = src[1]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
117 dst[2] = src[2]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
118 dst[3] = src[3]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
119 src += 4; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
120 dst += 4; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
121 cnt -= 4; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
122 if (cnt > 0) { |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
123 dst[0] = src[0]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
124 dst[1] = src[1]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
125 dst[2] = src[2]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
126 dst[3] = src[3]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
127 dst[4] = src[4]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
128 dst[5] = src[5]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
129 dst[6] = src[6]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
130 dst[7] = src[7]; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
131 src += 8; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
132 dst += 8; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
133 cnt -= 8; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
134 } |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
135 #endif |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
136 if (cnt > 0) { |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
137 int blocklen = back; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
138 while (cnt > blocklen) { |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
139 memcpy(dst, src, blocklen); |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
140 dst += blocklen; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
141 cnt -= blocklen; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
142 blocklen <<= 1; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
143 } |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
144 memcpy(dst, src, cnt); |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
145 } |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
146 dst += cnt; |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
147 } |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
148 c->out = dst; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
149 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
150 |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
151 /** |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
152 * \brief decode LZO 1x compressed data |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
153 * \param out output buffer |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
154 * \param outlen size of output buffer, number of bytes left are returned here |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
155 * \param in input buffer |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
156 * \param inlen size of input buffer, number of bytes left are returned here |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
157 * \return 0 on success, otherwise error flags, see lzo.h |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
158 * |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
159 * make sure all buffers are appropriately padded, in must provide |
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
160 * LZO_INPUT_PADDING, out must provide LZO_OUTPUT_PADDING additional bytes |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
161 */ |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
162 int lzo1x_decode(void *out, int *outlen, void *in, int *inlen) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
163 enum {COPY, BACKPTR} state = COPY; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
164 int x; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
165 LZOContext c; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
166 c.in = in; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
167 c.in_end = in + *inlen; |
3060
a2f611d6c34d
faster copy functions for lzo decoder that also need padding
reimar
parents:
3049
diff
changeset
|
168 c.out = c.out_start = out; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
169 c.out_end = out + * outlen; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
170 c.error = 0; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
171 x = get_byte(&c); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
172 if (x > 17) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
173 copy(&c, x - 17); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
174 x = get_byte(&c); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
175 if (x < 16) c.error |= LZO_ERROR; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
176 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
177 while (!c.error) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
178 int cnt, back; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
179 if (x >> 4) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
180 if (x >> 6) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
181 cnt = (x >> 5) - 1; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
182 back = (get_byte(&c) << 3) + ((x >> 2) & 7) + 1; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
183 } else if (x >> 5) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
184 cnt = get_len(&c, x, 31); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
185 x = get_byte(&c); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
186 back = (get_byte(&c) << 6) + (x >> 2) + 1; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
187 } else { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
188 cnt = get_len(&c, x, 7); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
189 back = (1 << 14) + ((x & 8) << 11); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
190 x = get_byte(&c); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
191 back += (get_byte(&c) << 6) + (x >> 2); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
192 if (back == (1 << 14)) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
193 if (cnt != 1) |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
194 c.error |= LZO_ERROR; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
195 break; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
196 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
197 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
198 } else |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
199 switch (state) { |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
200 case COPY: |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
201 cnt = get_len(&c, x, 15); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
202 copy(&c, cnt + 3); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
203 x = get_byte(&c); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
204 if (x >> 4) |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
205 continue; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
206 cnt = 1; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
207 back = (1 << 11) + (get_byte(&c) << 2) + (x >> 2) + 1; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
208 break; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
209 case BACKPTR: |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
210 cnt = 0; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
211 back = (get_byte(&c) << 2) + (x >> 2) + 1; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
212 break; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
213 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
214 copy_backptr(&c, back, cnt + 2); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
215 cnt = x & 3; |
3041
241b3a9bbd0c
Wrong state handling causing decompression errors in some cases
reimar
parents:
3036
diff
changeset
|
216 state = cnt ? BACKPTR : COPY; |
3034
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
217 if (cnt) |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
218 copy(&c, cnt); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
219 x = get_byte(&c); |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
220 } |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
221 *inlen = c.in_end - c.in; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
222 *outlen = c.out_end - c.out; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
223 return c.error; |
d37065d8aeff
Our own LZO (1X) implementation, under LGPL and optimized for readability.
reimar
parents:
diff
changeset
|
224 } |