/** * src/util/util.h * * Copyright (c) 2021-2022 Bartek Kryza * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include namespace clanguml { namespace util { std::string ltrim(const std::string &s); std::string rtrim(const std::string &s); std::string trim(const std::string &s); #define __FILENAME__ \ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #define LOG_ERROR(fmt__, ...) \ spdlog::get("console")->error(std::string("[{}:{}] ") + fmt__, \ __FILENAME__, __LINE__, ##__VA_ARGS__) #define LOG_WARN(fmt__, ...) \ spdlog::get("console")->warn(std::string("[{}:{}] ") + fmt__, \ __FILENAME__, __LINE__, ##__VA_ARGS__) #define LOG_INFO(fmt__, ...) \ spdlog::get("console")->info(std::string("[{}:{}] ") + fmt__, \ __FILENAME__, __LINE__, ##__VA_ARGS__) #define LOG_DBG(fmt__, ...) \ spdlog::get("console")->debug(std::string("[{}:{}] ") + fmt__, \ __FILENAME__, __LINE__, ##__VA_ARGS__) /** * @brief Setup spdlog logger. * * @param verbose Whether the logging should be verbose or not. */ void setup_logging(bool verbose); std::string get_process_output(const std::string &command); std::string get_env(const std::string &name); bool is_git_repository(); std::string get_git_branch(); std::string get_git_revision(); std::string get_git_commit(); std::string get_git_toplevel_dir(); /** * @brief Split a string using delimiter * * Basic string split function, because C++ stdlib does not have one. * In case the string does not contain the delimiter, the original * string is returned as the only element of the vector. * * @param str String to split * @param delimiter Delimiter string * @param skip_empty Skip empty toks between delimiters if true * * @return Vector of string tokens. */ std::vector split( std::string str, std::string_view delimiter, bool skip_empty = true); std::string join( const std::vector &toks, std::string_view delimiter); /** * @brief Remove any qualifiers (e.g. const) from type. * * @param s String spelling of the type. * * @return Unqualified type spelling. */ std::string unqualify(const std::string &s); /** * @brief Abbreviate string to max_length, and replace last 3 characters * with ellipsis. * * @param s Input string * @param max_length Maximum length * @return Abbreviated string */ std::string abbreviate(const std::string &s, const unsigned int max_length); /** * @brief Find element alias in Puml note * * Finds aliases of the form @A(entity_name) in the Puml notes * or directives. * The match, if any, is returned in the result tuple: * (entity_name, offset, length) * * @return True if match was found */ bool find_element_alias( const std::string &input, std::tuple &result); /** * @brief Find and replace in string * * Replaces all occurences of pattern with replace_with in input string. * * @return True if at least on replacement was made */ bool replace_all( std::string &input, std::string pattern, std::string replace_with); /** * @brief Appends a vector to a vector. * * @tparam T * @param l * @param r */ template void append(std::vector &l, const std::vector &r) { l.insert(l.end(), r.begin(), r.end()); } /** * @brief Checks if collection starts with a prefix. * * @tparam T e.g. std::vector * @param col Collection to be checked against prefix * @param prefix Container, which specifies the prefix * @return true if first prefix.size() elements of col are equal to prefix */ template bool starts_with(const T &col, const T &prefix) { if (prefix.size() > col.size()) return false; return std::search(col.begin(), col.end(), prefix.begin(), prefix.end()) == col.begin(); } template <> bool starts_with( const std::filesystem::path &path, const std::filesystem::path &prefix); template <> bool starts_with(const std::string &s, const std::string &prefix); template bool ends_with(const std::vector &col, const std::vector &suffix) { if (suffix.size() > col.size()) return false; return std::vector(suffix.rbegin(), suffix.rend()) == std::vector(col.rbegin(), col.rbegin() + suffix.size()); } /** * @brief Removes prefix sequence of elements from the beginning of col. * * @tparam T * @param col * @param prefix */ template void remove_prefix(std::vector &col, const std::vector &prefix) { if (!starts_with(col, prefix)) return; col = std::vector(col.begin() + prefix.size(), col.end()); } /** * Returns true if element exists in container. * * @tparam T * @tparam E * @param container * @param element * @return */ template bool contains(const T &container, const E &element) { if constexpr (std::is_pointer_v) { return std::find_if(container.begin(), container.end(), [&element](const auto &e) { return *e == *element; }) != container.end(); } else if constexpr (std::is_same_v, std::string>) { return container.find(element) != std::string::npos; } else { return std::find(container.begin(), container.end(), element) != container.end(); } } template void for_each(const T &collection, F &&func) { std::for_each(std::begin(collection), std::end(collection), std::forward(func)); } template void for_each_if(const T &collection, C &&cond, F &&func) { std::for_each(std::begin(collection), std::end(collection), [cond = std::forward(cond), func = std::forward(func)](const auto &e) { if (cond(e)) func(e); }); } } // namespace util } // namespace clanguml