Coverage Report

Created: 2025-08-28 06:06

/src/libsass/src/util_string.cpp
Line
Count
Source (jump to first uncovered line)
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
23.2k
    bool equalsLiteral(const char* lit, const sass::string& test) {
18
      // Work directly on characters
19
23.2k
      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
23.2k
      while (*lit && (*src == *lit || *src + 32 == *lit)) {
23
0
        ++src, ++lit;
24
0
      }
25
      // True if literal is at end
26
      // If not test was too long
27
23.2k
      return *lit == 0;
28
23.2k
    }
29
30
171k
    void ascii_str_tolower(sass::string* s) {
31
2.17M
      for (auto& ch : *s) {
32
2.17M
        ch = ascii_tolower(static_cast<unsigned char>(ch));
33
2.17M
      }
34
171k
    }
35
36
0
    void ascii_str_toupper(sass::string* s) {
37
0
      for (auto& ch : *s) {
38
0
        ch = ascii_toupper(static_cast<unsigned char>(ch));
39
0
      }
40
0
    }
41
42
0
    sass::string rtrim(sass::string str) {
43
0
      auto it = std::find_if_not(str.rbegin(), str.rend(), ascii_isspace);
44
0
      str.erase(str.rend() - it);
45
0
      return str;
46
0
    }
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
6.03k
    {
54
6.03k
      if (name.size() < 2) return name;
55
3.79k
      if (name[0] != '-') return name;
56
0
      if (name[1] == '-') return name;
57
0
      for (size_t i = 2; i < name.size(); i++) {
58
0
        if (name[i] == '-') return name.substr(i + 1);
59
0
      }
60
0
      return name;
61
0
    }
62
    // EO unvendor
63
64
0
    sass::string normalize_newlines(const sass::string& str) {
65
0
      sass::string result;
66
0
      result.reserve(str.size());
67
0
      std::size_t pos = 0;
68
0
      while (true) {
69
0
        const std::size_t newline = str.find_first_of("\n\f\r", pos);
70
0
        if (newline == sass::string::npos) break;
71
0
        result.append(str, pos, newline - pos);
72
0
        result += '\n';
73
0
        if (str[newline] == '\r' && str[newline + 1] == '\n') {
74
0
          pos = newline + 2;
75
0
        }
76
0
        else {
77
0
          pos = newline + 1;
78
0
        }
79
0
      }
80
0
      result.append(str, pos, sass::string::npos);
81
0
      return result;
82
0
    }
83
84
4.18k
    sass::string normalize_underscores(const sass::string& str) {
85
4.18k
      sass::string normalized = str;
86
4.18k
      std::replace(normalized.begin(), normalized.end(), '_', '-');
87
4.18k
      return normalized;
88
4.18k
    }
89
90
2
    sass::string normalize_decimals(const sass::string& str) {
91
2
      sass::string normalized;
92
2
      if (!str.empty() && str[0] == '.') {
93
0
        normalized.reserve(str.size() + 1);
94
0
        normalized += '0';
95
0
        normalized += str;
96
0
      }
97
2
      else {
98
2
        normalized = str;
99
2
      }
100
2
      return normalized;
101
2
    }
102
103
6
    char opening_bracket_for(char closing_bracket) {
104
6
      switch (closing_bracket) {
105
0
      case ')': return '(';
106
0
      case ']': return '[';
107
6
      case '}': return '{';
108
0
      default: return '\0';
109
6
      }
110
6
    }
111
112
0
    char closing_bracket_for(char opening_bracket) {
113
0
      switch (opening_bracket) {
114
0
      case '(': return ')';
115
0
      case '[': return ']';
116
0
      case '{': return '}';
117
0
      default: return '\0';
118
0
      }
119
0
    }
120
121
  }
122
  // namespace Util
123
124
}
125
// namespace Sass