Coverage Report

Created: 2025-09-04 06:47

/src/libsass/src/permutate.hpp
Line
Count
Source (jump to first uncovered line)
1
#ifndef SASS_PATHS_H
2
#define SASS_PATHS_H
3
4
#include <vector>
5
6
namespace Sass {
7
8
  // Returns a list of all possible paths through the given lists.
9
  //
10
  // For example, given `[[1, 2], [3, 4], [5, 6]]`, this returns:
11
  //
12
  // ```
13
  // [[1, 3, 5],
14
  //  [2, 3, 5],
15
  //  [1, 4, 5],
16
  //  [2, 4, 5],
17
  //  [1, 3, 6],
18
  //  [2, 3, 6],
19
  //  [1, 4, 6],
20
  //  [2, 4, 6]]
21
  // ```
22
  // 
23
  // Note: called `paths` in dart-sass
24
  template <class T>
25
  sass::vector<sass::vector<T>> permutate(
26
    const sass::vector<sass::vector<T>>& in)
27
0
  {
28
29
0
    size_t L = in.size(), n = 0;
30
31
0
    if (L == 0) return {};
32
    // Exit early if any entry is empty
33
0
    for (size_t i = 0; i < L; i += 1) {
34
0
      if (in[i].size() == 0) return {};
35
0
    }
36
37
0
    size_t* state = new size_t[L + 1];
38
0
    sass::vector<sass::vector<T>> out;
39
40
    // First initialize all states for every permutation group
41
0
    for (size_t i = 0; i < L; i += 1) {
42
0
      state[i] = in[i].size() - 1;
43
0
    }
44
0
    while (true) {
45
0
      sass::vector<T> perm;
46
      // Create one permutation for state
47
0
      for (size_t i = 0; i < L; i += 1) {
48
0
        perm.push_back(in.at(i).at(in[i].size() - state[i] - 1));
49
0
      }
50
      // Current group finished
51
0
      if (state[n] == 0) {
52
        // Find position of next decrement
53
0
        while (n < L && state[++n] == 0) {}
54
55
0
        if (n == L) {
56
0
          out.push_back(perm);
57
0
          break;
58
0
        }
59
60
0
        state[n] -= 1;
61
62
0
        for (size_t p = 0; p < n; p += 1) {
63
0
          state[p] = in[p].size() - 1;
64
0
        }
65
66
        // Restart from front
67
0
        n = 0;
68
69
0
      }
70
0
      else {
71
0
        state[n] -= 1;
72
0
      }
73
0
      out.push_back(perm);
74
0
    }
75
76
0
    delete[] state;
77
0
    return out;
78
0
  }
Unexecuted instantiation: std::__1::vector<std::__1::vector<Sass::SharedImpl<Sass::ComplexSelector>, std::__1::allocator<Sass::SharedImpl<Sass::ComplexSelector> > >, std::__1::allocator<std::__1::vector<Sass::SharedImpl<Sass::ComplexSelector>, std::__1::allocator<Sass::SharedImpl<Sass::ComplexSelector> > > > > Sass::permutate<Sass::SharedImpl<Sass::ComplexSelector> >(std::__1::vector<std::__1::vector<Sass::SharedImpl<Sass::ComplexSelector>, std::__1::allocator<Sass::SharedImpl<Sass::ComplexSelector> > >, std::__1::allocator<std::__1::vector<Sass::SharedImpl<Sass::ComplexSelector>, std::__1::allocator<Sass::SharedImpl<Sass::ComplexSelector> > > > > const&)
Unexecuted instantiation: std::__1::vector<std::__1::vector<Sass::Extension, std::__1::allocator<Sass::Extension> >, std::__1::allocator<std::__1::vector<Sass::Extension, std::__1::allocator<Sass::Extension> > > > Sass::permutate<Sass::Extension>(std::__1::vector<std::__1::vector<Sass::Extension, std::__1::allocator<Sass::Extension> >, std::__1::allocator<std::__1::vector<Sass::Extension, std::__1::allocator<Sass::Extension> > > > const&)
Unexecuted instantiation: std::__1::vector<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> > > > >, std::__1::allocator<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::permutate<std::__1::vector<Sass::SharedImpl<Sass::SelectorComponent>, std::__1::allocator<Sass::SharedImpl<Sass::SelectorComponent> > > >(std::__1::vector<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> > > > >, std::__1::allocator<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&)
79
  // EO permutate
80
81
  // ToDo: this variant is used in resolveParentSelectors
82
  // Returns a list of all possible paths through the given lists.
83
  //
84
  // For example, given `[[1, 2], [3, 4], [5, 6]]`, this returns:
85
  //
86
  // ```
87
  // [[1, 3, 5],
88
  //  [1, 3, 6],
89
  //  [1, 4, 5],
90
  //  [1, 4, 6],
91
  //  [2, 3, 5],
92
  //  [2, 3, 6],
93
  //  [2, 4, 5],
94
  //  [2, 4, 6]]
95
  // ```
96
  // 
97
  template <class T>
98
  sass::vector<sass::vector<T>>
99
2
    permutateAlt(const sass::vector<sass::vector<T>>& in) {
100
101
2
    size_t L = in.size();
102
2
    size_t n = in.size() - 1;
103
104
2
    if (L == 0) return {};
105
    // Exit early if any entry is empty
106
4
    for (size_t i = 0; i < L; i += 1) {
107
2
      if (in[i].size() == 0) return {};
108
2
    }
109
110
2
    size_t* state = new size_t[L];
111
2
    sass::vector<sass::vector<T>> out;
112
113
    // First initialize all states for every permutation group
114
4
    for (size_t i = 0; i < L; i += 1) {
115
2
      state[i] = in[i].size() - 1;
116
2
    }
117
118
2
    while (true) {
119
      /*
120
      // std::cerr << "PERM: ";
121
      for (size_t p = 0; p < L; p++)
122
      { // std::cerr << state[p] << " "; }
123
      // std::cerr << "\n";
124
      */
125
2
      sass::vector<T> perm;
126
      // Create one permutation for state
127
4
      for (size_t i = 0; i < L; i += 1) {
128
2
        perm.push_back(in.at(i).at(in[i].size() - state[i] - 1));
129
2
      }
130
      // Current group finished
131
2
      if (state[n] == 0) {
132
        // Find position of next decrement
133
2
        while (n > 0 && state[--n] == 0) {}
134
135
        // Check for end condition
136
2
        if (state[n] != 0) {
137
          // Decrease next on the left side
138
0
          state[n] -= 1;
139
          // Reset all counters to the right
140
0
          for (size_t p = n + 1; p < L; p += 1) {
141
0
            state[p] = in[p].size() - 1;
142
0
          }
143
          // Restart from end
144
0
          n = L - 1;
145
0
        }
146
2
        else {
147
2
          out.push_back(perm);
148
2
          break;
149
2
        }
150
2
      }
151
0
      else {
152
0
        state[n] -= 1;
153
0
      }
154
0
      out.push_back(perm);
155
0
    }
156
157
2
    delete[] state;
158
2
    return out;
159
2
  }
160
  // EO permutateAlt
161
162
}
163
164
#endif