1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
#include "sass.hpp"
#include "node.hpp"
namespace Sass {
/*
# This is the equivalent of ruby's Sass::Util.paths.
#
# Return an array of all possible paths through the given arrays.
#
# @param arrs [NodeCollection<NodeCollection<Node>>]
# @return [NodeCollection<NodeCollection<Node>>]
#
# @example
# paths([[1, 2], [3, 4], [5]]) #=>
# # [[1, 3, 5],
# # [2, 3, 5],
# # [1, 4, 5],
# # [2, 4, 5]]
The following is the modified version of the ruby code that was more portable to C++. You
should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
def paths(arrs)
// I changed the inject and maps to an iterative approach to make it easier to implement in C++
loopStart = [[]]
for arr in arrs do
permutations = []
for e in arr do
for path in loopStart do
permutations.push(path + [e])
end
end
loopStart = permutations
end
end
*/
Node paths(const Node& arrs) {
Node loopStart = Node::createCollection();
loopStart.collection()->push_back(Node::createCollection());
for (NodeDeque::iterator arrsIter = arrs.collection()->begin(), arrsEndIter = arrs.collection()->end();
arrsIter != arrsEndIter; ++arrsIter) {
Node& arr = *arrsIter;
Node permutations = Node::createCollection();
for (NodeDeque::iterator arrIter = arr.collection()->begin(), arrIterEnd = arr.collection()->end();
arrIter != arrIterEnd; ++arrIter) {
Node& e = *arrIter;
for (NodeDeque::iterator loopStartIter = loopStart.collection()->begin(), loopStartIterEnd = loopStart.collection()->end();
loopStartIter != loopStartIterEnd; ++loopStartIter) {
Node& path = *loopStartIter;
Node newPermutation = Node::createCollection();
newPermutation.got_line_feed = arr.got_line_feed;
newPermutation.plus(path);
newPermutation.collection()->push_back(e);
permutations.collection()->push_back(newPermutation);
}
}
loopStart = permutations;
}
return loopStart;
}
/*
This is the equivalent of ruby sass' Sass::Util.flatten and [].flatten.
Sass::Util.flatten requires the number of levels to flatten, while
[].flatten doesn't and will flatten the entire array. This function
supports both.
# Flattens the first `n` nested arrays. If n == -1, all arrays will be flattened
#
# @param arr [NodeCollection] The array to flatten
# @param n [int] The number of levels to flatten
# @return [NodeCollection] The flattened array
The following is the modified version of the ruby code that was more portable to C++. You
should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
def flatten(arr, n = -1)
if n != -1 and n == 0 then
return arr
end
flattened = []
for e in arr do
if e.is_a?(Array) then
flattened.concat(flatten(e, n - 1))
else
flattened << e
end
end
return flattened
end
*/
Node flatten(Node& arr, int n) {
if (n != -1 && n == 0) {
return arr;
}
Node flattened = Node::createCollection();
if (arr.got_line_feed) flattened.got_line_feed = true;
for (NodeDeque::iterator iter = arr.collection()->begin(), iterEnd = arr.collection()->end();
iter != iterEnd; iter++) {
Node& e = *iter;
// e has the lf set
if (e.isCollection()) {
// e.collection().got_line_feed = e.got_line_feed;
Node recurseFlattened = flatten(e, n - 1);
if(e.got_line_feed) {
flattened.got_line_feed = e.got_line_feed;
recurseFlattened.got_line_feed = e.got_line_feed;
}
for(auto i : (*recurseFlattened.collection())) {
if (recurseFlattened.got_line_feed) {
i.got_line_feed = true;
}
flattened.collection()->push_back(i);
}
} else {
flattened.collection()->push_back(e);
}
}
return flattened;
}
}
|