Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <pcl/io/lzf.h>
00039 #include <cstring>
00040 #include <climits>
00041 #include <pcl/console/print.h>
00042 #include <errno.h>
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #define HLOG 13
00053
00054 typedef unsigned int LZF_HSLOT;
00055 typedef unsigned int LZF_STATE[1 << (HLOG)];
00056
00057 #define STRICT_ALIGN !(defined(__i386) || defined (__amd64))
00058 #if !STRICT_ALIGN
00059
00060 # if USHRT_MAX == 65535
00061 typedef unsigned short u16;
00062 # elif UINT_MAX == 65535
00063 typedef unsigned int u16;
00064 # else
00065 # undef STRICT_ALIGN
00066 # define STRICT_ALIGN 1
00067 # endif
00068 #endif
00069
00070
00071
00072 #define IDX(h) ((( h >> (3*8 - HLOG)) - h ) & ((1 << (HLOG)) - 1))
00073
00075
00076
00077
00078
00079
00080
00081
00082
00083 unsigned int
00084 pcl::lzfCompress (const void *const in_data, unsigned int in_len,
00085 void *out_data, unsigned int out_len)
00086 {
00087 LZF_STATE htab;
00088 const unsigned char *ip = static_cast<const unsigned char *> (in_data);
00089 unsigned char *op = static_cast<unsigned char *> (out_data);
00090 const unsigned char *in_end = ip + in_len;
00091 unsigned char *out_end = op + out_len;
00092 const unsigned char *ref;
00093
00094
00095
00096
00097
00098
00099
00100 #if defined (WIN32) && defined (_M_X64)
00101
00102 unsigned _int64 off;
00103 #else
00104 unsigned long off;
00105 #endif
00106 unsigned int hval;
00107 int lit;
00108
00109 if (!in_len || !out_len)
00110 {
00111 PCL_WARN ("[pcl::lzf_compress] Input or output has 0 size!\n");
00112 return (0);
00113 }
00114
00115
00116 memset (htab, 0, sizeof (htab));
00117
00118
00119 lit = 0; op++;
00120
00121 hval = (ip[0] << 8) | ip[1];
00122 while (ip < in_end - 2)
00123 {
00124 unsigned int *hslot;
00125
00126 hval = (hval << 8) | ip[2];
00127 hslot = htab + IDX (hval);
00128 ref = *hslot + (static_cast<const unsigned char*> (in_data));
00129 *hslot = static_cast<unsigned int> (ip - (static_cast<const unsigned char*> (in_data)));
00130
00131 if (
00132
00133 ref < ip
00134 && (off = ip - ref - 1) < (1 << 13)
00135 && ref > static_cast<const unsigned char *> (in_data)
00136 && ref[2] == ip[2]
00137 #if STRICT_ALIGN
00138 && ((ref[1] << 8) | ref[0]) == ((ip[1] << 8) | ip[0])
00139 #else
00140 && *reinterpret_cast<const u16 *> (ref) == *reinterpret_cast<const u16 *> (ip)
00141 #endif
00142 )
00143 {
00144
00145 unsigned int len = 2;
00146 ptrdiff_t maxlen = in_end - ip - len;
00147 maxlen = maxlen > ((1 << 8) + (1 << 3)) ? ((1 << 8) + (1 << 3)) : maxlen;
00148
00149
00150 if (op + 3 + 1 >= out_end)
00151 {
00152
00153 if (op - !lit + 3 + 1 >= out_end)
00154 {
00155 PCL_WARN ("[pcl::lzf_compress] Attempting to write data outside the output buffer!\n");
00156 return (0);
00157 }
00158 }
00159
00160
00161 op [- lit - 1] = static_cast<unsigned char>(lit - 1);
00162
00163 op -= !lit;
00164
00165 while (true)
00166 {
00167 if (maxlen > 16)
00168 {
00169 len++; if (ref [len] != ip [len]) break;
00170 len++; if (ref [len] != ip [len]) break;
00171 len++; if (ref [len] != ip [len]) break;
00172 len++; if (ref [len] != ip [len]) break;
00173
00174 len++; if (ref [len] != ip [len]) break;
00175 len++; if (ref [len] != ip [len]) break;
00176 len++; if (ref [len] != ip [len]) break;
00177 len++; if (ref [len] != ip [len]) break;
00178
00179 len++; if (ref [len] != ip [len]) break;
00180 len++; if (ref [len] != ip [len]) break;
00181 len++; if (ref [len] != ip [len]) break;
00182 len++; if (ref [len] != ip [len]) break;
00183
00184 len++; if (ref [len] != ip [len]) break;
00185 len++; if (ref [len] != ip [len]) break;
00186 len++; if (ref [len] != ip [len]) break;
00187 len++; if (ref [len] != ip [len]) break;
00188 }
00189
00190 do
00191 len++;
00192 while (len < static_cast<unsigned int> (maxlen) && ref[len] == ip[len]);
00193
00194 break;
00195 }
00196
00197
00198 len -= 2;
00199 ip++;
00200
00201 if (len < 7)
00202 {
00203 *op++ = static_cast<unsigned char> ((off >> 8) + (len << 5));
00204 }
00205 else
00206 {
00207 *op++ = static_cast<unsigned char> ((off >> 8) + ( 7 << 5));
00208 *op++ = static_cast<unsigned char> (len - 7);
00209 }
00210
00211 *op++ = static_cast<unsigned char> (off);
00212
00213
00214 lit = 0; op++;
00215
00216 ip += len + 1;
00217
00218 if (ip >= in_end - 2)
00219 break;
00220
00221 --ip;
00222 hval = (ip[0] << 8) | ip[1];
00223
00224 hval = (hval << 8) | ip[2];
00225 htab[IDX (hval)] = static_cast<unsigned int> (ip - (static_cast<const unsigned char *> (in_data)));
00226 ip++;
00227 }
00228 else
00229 {
00230
00231 if (op >= out_end)
00232 {
00233 PCL_WARN ("[pcl::lzf_compress] Attempting to copy data outside the output buffer!\n");
00234 return (0);
00235 }
00236
00237 lit++; *op++ = *ip++;
00238
00239 if (lit == (1 << 5))
00240 {
00241
00242 op [- lit - 1] = static_cast<unsigned char> (lit - 1);
00243
00244 lit = 0; op++;
00245 }
00246 }
00247 }
00248
00249
00250 if (op + 3 > out_end)
00251 return (0);
00252
00253 while (ip < in_end)
00254 {
00255 lit++; *op++ = *ip++;
00256
00257 if (lit == (1 << 5))
00258 {
00259
00260 op [- lit - 1] = static_cast<unsigned char> (lit - 1);
00261
00262 lit = 0; op++;
00263 }
00264 }
00265
00266
00267 op [- lit - 1] = static_cast<unsigned char> (lit - 1);
00268
00269 op -= !lit;
00270
00271 return (static_cast<unsigned int> (op - static_cast<unsigned char *> (out_data)));
00272 }
00273
00275 unsigned int
00276 pcl::lzfDecompress (const void *const in_data, unsigned int in_len,
00277 void *out_data, unsigned int out_len)
00278 {
00279 unsigned char const *ip = static_cast<const unsigned char *> (in_data);
00280 unsigned char *op = static_cast<unsigned char *> (out_data);
00281 unsigned char const *const in_end = ip + in_len;
00282 unsigned char *const out_end = op + out_len;
00283
00284 do
00285 {
00286 unsigned int ctrl = *ip++;
00287
00288
00289 if (ctrl < (1 << 5))
00290 {
00291 ctrl++;
00292
00293 if (op + ctrl > out_end)
00294 {
00295 errno = E2BIG;
00296 return (0);
00297 }
00298
00299
00300 if (ip + ctrl > in_end)
00301 {
00302 errno = EINVAL;
00303 return (0);
00304 }
00305 switch (ctrl)
00306 {
00307 case 32: *op++ = *ip++; case 31: *op++ = *ip++; case 30: *op++ = *ip++; case 29: *op++ = *ip++;
00308 case 28: *op++ = *ip++; case 27: *op++ = *ip++; case 26: *op++ = *ip++; case 25: *op++ = *ip++;
00309 case 24: *op++ = *ip++; case 23: *op++ = *ip++; case 22: *op++ = *ip++; case 21: *op++ = *ip++;
00310 case 20: *op++ = *ip++; case 19: *op++ = *ip++; case 18: *op++ = *ip++; case 17: *op++ = *ip++;
00311 case 16: *op++ = *ip++; case 15: *op++ = *ip++; case 14: *op++ = *ip++; case 13: *op++ = *ip++;
00312 case 12: *op++ = *ip++; case 11: *op++ = *ip++; case 10: *op++ = *ip++; case 9: *op++ = *ip++;
00313 case 8: *op++ = *ip++; case 7: *op++ = *ip++; case 6: *op++ = *ip++; case 5: *op++ = *ip++;
00314 case 4: *op++ = *ip++; case 3: *op++ = *ip++; case 2: *op++ = *ip++; case 1: *op++ = *ip++;
00315 }
00316 }
00317
00318 else
00319 {
00320 unsigned int len = ctrl >> 5;
00321
00322 unsigned char *ref = op - ((ctrl & 0x1f) << 8) - 1;
00323
00324
00325 if (ip >= in_end)
00326 {
00327 errno = EINVAL;
00328 return (0);
00329 }
00330 if (len == 7)
00331 {
00332 len += *ip++;
00333
00334 if (ip >= in_end)
00335 {
00336 errno = EINVAL;
00337 return (0);
00338 }
00339 }
00340 ref -= *ip++;
00341
00342 if (op + len + 2 > out_end)
00343 {
00344 errno = E2BIG;
00345 return (0);
00346 }
00347
00348 if (ref < static_cast<unsigned char *> (out_data))
00349 {
00350 errno = EINVAL;
00351 return (0);
00352 }
00353
00354 switch (len)
00355 {
00356 default:
00357 {
00358 len += 2;
00359
00360 if (op >= ref + len)
00361 {
00362
00363 memcpy (op, ref, len);
00364 op += len;
00365 }
00366 else
00367 {
00368
00369 do
00370 *op++ = *ref++;
00371 while (--len);
00372 }
00373
00374 break;
00375 }
00376 case 9: *op++ = *ref++;
00377 case 8: *op++ = *ref++;
00378 case 7: *op++ = *ref++;
00379 case 6: *op++ = *ref++;
00380 case 5: *op++ = *ref++;
00381 case 4: *op++ = *ref++;
00382 case 3: *op++ = *ref++;
00383 case 2: *op++ = *ref++;
00384 case 1: *op++ = *ref++;
00385 case 0: *op++ = *ref++;
00386 *op++ = *ref++;
00387 }
00388 }
00389 }
00390 while (ip < in_end);
00391
00392 return (static_cast<unsigned int> (op - static_cast<unsigned char*> (out_data)));
00393 }
00394