1 | #include "util_string.hpp" |
2 | |
3 | #include <iostream> |
4 | #include <algorithm> |
5 | |
6 | namespace Sass { |
7 | namespace Util { |
8 | |
9 | // ########################################################################## |
10 | // Special case insensitive string matcher. We can optimize |
11 | // the more general compare case quite a bit by requiring |
12 | // consumers to obey some rules (lowercase and no space). |
13 | // - `literal` must only contain lower case ascii characters |
14 | // there is one edge case where this could give false positives |
15 | // test could contain a (non-ascii) char exactly 32 below literal |
16 | // ########################################################################## |
17 | bool equalsLiteral(const char* lit, const sass::string& test) { |
18 | // Work directly on characters |
19 | const char* src = test.c_str(); |
20 | // There is a small chance that the search string |
21 | // Is longer than the rest of the string to look at |
22 | while (*lit && (*src == *lit || *src + 32 == *lit)) { |
23 | ++src, ++lit; |
24 | } |
25 | // True if literal is at end |
26 | // If not test was too long |
27 | return *lit == 0; |
28 | } |
29 | |
30 | void ascii_str_tolower(sass::string* s) { |
31 | for (auto& ch : *s) { |
32 | ch = ascii_tolower(c: static_cast<unsigned char>(ch)); |
33 | } |
34 | } |
35 | |
36 | void ascii_str_toupper(sass::string* s) { |
37 | for (auto& ch : *s) { |
38 | ch = ascii_toupper(c: static_cast<unsigned char>(ch)); |
39 | } |
40 | } |
41 | |
42 | sass::string rtrim(sass::string str) { |
43 | auto it = std::find_if_not(first: str.rbegin(), last: str.rend(), pred: ascii_isspace); |
44 | str.erase(pos: str.rend() - it); |
45 | return str; |
46 | } |
47 | |
48 | // ########################################################################### |
49 | // Returns [name] without a vendor prefix. |
50 | // If [name] has no vendor prefix, it's returned as-is. |
51 | // ########################################################################### |
52 | sass::string unvendor(const sass::string& name) |
53 | { |
54 | if (name.size() < 2) return name; |
55 | if (name[0] != '-') return name; |
56 | if (name[1] == '-') return name; |
57 | for (size_t i = 2; i < name.size(); i++) { |
58 | if (name[i] == '-') return name.substr(pos: i + 1); |
59 | } |
60 | return name; |
61 | } |
62 | // EO unvendor |
63 | |
64 | sass::string normalize_newlines(const sass::string& str) { |
65 | sass::string result; |
66 | result.reserve(res_arg: str.size()); |
67 | std::size_t pos = 0; |
68 | while (true) { |
69 | const std::size_t newline = str.find_first_of(s: "\n\f\r" , pos: pos); |
70 | if (newline == sass::string::npos) break; |
71 | result.append(str: str, pos: pos, n: newline - pos); |
72 | result += '\n'; |
73 | if (str[newline] == '\r' && str[newline + 1] == '\n') { |
74 | pos = newline + 2; |
75 | } |
76 | else { |
77 | pos = newline + 1; |
78 | } |
79 | } |
80 | result.append(str: str, pos: pos, n: sass::string::npos); |
81 | return result; |
82 | } |
83 | |
84 | sass::string normalize_underscores(const sass::string& str) { |
85 | sass::string normalized = str; |
86 | std::replace(first: normalized.begin(), last: normalized.end(), old_value: '_', new_value: '-'); |
87 | return normalized; |
88 | } |
89 | |
90 | sass::string normalize_decimals(const sass::string& str) { |
91 | sass::string normalized; |
92 | if (!str.empty() && str[0] == '.') { |
93 | normalized.reserve(res_arg: str.size() + 1); |
94 | normalized += '0'; |
95 | normalized += str; |
96 | } |
97 | else { |
98 | normalized = str; |
99 | } |
100 | return normalized; |
101 | } |
102 | |
103 | char opening_bracket_for(char closing_bracket) { |
104 | switch (closing_bracket) { |
105 | case ')': return '('; |
106 | case ']': return '['; |
107 | case '}': return '{'; |
108 | default: return '\0'; |
109 | } |
110 | } |
111 | |
112 | char closing_bracket_for(char opening_bracket) { |
113 | switch (opening_bracket) { |
114 | case '(': return ')'; |
115 | case '[': return ']'; |
116 | case '{': return '}'; |
117 | default: return '\0'; |
118 | } |
119 | } |
120 | |
121 | } |
122 | // namespace Util |
123 | |
124 | } |
125 | // namespace Sass |
126 | |