Newer
Older
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
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
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
namespace util
{
using namespace std;
namespace internal
{
extern const char * error_prefix;
}
/************************************************************************/
/* Comparator for case-insensitive comparison in STL assos. containers */
/* From Abhay: */
/* http://stackoverflow.com/questions/1801892/making-mapfind-operation-case-insensitive */
/************************************************************************/
struct ci_less : std::binary_function<std::string, std::string, bool>
{
// case-independent (ci) compare_less binary function
struct nocase_compare : public std::binary_function<unsigned char,unsigned char,bool>
{
bool operator() (const unsigned char& c1, const unsigned char& c2) const
{
return tolower (c1) < tolower (c2);
}
};
bool operator() (const std::string & s1, const std::string & s2) const
{
return std::lexicographical_compare
(s1.begin (), s1.end (), // source range
s2.begin (), s2.end (), // dest range
nocase_compare ()); // comparison
}
};
// http://stackoverflow.com/questions/5300602/template-return-type-with-default-value
template <typename T>
struct Initializer
{
T value;
Initializer()
:value() // ====> default construction, works for classes _and_ built-in
{ }
};
class Signal
{
private:
const int signum;
public:
Signal(int signal_number) : signum(signal_number) { }
int number() const { return signum; }
const char * what() const;
};
/**
* Here we create a useful and easily understanable alias for the map.
**/
typedef map<string, vector<string>, ci_less> FileMap;
typedef map<string, bool, ci_less> OptionsMap;
class OptionsParser
{
private:
typedef map<string, bool*> optsMap_t;
typedef map<string, bool> valueMap_t;
valueMap_t valueMap; // not static to prevent still reachable memory
optsMap_t optsMap;
vector<string *> args;
public:
OptionsParser();
void addOption(const string & name, bool & setValue) { optsMap[name] = &setValue; }
void addArg(string & setValue) { args.push_back(&setValue); }
vector<string> parse(int argc, const char * const * argv);
// EXEC()
int8_t exec(int redirect_fd, const char * command,
const char * arg1 = NULL,
const char * arg2 = NULL,
const char * arg3 = NULL,
const char * arg4 = NULL,
const char * arg5 = NULL,
const char * arg6 = NULL);
inline
int8_t exec(const char * command,
const char * arg1 = NULL,
const char * arg2 = NULL,
const char * arg3 = NULL,
const char * arg4 = NULL,
const char * arg5 = NULL,
const char * arg6 = NULL)
{ return exec(STDOUT_FILENO, command, arg1, arg2, arg3, arg4, arg5, arg6); }
inline int8_t exec(const string & command) { return exec(command.c_str()); }
inline int8_t exec(const string & command, const string & arg1) { return exec(command.c_str(), arg1.c_str()); }
inline int8_t exec(const string & command, const string & arg1, const string & arg2) { return exec(command.c_str(), arg1.c_str(), arg2.c_str()); }
inline int8_t exec(const string & command, const string & arg1, const string & arg2, const string & arg3) { return exec(command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str()); }
inline int8_t exec(const string & command, const string & arg1, const string & arg2, const string & arg3, const string & arg4) { return exec(command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str()); }
inline int8_t exec(const string & command, const string & arg1, const string & arg2, const string & arg3, const string & arg4, const string & arg5) { return exec(command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str(), arg5.c_str()); }
inline int8_t exec(const string & command, const string & arg1, const string & arg2, const string & arg3, const string & arg4, const string & arg5, const string & arg6) { return exec(command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str(), arg5.c_str(), arg6.c_str()); }
inline int8_t exec(int redirect_fd, const string & command) { return exec(redirect_fd, command.c_str()); }
inline int8_t exec(int redirect_fd, const string & command, const string & arg1) { return exec(redirect_fd, command.c_str(), arg1.c_str()); }
inline int8_t exec(int redirect_fd, const string & command, const string & arg1, const string & arg2) { return exec(redirect_fd, command.c_str(), arg1.c_str(), arg2.c_str()); }
inline int8_t exec(int redirect_fd, const string & command, const string & arg1, const string & arg2, const string & arg3) { return exec(redirect_fd, command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str()); }
inline int8_t exec(int redirect_fd, const string & command, const string & arg1, const string & arg2, const string & arg3, const string & arg4) { return exec(redirect_fd, command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str()); }
inline int8_t exec(int redirect_fd, const string & command, const string & arg1, const string & arg2, const string & arg3, const string & arg4, const string & arg5) { return exec(redirect_fd, command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str(), arg5.c_str()); }
inline int8_t exec(int redirect_fd, const string & command, const string & arg1, const string & arg2, const string & arg3, const string & arg4, const string & arg5, const string & arg6) { return exec(redirect_fd, command.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str(), arg5.c_str(), arg6.c_str()); }
// FILESYSTEM FUNCTIONS
void assertExists(const string & path, int exit_code = -1);
bool exists(const string & path);
mode_t permissions(const string & path);
void forceRemoveDir(string dir);
string getcwdstr();
void copyFile(const string & source, const string & dest);
void copyFiles(const string & sourceFolder, const string & destFolder, const vector<string> & files);
void protectFiles(const string & folder, const vector<string> & files);
void protectDir(const string & dir);
void linkDirs(const string & sourceFolder, const string & destFolder, const vector<string> & dirs);
vector<string> get_files_in_dir(const string & dir, bool concatdir = true);
bool is_symlink(const string & file);
string get_symlink_target(const string & symlink);
// STRING REPLACEMENT
bool replaceFirst(string & str, const string & toreplace, const string & with);
size_t replaceAll (string & str, const string & toreplace, const string & with);
size_t replaceAllInternal(string & str, const string & toreplace, const string & with);
size_t findNthLast(const string & str, char c, size_t n);
vector<string> tokenize(const string & str, char delim);
// IO OPERATIONS
string read_string_from_FILE(FILE * file, size_t max_length = -1);
void write_string_to_FILE(FILE * file, const char * str);
ssize_t writeBytesToFile(signed int fileDescriptor, const char * buffer, unsigned int bufferLength);
ssize_t writen(int fd, const void *vptr, size_t n);
ssize_t write(int fd, const string & str);
ssize_t write(int fd, int val);
ssize_t write(int fd, long val);
ssize_t readn(int fd, void *vptr, size_t n);
ssize_t read(int fd, int & val);
ssize_t read(int fd, long & val);
// STRING TYPE OPERATIONS
void makeLower(string & str);
string toLower(const string & str);
// String concatenation
template <typename T>
string to_string(const T & value);
template <typename T>
T from_string(const string & s);
template <typename T, typename F>
T lexical_cast(const F & from);
string operator+(const string & lhs, const string & rhs); // These 5 functions are to disambiguate
string operator+(const string & lhs, const char * rhs); // operator+ so that the following
string operator+(const string & lhs, char rhs); // templates may exist
string operator+(const char * lhs, const string & rhs);
string operator+(char lhs, const string & rhs);
template <typename T>
string & operator+=(string & str, const T & value);
template <typename T>
string operator+(const string & str, const T & value);
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// CONFIGURATION
void readConfig(const string & testsFolder, FileMap & map, const string & discriminator = "");
void readFile(const string & file, vector<string> & lines);
string readFile(const string & filename);
void readFileGeneric(const string & file, FileMap * map, vector<string> * lines, const string & discriminator = "");
char * processOptions(int argc, char ** argv, OptionsMap & opts, vector<string> & args);
// AUTOGRADER
// STUDENT CODE COMPILATION FUNCTIONS
void rename_main(const string & file, const string & newname);
// MACROS
void SET_ERROR_MESSAGE(const char * message);
#define STRINGIFY1(p) #p
#define STR(p) STRINGIFY1(p)
namespace internal
{
template<typename StrType>
void exit_if_error_output(const char * file, int32_t line, StrType message);
}
#define EXIT_IF_ERROR2(statement_check, message) \
do { \
errno = 0; \
if ((statement_check) || errno != 0) \
util::internal::exit_if_error_output(__FILE__, __LINE__, message); \
} while (0)
#define EXIT_IF_ERROR1(statement_check) \
EXIT_IF_ERROR2(statement_check, #statement_check)
// Crazy hack for overloading!
// Arg counting from:
// http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/
// Overloading tips:
// http://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros
#define EXIT_IF_ERROR_THIRD_ARG(a, b, c, ...) c
#define EXIT_IF_ERROR(...) \
EXIT_IF_ERROR_THIRD_ARG(__VA_ARGS__, \
EXIT_IF_ERROR2, \
EXIT_IF_ERROR1, 0) (__VA_ARGS__)
// Colorization
namespace colorize
{
extern const char * BLACK;
extern const char * GREEN;
extern const char * RED;
extern const bool is_color_enabled;
inline string make_color(const char * color, const string & str)
{
return (is_color_enabled ? color + str + BLACK : str);
}
} // namespace colorize
// INLINE IMPLEMENTATIONS
// Originally by radu
// http://notfaq.wordpress.com/2006/08/30/c-convert-int-to-string/
template <typename T>
inline string to_string(const T & value)
{
stringstream ss;
ss << value;
return ss.str();
}
// http://stackoverflow.com/questions/5017001/like-atoi-but-to-float
template <typename T>
inline T from_string(const string & s)
{
stringstream ss(s);
T value;
ss >> value;
return value;
}
template <typename T, typename F>
inline T lexical_cast(const F & from)
{
stringstream ss;
if (!(ss << from))
{
cerr << "ERROR: Could not convert types" << endl;
return to.value; // TODO (toole1): Not sure if this forces a copy
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
a /= 10;
while (a != 0)
{
a = a/10;
len++;
}
return len;
}
inline ssize_t write(int fd, const string & str)
{
return writen(fd, str.c_str(), str.length()+1);
}
inline ssize_t write(int fd, int val)
{
return writen(fd, &val, sizeof val);
}
inline ssize_t write(int fd, long val)
{
return writen(fd, &val, sizeof val);
}
inline ssize_t read(int fd, int & val)
{
return readn(fd, &val, sizeof val);
}
inline ssize_t read(int fd, long & val)
{
return readn(fd, &val, sizeof val);
}
template <typename T, typename C, typename BinaryOp>
T accumulate(const C & collect, BinaryOp op, T init)
{
typename C::const_iterator it = collect.begin();
typename C::const_iterator end = collect.end();
while (it != end)
init = init + *it++;
return init;
}
inline string operator+(const string & lhs, const string & rhs) { return std::operator+(lhs, rhs); }
inline string operator+(const string & lhs, const char * rhs) { return std::operator+(lhs, rhs); }
inline string operator+(const string & lhs, char rhs) { return std::operator+(lhs, rhs); }
inline string operator+(char lhs, const string & rhs) { return std::operator+(lhs, rhs); }
inline string operator+(const char * lhs, const string & rhs) { return std::operator+(lhs, rhs); }
template <typename T>
inline std::string & operator+=(std::string & str, const T & value)
{
str += util::to_string(value);
return str;
template <typename T>
inline std::string operator+(const std::string & str, const T & value)
{
std::stringstream ss;
ss << str << value;
return ss.str();
}
inline uint64_t process_clock()
{
#ifdef CLOCK_PROCESS_CPUTIME_ID
timespec ts;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
return ts.tv_sec * 1000000 + (ts.tv_nsec + 500) / 1000;
#else
return clock();
#endif
}
inline uint64_t system_clock()
{
timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000 + tv.tv_usec;
}