/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 |