1 #ifndef SASS_UTIL_H
2 #define SASS_UTIL_H
3 
4 // sass.hpp must go before all system headers to get the
5 // __EXTENSIONS__ fix on Solaris.
6 #include "sass.hpp"
7 
8 #include "sass/base.h"
9 #include "ast_fwd_decl.hpp"
10 
11 #include <cmath>
12 #include <cstring>
13 #include <vector>
14 #include <string>
15 #include <assert.h>
16 
17 #define SASS_ASSERT(cond, msg) assert(cond && msg)
18 
19 namespace Sass {
20 
21   template <typename T>
clip(const T & n,const T & lower,const T & upper)22   T clip(const T& n, const T& lower, const T& upper) {
23     return std::max(lower, std::min(n, upper));
24   }
25 
26   template <typename T>
absmod(const T & n,const T & r)27   T absmod(const T& n, const T& r) {
28     T m = std::fmod(n, r);
29     if (m < 0.0) m += r;
30     return m;
31   }
32 
33   double round(double val, size_t precision = 0);
34   double sass_strtod(const char* str);
35   const char* safe_str(const char *, const char* = "");
36   void free_string_array(char **);
37   char **copy_strings(const sass::vector<sass::string>&, char ***, int = 0);
38   sass::string read_css_string(const sass::string& str, bool css = true);
39   sass::string evacuate_escapes(const sass::string& str);
40   sass::string string_to_output(const sass::string& str);
41   sass::string comment_to_compact_string(const sass::string& text);
42   sass::string read_hex_escapes(const sass::string& str);
43   sass::string escape_string(const sass::string& str);
44   void newline_to_space(sass::string& str);
45 
46   sass::string quote(const sass::string&, char q = 0);
47   sass::string unquote(const sass::string&, char* q = 0, bool keep_utf8_sequences = false, bool strict = true);
48   char detect_best_quotemark(const char* s, char qm = '"');
49 
50   bool is_hex_doublet(double n);
51   bool is_color_doublet(double r, double g, double b);
52 
53   bool peek_linefeed(const char* start);
54 
55   // Returns true iff `elements` ⊆ `container`.
56   template <typename C, typename T>
contains_all(C container,T elements)57   bool contains_all(C container, T elements) {
58     for (const auto &el : elements) {
59       if (container.find(el) == container.end()) return false;
60     }
61     return true;
62   }
63 
64   // C++20 `starts_with` equivalent.
65   // See https://en.cppreference.com/w/cpp/string/basic_string/starts_with
starts_with(const sass::string & str,const char * prefix,size_t prefix_len)66   inline bool starts_with(const sass::string& str, const char* prefix, size_t prefix_len) {
67     return str.compare(0, prefix_len, prefix) == 0;
68   }
69 
starts_with(const sass::string & str,const char * prefix)70   inline bool starts_with(const sass::string& str, const char* prefix) {
71     return starts_with(str, prefix, std::strlen(prefix));
72   }
73 
74   // C++20 `ends_with` equivalent.
75   // See https://en.cppreference.com/w/cpp/string/basic_string/ends_with
ends_with(const sass::string & str,const sass::string & suffix)76   inline bool ends_with(const sass::string& str, const sass::string& suffix) {
77     return suffix.size() <= str.size() && std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
78   }
79 
ends_with(const sass::string & str,const char * suffix,size_t suffix_len)80   inline bool ends_with(const sass::string& str, const char* suffix, size_t suffix_len) {
81     if (suffix_len > str.size()) return false;
82     const char* suffix_it = suffix + suffix_len;
83     const char* str_it = str.c_str() + str.size();
84     while (suffix_it != suffix) if (*(--suffix_it) != *(--str_it)) return false;
85     return true;
86   }
87 
ends_with(const sass::string & str,const char * suffix)88   inline bool ends_with(const sass::string& str, const char* suffix) {
89     return ends_with(str, suffix, std::strlen(suffix));
90   }
91 
92   namespace Util {
93 
94     bool isPrintable(StyleRule* r, Sass_Output_Style style = NESTED);
95     bool isPrintable(SupportsRule* r, Sass_Output_Style style = NESTED);
96     bool isPrintable(CssMediaRule* r, Sass_Output_Style style = NESTED);
97     bool isPrintable(Comment* b, Sass_Output_Style style = NESTED);
98     bool isPrintable(Block_Obj b, Sass_Output_Style style = NESTED);
99     bool isPrintable(String_Constant* s, Sass_Output_Style style = NESTED);
100     bool isPrintable(String_Quoted* s, Sass_Output_Style style = NESTED);
101     bool isPrintable(Declaration* d, Sass_Output_Style style = NESTED);
102 
103   }
104 }
105 #endif
106