Coverage Report

Created: 2026-02-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libsass/src/dart_helpers.hpp
Line
Count
Source
1
#ifndef SASS_DART_HELPERS_H
2
#define SASS_DART_HELPERS_H
3
4
#include <vector>
5
#include <utility>
6
#include <iterator>
7
#include <functional>
8
9
namespace Sass {
10
11
  // ##########################################################################
12
  // Flatten `vector<vector<T>>` to `vector<T>`
13
  // ##########################################################################
14
  template <class T>
15
  T flatten(const sass::vector<T>& all)
16
0
  {
17
0
    T flattened;
18
0
    for (const auto& sub : all) {
19
0
      std::copy(std::begin(sub), std::end(sub),
20
0
        std::back_inserter(flattened));
21
0
    }
22
0
    return flattened;
23
0
  }
24
25
  // ##########################################################################
26
  // Expands each element of this Iterable into zero or more elements.
27
  // Calls a function on every element and ads all results to flat array
28
  // ##########################################################################
29
  // Equivalent to dart `cnt.any`
30
  // Pass additional closure variables to `fn`
31
  template <class T, class U, typename ...Args>
32
0
  T expand(const T& cnt, U fn, Args... args) {
33
0
    T flattened;
34
0
    for (const auto& sub : cnt) {
35
0
      auto rv = fn(sub, args...);
36
0
      flattened.insert(flattened.end(),
37
0
        rv.begin(), rv.end());
38
0
    }
39
0
    return flattened;
40
0
  }
41
42
  // ##########################################################################
43
  // ##########################################################################
44
  template <class T>
45
  T flattenInner(const sass::vector<T>& vec)
46
0
  {
47
0
    T outer;
48
0
    for (const auto& sub : vec) {
49
0
      outer.emplace_back(std::move(flatten(sub)));
50
0
    }
51
0
    return outer;
52
0
  }
53
  // EO flattenInner
54
55
  // ##########################################################################
56
  // Equivalent to dart `cnt.any`
57
  // Pass additional closure variables to `fn`
58
  // ##########################################################################
59
  template <class T, class U, typename ...Args>
60
0
  bool hasAny(const T& cnt, U fn, Args... args) {
61
0
    for (const auto& sub : cnt) {
62
0
      if (fn(sub, args...)) {
63
0
        return true;
64
0
      }
65
0
    }
66
0
    return false;
67
0
  }
Unexecuted instantiation: bool Sass::hasAny<std::__1::vector<Sass::SharedImpl<Sass::ComplexSelector>, std::__1::allocator<Sass::SharedImpl<Sass::ComplexSelector> > >, bool (*)(Sass::SharedImpl<Sass::ComplexSelector> const&)>(std::__1::vector<Sass::SharedImpl<Sass::ComplexSelector>, std::__1::allocator<Sass::SharedImpl<Sass::ComplexSelector> > > const&, bool (*)(Sass::SharedImpl<Sass::ComplexSelector> const&))
Unexecuted instantiation: bool Sass::hasAny<std::__1::vector<Sass::SharedImpl<Sass::ComplexSelector>, std::__1::allocator<Sass::SharedImpl<Sass::ComplexSelector> > >, bool (*)(Sass::ComplexSelector const*, Sass::ComplexSelector const*, unsigned long), Sass::SharedImpl<Sass::ComplexSelector>, unsigned long>(std::__1::vector<Sass::SharedImpl<Sass::ComplexSelector>, std::__1::allocator<Sass::SharedImpl<Sass::ComplexSelector> > > const&, bool (*)(Sass::ComplexSelector const*, Sass::ComplexSelector const*, unsigned long), Sass::SharedImpl<Sass::ComplexSelector>, unsigned long)
68
  // EO hasAny
69
70
  // ##########################################################################
71
  // Equivalent to dart `cnt.take(len).any`
72
  // Pass additional closure variables to `fn`
73
  // ##########################################################################
74
  template <class T, class U, typename ...Args>
75
0
  bool hasSubAny(const T& cnt, size_t len, U fn, Args... args) {
76
0
    for (size_t i = 0; i < len; i++) {
77
0
      if (fn(cnt[i], args...)) {
78
0
        return true;
79
0
      }
80
0
    }
81
0
    return false;
82
0
  }
83
84
  // ##########################################################################
85
  // Default predicate for lcs algorithm
86
  // ##########################################################################
87
  template <class T>
88
  inline bool lcsIdentityCmp(const T& X, const T& Y, T& result)
89
0
  {
90
    // Assert equality
91
0
    if (!ObjEqualityFn(X, Y)) {
92
0
      return false;
93
0
    }
94
    // Store in reference
95
0
    result = X;
96
    // Return success
97
0
    return true;
98
0
  }
99
  // EO lcsIdentityCmp
100
101
  // ##########################################################################
102
  // Longest common subsequence with predicate
103
  // ##########################################################################
104
  template <class T>
105
  sass::vector<T> lcs(
106
    const sass::vector<T>& X, const sass::vector<T>& Y,
107
    bool(*select)(const T&, const T&, T&) = lcsIdentityCmp<T>)
108
0
  {
109
110
0
    std::size_t m = X.size(), mm = X.size() + 1;
111
0
    std::size_t n = Y.size(), nn = Y.size() + 1;
112
113
0
    if (m == 0) return {};
114
0
    if (n == 0) return {};
115
116
    // MSVC does not support variable-length arrays
117
    // To circumvent, allocate one array on the heap
118
    // Then use a macro to access via double index
119
    // e.g. `size_t L[m][n]` is supported by gcc
120
0
    size_t* len = new size_t[mm * nn + 1];
121
0
    bool* acc = new bool[mm * nn + 1];
122
0
    T* res = new T[mm * nn + 1];
123
124
0
    #define LEN(x, y) len[(x) * nn + (y)]
125
0
    #define ACC(x, y) acc[(x) * nn + (y)]
126
0
    #define RES(x, y) res[(x) * nn + (y)]
127
128
    /* Following steps build L[m+1][n+1] in bottom up fashion. Note
129
      that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1] */
130
0
    for (size_t i = 0; i <= m; i++) {
131
0
      for (size_t j = 0; j <= n; j++) {
132
0
        if (i == 0 || j == 0)
133
0
          LEN(i, j) = 0;
134
0
        else {
135
0
          ACC(i - 1, j - 1) = select(X[i - 1], Y[j - 1], RES(i - 1, j - 1));
136
0
          if (ACC(i - 1, j - 1))
137
0
            LEN(i, j) = LEN(i - 1, j - 1) + 1;
138
0
          else
139
0
            LEN(i, j) = std::max(LEN(i - 1, j), LEN(i, j - 1));
140
0
        }
141
0
      }
142
0
    }
143
144
    // Following code is used to print LCS
145
0
    sass::vector<T> lcs;
146
0
    std::size_t index = LEN(m, n);
147
0
    lcs.reserve(index);
148
149
    // Start from the right-most-bottom-most corner
150
    // and one by one store objects in lcs[]
151
0
    std::size_t i = m, j = n;
152
0
    while (i > 0 && j > 0) {
153
154
      // If current objects in X[] and Y are same,
155
      // then current object is part of LCS
156
0
      if (ACC(i - 1, j - 1))
157
0
      {
158
        // Put the stored object in result
159
        // Note: we push instead of unshift
160
        // Note: reverse the vector later
161
        // ToDo: is deque more performant?
162
0
        lcs.push_back(RES(i - 1, j - 1));
163
        // reduce values of i, j and index
164
0
        i -= 1; j -= 1; index -= 1;
165
0
      }
166
167
      // If not same, then find the larger of two and
168
      // go in the direction of larger value
169
0
      else if (LEN(i - 1, j) > LEN(i, j - 1)) {
170
0
        i--;
171
0
      }
172
0
      else {
173
0
        j--;
174
0
      }
175
176
0
    }
177
178
    // reverse now as we used push_back
179
0
    std::reverse(lcs.begin(), lcs.end());
180
181
    // Delete temp memory on heap
182
0
    delete[] len;
183
0
    delete[] acc;
184
0
    delete[] res;
185
186
0
    #undef LEN
187
0
    #undef ACC
188
0
    #undef RES
189
190
0
    return lcs;
191
0
  }
Unexecuted instantiation: std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > Sass::lcs<Sass::SharedImpl<Sass::SelectorComponent> >(std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > const&, std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > const&, bool (*)(Sass::SharedImpl<Sass::SelectorComponent> const&, Sass::SharedImpl<Sass::SelectorComponent> const&, Sass::SharedImpl<Sass::SelectorComponent>&))
Unexecuted instantiation: std::__1::vector<std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > >, std::__1::allocator<std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > > > Sass::lcs<std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > >(std::__1::vector<std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > >, std::__1::allocator<std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > > > const&, std::__1::vector<std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > >, std::__1::allocator<std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > > > const&, bool (*)(std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > const&, std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > const&, std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > >&))
192
  // EO lcs
193
194
  // ##########################################################################
195
  // ##########################################################################
196
197
}
198
199
#endif