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