sassc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +24 -0
  8. data/Rakefile +21 -0
  9. data/ext/libsass/.editorconfig +15 -0
  10. data/ext/libsass/.gitattributes +2 -0
  11. data/ext/libsass/.gitignore +61 -0
  12. data/ext/libsass/.travis.yml +38 -0
  13. data/ext/libsass/COPYING +25 -0
  14. data/ext/libsass/INSTALL +1 -0
  15. data/ext/libsass/LICENSE +25 -0
  16. data/ext/libsass/Makefile +223 -0
  17. data/ext/libsass/Makefile.am +145 -0
  18. data/ext/libsass/Readme.md +93 -0
  19. data/ext/libsass/appveyor.yml +76 -0
  20. data/ext/libsass/ast.cpp +581 -0
  21. data/ext/libsass/ast.hpp +1949 -0
  22. data/ext/libsass/ast_def_macros.hpp +16 -0
  23. data/ext/libsass/ast_factory.hpp +87 -0
  24. data/ext/libsass/ast_fwd_decl.hpp +72 -0
  25. data/ext/libsass/b64/cencode.h +32 -0
  26. data/ext/libsass/b64/encode.h +77 -0
  27. data/ext/libsass/backtrace.hpp +81 -0
  28. data/ext/libsass/base64vlq.cpp +43 -0
  29. data/ext/libsass/base64vlq.hpp +28 -0
  30. data/ext/libsass/bind.cpp +187 -0
  31. data/ext/libsass/bind.hpp +18 -0
  32. data/ext/libsass/cencode.c +102 -0
  33. data/ext/libsass/color_names.hpp +324 -0
  34. data/ext/libsass/configure.ac +130 -0
  35. data/ext/libsass/constants.cpp +144 -0
  36. data/ext/libsass/constants.hpp +145 -0
  37. data/ext/libsass/context.cpp +507 -0
  38. data/ext/libsass/context.hpp +150 -0
  39. data/ext/libsass/contextualize.cpp +157 -0
  40. data/ext/libsass/contextualize.hpp +65 -0
  41. data/ext/libsass/copy_c_str.cpp +13 -0
  42. data/ext/libsass/copy_c_str.hpp +5 -0
  43. data/ext/libsass/debug.hpp +39 -0
  44. data/ext/libsass/environment.hpp +75 -0
  45. data/ext/libsass/error_handling.cpp +28 -0
  46. data/ext/libsass/error_handling.hpp +28 -0
  47. data/ext/libsass/eval.cpp +1149 -0
  48. data/ext/libsass/eval.hpp +80 -0
  49. data/ext/libsass/expand.cpp +430 -0
  50. data/ext/libsass/expand.hpp +77 -0
  51. data/ext/libsass/extconf.rb +6 -0
  52. data/ext/libsass/extend.cpp +1962 -0
  53. data/ext/libsass/extend.hpp +50 -0
  54. data/ext/libsass/file.cpp +291 -0
  55. data/ext/libsass/file.hpp +18 -0
  56. data/ext/libsass/functions.cpp +1565 -0
  57. data/ext/libsass/functions.hpp +187 -0
  58. data/ext/libsass/inspect.cpp +727 -0
  59. data/ext/libsass/inspect.hpp +108 -0
  60. data/ext/libsass/json.cpp +1411 -0
  61. data/ext/libsass/json.hpp +117 -0
  62. data/ext/libsass/kwd_arg_macros.hpp +23 -0
  63. data/ext/libsass/m4/.gitkeep +0 -0
  64. data/ext/libsass/mapping.hpp +17 -0
  65. data/ext/libsass/memory_manager.hpp +54 -0
  66. data/ext/libsass/node.cpp +251 -0
  67. data/ext/libsass/node.hpp +122 -0
  68. data/ext/libsass/operation.hpp +153 -0
  69. data/ext/libsass/output_compressed.cpp +401 -0
  70. data/ext/libsass/output_compressed.hpp +95 -0
  71. data/ext/libsass/output_nested.cpp +364 -0
  72. data/ext/libsass/output_nested.hpp +108 -0
  73. data/ext/libsass/parser.cpp +2016 -0
  74. data/ext/libsass/parser.hpp +264 -0
  75. data/ext/libsass/paths.hpp +69 -0
  76. data/ext/libsass/position.hpp +22 -0
  77. data/ext/libsass/posix/getopt.c +562 -0
  78. data/ext/libsass/posix/getopt.h +95 -0
  79. data/ext/libsass/prelexer.cpp +688 -0
  80. data/ext/libsass/prelexer.hpp +513 -0
  81. data/ext/libsass/remove_placeholders.cpp +59 -0
  82. data/ext/libsass/remove_placeholders.hpp +43 -0
  83. data/ext/libsass/res/resource.rc +35 -0
  84. data/ext/libsass/sass.cpp +33 -0
  85. data/ext/libsass/sass.h +60 -0
  86. data/ext/libsass/sass2scss.cpp +834 -0
  87. data/ext/libsass/sass2scss.h +110 -0
  88. data/ext/libsass/sass_context.cpp +709 -0
  89. data/ext/libsass/sass_context.h +120 -0
  90. data/ext/libsass/sass_functions.cpp +137 -0
  91. data/ext/libsass/sass_functions.h +90 -0
  92. data/ext/libsass/sass_interface.cpp +277 -0
  93. data/ext/libsass/sass_interface.h +97 -0
  94. data/ext/libsass/sass_util.cpp +136 -0
  95. data/ext/libsass/sass_util.hpp +259 -0
  96. data/ext/libsass/sass_values.cpp +337 -0
  97. data/ext/libsass/sass_values.h +124 -0
  98. data/ext/libsass/script/bootstrap +10 -0
  99. data/ext/libsass/script/branding +10 -0
  100. data/ext/libsass/script/ci-build-libsass +72 -0
  101. data/ext/libsass/script/ci-install-compiler +4 -0
  102. data/ext/libsass/script/ci-install-deps +19 -0
  103. data/ext/libsass/script/ci-report-coverage +25 -0
  104. data/ext/libsass/script/coveralls-debug +32 -0
  105. data/ext/libsass/script/spec +5 -0
  106. data/ext/libsass/script/tap-driver +652 -0
  107. data/ext/libsass/script/tap-runner +1 -0
  108. data/ext/libsass/source_map.cpp +133 -0
  109. data/ext/libsass/source_map.hpp +46 -0
  110. data/ext/libsass/subset_map.hpp +145 -0
  111. data/ext/libsass/support/libsass.pc.in +11 -0
  112. data/ext/libsass/test-driver +127 -0
  113. data/ext/libsass/test/test_node.cpp +98 -0
  114. data/ext/libsass/test/test_paths.cpp +29 -0
  115. data/ext/libsass/test/test_selector_difference.cpp +28 -0
  116. data/ext/libsass/test/test_specificity.cpp +28 -0
  117. data/ext/libsass/test/test_subset_map.cpp +472 -0
  118. data/ext/libsass/test/test_superselector.cpp +71 -0
  119. data/ext/libsass/test/test_unification.cpp +33 -0
  120. data/ext/libsass/to_c.cpp +61 -0
  121. data/ext/libsass/to_c.hpp +44 -0
  122. data/ext/libsass/to_string.cpp +29 -0
  123. data/ext/libsass/to_string.hpp +32 -0
  124. data/ext/libsass/token.hpp +32 -0
  125. data/ext/libsass/units.cpp +54 -0
  126. data/ext/libsass/units.hpp +10 -0
  127. data/ext/libsass/utf8.h +34 -0
  128. data/ext/libsass/utf8/checked.h +327 -0
  129. data/ext/libsass/utf8/core.h +329 -0
  130. data/ext/libsass/utf8/unchecked.h +228 -0
  131. data/ext/libsass/utf8_string.cpp +102 -0
  132. data/ext/libsass/utf8_string.hpp +36 -0
  133. data/ext/libsass/util.cpp +189 -0
  134. data/ext/libsass/util.hpp +26 -0
  135. data/ext/libsass/win/libsass.filters +291 -0
  136. data/ext/libsass/win/libsass.sln +28 -0
  137. data/ext/libsass/win/libsass.vcxproj +255 -0
  138. data/lib/sassc.rb +6 -0
  139. data/lib/sassc/engine.rb +13 -0
  140. data/lib/sassc/native.rb +44 -0
  141. data/lib/sassc/native/native_context_api.rb +140 -0
  142. data/lib/sassc/native/native_functions_api.rb +41 -0
  143. data/lib/sassc/native/sass_input_style.rb +11 -0
  144. data/lib/sassc/native/sass_output_style.rb +10 -0
  145. data/lib/sassc/native/sass_value.rb +95 -0
  146. data/lib/sassc/native/string_list.rb +8 -0
  147. data/lib/sassc/version.rb +3 -0
  148. data/sassc.gemspec +43 -0
  149. data/test/smoke_test.rb +171 -0
  150. data/test/test_helper.rb +4 -0
  151. metadata +281 -0
