Panda3D
 All Classes Functions Variables Enumerations
withOutputFile.cxx
1 // Filename: withOutputFile.cxx
2 // Created by: drose (11Apr01)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "withOutputFile.h"
16 #include "executionEnvironment.h"
17 #include "zStream.h"
18 
19 #include "pnotify.h"
20 
21 ////////////////////////////////////////////////////////////////////
22 // Function: WithOutputFile::Constructor
23 // Access: Public
24 // Description:
25 ////////////////////////////////////////////////////////////////////
26 WithOutputFile::
27 WithOutputFile(bool allow_last_param, bool allow_stdout,
28  bool binary_output) {
29  _allow_last_param = allow_last_param;
30  _allow_stdout = allow_stdout;
31  _binary_output = binary_output;
32  _got_output_filename = false;
33  _output_ptr = (ostream *)NULL;
34  _owns_output_ptr = false;
35 }
36 
37 ////////////////////////////////////////////////////////////////////
38 // Function: WithOutputFile::Destructor
39 // Access: Public, Virtual
40 // Description:
41 ////////////////////////////////////////////////////////////////////
42 WithOutputFile::
43 ~WithOutputFile() {
44  if (_owns_output_ptr) {
45  delete _output_ptr;
46  _owns_output_ptr = false;
47  }
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: WithOutputFile::get_output
52 // Access: Public
53 // Description: Returns an output stream that corresponds to the
54 // user's intended egg file output--either stdout, or
55 // the named output file.
56 ////////////////////////////////////////////////////////////////////
57 ostream &WithOutputFile::
59  if (_output_ptr == (ostream *)NULL) {
60  if (!_got_output_filename) {
61  // No filename given; use standard output.
62  if (!_allow_stdout) {
63  nout << "No output filename specified.\n";
64  exit(1);
65  }
66  _output_ptr = &cout;
67  _owns_output_ptr = false;
68 
69  } else {
70  // Attempt to open the named file.
71  unlink(_output_filename.c_str());
72  _output_filename.make_dir();
73 
74  bool pz_file = false;
75 #ifdef HAVE_ZLIB
76  if (_output_filename.get_extension() == "pz") {
77  // The filename ends in .pz, which means to automatically compress
78  // the file that we write.
79  pz_file = true;
80  }
81 #endif // HAVE_ZLIB
82 
83  if (_binary_output || pz_file) {
84  _output_filename.set_binary();
85  } else {
86  _output_filename.set_text();
87  }
88 
89  _output_stream.clear();
90  if (!_output_filename.open_write(_output_stream)) {
91  nout << "Unable to write to " << _output_filename << "\n";
92  exit(1);
93  }
94  nout << "Writing " << _output_filename << "\n";
95  _output_ptr = &_output_stream;
96  _owns_output_ptr = false;
97 
98 #ifdef HAVE_ZLIB
99  if (pz_file) {
100  _output_ptr = new OCompressStream(_output_ptr, _owns_output_ptr);
101  _owns_output_ptr = true;
102  }
103 #endif // HAVE_ZLIB
104  }
105  }
106  return *_output_ptr;
107 }
108 
109 ////////////////////////////////////////////////////////////////////
110 // Function: WithOutputFile::close_output
111 // Access: Public
112 // Description: Closes the output stream previously opened by
113 // get_output(). A subsequent call to get_output() will
114 // open a new stream.
115 ////////////////////////////////////////////////////////////////////
116 void WithOutputFile::
118  if (_owns_output_ptr) {
119  delete _output_ptr;
120  _owns_output_ptr = false;
121  }
122  _output_ptr = NULL;
123  _output_stream.close();
124 }
125 
126 
127 
128 ////////////////////////////////////////////////////////////////////
129 // Function: WithOutputFile::has_output_filename
130 // Access: Public
131 // Description: Returns true if the user specified an output
132 // filename, false otherwise (e.g. the output file is
133 // implicitly stdout).
134 ////////////////////////////////////////////////////////////////////
135 bool WithOutputFile::
137  return _got_output_filename;
138 }
139 
140 ////////////////////////////////////////////////////////////////////
141 // Function: WithOutputFile::get_output_filename
142 // Access: Public
143 // Description: If has_output_filename() returns true, this is the
144 // filename that the user specified. Otherwise, it
145 // returns the empty string.
146 ////////////////////////////////////////////////////////////////////
149  if (_got_output_filename) {
150  return _output_filename;
151  }
152  return Filename();
153 }
154 
155 ////////////////////////////////////////////////////////////////////
156 // Function: WithOutputFile::check_last_arg
157 // Access: Protected
158 // Description: Checks if the last filename on the argument list is
159 // a file with the expected extension (if
160 // _allow_last_param was set true), and removes it from
161 // the argument list if it is. Returns true if the
162 // arguments are good, false if something is invalid.
163 //
164 // minimum_args is the number of arguments we know must
165 // be input parameters and therefore cannot be
166 // interpreted as output filenames.
167 ////////////////////////////////////////////////////////////////////
168 bool WithOutputFile::
169 check_last_arg(ProgramBase::Args &args, int minimum_args) {
170  if (_allow_last_param && !_got_output_filename &&
171  (int)args.size() > minimum_args) {
172  Filename filename = Filename::from_os_specific(args.back());
173 
174  if (!_preferred_extension.empty() &&
175  ("." + filename.get_extension()) != _preferred_extension) {
176  // This argument must not be an output filename.
177  if (!_allow_stdout) {
178  nout << "Output filename " << filename
179  << " does not end in " << _preferred_extension
180  << ". If this is really what you intended, "
181  "use the -o output_file syntax.\n";
182  return false;
183  }
184 
185  } else {
186  // This argument appears to be an output filename.
187  _got_output_filename = true;
188  _output_filename = filename;
189  args.pop_back();
190 
191  if (!verify_output_file_safe()) {
192  return false;
193  }
194  }
195  }
196 
197  return true;
198 }
199 
200 ////////////////////////////////////////////////////////////////////
201 // Function: WithOutputFile::verify_output_file_safe
202 // Access: Protected
203 // Description: This is called when the output file is given as the
204 // last parameter on the command line. Since this is a
205 // fairly dangerous way to specify the output file (it's
206 // easy to accidentally overwrite an input file this
207 // way), the convention is to disallow this syntax if
208 // the output file already exists.
209 //
210 // This function will test if the output file exists,
211 // and issue a warning message if it does, returning
212 // false. If all is well, it will return true.
213 ////////////////////////////////////////////////////////////////////
214 bool WithOutputFile::
215 verify_output_file_safe() const {
216  nassertr(_got_output_filename, false);
217 
218  if (_output_filename.exists()) {
219  nout << "The output filename " << _output_filename << " already exists. "
220  "If you wish to overwrite it, you must use the -o option to specify "
221  "the output filename, instead of simply specifying it as the last "
222  "parameter.\n";
223  return false;
224  }
225  return true;
226 }
bool make_dir() const
Creates all the directories in the path to the file specified in the filename, except for the basenam...
Definition: filename.cxx:2730
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:494
void set_text()
Indicates that the filename represents a text file.
Definition: filename.I:507
void close_output()
Closes the output stream previously opened by get_output().
Filename get_output_filename() const
If has_output_filename() returns true, this is the filename that the user specified.
bool has_output_filename() const
Returns true if the user specified an output filename, false otherwise (e.g.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1356
ostream & get_output()
Returns an output stream that corresponds to the user&#39;s intended egg file output–either stdout...
bool open_write(ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
Definition: filename.cxx:2045
string get_extension() const
Returns the file extension.
Definition: filename.I:477
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).
Definition: filename.cxx:332