Blame src/sass_util.cpp

Packit Service 7770af
#include "sass.hpp"
Packit Service 7770af
#include "node.hpp"
Packit Service 7770af
Packit Service 7770af
namespace Sass {
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
  /*
Packit Service 7770af
    # This is the equivalent of ruby's Sass::Util.paths.
Packit Service 7770af
    #
Packit Service 7770af
    # Return an array of all possible paths through the given arrays.
Packit Service 7770af
    #
Packit Service 7770af
    # @param arrs [NodeCollection<NodeCollection<Node>>]
Packit Service 7770af
    # @return [NodeCollection<NodeCollection<Node>>]
Packit Service 7770af
    #
Packit Service 7770af
    # @example
Packit Service 7770af
    #   paths([[1, 2], [3, 4], [5]]) #=>
Packit Service 7770af
    #     # [[1, 3, 5],
Packit Service 7770af
    #     #  [2, 3, 5],
Packit Service 7770af
    #     #  [1, 4, 5],
Packit Service 7770af
    #     #  [2, 4, 5]]
Packit Service 7770af
Packit Service 7770af
   The following is the modified version of the ruby code that was more portable to C++. You
Packit Service 7770af
   should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
Packit Service 7770af
Packit Service 7770af
    def paths(arrs)
Packit Service 7770af
        // I changed the inject and maps to an iterative approach to make it easier to implement in C++
Packit Service 7770af
      loopStart = [[]]
Packit Service 7770af
Packit Service 7770af
      for arr in arrs do
Packit Service 7770af
        permutations = []
Packit Service 7770af
        for e in arr do
Packit Service 7770af
          for path in loopStart do
Packit Service 7770af
            permutations.push(path + [e])
Packit Service 7770af
          end
Packit Service 7770af
        end
Packit Service 7770af
        loopStart = permutations
Packit Service 7770af
      end
Packit Service 7770af
    end
Packit Service 7770af
  */
Packit Service 7770af
  Node paths(const Node& arrs) {
Packit Service 7770af
Packit Service 7770af
    Node loopStart = Node::createCollection();
Packit Service 7770af
    loopStart.collection()->push_back(Node::createCollection());
Packit Service 7770af
Packit Service 7770af
    for (NodeDeque::iterator arrsIter = arrs.collection()->begin(), arrsEndIter = arrs.collection()->end();
Packit Service 7770af
    	arrsIter != arrsEndIter; ++arrsIter) {
Packit Service 7770af
Packit Service 7770af
      Node& arr = *arrsIter;
Packit Service 7770af
Packit Service 7770af
      Node permutations = Node::createCollection();
Packit Service 7770af
Packit Service 7770af
      for (NodeDeque::iterator arrIter = arr.collection()->begin(), arrIterEnd = arr.collection()->end();
Packit Service 7770af
      	arrIter != arrIterEnd; ++arrIter) {
Packit Service 7770af
Packit Service 7770af
        Node& e = *arrIter;
Packit Service 7770af
Packit Service 7770af
        for (NodeDeque::iterator loopStartIter = loopStart.collection()->begin(), loopStartIterEnd = loopStart.collection()->end();
Packit Service 7770af
          loopStartIter != loopStartIterEnd; ++loopStartIter) {
Packit Service 7770af
Packit Service 7770af
          Node& path = *loopStartIter;
Packit Service 7770af
Packit Service 7770af
          Node newPermutation = Node::createCollection();
Packit Service 7770af
          newPermutation.got_line_feed = arr.got_line_feed;
Packit Service 7770af
          newPermutation.plus(path);
Packit Service 7770af
          newPermutation.collection()->push_back(e);
Packit Service 7770af
Packit Service 7770af
          permutations.collection()->push_back(newPermutation);
Packit Service 7770af
        }
Packit Service 7770af
      }
Packit Service 7770af
Packit Service 7770af
      loopStart = permutations;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    return loopStart;
Packit Service 7770af
  }
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
  /*
Packit Service 7770af
  This is the equivalent of ruby sass' Sass::Util.flatten and [].flatten.
Packit Service 7770af
  Sass::Util.flatten requires the number of levels to flatten, while
Packit Service 7770af
  [].flatten doesn't and will flatten the entire array. This function
Packit Service 7770af
  supports both.
Packit Service 7770af
Packit Service 7770af
  # Flattens the first `n` nested arrays. If n == -1, all arrays will be flattened
Packit Service 7770af
  #
Packit Service 7770af
  # @param arr [NodeCollection] The array to flatten
Packit Service 7770af
  # @param n [int] The number of levels to flatten
Packit Service 7770af
  # @return [NodeCollection] The flattened array
Packit Service 7770af
Packit Service 7770af
  The following is the modified version of the ruby code that was more portable to C++. You
Packit Service 7770af
  should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
Packit Service 7770af
Packit Service 7770af
  def flatten(arr, n = -1)
Packit Service 7770af
    if n != -1 and n == 0 then
Packit Service 7770af
      return arr
Packit Service 7770af
    end
Packit Service 7770af
Packit Service 7770af
    flattened = []
Packit Service 7770af
Packit Service 7770af
    for e in arr do
Packit Service 7770af
      if e.is_a?(Array) then
Packit Service 7770af
        flattened.concat(flatten(e, n - 1))
Packit Service 7770af
      else
Packit Service 7770af
        flattened << e
Packit Service 7770af
      end
Packit Service 7770af
    end
Packit Service 7770af
Packit Service 7770af
    return flattened
Packit Service 7770af
  end
Packit Service 7770af
  */
Packit Service 7770af
  Node flatten(Node& arr, int n) {
Packit Service 7770af
    if (n != -1 && n == 0) {
Packit Service 7770af
      return arr;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    Node flattened = Node::createCollection();
Packit Service 7770af
    if (arr.got_line_feed) flattened.got_line_feed = true;
Packit Service 7770af
Packit Service 7770af
    for (NodeDeque::iterator iter = arr.collection()->begin(), iterEnd = arr.collection()->end();
Packit Service 7770af
    	iter != iterEnd; iter++) {
Packit Service 7770af
    	Node& e = *iter;
Packit Service 7770af
Packit Service 7770af
      // e has the lf set
Packit Service 7770af
      if (e.isCollection()) {
Packit Service 7770af
Packit Service 7770af
      	// e.collection().got_line_feed = e.got_line_feed;
Packit Service 7770af
      	Node recurseFlattened = flatten(e, n - 1);
Packit Service 7770af
Packit Service 7770af
      	if(e.got_line_feed) {
Packit Service 7770af
      		 flattened.got_line_feed = e.got_line_feed;
Packit Service 7770af
      	  recurseFlattened.got_line_feed = e.got_line_feed;
Packit Service 7770af
      	}
Packit Service 7770af
Packit Service 7770af
      	for(auto i : (*recurseFlattened.collection())) {
Packit Service 7770af
          if (recurseFlattened.got_line_feed) {
Packit Service 7770af
Packit Service 7770af
            i.got_line_feed = true;
Packit Service 7770af
          }
Packit Service 7770af
          flattened.collection()->push_back(i);
Packit Service 7770af
      	}
Packit Service 7770af
Packit Service 7770af
      } else {
Packit Service 7770af
      	flattened.collection()->push_back(e);
Packit Service 7770af
      }
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    return flattened;
Packit Service 7770af
  }
Packit Service 7770af
}