changeset 547:ecf5fb9319da

Fs: switch to spaces, add FS_EXPORT
author David Demelier <markand@malikania.fr>
date Wed, 15 Jun 2016 11:59:17 +0200
parents 40c27081958a
children f48bb09bccc7
files CMakeLists.txt modules/fs/fs.cpp modules/fs/fs.hpp
diffstat 3 files changed, 243 insertions(+), 222 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Jun 14 17:04:25 2016 +0200
+++ b/CMakeLists.txt	Wed Jun 15 11:59:17 2016 +0200
@@ -19,6 +19,9 @@
 cmake_minimum_required(VERSION 3.5)
 project(code)
 
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED On)
+
 include(${code_SOURCE_DIR}/cmake/CodeDefineModule.cmake)
 
 add_subdirectory(extern)
--- a/modules/fs/fs.cpp	Tue Jun 14 17:04:25 2016 +0200
+++ b/modules/fs/fs.cpp	Wed Jun 15 11:59:17 2016 +0200
@@ -54,22 +54,22 @@
 
 std::string error()
 {
-	LPSTR error = nullptr;
-	std::string errmsg = "Unknown error";
+    LPSTR error = nullptr;
+    std::string errmsg = "Unknown error";
 
-	FormatMessageA(
-		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-		nullptr,
-		GetLastError(),
-		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		(LPSTR)&error, 0, nullptr);
+    FormatMessageA(
+        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+        nullptr,
+        GetLastError(),
+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+        (LPSTR)&error, 0, nullptr);
 
-	if (error) {
-		errmsg = std::string(error);
-		LocalFree(error);
-	}
+    if (error) {
+        errmsg = std::string(error);
+        LocalFree(error);
+    }
 
-	return errmsg;
+    return errmsg;
 }
 
 #endif
