diff --git a/src/file.cpp b/src/file.cpp index 5d7aea281..778ce87ed 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -22,6 +22,7 @@ #include "utf8_string.hpp" #include "sass_functions.hpp" #include "error_handling.hpp" +#include "util.hpp" #include "sass2scss.h" #ifdef _WIN32 diff --git a/src/fn_colors.cpp b/src/fn_colors.cpp index b0142add4..66876acb3 100644 --- a/src/fn_colors.cpp +++ b/src/fn_colors.cpp @@ -3,20 +3,17 @@ #include "ast.hpp" #include "fn_utils.hpp" #include "fn_colors.hpp" +#include "util.hpp" namespace Sass { namespace Functions { bool special_number(String_Constant_Ptr s) { - if (s) { - static const char* const calc = "calc("; - static const char* const var = "var("; - const std::string& str = s->value(); - return str.compare(0, strlen(calc), calc) == 0 || - str.compare(0, strlen(var), var) == 0; - } - return false; + if (s == nullptr) return false; + const std::string& str = s->value(); + return starts_with(str, "calc(") || + starts_with(str, "var("); } Signature rgb_sig = "rgb($red, $green, $blue)"; diff --git a/src/output.cpp b/src/output.cpp index b2ca65e7e..c0e8bd27e 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -1,6 +1,7 @@ #include "sass.hpp" #include "ast.hpp" #include "output.hpp" +#include "util.hpp" namespace Sass { diff --git a/src/output.hpp b/src/output.hpp index c460b13fe..25c6d2b78 100644 --- a/src/output.hpp +++ b/src/output.hpp @@ -11,13 +11,6 @@ namespace Sass { class Context; - // Refactor to make it generic to find linefeed (look behind) - inline bool ends_with(std::string const & value, std::string const & ending) - { - if (ending.size() > value.size()) return false; - return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); - } - class Output : public Inspect { protected: using Inspect::operator(); diff --git a/src/plugins.cpp b/src/plugins.cpp index eecba7880..180ff2f28 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -2,6 +2,7 @@ #include #include "output.hpp" #include "plugins.hpp" +#include "util.hpp" #ifdef _WIN32 #include diff --git a/src/util.hpp b/src/util.hpp index f23475fe0..6c98f91c1 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -1,6 +1,7 @@ #ifndef SASS_UTIL_H #define SASS_UTIL_H +#include #include #include #include @@ -34,6 +35,34 @@ namespace Sass { bool peek_linefeed(const char* start); + // C++20 `starts_with` equivalent. + // See https://en.cppreference.com/w/cpp/string/basic_string/starts_with + inline bool starts_with(const std::string& str, const char* prefix, size_t prefix_len) { + return str.compare(0, prefix_len, prefix) == 0; + } + + inline bool starts_with(const std::string& str, const char* prefix) { + return starts_with(str, prefix, std::strlen(prefix)); + } + + // C++20 `ends_with` equivalent. + // See https://en.cppreference.com/w/cpp/string/basic_string/ends_with + inline bool ends_with(const std::string& str, const std::string& suffix) { + return suffix.size() <= str.size() && std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()); + } + + inline bool ends_with(const std::string& str, const char* suffix, size_t suffix_len) { + if (suffix_len > str.size()) return false; + const char* suffix_it = suffix + suffix_len; + const char* str_it = str.c_str() + str.size(); + while (suffix_it != suffix) if (*(--suffix_it) != *(--str_it)) return false; + return true; + } + + inline bool ends_with(const std::string& str, const char* suffix) { + return ends_with(str, suffix, std::strlen(suffix)); + } + namespace Util { std::string rtrim(const std::string& str);