diff --git a/panda/src/express/virtualFile.cxx b/panda/src/express/virtualFile.cxx index ea3dd2370a..1c32e6bd50 100644 --- a/panda/src/express/virtualFile.cxx +++ b/panda/src/express/virtualFile.cxx @@ -219,7 +219,20 @@ was_read_successful() const { // Returns NULL on failure. //////////////////////////////////////////////////////////////////// ostream *VirtualFile:: -open_write_file(bool auto_wrap) { +open_write_file(bool auto_wrap, bool truncate) { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFile::open_append_file +// Access: Published, Virtual +// Description: Works like open_write_file(), but the file is opened +// in append mode. Like open_write_file, the returned +// pointer should eventually be passed to +// close_write_file(). +//////////////////////////////////////////////////////////////////// +ostream *VirtualFile:: +open_append_file() { return NULL; } @@ -238,17 +251,43 @@ close_write_file(ostream *stream) { } //////////////////////////////////////////////////////////////////// -// Function: VirtualFile::was_write_successful +// Function: VirtualFile::open_read_write_file // Access: Published, Virtual -// Description: Call this method after a writing the ostream returned -// by open_write_file() to completion. If it returns -// true, the file was written completely and without -// error; if it returns false, there may have been some -// errors or a truncated file write. +// Description: Opens the file for writing. Returns a newly +// allocated iostream on success (which you should +// eventually delete when you are done writing). +// Returns NULL on failure. //////////////////////////////////////////////////////////////////// -bool VirtualFile:: -was_write_successful() const { - return true; +iostream *VirtualFile:: +open_read_write_file(bool truncate) { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFile::open_read_append_file +// Access: Published, Virtual +// Description: Works like open_read_write_file(), but the file is opened +// in append mode. Like open_read_write_file, the returned +// pointer should eventually be passed to +// close_read_write_file(). +//////////////////////////////////////////////////////////////////// +iostream *VirtualFile:: +open_read_append_file() { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFile::close_read_write_file +// Access: Published +// Description: Closes a file opened by a previous call to +// open_read_write_file(). This really just deletes the +// iostream pointer, but it is recommended to use this +// interface instead of deleting it explicitly, to help +// work around compiler issues. +//////////////////////////////////////////////////////////////////// +void VirtualFile:: +close_read_write_file(iostream *stream) { + nassertv(false); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/express/virtualFile.h b/panda/src/express/virtualFile.h index 98d0ebea4e..4eb5cdaf0a 100644 --- a/panda/src/express/virtualFile.h +++ b/panda/src/express/virtualFile.h @@ -60,9 +60,13 @@ PUBLISHED: virtual bool was_read_successful() const; BLOCKING INLINE bool write_file(const string &data, bool auto_wrap); - BLOCKING virtual ostream *open_write_file(bool auto_wrap); + BLOCKING virtual ostream *open_write_file(bool auto_wrap, bool truncate); + BLOCKING virtual ostream *open_append_file(); BLOCKING virtual void close_write_file(ostream *stream); - virtual bool was_write_successful() const; + + BLOCKING virtual iostream *open_read_write_file(bool truncate); + BLOCKING virtual iostream *open_read_append_file(); + BLOCKING virtual void close_read_write_file(iostream *stream); BLOCKING virtual off_t get_file_size(istream *stream) const; BLOCKING virtual off_t get_file_size() const; diff --git a/panda/src/express/virtualFileMount.cxx b/panda/src/express/virtualFileMount.cxx index fa7be7874b..ce84ab68e9 100644 --- a/panda/src/express/virtualFileMount.cxx +++ b/panda/src/express/virtualFileMount.cxx @@ -143,7 +143,7 @@ read_file(const Filename &file, bool do_uncompress, bool VirtualFileMount:: write_file(const Filename &file, bool do_compress, const unsigned char *data, size_t data_size) { - ostream *out = open_write_file(file, do_compress); + ostream *out = open_write_file(file, do_compress, true); if (out == (ostream *)NULL) { express_cat.info() << "Unable to write " << file << "\n"; @@ -210,7 +210,7 @@ close_read_file(istream *stream) const { // Returns NULL on failure. //////////////////////////////////////////////////////////////////// ostream *VirtualFileMount:: -open_write_file(const Filename &file) { +open_write_file(const Filename &file, bool truncate) { return NULL; } @@ -226,8 +226,8 @@ open_write_file(const Filename &file) { // compressed on-the-fly using zlib. //////////////////////////////////////////////////////////////////// ostream *VirtualFileMount:: -open_write_file(const Filename &file, bool do_compress) { - ostream *result = open_write_file(file); +open_write_file(const Filename &file, bool do_compress, bool truncate) { + ostream *result = open_write_file(file, truncate); #ifdef HAVE_ZLIB if (result != (ostream *)NULL && do_compress) { @@ -240,6 +240,19 @@ open_write_file(const Filename &file, bool do_compress) { return result; } +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileMount::open_append_file +// Access: Published, Virtual +// Description: Works like open_write_file(), but the file is opened +// in append mode. Like open_write_file, the returned +// pointer should eventually be passed to +// close_write_file(). +//////////////////////////////////////////////////////////////////// +ostream *VirtualFileMount:: +open_append_file(const Filename &file) { + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: VirtualFileMount::close_write_file // Access: Public, Virtual @@ -254,6 +267,46 @@ close_write_file(ostream *stream) { VirtualFileSystem::close_write_file(stream); } +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileMount::open_read_write_file +// Access: Published, Virtual +// Description: Opens the file for writing. Returns a newly +// allocated iostream on success (which you should +// eventually delete when you are done writing). +// Returns NULL on failure. +//////////////////////////////////////////////////////////////////// +iostream *VirtualFileMount:: +open_read_write_file(const Filename &file, bool truncate) { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileMount::open_read_append_file +// Access: Published, Virtual +// Description: Works like open_read_write_file(), but the file is opened +// in append mode. Like open_read_write_file, the returned +// pointer should eventually be passed to +// close_read_write_file(). +//////////////////////////////////////////////////////////////////// +iostream *VirtualFileMount:: +open_read_append_file(const Filename &file) { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileMount::close_read_write_file +// Access: Public, Virtual +// Description: Closes a file opened by a previous call to +// open_read_write_file(). This really just deletes the +// iostream pointer, but it is recommended to use this +// interface instead of deleting it explicitly, to help +// work around compiler issues. +//////////////////////////////////////////////////////////////////// +void VirtualFileMount:: +close_read_write_file(iostream *stream) { + VirtualFileSystem::close_read_write_file(stream); +} + //////////////////////////////////////////////////////////////////// // Function: VirtualFileMount::get_system_info // Access: Public, Virtual diff --git a/panda/src/express/virtualFileMount.h b/panda/src/express/virtualFileMount.h index f736a31faa..555d7f9f70 100644 --- a/panda/src/express/virtualFileMount.h +++ b/panda/src/express/virtualFileMount.h @@ -61,10 +61,15 @@ public: istream *open_read_file(const Filename &file, bool do_uncompress) const; virtual void close_read_file(istream *stream) const; - virtual ostream *open_write_file(const Filename &file); - ostream *open_write_file(const Filename &file, bool do_compress); + virtual ostream *open_write_file(const Filename &file, bool truncate); + ostream *open_write_file(const Filename &file, bool do_compress, bool truncate); + virtual ostream *open_append_file(const Filename &file); virtual void close_write_file(ostream *stream); + virtual iostream *open_read_write_file(const Filename &file, bool truncate); + virtual iostream *open_read_append_file(const Filename &file); + virtual void close_read_write_file(iostream *stream); + virtual off_t get_file_size(const Filename &file, istream *stream) const=0; virtual off_t get_file_size(const Filename &file) const=0; virtual time_t get_timestamp(const Filename &file) const=0; diff --git a/panda/src/express/virtualFileMountSystem.cxx b/panda/src/express/virtualFileMountSystem.cxx index f54e771853..9f9bb1eb4e 100644 --- a/panda/src/express/virtualFileMountSystem.cxx +++ b/panda/src/express/virtualFileMountSystem.cxx @@ -177,7 +177,7 @@ open_read_file(const Filename &file) const { // Returns NULL on failure. //////////////////////////////////////////////////////////////////// ostream *VirtualFileMountSystem:: -open_write_file(const Filename &file) { +open_write_file(const Filename &file, bool truncate) { #ifdef WIN32 // First ensure that the file exists to validate its case. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) { @@ -193,7 +193,109 @@ open_write_file(const Filename &file) { pathname.set_binary(); } pofstream *stream = new pofstream; - if (!pathname.open_write(*stream)) { + if (!pathname.open_write(*stream, truncate)) { + // Couldn't open the file for some reason. + close_write_file(stream); + return NULL; + } + + return stream; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileMountSystem::open_append_file +// Access: Published +// Description: Works like open_write_file(), but the file is opened +// in append mode. Like open_write_file, the returned +// pointer should eventually be passed to +// close_write_file(). +//////////////////////////////////////////////////////////////////// +ostream *VirtualFileMountSystem:: +open_append_file(const Filename &file) { +#ifdef WIN32 + // First ensure that the file exists to validate its case. + if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) { + if (!has_file(file)) { + return NULL; + } + } +#endif // WIN32 + Filename pathname(_physical_filename, file); + if (file.is_text()) { + pathname.set_text(); + } else { + pathname.set_binary(); + } + pofstream *stream = new pofstream; + if (!pathname.open_append(*stream)) { + // Couldn't open the file for some reason. + close_write_file(stream); + return NULL; + } + + return stream; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileMountSystem::open_read_write_file +// Access: Published, Virtual +// Description: Opens the file for writing. Returns a newly +// allocated iostream on success (which you should +// eventually delete when you are done writing). +// Returns NULL on failure. +//////////////////////////////////////////////////////////////////// +iostream *VirtualFileMountSystem:: +open_read_write_file(const Filename &file, bool truncate) { +#ifdef WIN32 + // First ensure that the file exists to validate its case. + if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) { + if (!has_file(file)) { + return NULL; + } + } +#endif // WIN32 + Filename pathname(_physical_filename, file); + if (file.is_text()) { + pathname.set_text(); + } else { + pathname.set_binary(); + } + pfstream *stream = new pfstream; + if (!pathname.open_read_write(*stream, truncate)) { + // Couldn't open the file for some reason. + close_write_file(stream); + return NULL; + } + + return stream; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileMountSystem::open_read_append_file +// Access: Published, Virtual +// Description: Works like open_read_write_file(), but the file is opened +// in append mode. Like open_read_write_file, the returned +// pointer should eventually be passed to +// close_read_write_file(). +//////////////////////////////////////////////////////////////////// +iostream *VirtualFileMountSystem:: +open_read_append_file(const Filename &file) { +#ifdef WIN32 + // First ensure that the file exists to validate its case. + if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) { + if (!has_file(file)) { + return NULL; + } + } +#endif // WIN32 + Filename pathname(_physical_filename, file); + if (file.is_text()) { + pathname.set_text(); + } else { + pathname.set_binary(); + } + pfstream *stream = new pfstream; + if (!pathname.open_read_append(*stream)) { // Couldn't open the file for some reason. close_write_file(stream); return NULL; diff --git a/panda/src/express/virtualFileMountSystem.h b/panda/src/express/virtualFileMountSystem.h index b3cd485687..8f33db266b 100644 --- a/panda/src/express/virtualFileMountSystem.h +++ b/panda/src/express/virtualFileMountSystem.h @@ -39,7 +39,11 @@ public: virtual bool is_writable(const Filename &file) const; virtual istream *open_read_file(const Filename &file) const; - virtual ostream *open_write_file(const Filename &file); + virtual ostream *open_write_file(const Filename &file, bool truncate); + virtual ostream *open_append_file(const Filename &file); + virtual iostream *open_read_write_file(const Filename &file, bool truncate); + virtual iostream *open_read_append_file(const Filename &file); + virtual off_t get_file_size(const Filename &file, istream *stream) const; virtual off_t get_file_size(const Filename &file) const; virtual time_t get_timestamp(const Filename &file) const; diff --git a/panda/src/express/virtualFileSimple.cxx b/panda/src/express/virtualFileSimple.cxx index 25c1bef946..8648f8446f 100644 --- a/panda/src/express/virtualFileSimple.cxx +++ b/panda/src/express/virtualFileSimple.cxx @@ -150,11 +150,13 @@ close_read_file(istream *stream) const { // eventually delete when you are done writing). // Returns NULL on failure. // -// If auto_wrap is true, an explicitly-named .pz file -// is automatically compressed. +// If auto_wrap is true, an explicitly-named .pz file is +// automatically compressed while writing. If truncate +// is true, the file is truncated to zero length before +// writing. //////////////////////////////////////////////////////////////////// ostream *VirtualFileSimple:: -open_write_file(bool auto_wrap) const { +open_write_file(bool auto_wrap, bool truncate) { // Will we be automatically wrapping a .pz file? bool do_compress = (_implicit_pz_file || (auto_wrap && _local_filename.get_extension() == "pz")); @@ -164,7 +166,20 @@ open_write_file(bool auto_wrap) const { local_filename.set_binary(); } - return _mount->open_write_file(local_filename, do_compress); + return _mount->open_write_file(local_filename, do_compress, truncate); +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSimple::open_append_file +// Access: Published, Virtual +// Description: Works like open_write_file(), but the file is opened +// in append mode. Like open_write_file, the returned +// pointer should eventually be passed to +// close_write_file(). +//////////////////////////////////////////////////////////////////// +ostream *VirtualFileSimple:: +open_append_file() { + return _mount->open_append_file(_local_filename); } //////////////////////////////////////////////////////////////////// @@ -181,6 +196,46 @@ close_write_file(ostream *stream) const { _mount->close_write_file(stream); } +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSimple::open_read_write_file +// Access: Published, Virtual +// Description: Opens the file for writing. Returns a newly +// allocated iostream on success (which you should +// eventually delete when you are done writing). +// Returns NULL on failure. +//////////////////////////////////////////////////////////////////// +iostream *VirtualFileSimple:: +open_read_write_file(bool truncate) { + return _mount->open_read_write_file(_local_filename, truncate); +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSimple::open_read_append_file +// Access: Published, Virtual +// Description: Works like open_read_write_file(), but the file is opened +// in append mode. Like open_read_write_file, the returned +// pointer should eventually be passed to +// close_read_write_file(). +//////////////////////////////////////////////////////////////////// +iostream *VirtualFileSimple:: +open_read_append_file() { + return _mount->open_read_append_file(_local_filename); +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSimple::close_read_write_file +// Access: Published +// Description: Closes a file opened by a previous call to +// open_read_write_file(). This really just deletes the +// iostream pointer, but it is recommended to use this +// interface instead of deleting it explicitly, to help +// work around compiler issues. +//////////////////////////////////////////////////////////////////// +void VirtualFileSimple:: +close_read_write_file(iostream *stream) { + _mount->close_read_write_file(stream); +} + //////////////////////////////////////////////////////////////////// // Function: VirtualFileSimple::get_file_size // Access: Published, Virtual diff --git a/panda/src/express/virtualFileSimple.h b/panda/src/express/virtualFileSimple.h index 4268a8b130..a66c64dc84 100644 --- a/panda/src/express/virtualFileSimple.h +++ b/panda/src/express/virtualFileSimple.h @@ -46,8 +46,13 @@ PUBLISHED: virtual istream *open_read_file(bool auto_unwrap) const; virtual void close_read_file(istream *stream) const; - virtual ostream *open_write_file(bool auto_wrap) const; + virtual ostream *open_write_file(bool auto_wrap, bool truncate); + virtual ostream *open_append_file(); virtual void close_write_file(ostream *stream) const; + virtual iostream *open_read_write_file(bool truncate); + virtual iostream *open_read_append_file(); + virtual void close_read_write_file(iostream *stream); + virtual off_t get_file_size(istream *stream) const; virtual off_t get_file_size() const; virtual time_t get_timestamp() const; diff --git a/panda/src/express/virtualFileSystem.cxx b/panda/src/express/virtualFileSystem.cxx index 64893805ff..6f7860ee63 100644 --- a/panda/src/express/virtualFileSystem.cxx +++ b/panda/src/express/virtualFileSystem.cxx @@ -911,16 +911,40 @@ __py__write_file(const Filename &filename, PyObject *data, bool auto_wrap) { // ostream if the file exists and can be written, or // NULL otherwise. Does not return an invalid ostream. // -// If auto_wrap is true, an explicitly-named .pz file -// is automatically compressed while writing. +// If auto_wrap is true, an explicitly-named .pz file is +// automatically compressed while writing. If truncate +// is true, the file is truncated to zero length before +// writing. //////////////////////////////////////////////////////////////////// ostream *VirtualFileSystem:: -open_write_file(const Filename &filename, bool auto_wrap) { +open_write_file(const Filename &filename, bool auto_wrap, bool truncate) { PT(VirtualFile) file = create_file(filename); if (file == (VirtualFile *)NULL) { return NULL; } - ostream *str = file->open_write_file(auto_wrap); + ostream *str = file->open_write_file(auto_wrap, truncate); + if (str != (ostream *)NULL && str->fail()) { + close_write_file(str); + str = (ostream *)NULL; + } + return str; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSystem::open_append_file +// Access: Published +// Description: Works like open_write_file(), but the file is opened +// in append mode. Like open_write_file, the returned +// pointer should eventually be passed to +// close_write_file(). +//////////////////////////////////////////////////////////////////// +ostream *VirtualFileSystem:: +open_append_file(const Filename &filename) { + PT(VirtualFile) file = create_file(filename); + if (file == (VirtualFile *)NULL) { + return NULL; + } + ostream *str = file->open_append_file(); if (str != (ostream *)NULL && str->fail()) { close_write_file(str); str = (ostream *)NULL; @@ -949,6 +973,70 @@ close_write_file(ostream *stream) { } } +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSystem::open_read_write_file +// Access: Published +// Description: Convenience function; returns a newly allocated +// iostream if the file exists and can be written, or +// NULL otherwise. Does not return an invalid iostream. +//////////////////////////////////////////////////////////////////// +iostream *VirtualFileSystem:: +open_read_write_file(const Filename &filename, bool truncate) { + PT(VirtualFile) file = create_file(filename); + if (file == (VirtualFile *)NULL) { + return NULL; + } + iostream *str = file->open_read_write_file(truncate); + if (str != (iostream *)NULL && str->fail()) { + close_read_write_file(str); + str = (iostream *)NULL; + } + return str; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSystem::open_read_append_file +// Access: Published +// Description: Works like open_read_write_file(), but the file is opened +// in append mode. Like open_read_write_file, the returned +// pointer should eventually be passed to +// close_read_write_file(). +//////////////////////////////////////////////////////////////////// +iostream *VirtualFileSystem:: +open_read_append_file(const Filename &filename) { + PT(VirtualFile) file = create_file(filename); + if (file == (VirtualFile *)NULL) { + return NULL; + } + iostream *str = file->open_read_append_file(); + if (str != (iostream *)NULL && str->fail()) { + close_read_write_file(str); + str = (iostream *)NULL; + } + return str; +} + +//////////////////////////////////////////////////////////////////// +// Function: VirtualFileSystem::close_read_write_file +// Access: Published, Static +// Description: Closes a file opened by a previous call to +// open_read_write_file(). This really just deletes the +// iostream pointer, but it is recommended to use this +// interface instead of deleting it explicitly, to help +// work around compiler issues. +//////////////////////////////////////////////////////////////////// +void VirtualFileSystem:: +close_read_write_file(iostream *stream) { + if (stream != (iostream *)NULL) { +#if (!defined(WIN32_VC) && !defined(WIN64_VC)) && !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) + stream->~iostream(); + (*global_operator_delete)(stream); +#else + delete stream; +#endif + } +} + //////////////////////////////////////////////////////////////////// // Function: VirtualFileSystem::scan_mount_points // Access: Public diff --git a/panda/src/express/virtualFileSystem.h b/panda/src/express/virtualFileSystem.h index 4d6446a82d..bd99e4f4fd 100644 --- a/panda/src/express/virtualFileSystem.h +++ b/panda/src/express/virtualFileSystem.h @@ -106,9 +106,14 @@ PUBLISHED: BLOCKING PyObject *__py__write_file(const Filename &filename, PyObject *data, bool auto_wrap); #endif // HAVE_PYTHON BLOCKING INLINE bool write_file(const Filename &filename, const string &data, bool auto_wrap); - BLOCKING ostream *open_write_file(const Filename &filename, bool auto_wrap); + BLOCKING ostream *open_write_file(const Filename &filename, bool auto_wrap, bool truncate); + BLOCKING ostream *open_append_file(const Filename &filename); BLOCKING static void close_write_file(ostream *stream); + BLOCKING iostream *open_read_write_file(const Filename &filename, bool truncate); + BLOCKING iostream *open_read_append_file(const Filename &filename); + BLOCKING static void close_read_write_file(iostream *stream); + public: INLINE bool read_file(const Filename &filename, string &result, bool auto_unwrap) const; INLINE bool read_file(const Filename &filename, pvector &result, bool auto_unwrap) const;