~ubuntu-branches/ubuntu/saucy/clucene-core/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/bug718187-ftbfs-hurd.patch/src/shared/CLucene/util/Misc.cpp

  • Committer: Package Import Robot
  • Author(s): Fathi Boudra
  • Date: 2013-07-29 08:31:38 UTC
  • mfrom: (6.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20130729083138-hiy0qx1pga1y6jh1
Tags: 2.3.3.4-4
Add bug718187-ftbfs-hurd.patch to fix build failure on HURD.
Thanks to Pino Toscano. (Closes: #718187)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*------------------------------------------------------------------------------
 
2
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
 
3
*
 
4
* Distributable under the terms of either the Apache License (Version 2.0) or
 
5
* the GNU Lesser General Public License, as specified in the COPYING file.
 
6
------------------------------------------------------------------------------*/
 
7
#include "CLucene/_ApiHeader.h"
 
8
#include "Misc.h"
 
9
#include <assert.h>
 
10
#include <iostream>
 
11
#include <map>
 
12
 
 
13
#if defined(_CL_HAVE_SYS_TIME_H)
 
14
# include <sys/time.h>
 
15
#elif defined(_CL_HAVE_TIME_H)
 
16
# include <time.h>
 
17
#endif
 
18
#ifdef _CL_HAVE_SYS_TIMEB_H
 
19
        #include <sys/timeb.h>
 
20
#endif
 
21
 
 
22
#if defined(_CL_HAVE_SYS_STAT_H)
 
23
    #include <sys/stat.h>
 
24
#endif
 
25
#ifdef _CL_HAVE_STRINGS_H
 
26
        #include <strings.h>
 
27
#endif
 
28
#ifdef _CL_HAVE_UNISTD_H
 
29
        #include <unistd.h>
 
30
#endif
 
31
 
 
32
#include <cctype>
 
33
#include <limits.h>
 
34
#include "CLucene/util/dirent.h" //if we have dirent, then the native one will be used
 
35
 
 
36
//for zlib...
 
37
#include "zlib.h"
 
38
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
 
39
#  include <fcntl.h>
 
40
#  include <io.h>
 
41
#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
 
42
#else
 
43
#  define SET_BINARY_MODE(file)
 
44
#endif
 
45
#define CL_Z_DEFAULT_CHUNK 1024
 
46
 
 
47
 
 
48
#ifdef _CL_HAVE_FUNCTION_SLEEP
 
49
        //don't ignore windows.h... breaks mingw32 in some cases. Define Sleep instead
 
50
        extern "C" __declspec(dllimport) void __stdcall Sleep(_cl_dword_t);
 
51
#endif
 
52
 
 
53
CL_NS_DEF(util)
 
54
 
 
55
size_t Misc::ahashCode(const char* str){
 
56
        // Compute the hash code using a local variable to be reentrant.
 
57
        size_t hashCode = 0;
 
58
        while ( *str != 0 )
 
59
                hashCode = hashCode * 31 + *str++;
 
60
        return hashCode;
 
61
}
 
62
size_t Misc::ahashCode(const char* str, size_t len){
 
63
        // Compute the hash code using a local variable to be reentrant.
 
64
        size_t hashCode = 0;
 
65
        for (size_t i = 0; i<len; i++)
 
66
                hashCode = hashCode * 31 + *str++;
 
67
        return hashCode;
 
68
}
 
69
 
 
70
int64_t Misc::filelength(int filehandle)
 
71
{
 
72
    struct cl_stat_t info;
 
73
    if (fileHandleStat(filehandle, &info) == -1)
 
74
                        return -1;
 
75
    return info.st_size;
 
76
}
 
77
 
 
78
//this is global...
 
79
void Misc::sleep(const int ms){
 
80
    #if defined(_CL_HAVE_FUNCTION_USLEEP)
 
81
        usleep(ms*1000);//expects microseconds
 
82
    #elif defined(SLEEPFUNCTION)
 
83
            SLEEPFUNCTION(ms);
 
84
        #else
 
85
            #error no sleep function???
 
86
        #endif
 
87
}
 
88
 
 
89
 
 
90
#ifdef _UCS2
 
91
size_t Misc::whashCode(const wchar_t* str){
 
92
        // Compute the hash code using a local variable to be reentrant.
 
93
        size_t hashCode = 0;
 
94
        while ( *str != 0 )
 
95
                hashCode = hashCode * 31 + *str++;
 
96
        return hashCode;
 
97
}
 
98
size_t Misc::whashCode(const wchar_t* str, size_t len){
 
99
        // Compute the hash code using a local variable to be reentrant.
 
100
        size_t hashCode = 0;
 
101
        for (size_t i = 0; i<len; i++)
 
102
                hashCode = hashCode * 31 + *str++;
 
103
        return hashCode;
 
104
}
 
105
 
 
106
std::string Misc::toString(const TCHAR* s, int32_t len){
 
107
  if ( s == NULL || len == 0 ) return "";
 
108
  if ( len < 0 ) len = _tcslen(s);
 
109
  char* buf = _CL_NEWARRAY(char,len+1);
 
110
  STRCPY_WtoA(buf,s,len+1);
 
111
  string ret = buf;
 
112
  _CLDELETE_CaARRAY(buf);
 
113
  return ret;
 
114
}
 
115
//static
 
116
char* Misc::_wideToChar(const wchar_t* s){
 
117
   size_t len = _tcslen(s);
 
118
   char* msg=_CL_NEWARRAY(char,len+1);
 
119
   _cpywideToChar( s,msg,len+1 );
 
120
   return msg;
 
121
}
 
122
wchar_t* Misc::_charToWide(const char* s){
 
123
   size_t len = strlen(s);
 
124
   wchar_t* msg = _CL_NEWARRAY(wchar_t,len+1);
 
125
   _cpycharToWide(s,msg,len+1);
 
126
   return msg;
 
127
}
 
128
 
 
129
void Misc::_cpywideToChar(const wchar_t* s, char* d, size_t len){
 
130
    size_t sLen = wcslen(s);
 
131
    for ( uint32_t i=0;i<len&&i<sLen+1;i++ )
 
132
        d[i] = LUCENE_OOR_CHAR(s[i]);
 
133
}
 
134
void Misc::_cpycharToWide(const char* s, wchar_t* d, size_t len){
 
135
    size_t sLen = strlen(s);
 
136
    for ( uint32_t i=0;i<len&&i<sLen+1;i++ )
 
137
      d[i] = s[i];
 
138
}
 
139
#endif
 
140
 
 
141
//static
 
142
uint64_t Misc::currentTimeMillis() {
 
143
#ifndef _CL_HAVE_FUNCTION_GETTIMEOFDAY
 
144
    struct _timeb tstruct;
 
145
    _ftime(&tstruct);
 
146
 
 
147
    return (((uint64_t) tstruct.time) * 1000) + tstruct.millitm;
 
148
#else
 
149
    struct timeval tstruct;
 
150
    if (gettimeofday(&tstruct, NULL) < 0) {
 
151
                        return 0;
 
152
    }
 
153
 
 
154
    return (((uint64_t) tstruct.tv_sec) * 1000) + tstruct.tv_usec / 1000;
 
155
#endif
 
156
}
 
157
 
 
158
//static
 
159
const TCHAR* Misc::replace_all( const TCHAR* val, const TCHAR* srch, const TCHAR* repl )
 
160
{
 
161
int32_t cnt = 0;
 
162
size_t repLen = _tcslen(repl);
 
163
size_t srchLen = _tcslen(srch);
 
164
size_t srcLen = _tcslen(val);
 
165
 
 
166
const TCHAR* pos = val;
 
167
while( (pos = _tcsstr(pos+1, srch)) != NULL ) {
 
168
    ++cnt;
 
169
}
 
170
 
 
171
size_t lenNew = (srcLen - (srchLen * cnt)) + (repLen * cnt);
 
172
TCHAR* ret = _CL_NEWARRAY(TCHAR,lenNew+1);
 
173
ret[lenNew] = 0;
 
174
if ( cnt == 0 ){
 
175
    _tcscpy(ret,val);
 
176
    return ret;
 
177
}
 
178
 
 
179
TCHAR* cur = ret; //position of return buffer
 
180
const TCHAR* lst = val; //position of value buffer
 
181
pos = val; //searched position of value buffer
 
182
while( (pos = _tcsstr(pos+1,srch)) != NULL ) {
 
183
    _tcsncpy(cur,lst,pos-lst); //copy till current
 
184
    cur += (pos-lst);
 
185
    lst = pos; //move val position
 
186
 
 
187
    _tcscpy( cur,repl); //copy replace
 
188
    cur += repLen; //move return buffer position
 
189
    lst += srchLen; //move last value buffer position
 
190
}
 
191
_tcscpy(cur, lst ); //copy rest of buffer
 
192
 
 
193
return ret;
 
194
}
 
195
 
 
196
//static
 
197
bool Misc::dir_Exists(const char* path){
 
198
        if ( !path || !*path )
 
199
                return false;
 
200
        struct cl_stat_t buf;
 
201
        int32_t ret = fileStat(path,&buf);
 
202
        return ( ret == 0);
 
203
}
 
204
 
 
205
int64_t Misc::file_Size(const char* path){
 
206
        struct cl_stat_t buf;
 
207
        if ( fileStat(path,&buf) == 0 )
 
208
                return buf.st_size;
 
209
        else
 
210
                return -1;
 
211
}
 
212
 
 
213
int Misc::file_Unlink(const char* path, int32_t maxAttempts )
 
214
{
 
215
    int32_t i;
 
216
 
 
217
    if( ! path || ! * path )
 
218
        return -1;
 
219
 
 
220
    if( maxAttempts == 0 )
 
221
        maxAttempts = 1;
 
222
 
 
223
    while( maxAttempts != 0 )
 
224
    {
 
225
        if( _unlink( path ) != 0 )
 
226
            return -1;
 
227
 
 
228
        i = 0;
 
229
        while( i < 100 )
 
230
        {
 
231
            if( ! Misc::dir_Exists( path ) )
 
232
                return 1;
 
233
 
 
234
            if( ++i > 50 )      // if it still doesn't show up, then we do some sleeping for the last 50ms
 
235
                _LUCENE_SLEEP( 1 );
 
236
        }
 
237
 
 
238
        if( maxAttempts > 0 )
 
239
            maxAttempts--;
 
240
    }
 
241
 
 
242
    return 0;
 
243
}
 
244
 
 
245
 
 
246
//static
 
247
TCHAR* Misc::join ( const TCHAR* a, const TCHAR* b, const TCHAR* c, const TCHAR* d,const TCHAR* e,const TCHAR* f ) {
 
248
#define LEN(x) (x == NULL ? 0 : _tcslen(x))
 
249
const size_t totalLen =
 
250
    LEN(a) + LEN(b) + LEN(c) + LEN(d) + LEN(e) + LEN(f)
 
251
    + sizeof(TCHAR); /* Space for terminator. */
 
252
 
 
253
TCHAR* buf = _CL_NEWARRAY(TCHAR,totalLen);
 
254
buf[0]=0;
 
255
if ( a != NULL) _tcscat(buf,a);
 
256
if ( b != NULL) _tcscat(buf,b);
 
257
if ( c != NULL) _tcscat(buf,c);
 
258
if ( d != NULL) _tcscat(buf,d);
 
259
if ( e != NULL) _tcscat(buf,e);
 
260
if ( f != NULL) _tcscat(buf,f);
 
261
return buf;
 
262
}
 
263
 
 
264
char* Misc::ajoin ( const char* a, const char* b, const char* c, const char* d,const char* e,const char* f ) {
 
265
  #define aLEN(x) (x == NULL ? 0 : strlen(x))
 
266
  const size_t totalLen =
 
267
    aLEN(a) + aLEN(b) + aLEN(c) + aLEN(d) + aLEN(e) + aLEN(f)
 
268
    + sizeof(char); /* Space for terminator. */
 
269
 
 
270
  char* buf = _CL_NEWARRAY(char,totalLen);
 
271
  buf[0]=0;
 
272
  if ( a != NULL) strcat(buf,a);
 
273
  if ( b != NULL) strcat(buf,b);
 
274
  if ( c != NULL) strcat(buf,c);
 
275
  if ( d != NULL) strcat(buf,d);
 
276
  if ( e != NULL) strcat(buf,e);
 
277
  if ( f != NULL) strcat(buf,f);
 
278
return buf;
 
279
}
 
280
 
 
281
//static
 
282
bool Misc::priv_isDotDir( const TCHAR* name )
 
283
{
 
284
if( name[0] == '\0' ) {
 
285
    return (false);
 
286
}
 
287
if( name[0] == '.' && name[1] == '\0' ) {
 
288
    return (true);
 
289
}
 
290
if( name[1] == '\0' ) {
 
291
    return (false);
 
292
}
 
293
if( name[0] == '.' && name[1] == '.' && name[2] == '\0' ) {
 
294
    return (true);
 
295
}
 
296
 
 
297
return (false);
 
298
}
 
299
 
 
300
//internal static function shared for clucene
 
301
string Misc::segmentname( const char* segment, const char* ext, const int32_t x ){
 
302
//Func -  Returns an allocated buffer in which it creates a filename by
 
303
//       concatenating segment with ext and x
 
304
//Pre    ext != NULL and holds the extension
 
305
//       x contains a number
 
306
//Post - A buffer has been instantiated an when x = -1 buffer contains the concatenation of
 
307
//       segment and ext otherwise buffer contains the contentation of segment, ext and x
 
308
 
 
309
        CND_PRECONDITION(ext != NULL, "ext is NULL");
 
310
 
 
311
 
 
312
  if ( x!=-1 ){
 
313
    char buf[30];
 
314
    _snprintf(buf,10,"%d",x);
 
315
    return string(segment) + ext + buf;
 
316
  }else{
 
317
    return string(segment) + ext;
 
318
  }
 
319
}
 
320
void Misc::segmentname(char* buffer,int32_t bufferLen, const char* Segment, const char* ext, const int32_t x){
 
321
//Func - Static Method
 
322
//       Creates a filename in buffer by concatenating Segment with ext and x
 
323
//Pre  - buffer  != NULL
 
324
//       Segment != NULL and holds the name of the segment
 
325
//       ext     != NULL and holds the extension
 
326
//       x contains a number
 
327
//Post - When x = -1 buffer contains the concatenation of Segment and ext otherwise
 
328
//       buffer contains the contentation of Segment, ext and x
 
329
 
 
330
        CND_PRECONDITION(buffer  != NULL, "buffer is NULL");
 
331
        CND_PRECONDITION(Segment != NULL, "Segment is NULL");
 
332
        CND_PRECONDITION(ext     != NULL, "ext is NULL");
 
333
 
 
334
        if ( x== -1 )
 
335
                _snprintf(buffer,bufferLen,"%s%s", Segment,ext );
 
336
        else
 
337
                _snprintf(buffer,bufferLen,"%s%s%d", Segment,ext,x );
 
338
}
 
339
 
 
340
 
 
341
//static
 
342
int32_t Misc::stringDifference(const TCHAR* s1, const int32_t len1, const TCHAR* s2, const int32_t len2) {
 
343
        int32_t len = len1 < len2 ? len1 : len2;
 
344
        for (int32_t i = 0; i < len; i++)
 
345
                if ( s1[i] != s2[i])
 
346
                        return i;
 
347
        return len;
 
348
}
 
349
 
 
350
TCHAR* Misc::stringTrim(TCHAR* text) {
 
351
        size_t j, i;
 
352
        size_t len = _tcslen(text);
 
353
 
 
354
        for ( i=0;i<len;i++ ){ // find the first non-space character and store it as i
 
355
                if ( ! _istspace(text[i]) )
 
356
                        break;
 
357
        }
 
358
        for ( j=len-1; j > i; --j ){ // find the last non-space character and store it as j
 
359
                if ( ! _istspace(text[j]) ) {
 
360
                        break;
 
361
                }
 
362
        }
 
363
 
 
364
        if (i==0 && j==len-1) // prevent unnecessary copy
 
365
                return text;
 
366
 
 
367
        if (i==0)
 
368
                text[j+1]=0;
 
369
        else {
 
370
                j++;
 
371
                _tcsncpy(text, text+i, j-i);
 
372
                text[j-i] = 0;
 
373
        }
 
374
 
 
375
        return text;
 
376
}
 
377
 
 
378
TCHAR* Misc::wordTrim(TCHAR* text) {
 
379
        size_t j, i;
 
380
        size_t len = _tcslen(text);
 
381
 
 
382
        for ( i=0;i<len;i++ ){ // find the first non-space character and store it as i
 
383
                if ( ! _istspace(text[i]) )
 
384
                        break;
 
385
        }
 
386
        for ( j=i; j < len; j++ ){ // find the last non-space character and store it as j
 
387
                if ( _istspace(text[j]) ) {
 
388
                        break;
 
389
                }
 
390
        }
 
391
 
 
392
        if (i == 0 && j==len)
 
393
                return text;
 
394
 
 
395
        if (i==j) // empty string
 
396
                return NULL;
 
397
 
 
398
        if (i == 0) {
 
399
                text[j] = 0;
 
400
                return text;
 
401
        } else {
 
402
                _tcsncpy(text, text+i, j-i);
 
403
                text[j-i] = 0;
 
404
        }
 
405
 
 
406
        return text;
 
407
}
 
408
 
 
409
size_t Misc::longToBase( int64_t value, int32_t base, char* retval ) {
 
410
    static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 
411
    char buf[(sizeof(unsigned long) << 3) + 1];
 
412
    char *ptr, *end;
 
413
 
 
414
    ptr = end = buf + sizeof(buf) - 1;
 
415
 
 
416
    *ptr = '\0';
 
417
    do {
 
418
            *--ptr = digits[ value % base ];
 
419
            value /= base;
 
420
    } while ( ptr > buf && value );
 
421
 
 
422
    memcpy( retval, ptr, end - ptr );
 
423
    retval[end-ptr] = 0;
 
424
 
 
425
    return end-ptr;
 
426
}
 
427
 
 
428
int64_t Misc::base36ToLong( const char* value ) {
 
429
        char* ptr = (char*)value;
 
430
        int64_t lval = 0;
 
431
 
 
432
        while ( *ptr != '\0' ) {
 
433
                lval = isdigit(*ptr) ? ( 36 * lval ) + ( *ptr - '0' ) : ( 36 * lval ) + ( *ptr - 'a' + 10 );
 
434
                ptr++;
 
435
        }
 
436
 
 
437
        return lval;
 
438
}
 
439
 
 
440
bool Misc::listFiles(const char* directory, std::vector<std::string>& files, bool fullPath){
 
441
  //clear old files
 
442
  DIR* dir = opendir(directory);
 
443
  if ( dir == NULL ) return false;
 
444
  struct dirent* fl = readdir(dir);
 
445
  struct cl_stat_t buf;
 
446
        string path;
 
447
  while ( fl != NULL ){
 
448
        path = string(directory) + "/" + fl->d_name;
 
449
                int32_t ret = fileStat(path.c_str(),&buf);
 
450
                if ( ret==0 && !(buf.st_mode & S_IFDIR) ) {
 
451
                        if ( (strcmp(fl->d_name, ".")) && (strcmp(fl->d_name, "..")) ) {
 
452
                                if ( fullPath ){
 
453
                                        files.push_back(path);
 
454
                                }else{
 
455
                                        files.push_back(fl->d_name);
 
456
                                }
 
457
                        }
 
458
                }
 
459
          fl = readdir(dir);
 
460
  }
 
461
  closedir(dir);
 
462
  return true;
 
463
}
 
464
 
 
465
 
 
466
std::string Misc::toString(const bool value){
 
467
  return value ? "true" : "false";
 
468
}
 
469
std::string Misc::toString(_LUCENE_THREADID_TYPE value){
 
470
  static int32_t nextindex = 0;
 
471
  static std::map<_LUCENE_THREADID_TYPE, int32_t> ids;
 
472
  if (ids.find(value) == ids.end()) {
 
473
    ids[value] = nextindex++;
 
474
  }
 
475
  return toString(ids[value]);
 
476
}
 
477
std::string Misc::toString(const int32_t value){
 
478
  char buf[20];
 
479
  TCHAR tbuf[20];
 
480
  _i64tot(value, tbuf, 10);
 
481
  STRCPY_TtoA(buf,tbuf,20);
 
482
  return buf;
 
483
}
 
484
std::string Misc::toString(const int64_t value){
 
485
  char buf[20];
 
486
  TCHAR tbuf[20];
 
487
  _i64tot(value, tbuf, 10);
 
488
  STRCPY_TtoA(buf,tbuf,20);
 
489
  return buf;
 
490
}
 
491
std::string Misc::toString(const float_t value){
 
492
  char buf[20];
 
493
  _snprintf(buf,20,"%0.2f",(double)value);
 
494
  return buf;
 
495
}
 
496
 
 
497
void Misc::zerr(int ret, string& err)
 
498
{
 
499
  switch (ret) {
 
500
  case Z_ERRNO:
 
501
    err = "error occurred while reading or writing from the zlib streams";
 
502
    break;
 
503
  case Z_STREAM_ERROR:
 
504
    err = "invalid compression level";
 
505
    break;
 
506
  case Z_DATA_ERROR:
 
507
    err = "invalid or incomplete deflate data";
 
508
    break;
 
509
  case Z_MEM_ERROR:
 
510
    err = "out of memory";
 
511
    break;
 
512
  case Z_VERSION_ERROR:
 
513
    err ="zlib version mismatch";
 
514
  }
 
515
}
 
516
 
 
517
 
 
518
 
 
519
/* Compress from file source to file dest until EOF on source.
 
520
   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
 
521
   allocated for processing, Z_STREAM_ERROR if an invalid compression
 
522
   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
 
523
   version of the library linked do not match, or Z_ERRNO if there is
 
524
   an error reading or writing the files. */
 
525
bool Misc::deflate(const uint8_t* in, size_t inlen, std::ostream& dest, string& err, int CHUNK, int level)
 
526
{
 
527
  int ret, flush;
 
528
  unsigned have;
 
529
  z_stream strm;
 
530
  if ( level == -1 ) level = Z_BEST_COMPRESSION;
 
531
  if ( CHUNK == -1 ) CHUNK = CL_Z_DEFAULT_CHUNK;
 
532
  uint8_t* out = (uint8_t*)malloc(CHUNK);
 
533
 
 
534
  /* allocate deflate state */
 
535
  strm.zalloc = Z_NULL;
 
536
  strm.zfree = Z_NULL;
 
537
  strm.opaque = Z_NULL;
 
538
  ret = deflateInit(&strm, level);
 
539
  if (ret != Z_OK){
 
540
    free(out);
 
541
    zerr(ret, err);
 
542
    return false;
 
543
  }
 
544
 
 
545
  /* compress until end of file */
 
546
  do {
 
547
    strm.avail_in = inlen;
 
548
    strm.next_in = (uint8_t*)in;
 
549
    flush = Z_FINISH;
 
550
 
 
551
    /* run deflate() on input until output buffer not full, finish
 
552
       compression if all of source has been read in */
 
553
    do {
 
554
      strm.avail_out = CHUNK;
 
555
      strm.next_out = out;
 
556
      ret = ::deflate(&strm, flush);  /* no bad return value */
 
557
      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
 
558
      have = CHUNK - strm.avail_out;
 
559
      dest.write( (char*)out,have);
 
560
      if ( dest.fail() ) {
 
561
        (void)deflateEnd(&strm);
 
562
        free(out);
 
563
        zerr(Z_ERRNO, err);
 
564
        return false;
 
565
      }
 
566
    } while (strm.avail_out == 0);
 
567
    assert(strm.avail_in == 0);   /* all input will be used */
 
568
 
 
569
    /* done when last data in file processed */
 
570
  } while (flush != Z_FINISH);
 
571
  assert(ret == Z_STREAM_END);    /* stream will be complete */
 
572
 
 
573
  /* clean up and return */
 
574
  (void)deflateEnd(&strm);
 
575
  free(out);
 
576
  return true;
 
577
}
 
578
 
 
579
/* Decompress from file source to file dest until stream ends or EOF.
 
580
   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
 
581
   allocated for processing, Z_DATA_ERROR if the deflate data is
 
582
   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
 
583
   the version of the library linked do not match, or Z_ERRNO if there
 
584
   is an error reading or writing the files. */
 
585
bool Misc::inflate(const uint8_t* in, size_t inlen, std::ostream& dest, string& err, int CHUNK)
 
586
{
 
587
  int ret;
 
588
  unsigned have;
 
589
  z_stream strm;
 
590
  if ( CHUNK == -1 ) CHUNK = CL_Z_DEFAULT_CHUNK;
 
591
  uint8_t* out = (uint8_t*)malloc(CHUNK);
 
592
 
 
593
  /* allocate inflate state */
 
594
  strm.zalloc = Z_NULL;
 
595
  strm.zfree = Z_NULL;
 
596
  strm.opaque = Z_NULL;
 
597
  strm.avail_in = 0;
 
598
  strm.next_in = Z_NULL;
 
599
  ret = inflateInit(&strm);
 
600
  if (ret != Z_OK){
 
601
    free(out);
 
602
    zerr(ret, err);
 
603
    return false;
 
604
  }
 
605
 
 
606
  /* decompress until deflate stream ends or end of file */
 
607
  do {
 
608
    strm.avail_in = inlen;
 
609
    if (strm.avail_in == 0)
 
610
      break;
 
611
    strm.next_in = (uint8_t*)in;
 
612
 
 
613
    /* run inflate() on input until output buffer not full */
 
614
    do {
 
615
      strm.avail_out = CHUNK;
 
616
      strm.next_out = out;
 
617
      ret = ::inflate(&strm, Z_NO_FLUSH);
 
618
      assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
 
619
      switch (ret) {
 
620
      case Z_NEED_DICT:
 
621
        ret = Z_DATA_ERROR;   /* and fall through */
 
622
      case Z_DATA_ERROR:
 
623
      case Z_MEM_ERROR:
 
624
        (void)inflateEnd(&strm);
 
625
        free(out);
 
626
        zerr(ret, err);
 
627
        return false;
 
628
      }
 
629
      have = CHUNK - strm.avail_out;
 
630
      dest.write( (char*)out,have);
 
631
      if ( dest.fail() ) {
 
632
        (void)inflateEnd(&strm);
 
633
        free(out);
 
634
        zerr(Z_ERRNO, err);
 
635
        return false;
 
636
      }
 
637
    } while (strm.avail_out == 0);
 
638
 
 
639
    /* done when inflate() says it's done */
 
640
  } while (ret != Z_STREAM_END);
 
641
 
 
642
  /* clean up and return */
 
643
  (void)inflateEnd(&strm);
 
644
  free(out);
 
645
  if ( ret == Z_STREAM_END )
 
646
    return true;
 
647
  zerr(Z_DATA_ERROR, err);
 
648
  return false;
 
649
}
 
650
 
 
651
CL_NS_END