Panda3D
|
00001 // Filename: compress_string.cxx 00002 // Created by: drose (09Aug09) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "compress_string.h" 00016 00017 #ifdef HAVE_ZLIB 00018 #include "zStream.h" 00019 #include "virtualFileSystem.h" 00020 #include "config_express.h" 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // Function: compress_string 00024 // Access: Published 00025 // Description: Compress the indicated source string at the given 00026 // compression level (1 through 9). Returns the 00027 // compressed string. 00028 //////////////////////////////////////////////////////////////////// 00029 string 00030 compress_string(const string &source, int compression_level) { 00031 ostringstream dest; 00032 00033 { 00034 OCompressStream compress; 00035 compress.open(&dest, false, compression_level); 00036 compress.write(source.data(), source.length()); 00037 00038 if (compress.fail()) { 00039 return string(); 00040 } 00041 } 00042 00043 return dest.str(); 00044 } 00045 00046 //////////////////////////////////////////////////////////////////// 00047 // Function: decompress_string 00048 // Access: Published 00049 // Description: Decompresss the previously-compressed string()). The 00050 // return value is the decompressed string. 00051 // 00052 // Note that a decompression error cannot easily be 00053 // detected, and the return value may simply be a 00054 // garbage or truncated string. 00055 //////////////////////////////////////////////////////////////////// 00056 string 00057 decompress_string(const string &source) { 00058 istringstream source_stream(source); 00059 ostringstream dest_stream; 00060 00061 if (!decompress_stream(source_stream, dest_stream)) { 00062 return string(); 00063 } 00064 00065 return dest_stream.str(); 00066 } 00067 00068 //////////////////////////////////////////////////////////////////// 00069 // Function: compress_file 00070 // Access: Published 00071 // Description: Compresss the data from the source file at the given 00072 // compression level (1 through 9). The source file is 00073 // read in its entirety, and the compressed results are 00074 // written to the dest file, overwriting its contents. 00075 // The return value is bool on success, or false on 00076 // failure. 00077 //////////////////////////////////////////////////////////////////// 00078 EXPCL_PANDAEXPRESS bool 00079 compress_file(const Filename &source, const Filename &dest, int compression_level) { 00080 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00081 Filename source_filename = source; 00082 if (!source_filename.is_binary_or_text()) { 00083 // The default is binary, if not specified otherwise. 00084 source_filename.set_binary(); 00085 } 00086 istream *source_stream = vfs->open_read_file(source_filename, false); 00087 if (source_stream == NULL) { 00088 express_cat.info() << "Couldn't open file " << source_filename << "\n"; 00089 return false; 00090 } 00091 00092 Filename dest_filename = Filename::binary_filename(dest); 00093 ostream *dest_stream = vfs->open_write_file(dest_filename, false, true); 00094 if (dest_stream == NULL) { 00095 express_cat.info() << "Couldn't open file " << dest_filename << "\n"; 00096 vfs->close_read_file(source_stream); 00097 return false; 00098 } 00099 00100 bool result = compress_stream(*source_stream, *dest_stream, compression_level); 00101 vfs->close_read_file(source_stream); 00102 vfs->close_write_file(dest_stream); 00103 return result; 00104 } 00105 00106 //////////////////////////////////////////////////////////////////// 00107 // Function: decompress_file 00108 // Access: Published 00109 // Description: Decompresss the data from the source file. The 00110 // source file is read in its entirety, and the 00111 // decompressed results are written to the dest file, 00112 // overwriting its contents. The return value is bool 00113 // on success, or false on failure. 00114 // 00115 // Note that a decompression error cannot easily be 00116 // detected, and the output may simply be a garbage 00117 // or truncated string. 00118 //////////////////////////////////////////////////////////////////// 00119 EXPCL_PANDAEXPRESS bool 00120 decompress_file(const Filename &source, const Filename &dest) { 00121 Filename source_filename = Filename::binary_filename(source); 00122 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00123 istream *source_stream = vfs->open_read_file(source_filename, false); 00124 if (source_stream == NULL) { 00125 express_cat.info() << "Couldn't open file " << source_filename << "\n"; 00126 return false; 00127 } 00128 00129 Filename dest_filename = dest; 00130 if (!dest_filename.is_binary_or_text()) { 00131 // The default is binary, if not specified otherwise. 00132 dest_filename.set_binary(); 00133 } 00134 ostream *dest_stream = vfs->open_write_file(dest_filename, false, true); 00135 if (dest_stream == NULL) { 00136 express_cat.info() << "Couldn't open file " << dest_filename << "\n"; 00137 vfs->close_read_file(source_stream); 00138 return false; 00139 } 00140 00141 bool result = decompress_stream(*source_stream, *dest_stream); 00142 vfs->close_read_file(source_stream); 00143 vfs->close_write_file(dest_stream); 00144 return result; 00145 } 00146 00147 //////////////////////////////////////////////////////////////////// 00148 // Function: compress_stream 00149 // Access: Published 00150 // Description: Compresss the data from the source stream at the 00151 // given compression level (1 through 9). The source 00152 // stream is read from its current position to the 00153 // end-of-file, and the compressed results are written 00154 // to the dest stream. The return value is bool on 00155 // success, or false on failure. 00156 //////////////////////////////////////////////////////////////////// 00157 bool 00158 compress_stream(istream &source, ostream &dest, int compression_level) { 00159 OCompressStream compress; 00160 compress.open(&dest, false, compression_level); 00161 00162 static const size_t buffer_size = 4096; 00163 char buffer[buffer_size]; 00164 00165 source.read(buffer, buffer_size); 00166 size_t count = source.gcount(); 00167 while (count != 0) { 00168 compress.write(buffer, count); 00169 source.read(buffer, buffer_size); 00170 count = source.gcount(); 00171 } 00172 compress.close(); 00173 00174 return (!source.fail() || source.eof()) && (!compress.fail()); 00175 } 00176 00177 //////////////////////////////////////////////////////////////////// 00178 // Function: decompress_stream 00179 // Access: Published 00180 // Description: Decompresss the data from the previously-compressed 00181 // source stream. The source stream is read from its 00182 // current position to the end-of-file, and the 00183 // decompressed results are written to the dest stream. 00184 // The return value is bool on success, or false on 00185 // failure. 00186 // 00187 // Note that a decompression error cannot easily be 00188 // detected, and the output may simply be a garbage 00189 // or truncated string. 00190 //////////////////////////////////////////////////////////////////// 00191 bool 00192 decompress_stream(istream &source, ostream &dest) { 00193 IDecompressStream decompress(&source, false); 00194 00195 static const size_t buffer_size = 4096; 00196 char buffer[buffer_size]; 00197 00198 decompress.read(buffer, buffer_size); 00199 size_t count = decompress.gcount(); 00200 while (count != 0) { 00201 dest.write(buffer, count); 00202 decompress.read(buffer, buffer_size); 00203 count = decompress.gcount(); 00204 } 00205 00206 return (!decompress.fail() || decompress.eof()) && (!dest.fail()); 00207 } 00208 00209 #endif // HAVE_ZLIB