1 /************
2 *
3 *   This file is part of a tool for reading 3D content in the PRC format.
4 *   Copyright (C) 2008 Orest Shardt <shardtor (at) gmail dot com>
5 *
6 *   This program is free software: you can redistribute it and/or modify
7 *   it under the terms of the GNU Lesser General Public License as published by
8 *   the Free Software Foundation, either version 3 of the License, or
9 *   (at your option) any later version.
10 *
11 *   This program is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *   GNU Lesser General Public License for more details.
15 *
16 *   You should have received a copy of the GNU Lesser General Public License
17 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 *
19 *************/
20 
21 #include "inflation.h"
22 
23 using std::istream;
24 using std::ios;
25 using std::cout;
26 using std::cerr;
27 using std::endl;
28 using std::exit;
29 
decompress(char * inb,int fileLength,char * & outb)30 int decompress(char* inb, int fileLength, char* &outb)
31 {
32   const int CHUNK = 16384;
33   unsigned int resultSize = 0;
34 
35   outb = (char*) realloc(outb,CHUNK);
36   z_stream strm;
37   strm.zalloc = Z_NULL;
38   strm.zfree = Z_NULL;
39   strm.avail_in = fileLength;
40   strm.next_in = (unsigned char*)inb;
41   strm.opaque = Z_NULL;
42   int code = inflateInit(&strm);
43 
44   if(code != Z_OK)
45     return -1;
46 
47   strm.next_out = (unsigned char*)outb;
48   strm.avail_out = CHUNK;
49   code = inflate(&strm,Z_NO_FLUSH);
50   resultSize = CHUNK-strm.avail_out;
51 
52   unsigned int size = CHUNK;
53   while(code == Z_OK)
54   {
55     outb = (char*) realloc(outb,2*size);
56     if(outb == NULL)
57     {
58       cerr << "Ran out of memory while decompressing." << endl;
59       exit(1);
60     }
61     strm.next_out = (Bytef*)(outb + resultSize);
62     strm.avail_out += size;
63     size *= 2;
64     code = inflate(&strm,Z_NO_FLUSH);
65     resultSize = size - strm.avail_out;
66   }
67 
68   code = inflateEnd(&strm);
69   if(code != Z_OK)
70   {
71     free(outb);
72     return 0;
73   }
74 
75   return resultSize;
76 }
77 
decompress(istream & input,char * & result)78 int decompress(istream &input,char* &result)
79 {
80   input.seekg(0,ios::end);
81   int fileLength = input.tellg();
82   input.seekg(0,ios::beg);
83 
84   char *inb = new char[fileLength];
85   input.read(inb,fileLength);
86 
87   int code = decompress(inb,fileLength,result);
88   delete[] inb;
89   return code;
90 }
91