@@ -0,0 +1,97 @@
1
+ #ifndef SASS_C_INTERFACE
2
+ #define SASS_C_INTERFACE
3
+
4
+ #include <stddef.h>
5
+ #include <stdbool.h>
6
+ #include "sass.h"
7
+
8
+ #ifdef __cplusplus
9
+ extern "C" {
10
+ #endif
11
+
12
+
13
+ // Please ensure there are no null values.
14
+ // Thar be dragons.
15
+ struct sass_options {
16
+ // Output style for the generated css code
17
+ // A value from above SASS_STYLE_* constants
18
+ int output_style;
19
+ // If you want inline source comments
20
+ bool source_comments;
21
+ // Path to source map file
22
+ // Enables the source map generating
23
+ // Used to create sourceMappingUrl
24
+ const char* source_map_file;
25
+ // Disable sourceMappingUrl in css output
26
+ bool omit_source_map_url;
27
+ // embed sourceMappingUrl as data uri
28
+ bool source_map_embed;
29
+ // embed include contents in maps
30
+ bool source_map_contents;
31
+ // Treat source_string as sass (as opposed to scss)
32
+ bool is_indented_syntax_src;
33
+ // Colon-separated list of paths
34
+ // Semicolon-separated on Windows
35
+ const char* include_paths;
36
+ // For the image-url Sass function
37
+ const char* image_path;
38
+ // Precision for outputting fractional numbers
39
+ int precision;
40
+ };
41
+
42
+ struct sass_context {
43
+ const char* input_path;
44
+ const char* output_path;
45
+ const char* source_string;
46
+ char* output_string;
47
+ char* source_map_string;
48
+ struct sass_options options;
49
+ int error_status;
50
+ char* error_message;
51
+ Sass_C_Function_List c_functions;
52
+ char** included_files;
53
+ int num_included_files;
54
+ };
55
+
56
+ struct sass_file_context {
57
+ const char* input_path;
58
+ const char* output_path;
59
+ char* output_string;
60
+ char* source_map_string;
61
+ struct sass_options options;
62
+ int error_status;
63
+ char* error_message;
64
+ Sass_C_Function_List c_functions;
65
+ char** included_files;
66
+ int num_included_files;
67
+ };
68
+
69
+ struct sass_folder_context {
70
+ const char* search_path;
71
+ const char* output_path;
72
+ struct sass_options options;
73
+ int error_status;
74
+ char* error_message;
75
+ Sass_C_Function_List c_functions;
76
+ char** included_files;
77
+ int num_included_files;
78
+ };
79
+
80
+ struct sass_context* sass_new_context (void);
81
+ struct sass_file_context* sass_new_file_context (void);
82
+ struct sass_folder_context* sass_new_folder_context (void);
83
+
84
+ void sass_free_context (struct sass_context* ctx);
85
+ void sass_free_file_context (struct sass_file_context* ctx);
86
+ void sass_free_folder_context(struct sass_folder_context* ctx);
87
+
88
+ int sass_compile (struct sass_context* ctx);
89
+ int sass_compile_file (struct sass_file_context* ctx);
90
+ int sass_compile_folder (struct sass_folder_context* ctx);
91
+
92
+
93
+ #ifdef __cplusplus
94
+ }
95
+ #endif
96
+
97
+ #endif
@@ -0,0 +1,136 @@
1
+ #ifndef SASS_AST
2
+ #include "node.hpp"
3
+ #endif
4
+
5
+ #include "to_string.hpp"
6
+
7
+
8
+ namespace Sass {
9
+
10
+
11
+ /*
12
+ This is the equivalent of ruby's Sass::Util.paths.
13
+
14
+ # Return an array of all possible paths through the given arrays.
15
+ #
16
+ # @param arrs [NodeCollection<NodeCollection<Node>>]
17
+ # @return [NodeCollection<NodeCollection<Node>>]
18
+ #
19
+ # @example
20
+ # paths([[1, 2], [3, 4], [5]]) #=>
21
+ # # [[1, 3, 5],
22
+ # # [2, 3, 5],
23
+ # # [1, 4, 5],
24
+ # # [2, 4, 5]]
25
+
26
+ The following is the modified version of the ruby code that was more portable to C++. You
27
+ should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
28
+
29
+ def paths(arrs)
30
+ // I changed the inject and maps to an iterative approach to make it easier to implement in C++
31
+ loopStart = [[]]
32
+
33
+ for arr in arrs do
34
+ permutations = []
35
+ for e in arr do
36
+ for path in loopStart do
37
+ permutations.push(path + [e])
38
+ end
39
+ end
40
+ loopStart = permutations
41
+ end
42
+ end
43
+ */
44
+ Node paths(const Node& arrs, Context& ctx) {
45
+ To_String to_string;
46
+
47
+ Node loopStart = Node::createCollection();
48
+ loopStart.collection()->push_back(Node::createCollection());
49
+
50
+ for (NodeDeque::iterator arrsIter = arrs.collection()->begin(), arrsEndIter = arrs.collection()->end();
51
+ arrsIter != arrsEndIter; ++arrsIter) {
52
+
53
+ Node& arr = *arrsIter;
54
+
55
+ Node permutations = Node::createCollection();
56
+
57
+ for (NodeDeque::iterator arrIter = arr.collection()->begin(), arrIterEnd = arr.collection()->end();
58
+ arrIter != arrIterEnd; ++arrIter) {
59
+
60
+ Node& e = *arrIter;
61
+
62
+ for (NodeDeque::iterator loopStartIter = loopStart.collection()->begin(), loopStartIterEnd = loopStart.collection()->end();
63
+ loopStartIter != loopStartIterEnd; ++loopStartIter) {
64
+
65
+ Node& path = *loopStartIter;
66
+
67
+ Node newPermutation = Node::createCollection();
68
+ newPermutation.plus(path);
69
+ newPermutation.collection()->push_back(e);
70
+
71
+ permutations.collection()->push_back(newPermutation);
72
+ }
73
+ }
74
+
75
+ loopStart = permutations;
76
+ }
77
+
78
+ return loopStart;
79
+ }
80
+
81
+
82
+ /*
83
+ This is the equivalent of ruby sass' Sass::Util.flatten and [].flatten.
84
+ Sass::Util.flatten requires the number of levels to flatten, while
85
+ [].flatten doesn't and will flatten the entire array. This function
86
+ supports both.
87
+
88
+ # Flattens the first `n` nested arrays. If n == -1, all arrays will be flattened
89
+ #
90
+ # @param arr [NodeCollection] The array to flatten
91
+ # @param n [int] The number of levels to flatten
92
+ # @return [NodeCollection] The flattened array
93
+
94
+ The following is the modified version of the ruby code that was more portable to C++. You
95
+ should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
96
+
97
+ def flatten(arr, n = -1)
98
+ if n != -1 and n == 0 then
99
+ return arr
100
+ end
101
+
102
+ flattened = []
103
+
104
+ for e in arr do
105
+ if e.is_a?(Array) then
106
+ flattened.concat(flatten(e, n - 1))
107
+ else
108
+ flattened << e
109
+ end
110
+ end
111
+
112
+ return flattened
113
+ end
114
+ */
115
+ Node flatten(const Node& arr, Context& ctx, int n = -1) {
116
+ if (n != -1 && n == 0) {
117
+ return arr;
118
+ }
119
+
120
+ Node flattened = Node::createCollection();
121
+
122
+ for (NodeDeque::iterator iter = arr.collection()->begin(), iterEnd = arr.collection()->end();
123
+ iter != iterEnd; iter++) {
124
+ Node& e = *iter;
125
+
126
+ if (e.isCollection()) {
127
+ Node recurseFlattened = flatten(e, ctx, n - 1);
128
+ flattened.collection()->insert(flattened.collection()->end(), recurseFlattened.collection()->begin(), recurseFlattened.collection()->end());
129
+ } else {
130
+ flattened.collection()->push_back(e);
131
+ }
132
+ }
133
+
134
+ return flattened;
135
+ }
136
+ }
@@ -0,0 +1,259 @@
1
+ #include <deque>
2
+ #include <iostream>
3
+
4
+ #ifndef SASS_AST
5
+ #include "ast.hpp"
6
+ #endif
7
+
8
+ #include "node.hpp"
9
+ #include "debug.hpp"
10
+
11
+
12
+ namespace Sass {
13
+
14
+
15
+ using namespace std;
16
+
17
+
18
+ /*
19
+ This is for ports of functions in the Sass:Util module.
20
+ */
21
+
22
+
23
+ /*
24
+ # Return a Node collection of all possible paths through the given Node collection of Node collections.
25
+ #
26
+ # @param arrs [NodeCollection<NodeCollection<Node>>]
27
+ # @return [NodeCollection<NodeCollection<Node>>]
28
+ #
29
+ # @example
30
+ # paths([[1, 2], [3, 4], [5]]) #=>
31
+ # # [[1, 3, 5],
32
+ # # [2, 3, 5],
33
+ # # [1, 4, 5],
34
+ # # [2, 4, 5]]
35
+ */
36
+ Node paths(const Node& arrs, Context& ctx);
37
+
38
+
39
+ /*
40
+ This class is a default implementation of a Node comparator that can be passed to the lcs function below.
41
+ It uses operator== for equality comparision. It then returns one if the Nodes are equal.
42
+ */
43
+ class DefaultLcsComparator {
44
+ public:
45
+ bool operator()(const Node& one, const Node& two, Node& out) const {
46
+ // TODO: Is this the correct C++ interpretation?
47
+ // block ||= proc {|a, b| a == b && a}
48
+ if (one == two) {
49
+ out = one;
50
+ return true;
51
+ }
52
+
53
+ return false;
54
+ }
55
+ };
56
+
57
+
58
+ typedef vector<vector<int> > LCSTable;
59
+
60
+
61
+ /*
62
+ This is the equivalent of ruby's Sass::Util.lcs_backtrace.
63
+
64
+ # Computes a single longest common subsequence for arrays x and y.
65
+ # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS
66
+ */
67
+ template<typename ComparatorType>
68
+ Node lcs_backtrace(const LCSTable& c, const Node& x, const Node& y, int i, int j, const ComparatorType& comparator) {
69
+ DEBUG_PRINTLN(LCS, "LCSBACK: X=" << x << " Y=" << y << " I=" << i << " J=" << j)
70
+
71
+ if (i == 0 || j == 0) {
72
+ DEBUG_PRINTLN(LCS, "RETURNING EMPTY")
73
+ return Node::createCollection();
74
+ }
75
+
76
+ NodeDeque& xChildren = *(x.collection());
77
+ NodeDeque& yChildren = *(y.collection());
78
+
79
+ Node compareOut = Node::createNil();
80
+ if (comparator(xChildren[i], yChildren[j], compareOut)) {
81
+ DEBUG_PRINTLN(LCS, "RETURNING AFTER ELEM COMPARE")
82
+ Node result = lcs_backtrace(c, x, y, i - 1, j - 1, comparator);
83
+ result.collection()->push_back(compareOut);
84
+ return result;
85
+ }
86
+
87
+ if (c[i][j - 1] > c[i - 1][j]) {
88
+ DEBUG_PRINTLN(LCS, "RETURNING AFTER TABLE COMPARE")
89
+ return lcs_backtrace(c, x, y, i, j - 1, comparator);
90
+ }
91
+
92
+ DEBUG_PRINTLN(LCS, "FINAL RETURN")
93
+ return lcs_backtrace(c, x, y, i - 1, j, comparator);
94
+ }
95
+
96
+
97
+ /*
98
+ This is the equivalent of ruby's Sass::Util.lcs_table.
99
+
100
+ # Calculates the memoization table for the Least Common Subsequence algorithm.
101
+ # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS
102
+ */
103
+ template<typename ComparatorType>
104
+ void lcs_table(const Node& x, const Node& y, const ComparatorType& comparator, LCSTable& out) {
105
+ DEBUG_PRINTLN(LCS, "LCSTABLE: X=" << x << " Y=" << y)
106
+
107
+ NodeDeque& xChildren = *(x.collection());
108
+ NodeDeque& yChildren = *(y.collection());
109
+
110
+ LCSTable c(xChildren.size(), vector<int>(yChildren.size()));
111
+
112
+ // These shouldn't be necessary since the vector will be initialized to 0 already.
113
+ // x.size.times {|i| c[i][0] = 0}
114
+ // y.size.times {|j| c[0][j] = 0}
115
+
116
+ for (size_t i = 1; i < xChildren.size(); i++) {
117
+ for (size_t j = 1; j < yChildren.size(); j++) {
118
+ Node compareOut = Node::createNil();
119
+
120
+ if (comparator(xChildren[i], yChildren[j], compareOut)) {
121
+ c[i][j] = c[i - 1][j - 1] + 1;
122
+ } else {
123
+ c[i][j] = max(c[i][j - 1], c[i - 1][j]);
124
+ }
125
+ }
126
+ }
127
+
128
+ out = c;
129
+ }
130
+
131
+
132
+ /*
133
+ This is the equivalent of ruby's Sass::Util.lcs.
134
+
135
+ # Computes a single longest common subsequence for `x` and `y`.
136
+ # If there are more than one longest common subsequences,
137
+ # the one returned is that which starts first in `x`.
138
+
139
+ # @param x [NodeCollection]
140
+ # @param y [NodeCollection]
141
+ # @comparator An equality check between elements of `x` and `y`.
142
+ # @return [NodeCollection] The LCS
143
+
144
+ http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
145
+ */
146
+ template<typename ComparatorType>
147
+ Node lcs(Node& x, Node& y, const ComparatorType& comparator, Context& ctx) {
148
+ DEBUG_PRINTLN(LCS, "LCS: X=" << x << " Y=" << y)
149
+
150
+ Node newX = Node::createCollection();
151
+ newX.collection()->push_back(Node::createNil());
152
+ newX.plus(x);
153
+
154
+ Node newY = Node::createCollection();
155
+ newY.collection()->push_back(Node::createNil());
156
+ newY.plus(y);
157
+
158
+ LCSTable table;
159
+ lcs_table(newX, newY, comparator, table);
160
+
161
+ return lcs_backtrace(table, newX, newY, static_cast<int>(newX.collection()->size()) - 1, static_cast<int>(newY.collection()->size()) - 1, comparator);
162
+ }
163
+
164
+
165
+ /*
166
+ This is the equivalent of ruby sass' Sass::Util.flatten and [].flatten.
167
+ Sass::Util.flatten requires the number of levels to flatten, while
168
+ [].flatten doesn't and will flatten the entire array. This function
169
+ supports both.
170
+
171
+ # Flattens the first `n` nested arrays. If n == -1, all arrays will be flattened
172
+ #
173
+ # @param arr [NodeCollection] The array to flatten
174
+ # @param n [int] The number of levels to flatten
175
+ # @return [NodeCollection] The flattened array
176
+ */
177
+ Node flatten(const Node& arr, Context& ctx, int n = -1);
178
+
179
+
180
+ /*
181
+ This is the equivalent of ruby's Sass::Util.group_by_to_a.
182
+
183
+ # Performs the equivalent of `enum.group_by.to_a`, but with a guaranteed
184
+ # order. Unlike [#hash_to_a], the resulting order isn't sorted key order;
185
+ # instead, it's the same order as `#group_by` has under Ruby 1.9 (key
186
+ # appearance order).
187
+ #
188
+ # @param enum [Enumerable]
189
+ # @return [Array<[Object, Array]>] An array of pairs.
190
+
191
+ TODO: update @param and @return once I know what those are.
192
+
193
+ The following is the modified version of the ruby code that was more portable to C++. You
194
+ should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
195
+
196
+ def group_by_to_a(enum, &block)
197
+ order = {}
198
+
199
+ arr = []
200
+
201
+ grouped = {}
202
+
203
+ for e in enum do
204
+ key = block[e]
205
+ unless order.include?(key)
206
+ order[key] = order.size
207
+ end
208
+
209
+ if not grouped.has_key?(key) then
210
+ grouped[key] = [e]
211
+ else
212
+ grouped[key].push(e)
213
+ end
214
+ end
215
+
216
+ grouped.each do |key, vals|
217
+ arr[order[key]] = [key, vals]
218
+ end
219
+
220
+ arr
221
+ end
222
+
223
+ */
224
+ template<typename EnumType, typename KeyType, typename KeyFunctorType>
225
+ void group_by_to_a(vector<EnumType>& enumeration, KeyFunctorType& keyFunc, vector<pair<KeyType, vector<EnumType> > >& arr /*out*/) {
226
+
227
+ map<unsigned int, KeyType> order;
228
+
229
+ map<KeyType, vector<EnumType> > grouped;
230
+
231
+ for (typename vector<EnumType>::iterator enumIter = enumeration.begin(), enumIterEnd = enumeration.end(); enumIter != enumIterEnd; enumIter++) {
232
+ EnumType& e = *enumIter;
233
+
234
+ KeyType key = keyFunc(e);
235
+
236
+ if (grouped.find(key) == grouped.end()) {
237
+ order.insert(make_pair(order.size(), key));
238
+
239
+ vector<EnumType> newCollection;
240
+ newCollection.push_back(e);
241
+ grouped.insert(make_pair(key, newCollection));
242
+ } else {
243
+ vector<EnumType>& collection = grouped.at(key);
244
+ collection.push_back(e);
245
+ }
246
+ }
247
+
248
+ for (unsigned int index = 0; index < order.size(); index++) {
249
+ KeyType& key = order.at(index);
250
+ vector<EnumType>& values = grouped.at(key);
251
+
252
+ pair<KeyType, vector<EnumType> > grouping = make_pair(key, values);
253
+
254
+ arr.push_back(grouping);
255
+ }
256
+ }
257
+
258
+
259
+ }