00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pandabase.h"
00016
00017 #ifdef HAVE_ZLIB
00018
00019 #include "config_downloader.h"
00020
00021 #include "error_utils.h"
00022 #include "filename.h"
00023 #include "ramfile.h"
00024 #include "zStream.h"
00025 #include "config_express.h"
00026 #include "trueClock.h"
00027
00028 #include "decompressor.h"
00029
00030 #include <stdio.h>
00031 #include <errno.h>
00032
00033
00034
00035
00036
00037
00038 Decompressor::
00039 Decompressor() {
00040 _source = NULL;
00041 _decompress = NULL;
00042 _dest = NULL;
00043 }
00044
00045
00046
00047
00048
00049
00050 Decompressor::
00051 ~Decompressor() {
00052 cleanup();
00053 }
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 int Decompressor::
00064 initiate(const Filename &source_file) {
00065 string extension = source_file.get_extension();
00066 if (extension == "pz") {
00067 Filename dest_file = source_file;
00068 dest_file = source_file.get_fullpath_wo_extension();
00069 return initiate(source_file, dest_file);
00070 }
00071
00072 if (downloader_cat.is_debug()) {
00073 downloader_cat.debug()
00074 << "Unknown file extension for decompressor: ."
00075 << extension << endl;
00076 }
00077 return EU_error_abort;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087 int Decompressor::
00088 initiate(const Filename &source_file, const Filename &dest_file) {
00089 cleanup();
00090
00091
00092 _source_filename = Filename(source_file);
00093 _source_filename.set_binary();
00094
00095 pifstream *source_pfstream = new pifstream;
00096 _source = source_pfstream;
00097 if (!_source_filename.open_read(*source_pfstream)) {
00098 downloader_cat.error()
00099 << "Unable to read " << _source_filename << "\n";
00100 return get_write_error();
00101 }
00102
00103
00104 source_pfstream->seekg(0, ios::end);
00105 _source_length = source_pfstream->tellg();
00106 if (_source_length == 0) {
00107 downloader_cat.warning()
00108 << "Zero length file: " << source_file << "\n";
00109 return EU_error_file_empty;
00110 }
00111 source_pfstream->seekg(0, ios::beg);
00112
00113
00114 Filename dest_filename(dest_file);
00115 dest_filename.set_binary();
00116
00117 pofstream *dest_pfstream = new pofstream;
00118 _dest = dest_pfstream;
00119 if (dest_filename.exists()) {
00120 downloader_cat.info()
00121 << dest_filename << " already exists, removing.\n";
00122 if (!dest_filename.unlink()) {
00123 downloader_cat.error()
00124 << "Unable to remove old " << dest_filename << "\n";
00125 return get_write_error();
00126 }
00127 } else {
00128 if (downloader_cat.is_debug()) {
00129 downloader_cat.debug()
00130 << dest_filename << " does not already exist.\n";
00131 }
00132 }
00133 if (!dest_filename.open_write(*dest_pfstream, true)) {
00134 downloader_cat.error()
00135 << "Unable to write to " << dest_filename << "\n";
00136 return get_write_error();
00137 }
00138
00139
00140 _decompress = new IDecompressStream(_source, false);
00141 return EU_success;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 int Decompressor::
00154 run() {
00155 if (_decompress == (istream *)NULL) {
00156
00157 return EU_success;
00158 }
00159
00160 TrueClock *clock = TrueClock::get_global_ptr();
00161 double now = clock->get_short_time();
00162 double finish = now + decompressor_step_time;
00163
00164 static const size_t buffer_size = 1024;
00165 char buffer[buffer_size];
00166
00167 _decompress->read(buffer, buffer_size);
00168 size_t count = _decompress->gcount();
00169 while (count != 0) {
00170 _dest->write(buffer, count);
00171
00172 now = clock->get_short_time();
00173 if (now >= finish) {
00174
00175 return EU_ok;
00176 }
00177
00178 _decompress->read(buffer, buffer_size);
00179 count = _decompress->gcount();
00180 }
00181
00182
00183 cleanup();
00184 if (!keep_temporary_files) {
00185 _source_filename.unlink();
00186 }
00187 return EU_success;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197 bool Decompressor::
00198 decompress(const Filename &source_file) {
00199 int ret = initiate(source_file);
00200 if (ret < 0)
00201 return false;
00202
00203 int ch = _decompress->get();
00204 while (!_decompress->eof() && !_decompress->fail()) {
00205 _dest->put(ch);
00206 ch = _decompress->get();
00207 }
00208
00209 cleanup();
00210 if (!keep_temporary_files) {
00211 _source_filename.unlink();
00212 }
00213 return true;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223 bool Decompressor::
00224 decompress(Ramfile &source_and_dest_file) {
00225 istringstream source(source_and_dest_file._data);
00226 ostringstream dest;
00227
00228 IDecompressStream decompress(&source, false);
00229
00230 int ch = decompress.get();
00231 while (!decompress.eof() && !decompress.fail()) {
00232 dest.put(ch);
00233 ch = decompress.get();
00234 }
00235
00236 source_and_dest_file._pos = 0;
00237 source_and_dest_file._data = dest.str();
00238 return true;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 PN_stdfloat Decompressor::
00248 get_progress() const {
00249 if (_decompress == (istream *)NULL) {
00250
00251 return 1.0f;
00252 }
00253
00254 nassertr(_source_length > 0, 0.0);
00255 size_t source_pos = _source->tellg();
00256
00257
00258
00259 return (0.99f * (PN_stdfloat)source_pos / (PN_stdfloat)_source_length);
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 void Decompressor::
00269 cleanup() {
00270 if (_source != (istream *)NULL) {
00271 delete _source;
00272 _source = NULL;
00273 }
00274 if (_dest != (ostream *)NULL) {
00275 delete _dest;
00276 _dest = NULL;
00277 }
00278 if (_decompress != (istream *)NULL) {
00279 delete _decompress;
00280 _decompress = NULL;
00281 }
00282 }
00283
00284 #endif // HAVE_ZLIB