init
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
PROJECT(openvibe-module-fs)
|
||||
|
||||
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
|
||||
SET(PROJECT_VERSION_MINOR ${OV_GLOBAL_VERSION_MINOR})
|
||||
SET(PROJECT_VERSION_PATCH ${OV_GLOBAL_VERSION_PATCH})
|
||||
SET(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
|
||||
|
||||
FILE(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.hpp src/*.inl include/*.h)
|
||||
INCLUDE_DIRECTORIES(include/fs)
|
||||
INCLUDE("FindSourceRCProperties")
|
||||
|
||||
ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRC_FILES})
|
||||
|
||||
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
FOLDER ${MODULES_FOLDER}
|
||||
COMPILE_FLAGS "-DFS_Shared -DFS_Exports")
|
||||
|
||||
ADD_LIBRARY(${PROJECT_NAME}-static STATIC ${SRC_FILES})
|
||||
SET_TARGET_PROPERTIES(${PROJECT_NAME}-static PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
FOLDER ${MODULES_FOLDER}
|
||||
COMPILE_FLAGS "-DFS_Static -DFS_Exports")
|
||||
|
||||
IF(UNIX)
|
||||
SET_TARGET_PROPERTIES(${PROJECT_NAME}-static PROPERTIES COMPILE_FLAGS "-fPIC")
|
||||
ENDIF()
|
||||
|
||||
INCLUDE("FindOpenViBECommon")
|
||||
INCLUDE("FindThirdPartyBoost")
|
||||
INCLUDE("FindThirdPartyBoost_FileSystem")
|
||||
|
||||
# ---------------------------------
|
||||
# Target macros
|
||||
# Defines target operating system, architecture and compiler
|
||||
# ---------------------------------
|
||||
SET_BUILD_PLATFORM()
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
INSTALL(TARGETS ${PROJECT_NAME}-static
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
INSTALL(DIRECTORY include/ DESTINATION ${DIST_INCLUDEDIR} FILES_MATCHING PATTERN "*.h")
|
||||
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
|
||||
namespace FS {
|
||||
class FS_API Files
|
||||
{
|
||||
public:
|
||||
static FILE* open(const char* file, const char* mode);
|
||||
static FILE* popen(const char* file, const char* mode);
|
||||
static void openOFStream(std::ofstream& stream, const char* file, std::ios_base::openmode mode = std::ios_base::out);
|
||||
static void openIFStream(std::ifstream& stream, const char* file, std::ios_base::openmode mode = std::ios_base::in);
|
||||
static void openFStream(std::fstream& stream, const char* file, std::ios_base::openmode mode);
|
||||
|
||||
static bool equals(const char* pFile1, const char* pFile2);
|
||||
static bool fileExists(const char* pathToCheck);
|
||||
static bool directoryExists(const char* pathToCheck);
|
||||
// Creates all components of a path to the filesystem
|
||||
static bool createPath(const char* path);
|
||||
// Creates all components of a path to the filesystem except the last part (i.e. for paths including a filename in the end)
|
||||
static bool createParentPath(const char* path);
|
||||
// Returns a path omitting the last part of it (essentially boost::filesystem::parent_path). Output sParentPath needs to be pre-allocated.
|
||||
static bool getParentPath(const char* path, char* parentPath);
|
||||
static bool getParentPath(const char* path, char* parentPath, size_t size);
|
||||
|
||||
/**
|
||||
* \brief Fills filename as a component of a path
|
||||
* \param path [in]: input path
|
||||
* \param filename [out]: file name, needs to be pre-allocated
|
||||
*
|
||||
* (essentially boost::filesystem::filename)
|
||||
* \return Success status
|
||||
*/
|
||||
static bool getFilename(const char* path, char* filename);
|
||||
static bool getFilename(const char* path, char* filename, size_t size);
|
||||
|
||||
/**
|
||||
* \brief Fills filename as a component of a path without the extension
|
||||
* \param path [in]: input path
|
||||
* \param filename [out]: file name without extension, needs to be pre-allocated
|
||||
*
|
||||
* (essentially boost::filesystem::filename)
|
||||
* \return Success status
|
||||
*/
|
||||
static bool getFilenameWithoutExtension(const char* path, char* filename);
|
||||
static bool getFilenameWithoutExtension(const char* path, char* filename, size_t size);
|
||||
// Returns the extension component of a path
|
||||
static bool getFilenameExtension(const char* path, char* fileNameExtension);
|
||||
static bool getFilenameExtension(const char* path, char* extension, size_t size);
|
||||
|
||||
static bool copyFile(const char* srcFile, const char* dstPath);
|
||||
static bool copyDirectory(const char* srcDir, const char* dstDir);
|
||||
|
||||
static bool remove(const char* path);
|
||||
static bool removeAll(const char* path);
|
||||
private:
|
||||
|
||||
Files() = delete;
|
||||
};
|
||||
} // namespace FS
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include <cinttypes>
|
||||
#include <cstdlib> // size_t for unix
|
||||
|
||||
namespace FS {
|
||||
class IEntryEnumeratorCallBack;
|
||||
|
||||
class FS_API IEntryEnumerator
|
||||
{
|
||||
public:
|
||||
|
||||
class FS_API IAttributes
|
||||
{
|
||||
public:
|
||||
virtual bool isFile() = 0;
|
||||
virtual bool isDirectory() = 0;
|
||||
virtual bool isSymbolicLink() = 0;
|
||||
|
||||
virtual bool isArchive() = 0;
|
||||
virtual bool isReadOnly() = 0;
|
||||
virtual bool isHidden() = 0;
|
||||
virtual bool isSystem() = 0;
|
||||
virtual bool isExecutable() = 0;
|
||||
|
||||
virtual size_t getSize() = 0;
|
||||
protected:
|
||||
virtual ~IAttributes() {}
|
||||
};
|
||||
|
||||
class FS_API IEntry
|
||||
{
|
||||
public:
|
||||
virtual const char* getName() = 0;
|
||||
protected:
|
||||
virtual ~IEntry() {}
|
||||
};
|
||||
|
||||
virtual bool enumerate(const char* sWildcard, bool bRecursive = false) = 0;
|
||||
virtual void release() = 0;
|
||||
protected:
|
||||
virtual ~IEntryEnumerator() { }
|
||||
};
|
||||
|
||||
class FS_API IEntryEnumeratorCallBack
|
||||
{
|
||||
public:
|
||||
virtual bool callback(IEntryEnumerator::IEntry& rEntry, IEntryEnumerator::IAttributes& rAttributes) = 0;
|
||||
virtual ~IEntryEnumeratorCallBack() { }
|
||||
};
|
||||
|
||||
extern FS_API IEntryEnumerator* createEntryEnumerator(IEntryEnumeratorCallBack& rCallBack);
|
||||
} // namespace FS
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <ov_common_defines.h>
|
||||
|
||||
#if defined FS_Shared
|
||||
# if defined TARGET_OS_Windows
|
||||
# define FS_API_Export __declspec(dllexport)
|
||||
# define FS_API_Import __declspec(dllimport)
|
||||
# elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
# define FS_API_Export __attribute__((visibility("default")))
|
||||
# define FS_API_Import __attribute__((visibility("default")))
|
||||
# else
|
||||
# define FS_API_Export
|
||||
# define FS_API_Import
|
||||
# endif
|
||||
#else
|
||||
# define FS_API_Export
|
||||
# define FS_API_Import
|
||||
#endif
|
||||
|
||||
#if defined FS_Exports
|
||||
# define FS_API FS_API_Export
|
||||
#else
|
||||
# define FS_API FS_API_Import
|
||||
#endif
|
||||
@@ -0,0 +1,391 @@
|
||||
#include "Files.h"
|
||||
|
||||
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
#include <stdio.h> // For fopen
|
||||
#include <unistd.h> //For access().
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h> // For stat().
|
||||
#include <cstdlib>
|
||||
#elif defined TARGET_OS_Windows
|
||||
#include "m_ConverterUtf8.h"
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
namespace FS {
|
||||
|
||||
// * 2006-08-30 YRD - Portability note : using namespace FS confuses windows platform SDK because it defines itself a 'boolean' type. Thus the following define to force the use of FS::boolean !
|
||||
|
||||
#if defined TARGET_HAS_Boost && BOOST_VERSION / 100 % 1000 >= 55
|
||||
/**
|
||||
* \brief Makes a recursive copy of source folder to target folder.
|
||||
* Operation can fail in several cases:
|
||||
* - target path exists
|
||||
* - bad permission rights
|
||||
* \param source the source folder path
|
||||
* \param target the destination folder path
|
||||
* \return true if succeeded
|
||||
* \return false if failed
|
||||
*/
|
||||
bool recursiveCopy(const boost::filesystem::path& source, const boost::filesystem::path& target)
|
||||
{
|
||||
if (exists(target)) { return false; }
|
||||
|
||||
if (is_directory(source))
|
||||
{
|
||||
if (!create_directories(target)) { return false; }
|
||||
for (boost::filesystem::directory_entry& item : boost::filesystem::directory_iterator(source))
|
||||
{
|
||||
// boost::filesystem::path overlods '/' operator !
|
||||
if (!recursiveCopy(item.path(), target / item.path().filename())) { return false; }
|
||||
}
|
||||
}
|
||||
else if (is_regular_file(source))
|
||||
{
|
||||
try { copy(source, target); }
|
||||
catch (...) { return false; }
|
||||
}
|
||||
else { return false; }
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
|
||||
|
||||
FILE* Files::open(const char* file, const char* mode)
|
||||
{
|
||||
FILE* fHandle = fopen(file, mode);
|
||||
return fHandle;
|
||||
}
|
||||
|
||||
FILE* Files::popen(const char* file, const char* mode)
|
||||
{
|
||||
FILE* fHandle = ::popen(file, mode);
|
||||
return fHandle;
|
||||
}
|
||||
|
||||
void Files::openOFStream(std::ofstream& stream, const char* file, std::ios_base::openmode mode) { stream.open(file, mode); }
|
||||
void Files::openIFStream(std::ifstream& stream, const char* file, std::ios_base::openmode mode) { stream.open(file, mode); }
|
||||
void Files::openFStream(std::fstream& stream, const char* file, std::ios_base::openmode mode) { stream.open(file, mode); }
|
||||
|
||||
#elif defined TARGET_OS_Windows
|
||||
|
||||
|
||||
FILE* Files::open(const char* file, const char* mode)
|
||||
{
|
||||
FILE* fHandle;
|
||||
|
||||
try
|
||||
{
|
||||
const std::wstring utf16FileName = Common::Converter::Utf8ToUtf16(file);
|
||||
const std::wstring utf16Mode = Common::Converter::Utf8ToUtf16(mode);
|
||||
|
||||
fHandle = _wfopen(utf16FileName.c_str(), utf16Mode.c_str());
|
||||
}
|
||||
catch (const std::logic_error&) { fHandle = fopen(file, mode); }
|
||||
|
||||
return fHandle;
|
||||
}
|
||||
|
||||
FILE* Files::popen(const char* file, const char* mode)
|
||||
{
|
||||
FILE* fHandle;
|
||||
|
||||
try
|
||||
{
|
||||
const std::wstring utf16FileName = Common::Converter::Utf8ToUtf16(file);
|
||||
const std::wstring utf16Mode = Common::Converter::Utf8ToUtf16(mode);
|
||||
|
||||
fHandle = _wpopen(utf16FileName.c_str(), utf16Mode.c_str());
|
||||
}
|
||||
catch (const std::logic_error&) { fHandle = popen(file, mode); }
|
||||
|
||||
return fHandle;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void openStream(T& stream, const char* file, std::ios_base::openmode mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
const std::wstring utf16FileName = Common::Converter::Utf8ToUtf16(file);
|
||||
stream.open(utf16FileName.c_str(), mode);
|
||||
}
|
||||
catch (const std::logic_error&) { stream.open(file, mode); }
|
||||
}
|
||||
|
||||
void Files::openOFStream(std::ofstream& stream, const char* file, const std::ios_base::openmode mode) { openStream<std::ofstream>(stream, file, mode); }
|
||||
void Files::openIFStream(std::ifstream& stream, const char* file, const std::ios_base::openmode mode) { openStream<std::ifstream>(stream, file, mode); }
|
||||
void Files::openFStream(std::fstream& stream, const char* file, const std::ios_base::openmode mode) { openStream<std::fstream>(stream, file, mode); }
|
||||
|
||||
#endif
|
||||
|
||||
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
|
||||
bool Files::equals(const char* pFile1, const char* pFile2)
|
||||
{
|
||||
bool res=true;
|
||||
if(pFile1 && pFile2)
|
||||
{
|
||||
struct stat stat1;
|
||||
struct stat stat2;
|
||||
bool bStat1=!stat(pFile1, &stat1);
|
||||
bool bStat2=!stat(pFile2, &stat2);
|
||||
|
||||
if(!bStat1 && !bStat2) { res=true; }
|
||||
else if(bStat1 && bStat2)
|
||||
{
|
||||
res=
|
||||
(stat1.st_dev==stat2.st_dev)&&
|
||||
(stat1.st_ino==stat2.st_ino)&&
|
||||
(stat1.st_size==stat2.st_size)&&
|
||||
(stat1.st_mtime==stat2.st_mtime);
|
||||
}
|
||||
else { res=false; }
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#elif defined TARGET_OS_Windows
|
||||
|
||||
bool Files::equals(const char* pFile1, const char* pFile2)
|
||||
{
|
||||
bool res = true;
|
||||
if (pFile1 && pFile2)
|
||||
{
|
||||
const HANDLE handle1 = ::CreateFile(pFile1, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
const HANDLE handle2 = ::CreateFile(pFile2, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
if (handle1 && handle2)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION stat1;
|
||||
BY_HANDLE_FILE_INFORMATION stat2;
|
||||
const BOOL bStat1 = GetFileInformationByHandle(handle1, &stat1);
|
||||
const BOOL bStat2 = GetFileInformationByHandle(handle2, &stat2);
|
||||
if (!bStat1 && !bStat2) { res = true; }
|
||||
else if (bStat1 && bStat2)
|
||||
{
|
||||
res = (stat1.dwVolumeSerialNumber == stat2.dwVolumeSerialNumber) && (stat1.nFileIndexHigh == stat2.nFileIndexHigh)
|
||||
&& (stat1.nFileIndexLow == stat2.nFileIndexLow) && (stat1.nFileSizeHigh == stat2.nFileSizeHigh)
|
||||
&& (stat1.nFileSizeLow == stat2.nFileSizeLow) && (stat1.ftLastWriteTime.dwHighDateTime == stat2.ftLastWriteTime.dwHighDateTime)
|
||||
&& (stat1.ftLastWriteTime.dwLowDateTime == stat2.ftLastWriteTime.dwLowDateTime);
|
||||
}
|
||||
else { res = false; }
|
||||
CloseHandle(handle1);
|
||||
CloseHandle(handle2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handle1) { CloseHandle(handle1); }
|
||||
if (handle2) { CloseHandle(handle2); }
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
bool Files::fileExists(const char* pathToCheck)
|
||||
{
|
||||
if (!pathToCheck) { return false; }
|
||||
FILE* fp = open(pathToCheck, "r");
|
||||
if (!fp) { return false; }
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::directoryExists(const char* pathToCheck)
|
||||
{
|
||||
if (!pathToCheck) { return false; }
|
||||
#if defined TARGET_OS_Windows
|
||||
const std::wstring pathUTF16 = Common::Converter::Utf8ToUtf16(pathToCheck);
|
||||
const DWORD ftyp = GetFileAttributesW(pathUTF16.c_str());
|
||||
if (ftyp == INVALID_FILE_ATTRIBUTES) { return false; }
|
||||
if (ftyp & FILE_ATTRIBUTE_DIRECTORY) { return true; }
|
||||
#endif
|
||||
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
if ( access( pathToCheck, 0 ) == 0 )
|
||||
{
|
||||
struct stat status;
|
||||
stat( pathToCheck, &status );
|
||||
|
||||
if ( status.st_mode & S_IFDIR ) { return true; }
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Files::createPath(const char* path)
|
||||
{
|
||||
if (strcmp(path, "") == 0) { return false; }
|
||||
#if defined TARGET_OS_Windows
|
||||
std::wstring pathUTF16 = Common::Converter::Utf8ToUtf16(path);
|
||||
create_directories(boost::filesystem::wpath(pathUTF16));
|
||||
return is_directory(boost::filesystem::wpath(pathUTF16));
|
||||
#else
|
||||
return boost::filesystem::create_directories(boost::filesystem::path(path));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Files::createParentPath(const char* path)
|
||||
{
|
||||
if (strcmp(path, "") == 0) { return false; }
|
||||
#if defined TARGET_OS_Windows
|
||||
std::wstring pathUTF16 = Common::Converter::Utf8ToUtf16(path);
|
||||
return create_directories(boost::filesystem::wpath(pathUTF16).parent_path());
|
||||
#else
|
||||
return boost::filesystem::create_directories(boost::filesystem::path(path).parent_path());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Files::getParentPath(const char* path, char* parentPath)
|
||||
{
|
||||
if (!path || !parentPath) { return false; }
|
||||
strcpy(parentPath, boost::filesystem::path(path).parent_path().string().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::getParentPath(const char* path, char* parentPath, const size_t size)
|
||||
{
|
||||
if (!path || !parentPath) { return false; }
|
||||
strncpy(parentPath, boost::filesystem::path(path).parent_path().string().c_str(), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::getFilename(const char* path, char* filename)
|
||||
{
|
||||
if (!path || !filename) { return false; }
|
||||
strcpy(filename, boost::filesystem::path(path).filename().string().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::getFilename(const char* path, char* filename, const size_t size)
|
||||
{
|
||||
if (!path || !filename) { return false; }
|
||||
strncpy(filename, boost::filesystem::path(path).filename().string().c_str(), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::getFilenameWithoutExtension(const char* path, char* filename)
|
||||
{
|
||||
if (!path || !filename) { return false; }
|
||||
strcpy(filename, boost::filesystem::path(path).filename().replace_extension("").string().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::getFilenameWithoutExtension(const char* path, char* filename, const size_t size)
|
||||
{
|
||||
if (!path || !filename) { return false; }
|
||||
strncpy(filename, boost::filesystem::path(path).filename().replace_extension("").string().c_str(), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::getFilenameExtension(const char* path, char* fileNameExtension)
|
||||
{
|
||||
if (!path || !fileNameExtension) { return false; }
|
||||
strcpy(fileNameExtension, boost::filesystem::path(path).extension().string().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::getFilenameExtension(const char* path, char* extension, const size_t size)
|
||||
{
|
||||
if (!path || !extension) { return false; }
|
||||
strncpy(extension, boost::filesystem::path(path).extension().string().c_str(), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::remove(const char* path)
|
||||
{
|
||||
if (fileExists(path) || directoryExists(path))
|
||||
{
|
||||
#if defined TARGET_OS_Windows
|
||||
const std::wstring pathUTF16 = Common::Converter::Utf8ToUtf16(path);
|
||||
return boost::filesystem::remove(boost::filesystem::wpath(pathUTF16.c_str()));
|
||||
#else
|
||||
return boost::filesystem::remove(boost::filesystem::path(path));
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::removeAll(const char* path)
|
||||
{
|
||||
if (fileExists(path) || directoryExists(path))
|
||||
{
|
||||
#if defined TARGET_OS_Windows
|
||||
const std::wstring pathUTF16 = Common::Converter::Utf8ToUtf16(path);
|
||||
return (remove_all(boost::filesystem::wpath(pathUTF16.c_str())) != 0);
|
||||
#else
|
||||
return (boost::filesystem::remove_all(boost::filesystem::path(path)) != 0);
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// old boost compliance
|
||||
// manage cases here
|
||||
|
||||
#if defined TARGET_HAS_Boost && BOOST_VERSION / 100 % 1000 >= 55
|
||||
|
||||
bool Files::copyFile(const char* srcFile, const char* dstPath)
|
||||
{
|
||||
if (!srcFile || !dstPath) { return false; }
|
||||
#if defined TARGET_OS_Windows
|
||||
std::wstring pathSourceUTF16 = Common::Converter::Utf8ToUtf16(srcFile);
|
||||
std::wstring pathDestinationUTF16 = Common::Converter::Utf8ToUtf16(dstPath);
|
||||
boost::filesystem::copy_file(pathSourceUTF16, pathDestinationUTF16);
|
||||
#else
|
||||
boost::filesystem::copy_file(srcFile, dstPath);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Files::copyDirectory(const char* srcDir, const char* dstDir)
|
||||
{
|
||||
if (!srcDir || !dstDir) { return false; }
|
||||
#if defined TARGET_OS_Windows
|
||||
const std::wstring pathSourceUTF16 = Common::Converter::Utf8ToUtf16(srcDir);
|
||||
const std::wstring pathTargetUTF16 = Common::Converter::Utf8ToUtf16(dstDir);
|
||||
const boost::filesystem::path source = boost::filesystem::wpath(pathSourceUTF16.c_str());
|
||||
const boost::filesystem::path target = boost::filesystem::wpath(pathTargetUTF16.c_str());
|
||||
#else
|
||||
boost::filesystem::path source = srcDir;
|
||||
boost::filesystem::path target = dstDir;
|
||||
#endif
|
||||
return recursiveCopy(source, target);
|
||||
}
|
||||
|
||||
#elif defined TARGET_OS_Windows
|
||||
|
||||
#error OpenViBE requires at least boost 1.55 to compile on Windows
|
||||
|
||||
#else
|
||||
// ugly hack for old boost on linux ...
|
||||
bool Files::copyFile(const char* srcFile, const char* dstPath)
|
||||
{
|
||||
if(!srcFile || !dstPath || FS::Files::fileExists(dstPath)) { return false; }
|
||||
std::string command = std::string("cp '") + srcFile + "' '" + dstPath+"'";
|
||||
return (std::system(command.c_str()) != -1);
|
||||
}
|
||||
|
||||
bool Files::copyDirectory(const char* srcDir, const char* dstDir)
|
||||
{
|
||||
|
||||
if(!srcDir || !srcDir || FS::Files::directoryExists(dstDir)) { return false; }
|
||||
std::string command = std::string("cp -r '") + srcDir + "' '" + dstDir+"'";
|
||||
return (std::system(command.c_str()) != -1);
|
||||
}
|
||||
#endif
|
||||
} // namespace FS
|
||||
@@ -0,0 +1,277 @@
|
||||
#include "IEntryEnumerator.h"
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <stack>
|
||||
|
||||
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
#include <glob.h>
|
||||
#include <sys/stat.h>
|
||||
#elif defined TARGET_OS_Windows
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#else
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace FS {
|
||||
class CEntry final : public IEntryEnumerator::IEntry
|
||||
{
|
||||
public:
|
||||
|
||||
explicit CEntry(const std::string& name) : m_Name(name) {}
|
||||
const char* getName() override { return m_Name.c_str(); }
|
||||
|
||||
std::string m_Name;
|
||||
};
|
||||
|
||||
class CAttributes final : public IEntryEnumerator::IAttributes
|
||||
{
|
||||
public:
|
||||
|
||||
CAttributes() {}
|
||||
~CAttributes() override {}
|
||||
bool isFile() override { return m_IsFile; }
|
||||
bool isDirectory() override { return m_IsDirectory; }
|
||||
bool isSymbolicLink() override { return m_IsSymbolicLink; }
|
||||
bool isArchive() override { return m_IsArchive; }
|
||||
bool isReadOnly() override { return m_IsReadOnly; }
|
||||
bool isHidden() override { return m_IsHidden; }
|
||||
bool isSystem() override { return m_IsSystem; }
|
||||
bool isExecutable() override { return m_IsExecutable; }
|
||||
size_t getSize() override { return m_Size; }
|
||||
|
||||
bool m_IsFile = false;
|
||||
bool m_IsDirectory = false;
|
||||
bool m_IsSymbolicLink = false;
|
||||
bool m_IsArchive = false;
|
||||
bool m_IsReadOnly = false;
|
||||
bool m_IsHidden = false;
|
||||
bool m_IsSystem = false;
|
||||
bool m_IsExecutable = false;
|
||||
size_t m_Size = 0;
|
||||
};
|
||||
|
||||
class CEntryEnumerator : public IEntryEnumerator
|
||||
{
|
||||
public:
|
||||
explicit CEntryEnumerator(IEntryEnumeratorCallBack& rEntryEnumeratorCallBack) : m_entryEnumeratorCB(rEntryEnumeratorCallBack) {}
|
||||
void release() override { delete this; }
|
||||
protected:
|
||||
IEntryEnumeratorCallBack& m_entryEnumeratorCB;
|
||||
};
|
||||
|
||||
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
class CEntryEnumeratorLinux final : public CEntryEnumerator
|
||||
{
|
||||
public:
|
||||
CEntryEnumeratorLinux(IEntryEnumeratorCallBack& rEntryEnumeratorCallBack) : CEntryEnumerator(rEntryEnumeratorCallBack) { }
|
||||
virtual bool enumerate(const char* sWildCard, bool bRecursive=false);
|
||||
};
|
||||
|
||||
#elif defined TARGET_OS_Windows
|
||||
class CEntryEnumeratorWindows final : public CEntryEnumerator
|
||||
{
|
||||
public:
|
||||
explicit CEntryEnumeratorWindows(IEntryEnumeratorCallBack& rEntryEnumeratorCallBack) : CEntryEnumerator(rEntryEnumeratorCallBack) {}
|
||||
bool enumerate(const char* sWildCard, bool bRecursive = false) override;
|
||||
};
|
||||
|
||||
#else
|
||||
class CEntryEnumeratorDummy : public CEntryEnumerator
|
||||
{
|
||||
public:
|
||||
explicit CEntryEnumeratorDummy(IEntryEnumeratorCallBack& rEntryEnumeratorCallBack) : CEntryEnumerator(rEntryEnumeratorCallBack) { }
|
||||
virtual bool enumerate(const char* sWildCard, bool bRecursive=false) { return !sWildCard ? false : true; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
|
||||
bool CEntryEnumeratorLinux::enumerate(const char* sWildCard, bool bRecursive)
|
||||
{
|
||||
if(!sWildCard) { return false; }
|
||||
|
||||
glob_t globStruc;
|
||||
memset(&globStruc, GLOB_NOSORT, sizeof(globStruc));
|
||||
|
||||
// Glob can retrn
|
||||
switch (glob(sWildCard, 0, nullptr, &globStruc))
|
||||
{
|
||||
case GLOB_NOSPACE:
|
||||
case GLOB_ABORTED:
|
||||
return false;
|
||||
break;
|
||||
case GLOB_NOMATCH:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(globStruc.gl_pathc<=0)
|
||||
{
|
||||
// Nothing found
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t i=0;
|
||||
bool finished=false;
|
||||
while(!finished)
|
||||
{
|
||||
if(i<globStruc.gl_pathc)
|
||||
{
|
||||
char* name=globStruc.gl_pathv[i];
|
||||
CEntry entry(name);
|
||||
CAttributes att;
|
||||
|
||||
struct stat sL;
|
||||
struct stat s;
|
||||
if(!lstat(name, &sL) && !stat(name, &s))
|
||||
{
|
||||
att.m_IsDirectory = S_ISDIR(s.st_mode) ? true : false;
|
||||
att.m_IsFile = S_ISREG(s.st_mode) ? true : false;
|
||||
att.m_IsSymbolicLink = S_ISLNK(sL.st_mode) ? true : false;
|
||||
|
||||
att.m_IsArchive = false;
|
||||
att.m_IsReadOnly = s.st_mode&S_IWUSR ? false : true;
|
||||
att.m_IsHidden = false;
|
||||
att.m_IsSystem = S_ISBLK(s.st_mode)|S_ISFIFO(s.st_mode)|S_ISSOCK(s.st_mode)|S_ISCHR(s.st_mode) ? true : false;
|
||||
att.m_IsExecutable = s.st_mode&S_IXUSR ? true : false;
|
||||
|
||||
att.m_Size=s.st_size;
|
||||
|
||||
// Sends to callback
|
||||
if(!m_entryEnumeratorCB.callback(entry, att)) { finished=true; }
|
||||
}
|
||||
i++;
|
||||
}
|
||||
else { finished = true; }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif defined TARGET_OS_Windows
|
||||
|
||||
bool CEntryEnumeratorWindows::enumerate(const char* sWildCard, bool bRecursive)
|
||||
{
|
||||
if (!sWildCard || strlen(sWildCard) == 0) { return false; }
|
||||
|
||||
wchar_t wildCardUtf16[1024];
|
||||
MultiByteToWideChar(CP_UTF8, 0, sWildCard, -1, wildCardUtf16, 1024);
|
||||
|
||||
// $$$ TODO
|
||||
// $$$ Find better method to enumerate files
|
||||
// $$$ under windows including their initial path
|
||||
// $$$ (cFileName member of WIN32_FIND_DATA structure
|
||||
// $$$ loses the initial path !!)
|
||||
// $$$ TODO
|
||||
wchar_t extendedWildCard[1024];
|
||||
wchar_t* extendedWildCardFilename = nullptr;
|
||||
GetFullPathName(wildCardUtf16, 1024, extendedWildCard, &extendedWildCardFilename);
|
||||
std::wstring path(wildCardUtf16, wcslen(wildCardUtf16) - (extendedWildCardFilename ? wcslen(extendedWildCardFilename) : 0));
|
||||
|
||||
std::stack<std::wstring> foldersToEnumerate;
|
||||
foldersToEnumerate.push(path);
|
||||
|
||||
// if we need to recurse over subfolders, let's fetch all subfolders in foldersToEnumerate
|
||||
if (bRecursive)
|
||||
{
|
||||
std::stack<std::wstring> temporaryFolderSearchStack;
|
||||
temporaryFolderSearchStack.push(path);
|
||||
std::wstring currentSearchPath;
|
||||
while (! temporaryFolderSearchStack.empty())
|
||||
{
|
||||
currentSearchPath = temporaryFolderSearchStack.top();
|
||||
temporaryFolderSearchStack.pop();
|
||||
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE fileHandle;
|
||||
fileHandle = FindFirstFile((currentSearchPath + L"*").c_str(), &findData);
|
||||
if (fileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
bool finished = false;
|
||||
while (!finished)
|
||||
{
|
||||
if (std::wstring(findData.cFileName) != L"." && std::wstring(findData.cFileName) != L"..")
|
||||
{
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
foldersToEnumerate.push(currentSearchPath + findData.cFileName + L"/");
|
||||
temporaryFolderSearchStack.push(currentSearchPath + findData.cFileName + L"/");
|
||||
}
|
||||
}
|
||||
|
||||
if (!FindNextFile(fileHandle, &findData)) { finished = true; }
|
||||
}
|
||||
FindClose(fileHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
|
||||
|
||||
std::wstring currentPath;
|
||||
while (! foldersToEnumerate.empty())
|
||||
{
|
||||
currentPath = foldersToEnumerate.top();
|
||||
foldersToEnumerate.pop();
|
||||
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE fileHandle;
|
||||
fileHandle = FindFirstFile((currentPath + extendedWildCardFilename).c_str(), &findData);
|
||||
|
||||
if (fileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
bool finished = false;
|
||||
while (!finished)
|
||||
{
|
||||
std::string entryName = converter.to_bytes(currentPath + findData.cFileName);
|
||||
CEntry entry(entryName);
|
||||
CAttributes attributes;
|
||||
|
||||
attributes.m_IsDirectory = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
|
||||
attributes.m_IsFile = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? false : true;
|
||||
attributes.m_IsSymbolicLink = false;
|
||||
|
||||
attributes.m_IsArchive = (findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
|
||||
attributes.m_IsReadOnly = (findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
|
||||
attributes.m_IsHidden = (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
|
||||
attributes.m_IsSystem = (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
|
||||
attributes.m_IsExecutable = false; // TODO
|
||||
|
||||
attributes.m_Size = (findData.nFileSizeHigh << 16) + findData.nFileSizeLow;
|
||||
|
||||
// Sends to callback
|
||||
if (!m_entryEnumeratorCB.callback(entry, attributes)) { finished = true; }
|
||||
|
||||
if (!FindNextFile(fileHandle, &findData)) { finished = true; }
|
||||
}
|
||||
FindClose(fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FS_API IEntryEnumerator* createEntryEnumerator(IEntryEnumeratorCallBack& rCallBack)
|
||||
{
|
||||
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
|
||||
IEntryEnumerator* res = new CEntryEnumeratorLinux(rCallBack);
|
||||
#elif defined TARGET_OS_Windows
|
||||
IEntryEnumerator* res = new CEntryEnumeratorWindows(rCallBack);
|
||||
#else
|
||||
IEntryEnumerator* res = new CEntryEnumeratorDummy(rCallBack);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace FS
|
||||
Reference in New Issue
Block a user