-
Notifications
You must be signed in to change notification settings - Fork 0
/
FileTransfer.cpp
146 lines (107 loc) · 4.32 KB
/
FileTransfer.cpp
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
#include "FileTransfer.h"
FileTransfer::FileTransfer(const std::string &directoryLocation, std::string targetLocation) :
bytesTransferred(0), numFilesTransferred(0), destLocation(std::move(targetLocation)),
filesTransferred(""), sourceLocation(directoryLocation) {
//reads files infos in the directory
scanDirectory(directoryLocation);
file = filesInfos.begin();
}
void FileTransfer::addObserver(Observer *o) {
obs.emplace_back(o);
}
void FileTransfer::removeObserver(Observer *o) {
obs.remove(o);
}
void FileTransfer::notify() {
for (auto o : obs)
o->update();
}
bool FileTransfer::Transfer(sf::RenderWindow &window, const std::string &sourcePath, const std::string &destPath) {
fs::create_directory(destPath);
for (const auto &entry : std::filesystem::directory_iterator(sourcePath))
if (entry.is_directory()) {
//recursive call to open every subdirectory if present
Transfer(window, entry.path().string(), destPath + "/" + entry.path().filename().string());
} else {
bytesTransferred = 0;
std::ifstream source(entry.path(), std::ios::binary);
std::ofstream dest(destPath + "/" + entry.path().filename().string(), std::ios::binary);
// setting file size
int size = file->second;
// reading source and filling buffer
std::vector<char> buffer((std::istreambuf_iterator<char>(source)), std::istreambuf_iterator<char>());
//it's not the best way because it has to save a buffer that
//has a size equal to the number of bytes of the file, so it's not good for big files
//writes to file 1 byte at a time
for (size_t i = 0; i < size; i++) {
dest.write(static_cast<char *> (&buffer[i]), 1);
//makes debug easier
sf::sleep(sf::microseconds(1));
bytesTransferred++;
//handles the possibility of closing the window during the transfer
sf::Event abort;
while (window.pollEvent(abort))
if (abort.type == sf::Event::Closed)
return false;
notify();
}
// clean up
source.close();
dest.close();
//updates the files transferred up until this iteration
filesTransferred.append((file->first) + "\n");
numFilesTransferred++;
notify();
++file;
}
return true;
}
void FileTransfer::scanDirectory(const std::string &directoryLocation) {
for (const auto &entry : fs::directory_iterator(directoryLocation))
if (entry.is_directory())
scanDirectory(entry.path());
else
filesInfos.emplace_back(entry.path().filename(), entry.file_size());
}
const unsigned long FileTransfer::getFilesSize() const {
return filesInfos.size();
}
const int FileTransfer::getNumFilesTransferred() const {
return numFilesTransferred;
}
const std::string &FileTransfer::getFilesTransferred() const {
return filesTransferred;
}
const int FileTransfer::getBytesTransferred() const {
return bytesTransferred;
}
const std::vector<std::pair<std::string, int>>::iterator &FileTransfer::getFileTransferring() const {
return file;
}
const std::string &FileTransfer::getSourceLocation() const {
return sourceLocation;
}
const std::string &FileTransfer::getDestLocation() const {
return destLocation;
}
void FileTransfer::setFilesInfos(const std::vector<std::pair<std::string, int>> &filesInfos) {
FileTransfer::filesInfos = filesInfos;
}
void FileTransfer::setSourceLocation(const std::string &sourceLocation) {
FileTransfer::sourceLocation = sourceLocation;
}
void FileTransfer::setDestLocation(const std::string &destLocation) {
FileTransfer::destLocation = destLocation;
}
void FileTransfer::setFilesTransferred(const std::string &filesTransferred) {
FileTransfer::filesTransferred = filesTransferred;
}
void FileTransfer::setNumFilesTransferred(int numFilesTransferred) {
FileTransfer::numFilesTransferred = numFilesTransferred;
}
void FileTransfer::setBytesTransferred(int bytesTransferred) {
FileTransfer::bytesTransferred = bytesTransferred;
}
const std::list<Observer *> &FileTransfer::getObs() const {
return obs;
}