Aging_MouthReplace / dlibs /dlib /dir_nav /dir_nav_kernel_1.h
AshanGimhana's picture
Upload folder using huggingface_hub
9375c9a verified
raw
history blame
18.3 kB
// Copyright (C) 2003 Davis E. King ([email protected])
// 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_