-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdata.h
165 lines (150 loc) · 6.86 KB
/
data.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright (c) 2023 Christopher Antos
// License: http://opensource.org/licenses/MIT
// Node represents a directory or file.
//
// DirNode contains other DirNode and FileNode instances.
// Querying and adding children are threadsafe operations.
//
// FileNode contains info about the file.
#pragma once
#include <memory>
#include <mutex>
#include <vector>
#undef GetFreeSpace
class DirNode;
class FileNode;
class RecycleBinNode;
class FreeSpaceNode;
class DriveNode;
#ifdef DEBUG
LONG CountNodes();
bool SetFake(bool fake);
#endif
class Node : public std::enable_shared_from_this<Node>
{
public:
Node(const WCHAR* name, const std::shared_ptr<DirNode>& parent);
virtual ~Node();
std::shared_ptr<DirNode> GetParent() const { return m_parent.lock(); }
bool IsParentFinished() const;
const WCHAR* GetName() const { return m_name.c_str(); }
void GetFullPath(std::wstring& out) const;
virtual DirNode* AsDir() { return nullptr; }
virtual const DirNode* AsDir() const { return nullptr; }
virtual FileNode* AsFile() { return nullptr; }
virtual const FileNode* AsFile() const { return nullptr; }
virtual RecycleBinNode* AsRecycleBin() { return nullptr; }
virtual const RecycleBinNode* AsRecycleBin() const { return nullptr; }
virtual const FreeSpaceNode* AsFreeSpace() const { return nullptr; }
virtual DriveNode* AsDrive() { return nullptr; }
virtual const DriveNode* AsDrive() const { return nullptr; }
void SetCompressed(bool compressed=true) { m_compressed = compressed; }
bool IsCompressed() const { return m_compressed; }
void SetSparse(bool sparse=true) { m_sparse = sparse; }
bool IsSparse() const { return m_sparse; }
virtual bool IsRecycleBin() const { return false; }
virtual bool IsDrive() const { return false; }
#ifdef DEBUG
bool IsFake() const { return m_fake; }
#endif
protected:
const std::weak_ptr<DirNode> m_parent;
const std::wstring m_name;
bool m_compressed = false;
bool m_sparse = false;
#ifdef DEBUG
const bool m_fake = false;
#endif
};
class DirNode : public Node
{
public:
DirNode(const WCHAR* name) : Node(name, nullptr) {}
DirNode(const WCHAR* name, const std::shared_ptr<DirNode>& parent) : Node(name, parent) {}
DirNode* AsDir() override { return this; }
const DirNode* AsDir() const override { return this; }
ULONGLONG CountDirs(bool include_recycle=false) const { return m_count_dirs + (include_recycle && GetRecycleBin()); }
ULONGLONG CountFiles() const { return m_count_files; }
std::vector<std::shared_ptr<DirNode>> CopyDirs(bool include_recycle=false) const;
std::vector<std::shared_ptr<FileNode>> CopyFiles() const;
virtual std::shared_ptr<RecycleBinNode> GetRecycleBin() const { return nullptr; }
virtual std::shared_ptr<FreeSpaceNode> GetFreeSpace() const { return nullptr; }
ULONGLONG GetSize() const { return m_size; }
ULONGLONG GetEffectiveSize() const;
void Hide(bool hide=true) { m_hide = hide; }
bool IsHidden() const { return m_hide; }
std::shared_ptr<DirNode> AddDir(const WCHAR* name);
std::shared_ptr<FileNode> AddFile(const WCHAR* name, ULONGLONG size);
void DeleteChild(const std::shared_ptr<Node>& node);
void Clear();
void Finish() { m_finished = true; }
bool IsFinished() const { return m_finished; }
protected:
void UpdateRecycleBinMetadata(ULONGLONG size);
mutable std::recursive_mutex m_node_mutex;
private:
std::vector<std::shared_ptr<DirNode>> m_dirs;
std::vector<std::shared_ptr<FileNode>> m_files;
ULONGLONG m_count_dirs = 0;
ULONGLONG m_count_files = 0;
ULONGLONG m_size = 0;
bool m_finished = false;
bool m_hide = false;
};
class FileNode : public Node
{
public:
FileNode(const WCHAR* name, ULONGLONG size, const std::shared_ptr<DirNode>& parent) : Node(name, parent), m_size(size) {}
FileNode* AsFile() override { return this; }
const FileNode* AsFile() const override { return this; }
ULONGLONG GetSize() const { return m_size; }
private:
const ULONGLONG m_size;
};
class RecycleBinNode : public DirNode
{
public:
RecycleBinNode(const std::shared_ptr<DirNode>& parent) : DirNode(TEXT("Recycle Bin"), parent) {}
virtual RecycleBinNode* AsRecycleBin() { return this; }
void UpdateRecycleBin(std::recursive_mutex& ui_mutex);
bool IsRecycleBin() const override { return true; }
};
class FreeSpaceNode : public Node
{
public:
FreeSpaceNode(const WCHAR* drive, ULONGLONG free, ULONGLONG total, const std::shared_ptr<DirNode>& parent);
const FreeSpaceNode* AsFreeSpace() const override { return this; }
ULONGLONG GetFreeSize() const { return m_free; }
ULONGLONG GetUsedSize() const { return m_total - m_free; }
ULONGLONG GetTotalSize() const { return m_total; }
private:
const ULONGLONG m_free;
const ULONGLONG m_total;
};
class DriveNode : public DirNode
{
public:
DriveNode(const WCHAR* name) : DirNode(name, nullptr) {}
virtual DriveNode* AsDrive() { return this; }
virtual const DriveNode* AsDrive() const { return this; }
void AddRecycleBin();
void AddFreeSpace();
void AddFreeSpace(ULONGLONG free, ULONGLONG total);
virtual std::shared_ptr<RecycleBinNode> GetRecycleBin() const override { return m_recycle; }
virtual std::shared_ptr<FreeSpaceNode> GetFreeSpace() const override { return m_free; }
bool IsDrive() const override { return true; }
private:
std::shared_ptr<RecycleBinNode> m_recycle;
std::shared_ptr<FreeSpaceNode> m_free;
};
inline bool is_separator(const WCHAR ch) { return ch == '/' || ch == '\\'; }
void ensure_separator(std::wstring& path);
void strip_separator(std::wstring& path);
void skip_separators(const WCHAR*& path);
void skip_nonseparators(const WCHAR*& path);
unsigned int has_io_prefix(const WCHAR* path);
bool is_root_finished(const std::shared_ptr<Node>& node);
bool is_drive(const WCHAR* path);
bool is_subst(const WCHAR* path);
bool is_unc(const WCHAR* path, const WCHAR** past_unc);
bool get_drivelike_prefix(const WCHAR* path, std::wstring&out);