Panda3D
Loading...
Searching...
No Matches
virtualFile.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file virtualFile.cxx
10 * @author drose
11 * @date 2002-08-03
12 */
13
14#include "virtualFile.h"
15#include "virtualFileSystem.h"
16#include "virtualFileList.h"
17#include "config_express.h"
18#include "pvector.h"
19#include <iterator>
20
21using std::iostream;
22using std::istream;
23using std::ostream;
24using std::string;
25
26TypeHandle VirtualFile::_type_handle;
27
28/**
29 * Returns true if this file exists, false otherwise.
30 */
32has_file() const {
33 return false;
34}
35
36/**
37 * Returns true if this file represents a directory (and scan_directory() may
38 * be called), false otherwise.
39 */
41is_directory() const {
42 return false;
43}
44
45/**
46 * Returns true if this file represents a regular file (and read_file() may be
47 * called), false otherwise.
48 */
50is_regular_file() const {
51 return false;
52}
53
54/**
55 * Returns true if this file may be written to, which implies write_file() may
56 * be called (unless it is a directory instead of a regular file).
57 */
59is_writable() const {
60 return false;
61}
62
63/**
64 * Attempts to delete this file or directory. This can remove a single file
65 * or an empty directory. It will not remove a nonempty directory. Returns
66 * true on success, false on failure.
67 */
70 return false;
71}
72
73/**
74 * Attempts to move or rename this file or directory. If the original file is
75 * an ordinary file, it will quietly replace any already-existing file in the
76 * new filename (but not a directory). If the original file is a directory,
77 * the new filename must not already exist.
78 *
79 * If the file is a directory, the new filename must be within the same mount
80 * point. If the file is an ordinary file, the new filename may be anywhere;
81 * but if it is not within the same mount point then the rename operation is
82 * automatically performed as a two-step copy-and-delete operation.
83 */
85rename_file(VirtualFile *new_file) {
86 return false;
87}
88
89/**
90 * Attempts to copy the contents of this file to the indicated file. Returns
91 * true on success, false on failure.
92 */
94copy_file(VirtualFile *new_file) {
95 return false;
96}
97
98/**
99 * If the file represents a directory (that is, is_directory() returns true),
100 * this returns the list of files within the directory at the current time.
101 * Returns NULL if the file is not a directory or if the directory cannot be
102 * read.
103 */
105scan_directory() const {
106 // First, we have to make sure there aren't any mount points attached under
107 // this directory. These will override any local filenames.
108 VirtualFileSystem *file_system = get_file_system();
109 Filename this_filename = get_filename();
110 vector_string mount_points_flat;
111 file_system->scan_mount_points(mount_points_flat, this_filename);
112
113 // Copy the set of nested mount points to a sorted list so we can search it
114 // quickly.
115 ov_set<string> mount_points;
116 std::copy(mount_points_flat.begin(), mount_points_flat.end(),
117 std::back_inserter(mount_points));
118 mount_points.sort();
119
120
121 PT(VirtualFileList) file_list = new VirtualFileList;
122
123 // Each of those mount points maps to a directory root or something from the
124 // file system.
125 ov_set<string>::const_iterator mi;
126 for (mi = mount_points.begin(); mi != mount_points.end(); ++mi) {
127 const string &basename = (*mi);
128 Filename filename(this_filename, basename);
129 PT(VirtualFile) file = file_system->get_file(filename);
130 file_list->add_file(file);
131 }
132
133 // Now, get the actual local files in this directory.
134 vector_string names;
135 if (!scan_local_directory(file_list, mount_points)) {
136 // Not a directory, or unable to read directory.
137 if (file_list->get_num_files() == 0) {
138 return nullptr;
139 }
140
141 // We couldn't read the physical directory, but we do have some mounted
142 // files to return.
143 return file_list;
144 }
145
146 return file_list;
147}
148
149/**
150 *
151 */
152void VirtualFile::
153output(ostream &out) const {
154 out << get_filename();
155}
156
157/**
158 * If the file represents a directory, lists its contents.
159 */
161ls(ostream &out) const {
162 CPT(VirtualFileList) contents = scan_directory();
163 if (contents == nullptr) {
164 if (!is_directory()) {
165 out << get_filename() << "\n";
166 } else {
167 out << get_filename() << " cannot be read.\n";
168 }
169 return;
170 }
171
172 int num_files = contents->get_num_files();
173 for (int i = 0; i < num_files; i++) {
174 VirtualFile *file = contents->get_file(i);
175 out << file->get_filename().get_basename() << "\n";
176 }
177}
178
179/**
180 * If the file represents a directory, recursively lists its contents and
181 * those of all subdirectories.
182 */
184ls_all(ostream &out) const {
185 if (!is_directory()) {
186 out << get_filename() << " is not a directory.\n";
187 } else {
188 r_ls_all(out, get_filename());
189 }
190}
191
192/**
193 * Opens the file for reading. Returns a newly allocated istream on success
194 * (which you should eventually delete when you are done reading). Returns
195 * NULL on failure.
196 */
198open_read_file(bool auto_unwrap) const {
199 return nullptr;
200}
201
202/**
203 * Closes a file opened by a previous call to open_read_file(). This really
204 * just deletes the istream pointer, but it is recommended to use this
205 * interface instead of deleting it explicitly, to help work around compiler
206 * issues.
207 */
209close_read_file(istream *stream) const {
210 nassertv(false);
211}
212
213/**
214 * Call this method after a reading the istream returned by open_read_file()
215 * to completion. If it returns true, the file was read completely and
216 * without error; if it returns false, there may have been some errors or a
217 * truncated file read. This is particularly likely if the stream is a
218 * VirtualFileHTTP.
219 */
221was_read_successful() const {
222 return true;
223}
224
225/**
226 * Opens the file for writing. Returns a newly allocated ostream on success
227 * (which you should eventually delete when you are done writing). Returns
228 * NULL on failure.
229 */
231open_write_file(bool auto_wrap, bool truncate) {
232 return nullptr;
233}
234
235/**
236 * Works like open_write_file(), but the file is opened in append mode. Like
237 * open_write_file, the returned pointer should eventually be passed to
238 * close_write_file().
239 */
242 return nullptr;
243}
244
245/**
246 * Closes a file opened by a previous call to open_write_file(). This really
247 * just deletes the ostream pointer, but it is recommended to use this
248 * interface instead of deleting it explicitly, to help work around compiler
249 * issues.
250 */
252close_write_file(ostream *stream) {
253 nassertv(false);
254}
255
256/**
257 * Opens the file for writing. Returns a newly allocated iostream on success
258 * (which you should eventually delete when you are done writing). Returns
259 * NULL on failure.
260 */
262open_read_write_file(bool truncate) {
263 return nullptr;
264}
265
266/**
267 * Works like open_read_write_file(), but the file is opened in append mode.
268 * Like open_read_write_file, the returned pointer should eventually be passed
269 * to close_read_write_file().
270 */
273 return nullptr;
274}
275
276/**
277 * Closes a file opened by a previous call to open_read_write_file(). This
278 * really just deletes the iostream pointer, but it is recommended to use this
279 * interface instead of deleting it explicitly, to help work around compiler
280 * issues.
281 */
283close_read_write_file(iostream *stream) {
284 nassertv(false);
285}
286
287/**
288 * Returns the current size on disk (or wherever it is) of the already-open
289 * file. Pass in the stream that was returned by open_read_file(); some
290 * implementations may require this stream to determine the size.
291 */
292std::streamsize VirtualFile::
293get_file_size(istream *stream) const {
294 return get_file_size();
295}
296
297/**
298 * Returns the current size on disk (or wherever it is) of the file before it
299 * has been opened.
300 */
301std::streamsize VirtualFile::
302get_file_size() const {
303 return 0;
304}
305
306/**
307 * Returns a time_t value that represents the time the file was last modified,
308 * to within whatever precision the operating system records this information
309 * (on a Windows95 system, for instance, this may only be accurate to within 2
310 * seconds).
311 *
312 * If the timestamp cannot be determined, either because it is not supported
313 * by the operating system or because there is some error (such as file not
314 * found), returns 0.
315 */
317get_timestamp() const {
318 return 0;
319}
320
321/**
322 * Populates the SubfileInfo structure with the data representing where the
323 * file actually resides on disk, if this is knowable. Returns true if the
324 * file might reside on disk, and the info is populated, or false if it does
325 * not (or it is not known where the file resides), in which case the info is
326 * meaningless.
327 */
330 return false;
331}
332
333/**
334 * See Filename::atomic_compare_and_exchange_contents().
335 */
337atomic_compare_and_exchange_contents(string &orig_contents,
338 const string &old_contents,
339 const string &new_contents) {
340 return false;
341}
342
343/**
344 * See Filename::atomic_read_contents().
345 */
347atomic_read_contents(string &contents) const {
348 return false;
349}
350
351/**
352 * Fills up the indicated string with the contents of the file, if it is a
353 * regular file. Returns true on success, false otherwise.
354 */
356read_file(string &result, bool auto_unwrap) const {
357 result = string();
358
359 vector_uchar pv;
360 if (!read_file(pv, auto_unwrap)) {
361 return false;
362 }
363
364 if (!pv.empty()) {
365 result.append((const char *)&pv[0], pv.size());
366 }
367
368 return true;
369}
370
371/**
372 * Fills up the indicated pvector with the contents of the file, if it is a
373 * regular file. Returns true on success, false otherwise.
374 */
376read_file(vector_uchar &result, bool auto_unwrap) const {
377 return false;
378}
379
380/**
381 * Writes the indicated data to the file, if it is writable. Returns true on
382 * success, false otherwise.
383 */
385write_file(const unsigned char *data, size_t data_size, bool auto_wrap) {
386 return false;
387}
388
389/**
390 * Fills up the indicated pvector with the contents of the just-opened file.
391 * Returns true on success, false otherwise. If the pvector was not empty on
392 * entry, the data read from the file will be appended onto it.
393 */
395simple_read_file(istream *in, vector_uchar &result) {
396 static const size_t buffer_size = 4096;
397 char buffer[buffer_size];
398
399 in->read(buffer, buffer_size);
400 size_t count = in->gcount();
401 while (count != 0) {
402 thread_consider_yield();
403 result.insert(result.end(), buffer, buffer + count);
404 in->read(buffer, buffer_size);
405 count = in->gcount();
406 }
407
408 return (!in->fail() || in->eof());
409}
410
411/**
412 * As in simple_read_file() with two parameters, above, but only reads up to
413 * max_bytes bytes from the file.
414 */
416simple_read_file(istream *in, vector_uchar &result, size_t max_bytes) {
417 static const size_t buffer_size = 4096;
418 char buffer[buffer_size];
419
420 in->read(buffer, std::min(buffer_size, max_bytes));
421 size_t count = in->gcount();
422 while (count != 0) {
423 thread_consider_yield();
424 nassertr(count <= max_bytes, false);
425 result.insert(result.end(), buffer, buffer + count);
426 max_bytes -= count;
427 in->read(buffer, std::min(buffer_size, max_bytes));
428 count = in->gcount();
429 }
430
431 return (!in->fail() || in->eof());
432}
433
434/**
435 * Fills file_list up with the list of files that are within this directory,
436 * excluding those whose basenames are listed in mount_points. Returns true
437 * if successful, false if the file is not a directory or the directory cannot
438 * be read.
439 */
440bool VirtualFile::
441scan_local_directory(VirtualFileList *, const ov_set<string> &) const {
442 return false;
443}
444
445/**
446 * The recursive implementation of ls_all().
447 */
448void VirtualFile::
449r_ls_all(ostream &out, const Filename &root) const {
450 CPT(VirtualFileList) contents = scan_directory();
451 if (contents == nullptr) {
452 return;
453 }
454
455 int num_files = contents->get_num_files();
456 for (int i = 0; i < num_files; i++) {
457 VirtualFile *file = contents->get_file(i);
458 Filename filename = file->get_filename();
459 filename.make_relative_to(root);
460 out << filename << "\n";
461 if (file->is_directory()) {
462 file->r_ls_all(out, root);
463 }
464 }
465}
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
std::string get_basename() const
Returns the basename part of the filename.
Definition filename.I:367
bool make_relative_to(Filename directory, bool allow_backups=true)
Adjusts this filename, which must be a fully-specified pathname beginning with a slash,...
This class records a particular byte sub-range within an existing file on disk.
Definition subfileInfo.h:26
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
A list of VirtualFiles, as returned by VirtualFile::scan_directory().
A hierarchy of directories and files that appears to be one continuous file system,...
void scan_mount_points(vector_string &names, const Filename &path) const
Adds to names a list of all the mount points in use that are one directory below path,...
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
The abstract base class for a file or directory within the VirtualFileSystem.
Definition virtualFile.h:35
virtual std::iostream * open_read_append_file()
Works like open_read_write_file(), but the file is opened in append mode.
virtual void close_read_file(std::istream *stream) const
Closes a file opened by a previous call to open_read_file().
virtual bool rename_file(VirtualFile *new_file)
Attempts to move or rename this file or directory.
virtual std::istream * open_read_file(bool auto_unwrap) const
Opens the file for reading.
virtual bool is_regular_file() const
Returns true if this file represents a regular file (and read_file() may be called),...
virtual bool copy_file(VirtualFile *new_file)
Attempts to copy the contents of this file to the indicated file.
virtual bool get_system_info(SubfileInfo &info)
Populates the SubfileInfo structure with the data representing where the file actually resides on dis...
PointerTo< VirtualFileList > scan_directory() const
If the file represents a directory (that is, is_directory() returns true), this returns the list of f...
virtual bool delete_file()
Attempts to delete this file or directory.
virtual std::ostream * open_write_file(bool auto_wrap, bool truncate)
Opens the file for writing.
void ls_all(std::ostream &out=std::cout) const
If the file represents a directory, recursively lists its contents and those of all subdirectories.
static bool simple_read_file(std::istream *stream, vector_uchar &result)
Fills up the indicated pvector with the contents of the just-opened file.
virtual bool is_writable() const
Returns true if this file may be written to, which implies write_file() may be called (unless it is a...
virtual bool has_file() const
Returns true if this file exists, false otherwise.
virtual bool is_directory() const
Returns true if this file represents a directory (and scan_directory() may be called),...
virtual void close_read_write_file(std::iostream *stream)
Closes a file opened by a previous call to open_read_write_file().
virtual bool atomic_read_contents(std::string &contents) const
See Filename::atomic_read_contents().
virtual bool was_read_successful() const
Call this method after a reading the istream returned by open_read_file() to completion.
virtual bool atomic_compare_and_exchange_contents(std::string &orig_contents, const std::string &old_contents, const std::string &new_contents)
See Filename::atomic_compare_and_exchange_contents().
std::string read_file(bool auto_unwrap) const
Returns the entire contents of the file as a string.
Definition virtualFile.I:35
void ls(std::ostream &out=std::cout) const
If the file represents a directory, lists its contents.
virtual std::ostream * open_append_file()
Works like open_write_file(), but the file is opened in append mode.
virtual time_t get_timestamp() const
Returns a time_t value that represents the time the file was last modified, to within whatever precis...
virtual std::iostream * open_read_write_file(bool truncate)
Opens the file for writing.
virtual void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
bool write_file(const std::string &data, bool auto_wrap)
Writes the entire contents of the file as a string, if it is writable.
Definition virtualFile.I:45
virtual std::streamsize get_file_size() const
Returns the current size on disk (or wherever it is) of the file before it has been opened.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
A specialization of ordered_vector that emulates a standard STL set: one copy of each element is allo...
void sort()
Maps to sort_unique().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.