1#include "util_string.hpp"
2
3#include <iostream>
4#include <algorithm>
5
6namespace 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

source code of gtk/subprojects/libsass/src/util_string.cpp