Panda3D

compress_string.cxx

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
 All Classes Functions Variables Enumerations