diff options
author | Hubert Figuière <hub@figuiere.net> | 2013-06-29 22:05:20 -0400 |
---|---|---|
committer | Hubert Figuière <hub@figuiere.net> | 2013-06-29 22:08:01 -0400 |
commit | 4652015fe779e12fb06ff8fa56bf70e373cd3894 (patch) | |
tree | de8d78fb704c3eb86802c07eace17eaea0f2ddde /source/XMPFiles_IO.cpp | |
parent | 81a4c6bcb1879cb321246590faca595e9746f8e5 (diff) |
Update to XMP SDK CC 2013.06
Diffstat (limited to 'source/XMPFiles_IO.cpp')
-rw-r--r-- | source/XMPFiles_IO.cpp | 132 |
1 files changed, 110 insertions, 22 deletions
diff --git a/source/XMPFiles_IO.cpp b/source/XMPFiles_IO.cpp index e2eccd6..6de8666 100644 --- a/source/XMPFiles_IO.cpp +++ b/source/XMPFiles_IO.cpp @@ -16,12 +16,46 @@ #include "source/XMPFiles_IO.hpp" #include "source/XIO.hpp" + +#define EMPTY_FILE_PATH "" +#define XMP_FILESIO_STATIC_START try { int a; +#define XMP_FILESIO_STATIC_END1(errorCallbackPtr, filePath, severity) \ + a = 1; \ + } catch ( XMP_Error & error ) { \ + if ( (errorCallbackPtr) != NULL ) (errorCallbackPtr)->NotifyClient ( (severity), error, (filePath) ); \ + else throw; \ + } +#define XMP_FILESIO_START try { int b; +#define XMP_FILESIO_END1(severity) \ + b = 1; \ + } catch ( XMP_Error & error ) { \ + if ( errorCallback != NULL ) errorCallback->NotifyClient ( (severity), error, filePath.c_str() ); \ + else throw; \ + } +#define XMP_FILESIO_END2(filePath, severity) \ + b = 1; \ + } catch ( XMP_Error & error ) { \ + if ( errorCallback != NULL ) errorCallback->NotifyClient ( (severity), error, (filePath) ); \ + else throw; \ + } +#define XMP_FILESIO_STATIC_NOTIFY_ERROR(errorCallbackPtr, filePath, severity, error) \ + if ( (errorCallbackPtr) != NULL ) errorCallbackPtr->NotifyClient ( (severity), (error), (filePath) ); +#define XMP_FILESIO_NOTIFY_ERROR(filePath, severity, error) \ + XMP_FILESIO_STATIC_NOTIFY_ERROR(errorCallback, (filePath), (severity), (error)) + + // ================================================================================================= // XMPFiles_IO::New_XMPFiles_IO // ============================ -XMPFiles_IO* XMPFiles_IO::New_XMPFiles_IO ( const char* filePath, bool readOnly ) +/* class static */ +XMPFiles_IO * XMPFiles_IO::New_XMPFiles_IO ( + const char * filePath, + bool readOnly, + GenericErrorCallback * _errorCallback, + XMP_ProgressTracker * _progressTracker ) { + XMP_FILESIO_STATIC_START Host_IO::FileRef hostFile = Host_IO::noFileRef; switch ( Host_IO::GetFileMode ( filePath ) ) { @@ -31,14 +65,20 @@ XMPFiles_IO* XMPFiles_IO::New_XMPFiles_IO ( const char* filePath, bool readOnly case Host_IO::kFMode_DoesNotExist: break; default: - XMP_Throw ( "New_XMPFiles_IO, path must be a file or not exist", kXMPErr_BadParam ); + XMP_Throw ( "New_XMPFiles_IO, path must be a file or not exist", kXMPErr_FilePathNotAFile ); + } + if ( hostFile == Host_IO::noFileRef ) { + XMP_Error error (kXMPErr_NoFile, "New_XMPFiles_IO, file does not exist"); + XMP_FILESIO_STATIC_NOTIFY_ERROR ( _errorCallback, filePath, kXMPErrSev_Recoverable, error ); + return 0; } - if ( hostFile == Host_IO::noFileRef ) return 0; Host_IO::Rewind ( hostFile ); // Make sure offset really is 0. - XMPFiles_IO* newFile = new XMPFiles_IO ( hostFile, filePath, readOnly ); + XMPFiles_IO * newFile = new XMPFiles_IO ( hostFile, filePath, readOnly, _errorCallback, _progressTracker ); return newFile; + XMP_FILESIO_STATIC_END1 ( _errorCallback, filePath, kXMPErrSev_FileFatal ) + return NULL; } // XMPFiles_IO::New_XMPFiles_IO @@ -46,13 +86,26 @@ XMPFiles_IO* XMPFiles_IO::New_XMPFiles_IO ( const char* filePath, bool readOnly // XMPFiles_IO::XMPFiles_IO // ======================== -XMPFiles_IO::XMPFiles_IO ( Host_IO::FileRef hostFile, const char* _filePath, bool _readOnly ) - : readOnly(_readOnly), filePath(_filePath), fileRef(hostFile), currOffset(0), isTemp(false), derivedTemp(0) +XMPFiles_IO::XMPFiles_IO ( + Host_IO::FileRef hostFile, + const char * _filePath, + bool _readOnly, + GenericErrorCallback * _errorCallback, + XMP_ProgressTracker * _progressTracker ) + : readOnly(_readOnly) + , filePath(_filePath) + , fileRef(hostFile) + , currOffset(0) + , isTemp(false) + , derivedTemp(0) + , errorCallback(_errorCallback) + , progressTracker(_progressTracker) { + XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); this->currLength = Host_IO::Length ( this->fileRef ); - + XMP_FILESIO_END2 ( _filePath, kXMPErrSev_FileFatal ) } // XMPFiles_IO::XMPFiles_IO // ================================================================================================= @@ -61,25 +114,26 @@ XMPFiles_IO::XMPFiles_IO ( Host_IO::FileRef hostFile, const char* _filePath, boo XMPFiles_IO::~XMPFiles_IO() { - try { + XMP_FILESIO_START if ( this->derivedTemp != 0 ) this->DeleteTemp(); if ( this->fileRef != Host_IO::noFileRef ) Host_IO::Close ( this->fileRef ); if ( this->isTemp && (! this->filePath.empty()) ) Host_IO::Delete ( this->filePath.c_str() ); + XMP_FILESIO_END1 ( kXMPErrSev_Recoverable ) } catch ( ... ) { // All of the above is fail-safe cleanup, ignore problems. } - } // XMPFiles_IO::~XMPFiles_IO // ================================================================================================= // XMPFiles_IO::operator= // ====================== -void XMPFiles_IO::operator= ( const XMP_IO& in ) +void XMPFiles_IO::operator = ( const XMP_IO& in ) { - + XMP_FILESIO_START XMP_Throw ( "No assignment for XMPFiles_IO", kXMPErr_InternalFailure ); + XMP_FILESIO_END1 ( kXMPErrSev_OperationFatal ) }; // XMPFiles_IO::operator= @@ -87,8 +141,9 @@ void XMPFiles_IO::operator= ( const XMP_IO& in ) // XMPFiles_IO::Read // ================= -XMP_Uns32 XMPFiles_IO::Read ( void* buffer, XMP_Uns32 count, bool readAll /* = false */ ) +XMP_Uns32 XMPFiles_IO::Read ( void * buffer, XMP_Uns32 count, bool readAll /* = false */ ) { + XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); XMP_Assert ( this->currLength == Host_IO::Length ( this->fileRef ) ); @@ -104,6 +159,8 @@ XMP_Uns32 XMPFiles_IO::Read ( void* buffer, XMP_Uns32 count, bool readAll /* = f this->currOffset += amountRead; return amountRead; + XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) + return 0; } // XMPFiles_IO::Read @@ -111,24 +168,35 @@ XMP_Uns32 XMPFiles_IO::Read ( void* buffer, XMP_Uns32 count, bool readAll /* = f // XMPFiles_IO::Write // ================== -void XMPFiles_IO::Write ( const void* buffer, XMP_Uns32 count ) +void XMPFiles_IO::Write ( const void * buffer, XMP_Uns32 count ) { + XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); XMP_Assert ( this->currLength == Host_IO::Length ( this->fileRef ) ); XMP_Assert ( this->currOffset <= this->currLength ); try { + if ( this->readOnly ) + XMP_Throw ( "New_XMPFiles_IO, write not permitted on read only file", kXMPErr_FilePermission ); Host_IO::Write ( this->fileRef, buffer, count ); + if ( this->progressTracker != 0 ) this->progressTracker->AddWorkDone ( (float) count ); } catch ( ... ) { - // Make sure the internal state reflects partial writes. - this->currOffset = Host_IO::Offset ( this->fileRef ); - this->currLength = Host_IO::Length ( this->fileRef ); + try { + // we should try to maintain the state as best as possible + // but no exception should escape from this backup plan. + // Make sure the internal state reflects partial writes. + this->currOffset = Host_IO::Offset ( this->fileRef ); + this->currLength = Host_IO::Length ( this->fileRef ); + } catch ( ... ) { + // don't do anything + } throw; } this->currOffset += count; if ( this->currOffset > this->currLength ) this->currLength = this->currOffset; + XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) } // XMPFiles_IO::Write @@ -138,6 +206,7 @@ void XMPFiles_IO::Write ( const void* buffer, XMP_Uns32 count ) XMP_Int64 XMPFiles_IO::Seek ( XMP_Int64 offset, SeekMode mode ) { + XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); XMP_Assert ( this->currLength == Host_IO::Length ( this->fileRef ) ); @@ -162,6 +231,8 @@ XMP_Int64 XMPFiles_IO::Seek ( XMP_Int64 offset, SeekMode mode ) XMP_Assert ( this->currOffset == newOffset ); return this->currOffset; + XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ); + return -1; } // XMPFiles_IO::Seek @@ -171,10 +242,11 @@ XMP_Int64 XMPFiles_IO::Seek ( XMP_Int64 offset, SeekMode mode ) XMP_Int64 XMPFiles_IO::Length() { + XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); XMP_Assert ( this->currLength == Host_IO::Length ( this->fileRef ) ); - + XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) return this->currLength; } // XMPFiles_IO::Length @@ -185,10 +257,14 @@ XMP_Int64 XMPFiles_IO::Length() void XMPFiles_IO::Truncate ( XMP_Int64 length ) { + XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); XMP_Assert ( this->currLength == Host_IO::Length ( this->fileRef ) ); + if ( this->readOnly ) + XMP_Throw ( "New_XMPFiles_IO, truncate not permitted on read only file", kXMPErr_FilePermission ); + XMP_Enforce ( length <= this->currLength ); Host_IO::SetEOF ( this->fileRef, length ); @@ -198,6 +274,7 @@ void XMPFiles_IO::Truncate ( XMP_Int64 length ) // ! Seek to the expected offset, some versions of Host_IO::SetEOF implicitly seek to EOF. Host_IO::Seek ( this->fileRef, this->currOffset, kXMP_SeekFromStart ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); + XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) } // XMPFiles_IO::Truncate @@ -207,6 +284,7 @@ void XMPFiles_IO::Truncate ( XMP_Int64 length ) XMP_IO* XMPFiles_IO::DeriveTemp() { + XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); if ( this->derivedTemp != 0 ) return this->derivedTemp; @@ -214,8 +292,12 @@ XMP_IO* XMPFiles_IO::DeriveTemp() if ( this->readOnly ) { XMP_Throw ( "XMPFiles_IO::DeriveTemp, can't derive from read-only", kXMPErr_InternalFailure ); } + XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) + + std::string tempPath; - std::string tempPath = Host_IO::CreateTemp ( this->filePath.c_str() ); + XMP_FILESIO_START + tempPath = Host_IO::CreateTemp ( this->filePath.c_str() ); XMPFiles_IO* newTemp = XMPFiles_IO::New_XMPFiles_IO ( tempPath.c_str(), Host_IO::openReadWrite ); if ( newTemp == 0 ) { @@ -225,7 +307,8 @@ XMP_IO* XMPFiles_IO::DeriveTemp() newTemp->isTemp = true; this->derivedTemp = newTemp; - + newTemp->progressTracker = this->progressTracker; // Automatically track writes to the temp file. + XMP_FILESIO_END2 ( tempPath.c_str(), kXMPErrSev_FileFatal ) return this->derivedTemp; } // XMPFiles_IO::DeriveTemp @@ -236,9 +319,10 @@ XMP_IO* XMPFiles_IO::DeriveTemp() void XMPFiles_IO::AbsorbTemp() { + XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); - XMPFiles_IO* temp = this->derivedTemp; + XMPFiles_IO * temp = this->derivedTemp; if ( temp == 0 ) { XMP_Throw ( "XMPFiles_IO::AbsorbTemp, no temp to absorb", kXMPErr_InternalFailure ); } @@ -253,6 +337,7 @@ void XMPFiles_IO::AbsorbTemp() this->fileRef = Host_IO::Open ( this->filePath.c_str(), Host_IO::openReadWrite ); this->currLength = Host_IO::Length ( this->fileRef ); this->currOffset = 0; + XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) } // XMPFiles_IO::AbsorbTemp @@ -262,7 +347,8 @@ void XMPFiles_IO::AbsorbTemp() void XMPFiles_IO::DeleteTemp() { - XMPFiles_IO* temp = this->derivedTemp; + XMP_FILESIO_START + XMPFiles_IO * temp = this->derivedTemp; if ( temp != 0 ) { @@ -280,6 +366,7 @@ void XMPFiles_IO::DeleteTemp() this->derivedTemp = 0; } + XMP_FILESIO_END2 ( this->derivedTemp->filePath.c_str(), kXMPErrSev_FileFatal ) } // XMPFiles_IO::DeleteTemp @@ -289,11 +376,12 @@ void XMPFiles_IO::DeleteTemp() void XMPFiles_IO::Close() { - + XMP_FILESIO_START if ( this->fileRef != Host_IO::noFileRef ) { Host_IO::Close ( this->fileRef ); this->fileRef = Host_IO::noFileRef; } + XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) } // XMPFiles_IO::Close |