summaryrefslogtreecommitdiffstats
path: root/src/ml/dlib/dlib/dir_nav/dir_nav_kernel_1.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ml/dlib/dlib/dir_nav/dir_nav_kernel_1.h')
-rw-r--r--src/ml/dlib/dlib/dir_nav/dir_nav_kernel_1.h634
1 files changed, 634 insertions, 0 deletions
diff --git a/src/ml/dlib/dlib/dir_nav/dir_nav_kernel_1.h b/src/ml/dlib/dlib/dir_nav/dir_nav_kernel_1.h
new file mode 100644
index 000000000..a31f689de
--- /dev/null
+++ b/src/ml/dlib/dlib/dir_nav/dir_nav_kernel_1.h
@@ -0,0 +1,634 @@
+// Copyright (C) 2003 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#ifndef DLIB_DIR_NAV_KERNEl_1_
+#define DLIB_DIR_NAV_KERNEl_1_
+
+#ifdef DLIB_ISO_CPP_ONLY
+#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it."
+#endif
+
+#include "../platform.h"
+
+
+#include "dir_nav_kernel_abstract.h"
+#include <string>
+#include "../uintn.h"
+#include "../algs.h"
+
+#include "../windows_magic.h"
+#include <windows.h>
+#include <vector>
+#include "../stl_checked.h"
+#include "../enable_if.h"
+#include "../queue.h"
+#include <chrono>
+
+namespace dlib
+{
+
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+ // file object
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ class file
+ {
+ /*!
+ INITIAL VALUES
+ state.name == name()
+ state.full_name == full_name()
+ state.file_size == size()
+ state.last_modified == last_modified()
+
+ CONVENTION
+ state.name == name()
+ state.full_name == full_name()
+ state.file_size == size()
+ state.last_modified == last_modified()
+
+ !*/
+
+ friend class directory;
+
+ struct data
+ {
+ uint64 file_size;
+ std::string name;
+ std::string full_name;
+ std::chrono::time_point<std::chrono::system_clock> last_modified;
+ };
+
+
+ void init ( const std::string& name);
+
+ public:
+
+ struct private_constructor{};
+ inline file (
+ const std::string& name,
+ const std::string& full_name,
+ const uint64 file_size,
+ const std::chrono::time_point<std::chrono::system_clock>& last_modified,
+ private_constructor
+ )
+ {
+ state.file_size = file_size;
+ state.name = name;
+ state.full_name = full_name;
+ state.last_modified = last_modified;
+ }
+
+
+
+
+ class file_not_found : public error {
+ public: file_not_found(const std::string& s): error(s){}
+ };
+
+ inline file (
+ )
+ {
+ state.file_size = 0;
+ }
+
+ file (
+ const std::string& name
+ ) { init(name); }
+
+ file (
+ const char* name
+ ) { init(name); }
+
+ inline const std::string& name (
+ ) const { return state.name; }
+
+ inline const std::string& full_name (
+ ) const { return state.full_name; }
+
+ operator std::string (
+ ) const { return full_name(); }
+
+ inline uint64 size (
+ ) const { return state.file_size; }
+
+ inline std::chrono::time_point<std::chrono::system_clock> last_modified (
+ ) const { return state.last_modified; }
+
+ bool operator == (
+ const file& rhs
+ ) const;
+
+ bool operator != (
+ const file& rhs
+ ) const { return !(*this == rhs); }
+
+ inline bool operator < (
+ const file& item
+ ) const { return full_name() < item.full_name(); }
+
+ inline void swap (
+ file& item
+ )
+ {
+ exchange(state,item.state);
+ }
+
+ private:
+
+ data state;
+
+ };
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+ // directory object
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ class directory
+ {
+ /*!
+ INITIAL VALUES
+ state.name == name()
+ state.full_name == full_name()
+
+ CONVENTION
+ state.name == name()
+ state.full_name == full_name()
+ is_root() == state.name.size() == 0
+
+ !*/
+
+ void init (const std::string& name);
+
+ public:
+
+ struct data
+ {
+ std::string name;
+ std::string full_name;
+ };
+
+
+ /*
+ The reason we don't just make this constructor actually
+ private is because doing it this way avoids a bug that
+ sometimes occurs in visual studio 7.1. The bug has
+ something to do with templated friend functions
+ such as the get_filesystem_roots() function below if
+ it was declared as a friend template of this class.
+ */
+ struct private_constructor{};
+ inline directory (
+ const std::string& name,
+ const std::string& full_name,
+ private_constructor
+ )
+ {
+ state.name = name;
+ state.full_name = full_name;
+ }
+
+
+ class dir_not_found : public error {
+ public: dir_not_found(const std::string& s):error(s){}
+ };
+ class listing_error : public error {
+ public: listing_error(const std::string& s):error(s){}
+ };
+
+ inline directory (
+ )
+ {
+ }
+
+ directory (
+ const std::string& name
+ ) { init(name); }
+
+ directory (
+ const char* name
+ ) { init(name); }
+
+
+ static char get_separator (
+ );
+
+
+ template <
+ typename queue_of_files
+ >
+ void get_files (
+ queue_of_files& files
+ ) const;
+
+ template <
+ typename queue_of_dirs
+ >
+ void get_dirs (
+ queue_of_dirs& dirs
+ ) const;
+
+ std::vector<file> get_files (
+ ) const
+ {
+ std::vector<file> temp_vector;
+ get_files(temp_vector);
+ return temp_vector;
+ }
+
+ std::vector<directory> get_dirs (
+ ) const
+ {
+ std::vector<directory> temp_vector;
+ get_dirs(temp_vector);
+ return temp_vector;
+ }
+
+ const directory get_parent (
+ ) const;
+
+ inline bool is_root (
+ ) const { return state.name.size() == 0; }
+
+ inline const std::string& name (
+ ) const { return state.name; }
+
+ inline const std::string& full_name (
+ ) const { return state.full_name; }
+
+ operator std::string (
+ ) const { return full_name(); }
+
+ bool operator == (
+ const directory& rhs
+ ) const;
+
+ bool operator != (
+ const directory& rhs
+ ) const { return !(*this == rhs); }
+
+ inline bool operator < (
+ const directory& item
+ ) const { return full_name() < item.full_name(); }
+
+ inline void swap (
+ directory& item
+ )
+ {
+ exchange(state,item.state);
+ }
+
+ private:
+
+ // member data
+ data state;
+
+ bool is_root_path (
+ const std::string& path
+ ) const;
+ /*!
+ ensures
+ - returns true if path is a root path.
+ Note that this function considers root paths that don't
+ have a trailing separator to also be valid.
+ !*/
+
+
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ inline std::ostream& operator<< (
+ std::ostream& out,
+ const directory& item
+ ) { out << (std::string)item; return out; }
+
+ inline std::ostream& operator<< (
+ std::ostream& out,
+ const file& item
+ ) { out << (std::string)item; return out; }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename queue_of_dir
+ >
+ typename disable_if<is_std_vector<queue_of_dir>,void>::type get_filesystem_roots (
+ queue_of_dir& roots
+ )
+ {
+ roots.clear();
+ const DWORD mask = GetLogicalDrives();
+ DWORD bit = 1;
+ char buf[] = "A:\\";
+
+ do
+ {
+ if (mask & bit)
+ {
+ directory dir("",buf,directory::private_constructor());
+ roots.enqueue(dir);
+ }
+ bit <<= 1;
+ ++buf[0];
+ } while (buf[0] != 'Z');
+ }
+
+ template <
+ typename queue_of_dir
+ >
+ typename enable_if<is_std_vector<queue_of_dir>,void>::type get_filesystem_roots (
+ queue_of_dir& roots
+ )
+ {
+ roots.clear();
+ const DWORD mask = GetLogicalDrives();
+ DWORD bit = 1;
+ char buf[] = "A:\\";
+
+ do
+ {
+ if (mask & bit)
+ {
+ directory dir("",buf,directory::private_constructor());
+ roots.push_back(dir);
+ }
+ bit <<= 1;
+ ++buf[0];
+ } while (buf[0] != 'Z');
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void swap (
+ file& a,
+ file& b
+ ) { a.swap(b); }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void swap (
+ directory& a,
+ directory& b
+ ) { a.swap(b); }
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+ // templated member function definitions
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename queue_of_files
+ >
+ typename disable_if<is_std_vector<queue_of_files>,void>::type
+ directory_helper_get_files (
+ const directory::data& state,
+ queue_of_files& files
+ )
+ {
+ using namespace std;
+ typedef directory::listing_error listing_error;
+ typedef file::private_constructor private_constructor;
+
+ files.clear();
+ if (state.full_name.size() == 0)
+ throw listing_error("This directory object currently doesn't represent any directory.");
+
+ HANDLE ffind = INVALID_HANDLE_VALUE;
+ try
+ {
+ WIN32_FIND_DATAA data;
+ string path = state.full_name;
+ // ensure that the path ends with a separator
+ if (path[path.size()-1] != directory::get_separator())
+ path += directory::get_separator();
+
+ ffind = FindFirstFileA((path+"*").c_str(), &data);
+ if (ffind == INVALID_HANDLE_VALUE)
+ {
+ throw listing_error("Unable to list the contents of " + state.full_name);
+ }
+
+
+ bool no_more_files = false;
+ do
+ {
+ if ((data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) == 0)
+ {
+ uint64 file_size = data.nFileSizeHigh;
+ file_size <<= 32;
+ file_size |= data.nFileSizeLow;
+
+ ULARGE_INTEGER ull;
+ ull.LowPart = data.ftLastWriteTime.dwLowDateTime;
+ ull.HighPart = data.ftLastWriteTime.dwHighDateTime;
+ std::chrono::nanoseconds epoch(100 * (ull.QuadPart - 116444736000000000));
+ auto last_modified = std::chrono::time_point<std::chrono::system_clock>(std::chrono::duration_cast<std::chrono::system_clock::duration>(epoch));
+
+ // this is a file so add it to the queue
+ file temp(data.cFileName,path+data.cFileName,file_size, last_modified, private_constructor());
+ files.enqueue(temp);
+ }
+
+ if (FindNextFileA(ffind,&data) == 0)
+ {
+ // an error occurred
+ if ( GetLastError() == ERROR_NO_MORE_FILES)
+ {
+ // there are no more files
+ no_more_files = true;
+ }
+ else
+ {
+ // there was an error
+ throw listing_error("Unable to list the contents of " + state.full_name);
+ }
+ }
+ } while (no_more_files == false);
+
+ FindClose(ffind);
+ ffind = INVALID_HANDLE_VALUE;
+ }
+ catch (...)
+ {
+ if (ffind != INVALID_HANDLE_VALUE)
+ FindClose(ffind);
+ files.clear();
+ throw;
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename queue_of_files
+ >
+ typename enable_if<is_std_vector<queue_of_files>,void>::type
+ directory_helper_get_files (
+ const directory::data& state,
+ queue_of_files& files
+ )
+ {
+ queue<file>::kernel_2a temp_files;
+ directory_helper_get_files(state,temp_files);
+
+ files.clear();
+
+ // copy the queue of files into the vector
+ temp_files.reset();
+ while (temp_files.move_next())
+ {
+ files.push_back(temp_files.element());
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename queue_of_files
+ >
+ void directory::
+ get_files (
+ queue_of_files& files
+ ) const
+ {
+ // the reason for this indirection here is because it avoids a bug in
+ // the mingw version of gcc
+ directory_helper_get_files(state,files);
+ }
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename queue_of_dirs
+ >
+ typename disable_if<is_std_vector<queue_of_dirs>,void>::type
+ directory_helper_get_dirs (
+ const directory::data& state,
+ queue_of_dirs& dirs
+ )
+ {
+ using namespace std;
+ typedef directory::listing_error listing_error;
+ typedef directory::private_constructor private_constructor;
+
+ dirs.clear();
+ if (state.full_name.size() == 0)
+ throw listing_error("This directory object currently doesn't represent any directory.");
+
+ HANDLE dfind = INVALID_HANDLE_VALUE;
+ try
+ {
+ WIN32_FIND_DATAA data;
+ string path = state.full_name;
+ // ensure that the path ends with a separator
+ if (path[path.size()-1] != directory::get_separator())
+ path += directory::get_separator();
+
+ dfind = FindFirstFileA((path+"*").c_str(), &data);
+ if (dfind == INVALID_HANDLE_VALUE)
+ {
+ throw listing_error("Unable to list the contents of " + state.full_name);
+ }
+
+
+ bool no_more_files = false;
+ do
+ {
+ string tname(data.cFileName);
+ if ((data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) != 0 &&
+ tname != "." &&
+ tname != "..")
+ {
+ // this is a directory so add it to the queue
+ directory temp(tname,path+tname,private_constructor());
+ dirs.enqueue(temp);
+ }
+
+ if (FindNextFileA(dfind,&data) == 0)
+ {
+ // an error occurred
+ if ( GetLastError() == ERROR_NO_MORE_FILES)
+ {
+ // there are no more files
+ no_more_files = true;
+ }
+ else
+ {
+ // there was an error
+ throw listing_error("Unable to list the contents of " + state.full_name);
+ }
+ }
+ } while (no_more_files == false);
+
+ FindClose(dfind);
+ dfind = INVALID_HANDLE_VALUE;
+ }
+ catch (...)
+ {
+ if (dfind != INVALID_HANDLE_VALUE)
+ FindClose(dfind);
+ dirs.clear();
+ throw;
+ }
+
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename queue_of_dirs
+ >
+ typename enable_if<is_std_vector<queue_of_dirs>,void>::type
+ directory_helper_get_dirs (
+ const directory::data& state,
+ queue_of_dirs& dirs
+ )
+ {
+ queue<directory>::kernel_2a temp_dirs;
+ directory_helper_get_dirs(state,temp_dirs);
+
+ dirs.clear();
+
+ // copy the queue of dirs into the vector
+ temp_dirs.reset();
+ while (temp_dirs.move_next())
+ {
+ dirs.push_back(temp_dirs.element());
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename queue_of_dirs
+ >
+ void directory::
+ get_dirs (
+ queue_of_dirs& dirs
+ ) const
+ {
+ // the reason for this indirection here is because it avoids a bug in
+ // the mingw version of gcc
+ directory_helper_get_dirs(state,dirs);
+ }
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+}
+
+
+#ifdef NO_MAKEFILE
+#include "dir_nav_kernel_1.cpp"
+#endif
+
+#endif // DLIB_DIR_NAV_KERNEl_1_
+