@@ -82,17 +82,17 @@
  */
 bool hasAccess(const std::string &path, const std::string &mode)
 {
-	assert(mode.length() == 1);
-	assert(mode[0] == 'r' || mode[0] == 'w');
+    assert(mode.length() == 1);
+    assert(mode[0] == 'r' || mode[0] == 'w');
 
-	auto fp = std::fopen(path.c_str(), mode.c_str());
+    auto fp = std::fopen(path.c_str(), mode.c_str());
 
-	if (fp == nullptr)
-		return false;
+    if (fp == nullptr)
+        return false;
 
-	std::fclose(fp);
+    std::fclose(fp);
 
-	return true;
+    return true;
 }
 
 /*
@@ -110,12 +110,12 @@
 template <typename Predicate>
 bool typeOf(const std::string &path, Predicate &&predicate)
 {
-	DWORD result = GetFileAttributesA(path.c_str());
+    DWORD result = GetFileAttributesA(path.c_str());
 
-	if (result == INVALID_FILE_ATTRIBUTES)
-		return false;
+    if (result == INVALID_FILE_ATTRIBUTES)
+        return false;
 
-	return predicate(result);
+    return predicate(result);
 }
 
 #elif defined(FS_HAVE_STAT)
@@ -123,12 +123,12 @@
 template <typename Predicate>
 bool typeOf(const std::string &path, Predicate &&predicate) noexcept
 {
-	struct stat st;
+    struct stat st;
 
-	if (::stat(path.c_str(), &st) < 0)
-		return false;
+    if (::stat(path.c_str(), &st) < 0)
+        return false;
 
-	return predicate(st);
+    return predicate(st);
 }
 
 #else
@@ -136,7 +136,7 @@
 template <typename Predicate>
 bool typeOf(const std::string &path, Predicate &&predicate) noexcept
 {
-	throw std::runtime_error(std::strerror(ENOSYS));
+    throw std::runtime_error(std::strerror(ENOSYS));
 }
 
 #endif
@@ -149,28 +149,28 @@
  */
 std::string clean(std::string input)
 {
-	if (input.empty())
-		return input;
+    if (input.empty())
+        return input;
 
-	/* First, remove any duplicates */
-	input.erase(std::unique(input.begin(), input.end(), [&] (char c1, char c2) {
-		return c1 == c2 && (c1 == '/' || c1 == '\\');
-	}), input.end());
+    // First, remove any duplicates.
+    input.erase(std::unique(input.begin(), input.end(), [&] (char c1, char c2) {
+        return c1 == c2 && (c1 == '/' || c1 == '\\');
+    }), input.end());
 
-	/* Add a trailing / or \\ */
-	char c = input[input.length() - 1];
+    // Add a trailing / or \\.
+    char c = input[input.length() - 1];
 
-	if (c != '/' && c != '\\')
-		input += separator();
+    if (c != '/' && c != '\\')
+        input += separator();
 
-	/* Now converts all / to \\ for Windows and the opposite for Unix */
+    // Now converts all / to \\ for Windows and the opposite for Unix.
 #if defined(_WIN32)
-	std::replace(input.begin(), input.end(), '/', '\\');
+    std::replace(input.begin(), input.end(), '/', '\\');
 #else
-	std::replace(input.begin(), input.end(), '\\', '/');
+    std::replace(input.begin(), input.end(), '\\', '/');
 #endif
 
-	return input;
+    return input;
 }
 
 /*
@@ -179,12 +179,12 @@
  */
 std::string baseName(std::string path)
 {
-	auto pos = path.find_last_of("\\/");
+    auto pos = path.find_last_of("\\/");
 
-	if (pos != std::string::npos)
-		path = path.substr(pos + 1);
+    if (pos != std::string::npos)
+        path = path.substr(pos + 1);
 
-	return path;
+    return path;
 }
 
 /*
@@ -193,14 +193,14 @@
  */
 std::string dirName(std::string path)
 {
-	auto pos = path.find_last_of("\\/");
+    auto pos = path.find_last_of("\\/");
 
-	if (pos == std::string::npos)
-		path = ".";
-	else
-		path = path.substr(0, pos);
+    if (pos == std::string::npos)
+        path = ".";
+    else
+        path = path.substr(0, pos);
 
-	return path;
+    return path;
 }
 
 /*
@@ -210,9 +210,9 @@
 bool isAbsolute(const std::string &path) noexcept
 {
 #if defined(_WIN32)
-	return !isRelative(path);
+    return !isRelative(path);
 #else
-	return path.size() > 0 && path[0] == '/';
+    return path.size() > 0 && path[0] == '/';
 #endif
 }
 
@@ -223,9 +223,9 @@
 bool isRelative(const std::string &path) noexcept
 {
 #if defined(_WIN32)
-	return PathIsRelativeA(path.c_str()) == 1;
+    return PathIsRelativeA(path.c_str()) == 1;
 #else
-	return !isAbsolute(path);
+    return !isAbsolute(path);
 #endif
 }
 
@@ -235,7 +235,7 @@
  */
 bool isReadable(const std::string &path) noexcept
 {
-	return hasAccess(path, "r");
+    return hasAccess(path, "r");
 }
 
 /*
@@ -244,7 +244,7 @@
  */
 bool isWritable(const std::string &path) noexcept
 {
-	return hasAccess(path, "w");
+    return hasAccess(path, "w");
 }
 
 /*
@@ -253,13 +253,13 @@
  */
 bool isFile(const std::string &path)
 {
-	return typeOf(path, [] (const auto &object) {
+    return typeOf(path, [] (const auto &object) {
 #if defined(_WIN32)
-		return (object & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE;
+        return (object & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE;
 #elif defined(FS_HAVE_STAT)
-		return S_ISREG(object.st_mode);
+        return S_ISREG(object.st_mode);
 #endif
-	});
+    });
 }
 
 /*
@@ -268,13 +268,13 @@
  */
 bool isDirectory(const std::string &path)
 {
-	return typeOf(path, [] (const auto &object) {
+    return typeOf(path, [] (const auto &object) {
 #if defined(_WIN32)
-		return (object & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
+        return (object & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
 #elif defined(FS_HAVE_STAT)
-		return S_ISDIR(object.st_mode);
+        return S_ISDIR(object.st_mode);
 #endif
-	});
+    });
 }
 
 /*
@@ -283,13 +283,13 @@
  */
 bool isSymlink(const std::string &path)
 {
-	return typeOf(path, [] (const auto &object) {
+    return typeOf(path, [] (const auto &object) {
 #if defined(_WIN32)
-		return (object & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT;
+        return (object & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT;
 #elif defined(FS_HAVE_STAT)
-		return S_ISLNK(object.st_mode);
+        return S_ISLNK(object.st_mode);
 #endif
-	});
+    });
 }
 
 /*
@@ -300,12 +300,12 @@
 
 struct stat stat(const std::string &path)
 {
-	struct stat st;
+    struct stat st;
 
-	if (::stat(path.c_str(), &st) < 0)
-		throw std::runtime_error(std::strerror(errno));
+    if (::stat(path.c_str(), &st) < 0)
+        throw std::runtime_error(std::strerror(errno));
 
-	return st;
+    return st;
 }
 
 #endif
@@ -317,11 +317,11 @@
 bool exists(const std::string &path) noexcept
 {
 #if defined(FS_HAVE_STAT)
-	struct stat st;
+    struct stat st;
 
-	return ::stat(path.c_str(), &st) == 0;
+    return ::stat(path.c_str(), &st) == 0;
 #else
-	return  hasAccess(path, "r");
+    return  hasAccess(path, "r");
 #endif
 }
 
@@ -331,84 +331,84 @@
  */
 std::vector<Entry> readdir(const std::string &path, int flags)
 {
-	std::vector<Entry> entries;
+    std::vector<Entry> entries;
 
 #if defined(_WIN32)
-	std::ostringstream oss;
-	HANDLE handle;
-	WIN32_FIND_DATA fdata;
+    std::ostringstream oss;
+    HANDLE handle;
+    WIN32_FIND_DATA fdata;
 
-	oss << path << "\\*";
-	handle = FindFirstFile(oss.str().c_str(), &fdata);
+    oss << path << "\\*";
+    handle = FindFirstFile(oss.str().c_str(), &fdata);
 
-	if (handle == nullptr)
-		throw std::runtime_error(error());
+    if (handle == nullptr)
+        throw std::runtime_error(error());
 
-	do {
-		Entry entry;
+    do {
+        Entry entry;
 
-		entry.name = fdata.cFileName;
+        entry.name = fdata.cFileName;
 
-		if (entry.name == "." && !(flags & Dot))
-			continue;
-		if (entry.name == ".." && !(flags & DotDot))
-			continue;
+        if (entry.name == "." && !(flags & Dot))
+            continue;
+        if (entry.name == ".." && !(flags & DotDot))
+            continue;
 
-		switch (fdata.dwFileAttributes) {
-		case FILE_ATTRIBUTE_DIRECTORY:
-			entry.type = Entry::Dir;
-			break;
-		case FILE_ATTRIBUTE_NORMAL:
-			entry.type = Entry::File;
-			break;
-		case FILE_ATTRIBUTE_REPARSE_POINT:
-			entry.type = Entry::Link;
-			break;
-		default:
-			break;
-		}
+        switch (fdata.dwFileAttributes) {
+        case FILE_ATTRIBUTE_DIRECTORY:
+            entry.type = Entry::Dir;
+            break;
+        case FILE_ATTRIBUTE_NORMAL:
+            entry.type = Entry::File;
+            break;
+        case FILE_ATTRIBUTE_REPARSE_POINT:
+            entry.type = Entry::Link;
+            break;
+        default:
+            break;
+        }
 
-		entries.push_back(std::move(entry));
-	} while (FindNextFile(handle, &fdata) != 0);
+        entries.push_back(std::move(entry));
+    } while (FindNextFile(handle, &fdata) != 0);
 
-	FindClose(handle);
+    FindClose(handle);
 #else
-	DIR *dp;
-	struct dirent *ent;
+    DIR *dp;
+    struct dirent *ent;
 
-	if ((dp = opendir(path.c_str())) == nullptr)
-		throw std::runtime_error(std::strerror(errno));
+    if ((dp = opendir(path.c_str())) == nullptr)
+        throw std::runtime_error(std::strerror(errno));
 
-	while ((ent = readdir(dp)) != nullptr) {
-		Entry entry;
+    while ((ent = readdir(dp)) != nullptr) {
+        Entry entry;
 
-		entry.name = ent->d_name;
-		if (entry.name == "." && !(flags & Dot))
-			continue;
-		if (entry.name == ".." && !(flags & DotDot))
-			continue;
+        entry.name = ent->d_name;
+        if (entry.name == "." && !(flags & Dot))
+            continue;
+        if (entry.name == ".." && !(flags & DotDot))
+            continue;
 
-		switch (ent->d_type) {
-		case DT_DIR:
-			entry.type = Entry::Dir;
-			break;
-		case DT_REG:
-			entry.type = Entry::File;
-			break;
-		case DT_LNK:
-			entry.type = Entry::Link;
-			break;
-		default:
-			break;
-		}
+        switch (ent->d_type) {
+        case DT_DIR:
+            entry.type = Entry::Dir;
+            break;
+        case DT_REG:
+            entry.type = Entry::File;
+            break;
+        case DT_LNK:
+            entry.type = Entry::Link;
+            break;
+        default:
+            break;
+        }
 
-		entries.push_back(std::move(entry));
-	}
+        entries.push_back(std::move(entry));
+    }
 
-	closedir(dp);
+    closedir(dp);
 #endif
 
-	return entries;
+    return entries;
 }
 
 /*
@@ -417,28 +417,28 @@
  */
 void mkdir(const std::string &path, int mode)
 {
-	std::string::size_type next = 0;
-	std::string part;
+    std::string::size_type next = 0;
+    std::string part;
 
-	for (;;) {
-		next = path.find_first_of("\\/", next);
-		part = path.substr(0, next);
+    for (;;) {
+        next = path.find_first_of("\\/", next);
+        part = path.substr(0, next);
 
-		if (!part.empty()) {
+        if (!part.empty()) {
 #if defined(_WIN32)
-			(void)mode;
+            (void)mode;
 
-			if (::_mkdir(part.c_str()) < 0 && errno != EEXIST)
-				throw std::runtime_error(std::strerror(errno));
+            if (::_mkdir(part.c_str()) < 0 && errno != EEXIST)
+                throw std::runtime_error(std::strerror(errno));
 #else
-			if (::mkdir(part.c_str(), mode) < 0 && errno != EEXIST)
-				throw std::runtime_error(std::strerror(errno));
+            if (::mkdir(part.c_str(), mode) < 0 && errno != EEXIST)
+                throw std::runtime_error(std::strerror(errno));
 #endif
-		}
+        }
 
-		if (next++ == std::string::npos)
-			break;
-	}
+        if (next++ == std::string::npos)
+            break;
+    }
 }
 
 /*
@@ -447,23 +447,23 @@
  */
 void rmdir(const std::string &base) noexcept
 {
-	try {
-		for (const auto &entry : readdir(base)) {
-			std::string path = base + separator() + entry.name;
+    try {
+        for (const auto &entry : readdir(base)) {
+            std::string path = base + separator() + entry.name;
 
-			if (entry.type == Entry::Dir)
-				rmdir(path);
-			else
-				remove(path.c_str());
-		}
-	} catch (...) {
-		/* Silently discard to remove as much as possible */
-	}
+            if (entry.type == Entry::Dir)
+                rmdir(path);
+            else
+                ::remove(path.c_str());
+        }
+    } catch (...) {
+        // Silently discard to remove as much as possible.
+    }
 
 #if defined(_WIN32)
-	RemoveDirectoryA(base.c_str());
+    ::RemoveDirectoryA(base.c_str());
 #else
-	remove(base.c_str());
+    ::remove(base.c_str());
 #endif
 }
 
@@ -474,19 +474,19 @@
 std::string cwd()
 {
 #if defined(_WIN32)
-	char path[MAX_PATH];
+    char path[MAX_PATH];
 
-	if (!GetCurrentDirectoryA(sizeof (path), path))
-		throw std::runtime_error("failed to get current working directory");
+    if (!::GetCurrentDirectoryA(sizeof (path), path))
+        throw std::runtime_error("failed to get current working directory");
 
-	return path;
+    return path;
 #else
-	char path[PATH_MAX];
+    char path[PATH_MAX];
 
-	if (getcwd(path, sizeof (path)) == nullptr)
-		throw std::runtime_error{std::strerror(errno)};
+    if (::getcwd(path, sizeof (path)) == nullptr)
+        throw std::runtime_error{std::strerror(errno)};
 
-	return path;
+    return path;
 #endif
 }
 
--- a/modules/fs/fs.hpp	Tue Jun 14 17:04:25 2016 +0200
+++ b/modules/fs/fs.hpp	Wed Jun 15 11:59:17 2016 +0200
@@ -28,11 +28,20 @@
  * \page filesystem Filesystem
  * \brief Filesystem support
  *
+ * ## Options
+ *
  * The following options can be set by the user:
  *
  *   - **FS_HAVE_STAT**: (bool) Set to true if sys/stat.h and stat function are available, automatically detected.
- *   - **FS_BUILDING_DLL**: (bool) Set to true if building this code as DLL, see also FS_EXPORT,
- *   - **FS_EXPORT**: (unspecified) Attribute to export symbols, __declspec(dllexport) on Windows if FS_BUILDING_DLL is set.
+ *
+ * ## Export macros
+ *
+ * You must define `FS_DLL` globally and `FS_BUILDING_DLL` when compiling the library if you want a DLL, alternatively you can provide
+ * your own `FS_EXPORT` macro instead.
+ */
+
+/**
+ * \cond FS_HIDDEN_SYMBOLS
  */
 
 #if !defined(FS_HAVE_STAT)
@@ -47,17 +56,26 @@
 #  endif
 #endif
 
-/**
- * \brief DLL export.
- */
 #if !defined(FS_EXPORT)
-#  if defined(FS_BUILDING_DLL) && defined(_WIN32)
-#    define FS_EXPORT __declspec(dllexport)
+#  if defined(FS_DLL)
+#    if defined(_WIN32)
+#      if defined(FS_BUILDING_DLL)
+#        define FS_EXPORT __declspec(dllexport)
+#      else
+#        define FS_EXPORT __declspec(dllimport)
+#      endif
+#    else
+#      define FS_EXPORT
+#    endif
 #  else
 #    define FS_EXPORT
 #  endif
 #endif
 
+/**
+ * \endcond
+ */
+
 #if defined(FS_HAVE_STAT)
 #  include <sys/stat.h>
 #endif
@@ -76,8 +94,8 @@
  * \brief Flags for readdir.
  */
 enum Flags {
-	Dot	= (1 << 0),	//!< if set, also lists "."
-	DotDot	= (1 << 1)	//!< if set, also lists ".."
+    Dot     = (1 << 0),     //!< if set, also lists "."
+    DotDot  = (1 << 1)      //!< if set, also lists ".."
 };
 
 /**
@@ -86,18 +104,18 @@
  */
 class Entry {
 public:
-	/**
-	 * \brief Describe the type of an entry
-	 */
-	enum Type : char {
-		Unknown,	//!< File type is unknown,
-		File,		//!< File is regular type,
-		Dir,		//!< File is directory,
-		Link		//!< File is link
-	};
+    /**
+     * \brief Describe the type of an entry
+     */
+    enum Type : char {
+        Unknown,            //!< File type is unknown,
+        File,               //!< File is regular type,
+        Dir,                //!< File is directory,
+        Link                //!< File is link
+    };
 
-	std::string name;	//!< name of entry (base name)
-	Type type{Unknown};	//!< type of file
+    std::string name;       //!< name of entry (base name)
+    Type type{Unknown};     //!< type of file
 };
 
 /**
@@ -109,7 +127,7 @@
  */
 inline bool operator==(const Entry &e1, const Entry &e2) noexcept
 {
-	return e1.name == e2.name && e1.type == e2.type;
+    return e1.name == e2.name && e1.type == e2.type;
 }
 
 /**
@@ -121,7 +139,7 @@
  */
 inline bool operator!=(const Entry &e1, const Entry &e2) noexcept
 {
-	return !(e1 == e2);
+    return !(e1 == e2);
 }
 
 /**
@@ -132,9 +150,9 @@
 inline char separator() noexcept
 {
 #if defined(_WIN32)
-	return '\\';
+    return '\\';
 #else
-	return '/';
+    return '/';
 #endif
 }
 
@@ -281,7 +299,7 @@
  * Search an item recursively.
  *
  * The predicate must have the following signature:
- *	void f(const std::string &base, const Entry &entry)
+ *  void f(const std::string &base, const Entry &entry)
  *
  * Where:
  *   - base is the current parent directory in the tree
@@ -295,34 +313,34 @@
 template <typename Predicate>
 std::string findIf(const std::string &base, Predicate &&predicate)
 {
-	/*
-	 * Do not go deeply to the tree before testing all files in the current directory for performances reasons, we iterate
-	 * this directory to search for the entry name and iterate again over all sub directories if not found.
-	 */
-	std::string path;
-	std::vector<Entry> entries = readdir(base);
+    /*
+     * Do not go deeply to the tree before testing all files in the current directory for performances reasons, we iterate
+     * this directory to search for the entry name and iterate again over all sub directories if not found.
+     */
+    std::string path;
+    std::vector<Entry> entries = readdir(base);
 
-	for (const auto &entry : entries) {
-		if (predicate(base, entry)) {
-			path = base + separator() + entry.name;
-			break;
-		}
-	}
+    for (const auto &entry : entries) {
+        if (predicate(base, entry)) {
+            path = base + separator() + entry.name;
+            break;
+        }
+    }
 
-	if (!path.empty())
-		return path;
+    if (!path.empty())
+        return path;
 
-	for (const auto &entry : entries) {
-		if (entry.type != Entry::Dir)
-			continue;
+    for (const auto &entry : entries) {
+        if (entry.type != Entry::Dir)
+            continue;
 
-		path = findIf(base + separator() + entry.name, std::forward<Predicate>(predicate));
+        path = findIf(base + separator() + entry.name, std::forward<Predicate>(predicate));
 
-		if (!path.empty())
-			break;
-	}
+        if (!path.empty())
+            break;
+    }
 
-	return path;
+    return path;
 }
 
 /**
@@ -335,7 +353,7 @@
  */
 inline std::string find(const std::string &base, const std::string &name)
 {
-	return findIf(base, [&] (const auto &, const auto &entry) { return entry.name == name; });
+    return findIf(base, [&] (const auto &, const auto &entry) { return entry.name == name; });
 }
 
 /**
@@ -348,7 +366,7 @@
  */
 inline std::string find(const std::string &base, const std::regex &regex)
 {
-	return findIf(base, [&] (const auto &, const auto &entry) { return std::regex_match(entry.name, regex); });
+    return findIf(base, [&] (const auto &, const auto &entry) { return std::regex_match(entry.name, regex); });
 }
 
 /**