mirror of https://github.com/opencv/opencv.git
parent
f8ad289311
commit
8e6280fc8e
7 changed files with 1471 additions and 51 deletions
@ -0,0 +1,38 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_UTILS_FILESYSTEM_HPP |
||||
#define OPENCV_UTILS_FILESYSTEM_HPP |
||||
|
||||
namespace cv { namespace utils { namespace fs { |
||||
|
||||
|
||||
CV_EXPORTS bool exists(const cv::String& path); |
||||
CV_EXPORTS bool isDirectory(const cv::String& path); |
||||
|
||||
|
||||
CV_EXPORTS cv::String getcwd(); |
||||
|
||||
|
||||
CV_EXPORTS bool createDirectory(const cv::String& path); |
||||
CV_EXPORTS bool createDirectories(const cv::String& path); |
||||
|
||||
#ifdef __OPENCV_BUILD |
||||
// TODO
|
||||
//CV_EXPORTS cv::String getTempDirectory();
|
||||
|
||||
/**
|
||||
* @brief Returns directory to store OpenCV cache files |
||||
* Create sub-directory in common OpenCV cache directory if it doesn't exist. |
||||
* @param sub_directory_name name of sub-directory. NULL or "" value asks to return root cache directory. |
||||
* @param configuration_name optional name of configuration parameter name which overrides default behavior. |
||||
* @return Path to cache directory. Returns empty string if cache directories support is not available. Returns "disabled" if cache disabled by user. |
||||
*/ |
||||
CV_EXPORTS cv::String getCacheDirectory(const char* sub_directory_name, const char* configuration_name = NULL); |
||||
|
||||
#endif |
||||
|
||||
}}} // namespace
|
||||
|
||||
#endif // OPENCV_UTILS_FILESYSTEM_HPP
|
@ -0,0 +1,64 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_UTILS_FILESYSTEM_PRIVATE_HPP |
||||
#define OPENCV_UTILS_FILESYSTEM_PRIVATE_HPP |
||||
|
||||
// TODO Move to CMake?
|
||||
#ifndef OPENCV_HAVE_FILESYSTEM_SUPPORT |
||||
# if defined(__EMSCRIPTEN__) || defined(__native_client__) |
||||
/* no support */ |
||||
# elif defined __ANDROID__ || defined __linux__ || defined _WIN32 || \ |
||||
defined __FreeBSD__ || defined __bsdi__ |
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1 |
||||
# elif defined(__APPLE__) |
||||
# include <TargetConditionals.h> |
||||
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (!defined(TARGET_OS_OSX) && !TARGET_OS_IPHONE) |
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1 // OSX only
|
||||
# endif |
||||
# else |
||||
/* unknown */ |
||||
# endif |
||||
# ifndef OPENCV_HAVE_FILESYSTEM_SUPPORT |
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 0 |
||||
# endif |
||||
#endif |
||||
|
||||
#if OPENCV_HAVE_FILESYSTEM_SUPPORT |
||||
namespace cv { namespace utils { namespace fs { |
||||
|
||||
/**
|
||||
* File-based lock object. |
||||
* |
||||
* Provides interprocess synchronization mechanism. |
||||
* Platform dependent. |
||||
* |
||||
* Supports multiple readers / single writer access pattern (RW / readers–writer / shared-exclusive lock). |
||||
* |
||||
* File must exist. |
||||
* File can't be re-used (for example, I/O operations via std::fstream is not safe) |
||||
*/ |
||||
class CV_EXPORTS FileLock { |
||||
public: |
||||
explicit FileLock(const char* fname); |
||||
~FileLock(); |
||||
|
||||
void lock(); //< acquire exclusive (writer) lock
|
||||
void unlock(); //< release exclusive (writer) lock
|
||||
|
||||
void lock_shared(); //< acquire sharable (reader) lock
|
||||
void unlock_shared(); //< release sharable (reader) lock
|
||||
|
||||
struct Impl; |
||||
protected: |
||||
Impl* pImpl; |
||||
|
||||
private: |
||||
FileLock(const FileLock&); // disabled
|
||||
FileLock& operator=(const FileLock&); // disabled
|
||||
}; |
||||
|
||||
}}} // namespace
|
||||
#endif |
||||
#endif // OPENCV_UTILS_FILESYSTEM_PRIVATE_HPP
|
@ -0,0 +1,119 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_UTILS_LOCK_HPP |
||||
#define OPENCV_UTILS_LOCK_HPP |
||||
|
||||
namespace cv { namespace utils { |
||||
|
||||
|
||||
/** @brief A simple scoped lock (RAII-style locking for exclusive/write access).
|
||||
* |
||||
* Emulate std::lock_guard (C++11), partially std::unique_lock (C++11), |
||||
*/ |
||||
template <class _Mutex> |
||||
class lock_guard { |
||||
public: |
||||
typedef _Mutex Mutex; |
||||
|
||||
explicit inline lock_guard(Mutex &m) : mutex_(&m) { mutex_->lock(); } |
||||
|
||||
inline ~lock_guard() { if (mutex_) mutex_->unlock(); } |
||||
|
||||
inline void release() |
||||
{ |
||||
CV_DbgAssert(mutex_); |
||||
mutex_->unlock(); |
||||
mutex_ = NULL; |
||||
} |
||||
|
||||
private: |
||||
Mutex* mutex_; |
||||
|
||||
private: |
||||
lock_guard(const lock_guard&); // disabled
|
||||
lock_guard& operator=(const lock_guard&); // disabled
|
||||
}; |
||||
|
||||
|
||||
/** @brief A shared scoped lock (RAII-style locking for shared/reader access).
|
||||
* |
||||
* Emulate boost::shared_lock_guard, subset of std::shared_lock (C++14), |
||||
*/ |
||||
template <class _Mutex> |
||||
class shared_lock_guard { |
||||
public: |
||||
typedef _Mutex Mutex; |
||||
|
||||
explicit inline shared_lock_guard(Mutex &m) : mutex_(&m) { mutex_->lock_shared(); } |
||||
|
||||
inline ~shared_lock_guard() { if (mutex_) mutex_->unlock_shared(); } |
||||
|
||||
inline void release() |
||||
{ |
||||
CV_DbgAssert(mutex_); |
||||
mutex_->unlock_shared(); |
||||
mutex_ = NULL; |
||||
} |
||||
|
||||
protected: |
||||
Mutex* mutex_; |
||||
|
||||
private: |
||||
shared_lock_guard(const shared_lock_guard&); // disabled
|
||||
shared_lock_guard& operator=(const shared_lock_guard&); // disabled
|
||||
}; |
||||
|
||||
|
||||
/** @brief An optional simple scoped lock (RAII-style locking for exclusive/write access).
|
||||
* |
||||
* Doesn't lock if mutex pointer is NULL. |
||||
* |
||||
* @sa lock_guard |
||||
*/ |
||||
template <class _Mutex> |
||||
class optional_lock_guard { |
||||
public: |
||||
typedef _Mutex Mutex; |
||||
|
||||
explicit inline optional_lock_guard(Mutex* m) : mutex_(m) { if (mutex_) mutex_->lock(); } |
||||
|
||||
inline ~optional_lock_guard() { if (mutex_) mutex_->unlock(); } |
||||
|
||||
private: |
||||
Mutex* mutex_; |
||||
|
||||
private: |
||||
optional_lock_guard(const optional_lock_guard&); // disabled
|
||||
optional_lock_guard& operator=(const optional_lock_guard&); // disabled
|
||||
}; |
||||
|
||||
|
||||
/** @brief An optional shared scoped lock (RAII-style locking for shared/reader access).
|
||||
* |
||||
* Doesn't lock if mutex pointer is NULL. |
||||
* |
||||
* @sa shared_lock_guard |
||||
*/ |
||||
template <class _Mutex> |
||||
class optional_shared_lock_guard { |
||||
public: |
||||
typedef _Mutex Mutex; |
||||
|
||||
explicit inline optional_shared_lock_guard(Mutex* m) : mutex_(m) { if (mutex_) mutex_->lock_shared(); } |
||||
|
||||
inline ~optional_shared_lock_guard() { if (mutex_) mutex_->unlock_shared(); } |
||||
|
||||
protected: |
||||
Mutex* mutex_; |
||||
|
||||
private: |
||||
optional_shared_lock_guard(const optional_shared_lock_guard&); // disabled
|
||||
optional_shared_lock_guard& operator=(const optional_shared_lock_guard&); // disabled
|
||||
}; |
||||
|
||||
|
||||
}} // namespace
|
||||
|
||||
#endif // OPENCV_UTILS_LOCK_HPP
|
@ -0,0 +1,445 @@ |
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
#include <opencv2/core/utils/configuration.private.hpp> |
||||
|
||||
#include <opencv2/core/utils/logger.hpp> |
||||
|
||||
#include "opencv2/core/utils/filesystem.private.hpp" |
||||
#include "opencv2/core/utils/filesystem.hpp" |
||||
|
||||
//#define DEBUG_FS_UTILS
|
||||
|
||||
#ifdef DEBUG_FS_UTILS |
||||
#include <iostream> |
||||
#define DBG(...) __VA_ARGS__ |
||||
#else |
||||
#define DBG(...) |
||||
#endif |
||||
|
||||
|
||||
#if OPENCV_HAVE_FILESYSTEM_SUPPORT |
||||
|
||||
#ifdef _WIN32 |
||||
#define WIN32_LEAN_AND_MEAN |
||||
#define NOMINMAX |
||||
#include <windows.h> |
||||
#include <direct.h> |
||||
#include <sys/types.h> |
||||
#include <sys/stat.h> |
||||
#include <errno.h> |
||||
#elif defined __linux__ || defined __APPLE__ |
||||
#include <sys/types.h> |
||||
#include <sys/stat.h> |
||||
#include <fcntl.h> |
||||
#include <unistd.h> |
||||
#include <errno.h> |
||||
#endif |
||||
|
||||
namespace cv { namespace utils { namespace fs { |
||||
|
||||
static inline |
||||
bool isPathSeparator(char c) |
||||
{ |
||||
return c == '/' || c == '\\'; |
||||
} |
||||
|
||||
bool exists(const cv::String& path) |
||||
{ |
||||
CV_INSTRUMENT_REGION() |
||||
|
||||
#if defined _WIN32 || defined WINCE |
||||
BOOL status = TRUE; |
||||
{ |
||||
WIN32_FILE_ATTRIBUTE_DATA all_attrs; |
||||
#ifdef WINRT |
||||
wchar_t wpath[MAX_PATH]; |
||||
size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH); |
||||
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); |
||||
status = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &all_attrs); |
||||
#else |
||||
status = ::GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &all_attrs); |
||||
#endif |
||||
} |
||||
|
||||
return !!status; |
||||
#else |
||||
struct stat stat_buf; |
||||
return (0 == stat(path.c_str(), &stat_buf)); |
||||
#endif |
||||
} |
||||
|
||||
cv::String getcwd() |
||||
{ |
||||
CV_INSTRUMENT_REGION() |
||||
cv::AutoBuffer<char, 4096> buf; |
||||
#if defined WIN32 || defined _WIN32 || defined WINCE |
||||
#ifdef WINRT |
||||
return cv::String(); |
||||
#else |
||||
DWORD sz = GetCurrentDirectoryA(0, NULL); |
||||
buf.allocate((size_t)sz); |
||||
sz = GetCurrentDirectoryA((DWORD)buf.size(), (char*)buf); |
||||
return cv::String((char*)buf, (size_t)sz); |
||||
#endif |
||||
#elif defined __linux__ || defined __APPLE__ |
||||
for(;;) |
||||
{ |
||||
char* p = ::getcwd((char*)buf, buf.size()); |
||||
if (p == NULL) |
||||
{ |
||||
if (errno == ERANGE) |
||||
{ |
||||
buf.allocate(buf.size() * 2); |
||||
continue; |
||||
} |
||||
return cv::String(); |
||||
} |
||||
break; |
||||
} |
||||
return cv::String((char*)buf, (size_t)strlen((char*)buf)); |
||||
#else |
||||
return cv::String(); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
bool createDirectory(const cv::String& path) |
||||
{ |
||||
CV_INSTRUMENT_REGION() |
||||
#if defined WIN32 || defined _WIN32 || defined WINCE |
||||
#ifdef WINRT |
||||
wchar_t wpath[MAX_PATH]; |
||||
size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH); |
||||
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1)); |
||||
int result = CreateDirectoryA(wpath, NULL) ? 0 : -1; |
||||
#else |
||||
int result = _mkdir(path.c_str()); |
||||
#endif |
||||
#elif defined __linux__ || defined __APPLE__ |
||||
int result = mkdir(path.c_str(), 0777); |
||||
#else |
||||
int result = -1; |
||||
#endif |
||||
|
||||
if (result == -1) |
||||
{ |
||||
return isDirectory(path); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
bool createDirectories(const cv::String& path_) |
||||
{ |
||||
cv::String path = path_; |
||||
for (;;) |
||||
{ |
||||
char last_char = path.empty() ? 0 : path[path.length() - 1]; |
||||
if (last_char == '/' || last_char == '\\') |
||||
{ |
||||
path = path.substr(0, path.length() - 1); |
||||
continue; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
if (path.empty() || path == "./" || path == ".\\" || path == ".") |
||||
return true; |
||||
if (isDirectory(path)) |
||||
return true; |
||||
|
||||
size_t pos = path.rfind('/'); |
||||
if (pos == cv::String::npos) |
||||
pos = path.rfind('\\'); |
||||
if (pos != cv::String::npos) |
||||
{ |
||||
cv::String parent_directory = path.substr(0, pos); |
||||
if (!parent_directory.empty()) |
||||
{ |
||||
if (!createDirectories(parent_directory)) |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return createDirectory(path); |
||||
} |
||||
|
||||
#ifdef _WIN32 |
||||
|
||||
struct FileLock::Impl |
||||
{ |
||||
Impl(const char* fname) |
||||
{ |
||||
// http://support.microsoft.com/kb/316609
|
||||
int numRetries = 5; |
||||
do |
||||
{ |
||||
handle = ::CreateFileA(fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, |
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
||||
if (INVALID_HANDLE_VALUE == handle) |
||||
{ |
||||
if (ERROR_SHARING_VIOLATION == GetLastError()) |
||||
{ |
||||
numRetries--; |
||||
Sleep(250); |
||||
continue; |
||||
} |
||||
else |
||||
{ |
||||
CV_ErrorNoReturn_(Error::StsAssert, ("Can't open lock file: %s", fname)); |
||||
} |
||||
} |
||||
break; |
||||
} while (numRetries > 0); |
||||
} |
||||
~Impl() |
||||
{ |
||||
if (INVALID_HANDLE_VALUE != handle) |
||||
{ |
||||
::CloseHandle(handle); |
||||
} |
||||
} |
||||
|
||||
bool lock() |
||||
{ |
||||
OVERLAPPED overlapped; |
||||
std::memset(&overlapped, 0, sizeof(overlapped)); |
||||
return !!::LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped); |
||||
} |
||||
bool unlock() |
||||
{ |
||||
OVERLAPPED overlapped; |
||||
std::memset(&overlapped, 0, sizeof(overlapped)); |
||||
return !!::UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped); |
||||
} |
||||
|
||||
bool lock_shared() |
||||
{ |
||||
OVERLAPPED overlapped; |
||||
std::memset(&overlapped, 0, sizeof(overlapped)); |
||||
return !!::LockFileEx(handle, 0, 0, MAXDWORD, MAXDWORD, &overlapped); |
||||
} |
||||
bool unlock_shared() |
||||
{ |
||||
return unlock(); |
||||
} |
||||
|
||||
HANDLE handle; |
||||
|
||||
private: |
||||
Impl(const Impl&); // disabled
|
||||
Impl& operator=(const Impl&); // disabled
|
||||
}; |
||||
|
||||
#elif defined __linux__ || defined __APPLE__ |
||||
|
||||
struct FileLock::Impl |
||||
{ |
||||
Impl(const char* fname) |
||||
{ |
||||
handle = ::open(fname, O_RDWR); |
||||
CV_Assert(handle != -1); |
||||
} |
||||
~Impl() |
||||
{ |
||||
if (handle >= 0) |
||||
::close(handle); |
||||
} |
||||
|
||||
bool lock() |
||||
{ |
||||
struct ::flock l; |
||||
std::memset(&l, 0, sizeof(l)); |
||||
l.l_type = F_WRLCK; |
||||
l.l_whence = SEEK_SET; |
||||
l.l_start = 0; |
||||
l.l_len = 0; |
||||
DBG(std::cout << "Lock..." << std::endl); |
||||
bool res = -1 != ::fcntl(handle, F_SETLKW, &l); |
||||
return res; |
||||
} |
||||
bool unlock() |
||||
{ |
||||
struct ::flock l; |
||||
std::memset(&l, 0, sizeof(l)); |
||||
l.l_type = F_UNLCK; |
||||
l.l_whence = SEEK_SET; |
||||
l.l_start = 0; |
||||
l.l_len = 0; |
||||
DBG(std::cout << "Unlock..." << std::endl); |
||||
bool res = -1 != ::fcntl(handle, F_SETLK, &l); |
||||
return res; |
||||
} |
||||
|
||||
bool lock_shared() |
||||
{ |
||||
struct ::flock l; |
||||
std::memset(&l, 0, sizeof(l)); |
||||
l.l_type = F_RDLCK; |
||||
l.l_whence = SEEK_SET; |
||||
l.l_start = 0; |
||||
l.l_len = 0; |
||||
DBG(std::cout << "Lock read..." << std::endl); |
||||
bool res = -1 != ::fcntl(handle, F_SETLKW, &l); |
||||
return res; |
||||
} |
||||
bool unlock_shared() |
||||
{ |
||||
return unlock(); |
||||
} |
||||
|
||||
int handle; |
||||
|
||||
private: |
||||
Impl(const Impl&); // disabled
|
||||
Impl& operator=(const Impl&); // disabled
|
||||
}; |
||||
|
||||
#endif |
||||
|
||||
FileLock::FileLock(const char* fname) |
||||
: pImpl(new Impl(fname)) |
||||
{ |
||||
// nothing
|
||||
} |
||||
FileLock::~FileLock() |
||||
{ |
||||
delete pImpl; |
||||
pImpl = NULL; |
||||
} |
||||
|
||||
void FileLock::lock() { CV_Assert(pImpl->lock()); } |
||||
void FileLock::unlock() { CV_Assert(pImpl->unlock()); } |
||||
void FileLock::lock_shared() { CV_Assert(pImpl->lock_shared()); } |
||||
void FileLock::unlock_shared() { CV_Assert(pImpl->unlock_shared()); } |
||||
|
||||
|
||||
|
||||
cv::String getCacheDirectory(const char* sub_directory_name, const char* configuration_name) |
||||
{ |
||||
String cache_path; |
||||
if (configuration_name) |
||||
{ |
||||
cache_path = utils::getConfigurationParameterString(configuration_name, ""); |
||||
} |
||||
if (cache_path.empty()) |
||||
{ |
||||
cv::String default_cache_path; |
||||
#ifdef _WIN32 |
||||
char tmp_path_buf[MAX_PATH+1] = {0}; |
||||
DWORD res = GetTempPath(MAX_PATH, tmp_path_buf); |
||||
if (res > 0 && res <= MAX_PATH) |
||||
{ |
||||
default_cache_path = tmp_path_buf; |
||||
} |
||||
#elif defined __ANDROID__ |
||||
// no defaults
|
||||
#elif defined __APPLE__ |
||||
const char* tmpdir_env = getenv("TMPDIR"); |
||||
if (tmpdir_env && utils::fs::isDirectory(tmpdir_env)) |
||||
{ |
||||
default_cache_path = tmpdir_env; |
||||
} |
||||
else |
||||
{ |
||||
default_cache_path = "/tmp/"; |
||||
CV_LOG_WARNING(NULL, "Using world accessible cache directory. This may be not secure: " << default_cache_path); |
||||
} |
||||
#elif defined __linux__ |
||||
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
if (default_cache_path.empty()) |
||||
{ |
||||
const char* xdg_cache_env = getenv("XDG_CACHE_HOME"); |
||||
if (xdg_cache_env && xdg_cache_env[0] && utils::fs::isDirectory(xdg_cache_env)) |
||||
{ |
||||
default_cache_path = xdg_cache_env; |
||||
} |
||||
} |
||||
if (default_cache_path.empty()) |
||||
{ |
||||
const char* home_env = getenv("HOME"); |
||||
if (home_env && home_env[0] && utils::fs::isDirectory(home_env)) |
||||
{ |
||||
cv::String home_path = home_env; |
||||
cv::String home_cache_path = home_path + "/.cache/"; |
||||
if (utils::fs::isDirectory(home_cache_path)) |
||||
{ |
||||
default_cache_path = home_cache_path; |
||||
} |
||||
} |
||||
} |
||||
if (default_cache_path.empty()) |
||||
{ |
||||
const char* temp_path = "/var/tmp/"; |
||||
if (utils::fs::isDirectory(temp_path)) |
||||
{ |
||||
default_cache_path = temp_path; |
||||
CV_LOG_WARNING(NULL, "Using world accessible cache directory. This may be not secure: " << default_cache_path); |
||||
} |
||||
} |
||||
if (default_cache_path.empty()) |
||||
{ |
||||
default_cache_path = "/tmp/"; |
||||
CV_LOG_WARNING(NULL, "Using world accessible cache directory. This may be not secure: " << default_cache_path); |
||||
} |
||||
#else |
||||
// no defaults
|
||||
#endif |
||||
CV_LOG_VERBOSE(NULL, 0, "default_cache_path = " << default_cache_path); |
||||
if (!default_cache_path.empty()) |
||||
{ |
||||
if (utils::fs::isDirectory(default_cache_path)) |
||||
{ |
||||
default_cache_path += "/opencv/" CV_VERSION "/"; |
||||
if (sub_directory_name && sub_directory_name[0] != '\0') |
||||
default_cache_path += cv::String(sub_directory_name) + "/"; |
||||
if (!utils::fs::createDirectories(default_cache_path)) |
||||
{ |
||||
CV_LOG_DEBUG(NULL, "Can't create OpenCV cache sub-directory: " << default_cache_path); |
||||
} |
||||
else |
||||
{ |
||||
cache_path = default_cache_path; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
CV_LOG_INFO(NULL, "Can't find default cache directory (does it exist?): " << default_cache_path); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
CV_LOG_DEBUG(NULL, "OpenCV has no support to discover default cache directory on the current platform"); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
if (cache_path == "disabled") |
||||
return cache_path; |
||||
if (!isDirectory(cache_path)) |
||||
{ |
||||
CV_LOG_WARNING(NULL, "Specified non-existed directory, creating OpenCV sub-directory for caching purposes: " << cache_path); |
||||
if (!createDirectories(cache_path)) |
||||
{ |
||||
CV_LOG_ERROR(NULL, "Can't create OpenCV cache sub-directory: " << cache_path); |
||||
cache_path.clear(); |
||||
} |
||||
} |
||||
} |
||||
CV_Assert(cache_path.empty() || utils::fs::isDirectory(cache_path)); |
||||
if (!cache_path.empty()) |
||||
{ |
||||
if (!isPathSeparator(cache_path[cache_path.size() - 1])) |
||||
{ |
||||
cache_path += '/'; |
||||
} |
||||
} |
||||
return cache_path; |
||||
} |
||||
|
||||
}}} // namespace
|
||||
|
||||
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT
|
Loading…
Reference in new issue