-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.cpp
221 lines (188 loc) · 6.24 KB
/
utils.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/**
* @file utils.cpp
* @author Henry Kaus (https://github.com/henrykaus)
* @brief Holds method definitions for the utils class. Should be used as a base
* class for any and all derived classes.
*
* @copyright Copyright (c) 2022
*/
#include "utils.h"
using namespace std;
/**
* @brief Uses binary representations to determine if num is power of two.
*
* @param _num is the number to test
* @return true if _num is a power of two.
* @return false if _num is not a power of two.
*/
bool utils::is_pow_two(int _num) const
{
return _num <= 0 || !(_num & (_num - 1));
}
/**
* @brief Gets error checking input for an integer
*
* @param in is the input stream
* @param _err_msg is the error message to display (default: nullptr)
* @param _min is the minimum integer the number can be (default: INT_MIN)
* @param _max is the maximum integer the number can be (default: INT_MAX)
* @return int of the number the user input
*/
int utils::integer_input(std::istream & in, const char * _err_msg, int _min, int _max) const
{
int number; // Temp number for user to enter into
// Gets number from user as long as valid and between _min and _max (inclusive)
in >> number;
while (in.fail() || number < _min || number > _max)
{
in.clear();
in.ignore(10000, '\n');
if (_err_msg)
cout << _err_msg;
in >> number;
}
return number;
}
/**
* @brief Gets input for an integer
*
* @param in is the input stream
* @param _err_msg is the error message to throw (default: "Unknown")
* @param _min is the minimum integer the number can be (default: INT_MIN)
* @param _max is the maximum integer the number can be (default: INT_MAX)
* @return int of the number the user input
*/
int utils::integer_input_throw(std::istream & in, const char * _err_msg, int _min, int _max) const
{
int number; // Temp number for user to enter into
// Gets number from user as long as valid and between _min and _max (inclusive)
in >> number;
while (in.fail() || number < _min || number > _max)
{
in.clear();
in.ignore(10000, '\n');
if (_err_msg)
throw invalid_argument(_err_msg);
in >> number;
}
return number;
}
/**
* @brief Gets a character from user and return the uppercase variant.
* NOTE: Does not clear stream of excess characters
* @param in is the input stream
* @return char: is the uppercase character
*/
char utils::capital_char_input(std::istream & in) const
{
char option;
in >> option;
return toupper(option);
}
/**
* @brief Asks user for confirmation and returns if they said Y or N
*
* @param in is the input stream
* @param _msg is the confirmation message to display (default: Are you sure
* (Y/N)?)
* @return true: user entered y or Y
* @return false: user entered n or N
*/
bool utils::are_you_sure(std::istream & in, const char * _msg, bool print_newline) const
{
char option;
// Print confirmation message
if (_msg) cout << _msg << " (Y/N)?" << endl;
else cout << "Are you sure (Y/N)?" << endl;
do {
cout << "-> ";
option = capital_char_input(cin);
cin.ignore(10000, '\n');
} while (option != 'Y' && option != 'N');
if (print_newline) cout << endl;
return option == 'Y';
}
/**
* @brief Asks user for 'Y' or 'N' input, takes in the input with input checking
* and returns the character given as a capital. Allows the following
* input: 'y', 'Y', 'n', 'N'
*
* @param in is the input stream
* @param _msg is the message to be displayed before " (Y/N): "
* @return char of either 'Y' or 'N'
*/
char utils::y_n_input(std::istream & in, const char * _msg) const
{
char option;
// Print confirmation message
if (_msg) cout << _msg << " (Y/N): ";
else cout << "Yes or no (Y/N): ";
do {
option = capital_char_input(cin);
cin.ignore(10000, '\n');
} while (option != 'Y' && option != 'N');
return option;
}
/**
* @brief Reads in name of file to save bracket as with error checking
*
* @param _output_file is the file name to save into (is updated in method)
*/
void utils::read_output_file(string & _output_file) const
{
cout << "What would you like to save the file as? " << endl
<< "-> ";
getline(cin, _output_file);
// Disallow forbidden characters in file name
while (_output_file.find('\\') != string::npos || _output_file.find('/') != string::npos)
{
_output_file.clear();
cout << "Do not use \\ or / in your name..." << endl
<< "-> ";
getline(cin, _output_file);
}
_output_file.append(".txt");
}
/**
* @brief Fills a vector of strings with all entries in a directory
*
* @param _files is a std::vector<std::string> to fill with directory entries
* (must be empty)
* @param _path is a string path to directory to get entries of
*/
void utils::get_files(vector<string> & _files, const string & _path) const
{
if (_files.size() > 0)
throw invalid_argument("Vector argument is non-empty");
// Get all files in directory
for (const auto & entry : filesystem::directory_iterator(_path))
_files.push_back(entry.path().filename().string());
// Throw error if empty directory
if (_files.size() < 1)
throw invalid_argument("No files in the selection, please try adding one to resources\\new.");
}
/**
* @brief Checks if file name exists in the 'saved' directory
*
* @param _output_file is the file name to check for
* @param _path is the path to read files from
* @return true if file exists in 'saved' directory
* @return false if file doesn't exist in 'saved' directory
*/
bool utils::check_file_exists(const string & _output_file, const char * _path) const
{
vector<string> reserved_files; // Files in resources/saved
if (!_path)
throw invalid_argument("Path must be non-null");
// resources/saved can be a size of 0, so ignore the throw
try {
this->get_files(reserved_files, _path);
} catch (...) {}
// If the file name exists, return that it exists
for (int i = 0; i < (int)reserved_files.size(); ++i)
{
if (reserved_files[i] == _output_file)
return true;
}
return false;
}