#pragma once #include #include #include #include #include #include #include #include // Trim from start (in place) void TrimStartInPlace(std::string& s); // Trim from end (in place) void TrimEndInPlace(std::string& s); // Trim from both ends (in place) void TrimInPlace(std::string& s); std::string Trim(std::string s); uint64_t HashUsr(const std::string& s); uint64_t HashUsr(const char* s); uint64_t HashUsr(const char* s, size_t n); // 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); bool AnyStartsWith(const std::vector& values, const std::string& start); bool StartsWithAny(const std::string& value, const std::vector& startings); bool EndsWithAny(const std::string& value, const std::vector& endings); bool FindAnyPartial(const std::string& value, const std::vector& values); // Returns the dirname of |path|, i.e. "foo/bar.cc" => "foo", "foo" => ".", "/foo" => "/". std::string GetDirName(std::string path); // Returns the basename of |path|, ie, "foo/bar.cc" => "bar.cc". std::string GetBaseName(const std::string& path); // Returns |path| without the filetype, ie, "foo/bar.cc" => "foo/bar". std::string StripFileType(const std::string& path); std::string ReplaceAll(const std::string& source, const std::string& from, const std::string& to); std::vector SplitString(const std::string& str, const std::string& delimiter); std::string LowerPathIfCaseInsensitive(const std::string& path); template std::string StringJoinMap(const TValues& values, const TMap& map, const std::string& sep = ", ") { std::string result; bool first = true; for (auto& entry : values) { if (!first) result += sep; first = false; result += map(entry); } return result; } template std::string StringJoin(const TValues& values, const std::string& sep = ", ") { return StringJoinMap(values, [](const std::string& entry) { return entry; }, sep); } template bool ContainsValue(const TCollection& collection, const TValue& value) { return collection.find(value) != collection.end(); } // Finds all files in the given folder. This is recursive. std::vector GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path); void GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path, const std::function& handler); // Ensures that |path| ends in a slash. void EnsureEndsInSlash(std::string& path); // Converts a file path to one that can be used as filename. // e.g. foo/bar.c => foo_bar.c std::string EscapeFileName(std::string path); // FIXME: Move ReadContent into ICacheManager? bool FileExists(const std::string& filename); optional ReadContent(const std::string& filename); std::vector ReadLinesWithEnding(std::string filename); std::vector ToLines(const std::string& content, bool trim_whitespace); struct TextReplacer { struct Replacement { std::string from; std::string to; }; std::vector replacements; std::string Apply(const std::string& content); }; void ParseTestExpectation( const std::string& filename, const std::vector& lines_with_endings, TextReplacer* text_replacer, std::vector* flags, std::unordered_map* output_sections); void UpdateTestExpectation(const std::string& filename, const std::string& expectation, const std::string& actual); 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) { dest->insert(dest->end(), to_add.begin(), to_add.end()); } template void AddRange(std::vector* dest, std::vector&& to_add) { for (T& x : to_add) dest->push_back(std::move(x)); } 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) { dest->erase(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(); }), dest->end()); } // 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)); \ } \ }; \ } float GetProcessMemoryUsedInMb(); std::string FormatMicroseconds(long long microseconds); std::string GetDefaultResourceDirectory(); // Makes sure all newlines in |output| are in \r\n format. std::string UpdateToRnNewlines(std::string output);