#ifndef UTIL_H #define UTIL_H #include <errno.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #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 } }; /** * 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; // 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); } // 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 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 template <typename T> string to_string(const T & value); int intlen(unsigned int a); void makeLower(string & str); string toLower(const string & str); // 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__) // 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(); } inline int intlen(unsigned int a) { int len = 1; 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; } #if 0 template <typename C> class collection_view<C> { public: class iterator { C::iterator it; public: } template <typename T, C> Collection<T> transform(C collection, UnaryOperator op) #endif } // namespace util #endif