Panda3D

withOutputFile.cxx

00001 // Filename: withOutputFile.cxx
00002 // Created by:  drose (11Apr01)
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 "withOutputFile.h"
00016 #include "executionEnvironment.h"
00017 #include "zStream.h"
00018 
00019 #include "pnotify.h"
00020 
00021 ////////////////////////////////////////////////////////////////////
00022 //     Function: WithOutputFile::Constructor
00023 //       Access: Public
00024 //  Description:
00025 ////////////////////////////////////////////////////////////////////
00026 WithOutputFile::
00027 WithOutputFile(bool allow_last_param, bool allow_stdout,
00028                bool binary_output) {
00029   _allow_last_param = allow_last_param;
00030   _allow_stdout = allow_stdout;
00031   _binary_output = binary_output;
00032   _got_output_filename = false;
00033   _output_ptr = (ostream *)NULL;
00034   _owns_output_ptr = false;
00035 }
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: WithOutputFile::Destructor
00039 //       Access: Public, Virtual
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 WithOutputFile::
00043 ~WithOutputFile() {
00044   if (_owns_output_ptr) {
00045     delete _output_ptr;
00046     _owns_output_ptr = false;
00047   }
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: WithOutputFile::get_output
00052 //       Access: Public
00053 //  Description: Returns an output stream that corresponds to the
00054 //               user's intended egg file output--either stdout, or
00055 //               the named output file.
00056 ////////////////////////////////////////////////////////////////////
00057 ostream &WithOutputFile::
00058 get_output() {
00059   if (_output_ptr == (ostream *)NULL) {
00060     if (!_got_output_filename) {
00061       // No filename given; use standard output.
00062       if (!_allow_stdout) {
00063         nout << "No output filename specified.\n";
00064         exit(1);
00065       }
00066       _output_ptr = &cout;
00067       _owns_output_ptr = false;
00068 
00069     } else {
00070       // Attempt to open the named file.
00071       unlink(_output_filename.c_str());
00072       _output_filename.make_dir();
00073 
00074       bool pz_file = false;
00075 #ifdef HAVE_ZLIB
00076       if (_output_filename.get_extension() == "pz") {
00077         // The filename ends in .pz, which means to automatically compress
00078         // the file that we write.
00079         pz_file = true;
00080       }
00081 #endif  // HAVE_ZLIB
00082 
00083       if (_binary_output || pz_file) {
00084         _output_filename.set_binary();
00085       } else {
00086         _output_filename.set_text();
00087       }
00088 
00089       _output_stream.clear();
00090       if (!_output_filename.open_write(_output_stream)) {
00091         nout << "Unable to write to " << _output_filename << "\n";
00092         exit(1);
00093       }
00094       nout << "Writing " << _output_filename << "\n";
00095       _output_ptr = &_output_stream;
00096       _owns_output_ptr = false;
00097 
00098 #ifdef HAVE_ZLIB
00099       if (pz_file) {
00100         _output_ptr = new OCompressStream(_output_ptr, _owns_output_ptr);
00101         _owns_output_ptr = true;
00102       }
00103 #endif  // HAVE_ZLIB
00104     }
00105   }
00106   return *_output_ptr;
00107 }
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: WithOutputFile::close_output
00111 //       Access: Public
00112 //  Description: Closes the output stream previously opened by
00113 //               get_output().  A subsequent call to get_output() will
00114 //               open a new stream.
00115 ////////////////////////////////////////////////////////////////////
00116 void WithOutputFile::
00117 close_output() {
00118   if (_owns_output_ptr) {
00119     delete _output_ptr;
00120     _owns_output_ptr = false;
00121   }
00122   _output_ptr = NULL;
00123   _output_stream.close();
00124 }
00125 
00126 
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: WithOutputFile::has_output_filename
00130 //       Access: Public
00131 //  Description: Returns true if the user specified an output
00132 //               filename, false otherwise (e.g. the output file is
00133 //               implicitly stdout).
00134 ////////////////////////////////////////////////////////////////////
00135 bool WithOutputFile::
00136 has_output_filename() const {
00137   return _got_output_filename;
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: WithOutputFile::get_output_filename
00142 //       Access: Public
00143 //  Description: If has_output_filename() returns true, this is the
00144 //               filename that the user specified.  Otherwise, it
00145 //               returns the empty string.
00146 ////////////////////////////////////////////////////////////////////
00147 Filename WithOutputFile::
00148 get_output_filename() const {
00149   if (_got_output_filename) {
00150     return _output_filename;
00151   }
00152   return Filename();
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: WithOutputFile::check_last_arg
00157 //       Access: Protected
00158 //  Description: Checks if the last filename on the argument list is
00159 //               a file with the expected extension (if
00160 //               _allow_last_param was set true), and removes it from
00161 //               the argument list if it is.  Returns true if the
00162 //               arguments are good, false if something is invalid.
00163 //
00164 //               minimum_args is the number of arguments we know must
00165 //               be input parameters and therefore cannot be
00166 //               interpreted as output filenames.
00167 ////////////////////////////////////////////////////////////////////
00168 bool WithOutputFile::
00169 check_last_arg(ProgramBase::Args &args, int minimum_args) {
00170   if (_allow_last_param && !_got_output_filename &&
00171       (int)args.size() > minimum_args) {
00172     Filename filename = Filename::from_os_specific(args.back());
00173 
00174     if (!_preferred_extension.empty() &&
00175         ("." + filename.get_extension()) != _preferred_extension) {
00176       // This argument must not be an output filename.
00177       if (!_allow_stdout) {
00178         nout << "Output filename " << filename
00179              << " does not end in " << _preferred_extension
00180              << ".  If this is really what you intended, "
00181           "use the -o output_file syntax.\n";
00182         return false;
00183       }
00184 
00185     } else {
00186       // This argument appears to be an output filename.
00187       _got_output_filename = true;
00188       _output_filename = filename;
00189       args.pop_back();
00190 
00191       if (!verify_output_file_safe()) {
00192         return false;
00193       }
00194     }
00195   }
00196 
00197   return true;
00198 }
00199 
00200 ////////////////////////////////////////////////////////////////////
00201 //     Function: WithOutputFile::verify_output_file_safe
00202 //       Access: Protected
00203 //  Description: This is called when the output file is given as the
00204 //               last parameter on the command line.  Since this is a
00205 //               fairly dangerous way to specify the output file (it's
00206 //               easy to accidentally overwrite an input file this
00207 //               way), the convention is to disallow this syntax if
00208 //               the output file already exists.
00209 //
00210 //               This function will test if the output file exists,
00211 //               and issue a warning message if it does, returning
00212 //               false.  If all is well, it will return true.
00213 ////////////////////////////////////////////////////////////////////
00214 bool WithOutputFile::
00215 verify_output_file_safe() const {
00216   nassertr(_got_output_filename, false);
00217 
00218   if (_output_filename.exists()) {
00219     nout << "The output filename " << _output_filename << " already exists.  "
00220       "If you wish to overwrite it, you must use the -o option to specify "
00221       "the output filename, instead of simply specifying it as the last "
00222       "parameter.\n";
00223     return false;
00224   }
00225   return true;
00226 }
 All Classes Functions Variables Enumerations