#pragma once #include #include #include #include #include #include #include #include using std::experimental::optional; using std::experimental::nullopt; // Returns true if |value| starts/ends with |start| or |ending|. bool StartsWith(const std::string& value, const std::string& start); bool EndsWith(const std::string& value, const std::string& ending); std::string ReplaceAll(const std::string& source, const std::string& from, const std::string& to); // Finds all files in the given folder. This is recursive. std::vector GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path); optional ReadContent(const std::string& filename); std::vector ReadLines(std::string filename); std::vector ToLines(const std::string& content, bool trim_whitespace); std::unordered_map ParseTestExpectation(std::string filename); void UpdateTestExpectation(const std::string& filename, const std::string& expectation, const std::string& actual); void Fail(const std::string& message); void WriteToFile(const std::string& filename, const std::string& content); // note: this implementation does not disable this overload for array types // See http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique#Possible_Implementatiog template std::unique_ptr MakeUnique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); } template void AddRange(std::vector* dest, const std::vector& to_add) { for (const T& e : to_add) dest->push_back(e); } template void PushRange(std::queue* dest, const std::vector& to_add) { for (const T& e : to_add) dest->push(e); } template void RemoveRange(std::vector* dest, const std::vector& to_remove) { auto it = std::remove_if(dest->begin(), dest->end(), [&](const T& t) { // TODO: make to_remove a set? return std::find(to_remove.begin(), to_remove.end(), t) != to_remove.end(); }); if (it != dest->end()) dest->erase(it); } // http://stackoverflow.com/a/38140932 // // struct SomeHashKey { // std::string key1; // std::string key2; // bool key3; // }; // MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3) inline void hash_combine(std::size_t& seed) { } template inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) { std::hash hasher; seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); hash_combine(seed, rest...); } #define MAKE_HASHABLE(type, ...) \ namespace std {\ template<> struct hash {\ std::size_t operator()(const type &t) const {\ std::size_t ret = 0;\ hash_combine(ret, __VA_ARGS__);\ return ret;\ }\ };\ } #define MAKE_ENUM_HASHABLE(type) \ namespace std {\ template<> struct hash {\ std::size_t operator()(const type &t) const {\ return hash()(static_cast(t));\ }\ };\ }