diff --git a/src/OpenColorIO/PathUtils.cpp b/src/OpenColorIO/PathUtils.cpp index bd9fb1135..3a68d366b 100644 --- a/src/OpenColorIO/PathUtils.cpp +++ b/src/OpenColorIO/PathUtils.cpp @@ -88,20 +88,26 @@ std::string GetFastFileHash(const std::string & filename, const Context & contex fileHashResultPtr->ready = true; std::string h = ""; - if (!context.getConfigIOProxy()) + if (context.getConfigIOProxy()) { - // Default case. - h = g_hashFunction(filename); + // Case for when ConfigIOProxy is used (callbacks mechanism). + h = context.getConfigIOProxy()->getFastLutFileHash(filename.c_str()); + + // For absolute paths, if the proxy does not provide a hash, try the file system. + if (h.empty() && pystring::os::path::isabs(filename)) + { + h = g_hashFunction(filename); + } } else { - // Case for when ConfigIOProxy is used (callbacks mechanism). - h = context.getConfigIOProxy()->getFastLutFileHash(filename.c_str()); + // Default case + h = g_hashFunction(filename); } fileHashResultPtr->hash = h; } - + hash = fileHashResultPtr->hash; } diff --git a/src/OpenColorIO/transforms/FileTransform.cpp b/src/OpenColorIO/transforms/FileTransform.cpp index faf1d343e..33da5f307 100755 --- a/src/OpenColorIO/transforms/FileTransform.cpp +++ b/src/OpenColorIO/transforms/FileTransform.cpp @@ -192,35 +192,33 @@ std::unique_ptr getLutData( { if (config.getConfigIOProxy()) { - std::vector buffer = config.getConfigIOProxy()->getLutData(filepath.c_str()); - std::stringstream ss; - ss.write(reinterpret_cast(buffer.data()), buffer.size()); - - return std::unique_ptr( - new std::stringstream(std::move(ss)) - ); - } - - // Default behavior. Return file stream. - return std::unique_ptr( - new std::ifstream(Platform::filenameToUTF(filepath).c_str(), mode) - ); -} + std::vector buffer; + // Try to open through proxy. + try + { + buffer = config.getConfigIOProxy()->getLutData(filepath.c_str()); + } + catch (const std::exception&) + { + // If the path is absolute, we'll try the file system, but otherwise + // nothing to do. + if (!pystring::os::path::isabs(filepath)) + throw; + } -// Close stream returned by getLutData -void closeLutStream(const Config & config, const std::istream & istream) -{ - // No-op when it is using ConfigIOProxy since getLutData returns a vector. - if (config.getConfigIOProxy() == nullptr) - { - // The std::istream is coming from a std::ifstream. - // Pointer cast to ifstream and then close it. - std::ifstream * pIfStream = (std::ifstream *) &istream; - if (pIfStream->is_open()) + // If the buffer is empty, we'll try the file system for abs paths. + if (!buffer.empty() || !pystring::os::path::isabs(filepath)) { - pIfStream->close(); + auto pss = std::unique_ptr(new std::stringstream); + pss->write(reinterpret_cast(buffer.data()), buffer.size()); + + return pss; } } + + // Default behavior. Return file stream. + return std::unique_ptr(new std::ifstream( + Platform::filenameToUTF(filepath), mode)); } bool CollectContextVariables(const Config &, @@ -635,9 +633,8 @@ void LoadFileUncached(FileFormat * & returnFormat, filepath, tryFormat->isBinary() ? std::ios_base::binary : std::ios_base::in ); - auto & filestream = *pStream; - if (!filestream.good()) + if (!pStream || !pStream->good()) { std::ostringstream os; os << "The specified FileTransform srcfile, '"; @@ -647,7 +644,7 @@ void LoadFileUncached(FileFormat * & returnFormat, throw Exception(os.str().c_str()); } - CachedFileRcPtr cachedFile = tryFormat->read(filestream, filepath, interp); + CachedFileRcPtr cachedFile = tryFormat->read(*pStream, filepath, interp); if(IsDebugLoggingEnabled()) { @@ -660,17 +657,10 @@ void LoadFileUncached(FileFormat * & returnFormat, returnFormat = tryFormat; returnCachedFile = cachedFile; - closeLutStream(config, filestream); - return; } catch(std::exception & e) { - if (pStream) - { - closeLutStream(config, *pStream); - } - primaryErrorText += " '"; primaryErrorText += tryFormat->getName(); primaryErrorText += "' failed with: "; @@ -712,9 +702,8 @@ void LoadFileUncached(FileFormat * & returnFormat, filepath, altFormat->isBinary() ? std::ios_base::binary : std::ios_base::in ); - auto& filestream = *pStream; - if (!filestream.good()) + if (!pStream || !pStream->good()) { std::ostringstream os; os << "The specified FileTransform srcfile, '"; @@ -725,7 +714,7 @@ void LoadFileUncached(FileFormat * & returnFormat, throw Exception(os.str().c_str()); } - cachedFile = altFormat->read(filestream, filepath, interp); + cachedFile = altFormat->read(*pStream, filepath, interp); if(IsDebugLoggingEnabled()) { @@ -738,17 +727,10 @@ void LoadFileUncached(FileFormat * & returnFormat, returnFormat = altFormat; returnCachedFile = cachedFile; - closeLutStream(config, filestream); - return; } catch(std::exception & e) { - if (pStream) - { - closeLutStream(config, *pStream); - } - if(IsDebugLoggingEnabled()) { std::ostringstream os; diff --git a/tests/cpu/OCIOZArchive_tests.cpp b/tests/cpu/OCIOZArchive_tests.cpp index 1f2355000..bc1d2c497 100644 --- a/tests/cpu/OCIOZArchive_tests.cpp +++ b/tests/cpu/OCIOZArchive_tests.cpp @@ -435,6 +435,29 @@ OCIO_ADD_TEST(OCIOZArchive, context_test_for_search_paths_and_filetransform_sour mtx->getMatrix(mat); OCIO_CHECK_EQUAL(mat[0], 4.); } + + { + // File transform source is an absolute path, not in the archive. + const std::string filePath = + OCIO::GetTestFilesDir() + "/matrix_example4x4.ctf"; + OCIO::FileTransformRcPtr transform = OCIO::FileTransform::Create(); + transform->setSrc(filePath.c_str()); + OCIO::ConstProcessorRcPtr processor = cfg->getProcessor(transform); + OCIO::ConstTransformRcPtr tr = + processor->createGroupTransform()->getTransform(0); + auto mtx = OCIO::DynamicPtrCast(tr); + OCIO_REQUIRE_ASSERT(mtx); + mtx->getMatrix(mat); + OCIO_CHECK_EQUAL(mat[0], 3.24); + } + + { + // File transform source is an abs path but doesn't exist anywhere. + const std::string filePath = OCIO::GetTestFilesDir() + "/missing.ctf"; + OCIO::FileTransformRcPtr transform = OCIO::FileTransform::Create(); + transform->setSrc(filePath.c_str()); + OCIO_CHECK_THROW(cfg->getProcessor(transform), OCIO::Exception); + } }; testPaths(cfgWindowsArchive, ctxWindowsArchive);