sassc 2.1.0.pre3 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +24 -0
  4. data/Rakefile +2 -4
  5. data/ext/extconf.rb +13 -5
  6. data/ext/libsass/VERSION +1 -1
  7. data/ext/libsass/include/sass/base.h +2 -1
  8. data/ext/libsass/include/sass/context.h +4 -0
  9. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  10. data/ext/libsass/src/ast.cpp +158 -168
  11. data/ext/libsass/src/ast.hpp +389 -230
  12. data/ext/libsass/src/ast_def_macros.hpp +18 -10
  13. data/ext/libsass/src/ast_fwd_decl.cpp +4 -3
  14. data/ext/libsass/src/ast_fwd_decl.hpp +98 -165
  15. data/ext/libsass/src/ast_helpers.hpp +292 -0
  16. data/ext/libsass/src/ast_sel_cmp.cpp +219 -732
  17. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  18. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  19. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  20. data/ext/libsass/src/ast_selectors.cpp +594 -1026
  21. data/ext/libsass/src/ast_selectors.hpp +339 -385
  22. data/ext/libsass/src/ast_supports.cpp +36 -52
  23. data/ext/libsass/src/ast_supports.hpp +29 -29
  24. data/ext/libsass/src/ast_values.cpp +271 -84
  25. data/ext/libsass/src/ast_values.hpp +116 -107
  26. data/ext/libsass/src/backtrace.cpp +9 -9
  27. data/ext/libsass/src/backtrace.hpp +5 -5
  28. data/ext/libsass/src/base64vlq.cpp +2 -2
  29. data/ext/libsass/src/base64vlq.hpp +1 -1
  30. data/ext/libsass/src/bind.cpp +18 -18
  31. data/ext/libsass/src/bind.hpp +1 -1
  32. data/ext/libsass/src/c2ast.cpp +3 -3
  33. data/ext/libsass/src/c2ast.hpp +1 -1
  34. data/ext/libsass/src/cencode.c +4 -6
  35. data/ext/libsass/src/check_nesting.cpp +40 -41
  36. data/ext/libsass/src/check_nesting.hpp +6 -2
  37. data/ext/libsass/src/color_maps.cpp +14 -13
  38. data/ext/libsass/src/color_maps.hpp +1 -9
  39. data/ext/libsass/src/constants.cpp +5 -0
  40. data/ext/libsass/src/constants.hpp +6 -0
  41. data/ext/libsass/src/context.cpp +92 -119
  42. data/ext/libsass/src/context.hpp +41 -53
  43. data/ext/libsass/src/cssize.cpp +66 -149
  44. data/ext/libsass/src/cssize.hpp +17 -23
  45. data/ext/libsass/src/dart_helpers.hpp +199 -0
  46. data/ext/libsass/src/debugger.hpp +451 -295
  47. data/ext/libsass/src/emitter.cpp +15 -16
  48. data/ext/libsass/src/emitter.hpp +10 -12
  49. data/ext/libsass/src/environment.cpp +27 -27
  50. data/ext/libsass/src/environment.hpp +29 -24
  51. data/ext/libsass/src/error_handling.cpp +62 -41
  52. data/ext/libsass/src/error_handling.hpp +61 -51
  53. data/ext/libsass/src/eval.cpp +167 -281
  54. data/ext/libsass/src/eval.hpp +27 -29
  55. data/ext/libsass/src/eval_selectors.cpp +75 -0
  56. data/ext/libsass/src/expand.cpp +275 -222
  57. data/ext/libsass/src/expand.hpp +36 -16
  58. data/ext/libsass/src/extender.cpp +1188 -0
  59. data/ext/libsass/src/extender.hpp +399 -0
  60. data/ext/libsass/src/extension.cpp +43 -0
  61. data/ext/libsass/src/extension.hpp +89 -0
  62. data/ext/libsass/src/file.cpp +81 -72
  63. data/ext/libsass/src/file.hpp +28 -37
  64. data/ext/libsass/src/fn_colors.cpp +20 -18
  65. data/ext/libsass/src/fn_lists.cpp +30 -29
  66. data/ext/libsass/src/fn_maps.cpp +3 -3
  67. data/ext/libsass/src/fn_miscs.cpp +34 -46
  68. data/ext/libsass/src/fn_numbers.cpp +20 -13
  69. data/ext/libsass/src/fn_selectors.cpp +98 -128
  70. data/ext/libsass/src/fn_strings.cpp +47 -33
  71. data/ext/libsass/src/fn_utils.cpp +31 -29
  72. data/ext/libsass/src/fn_utils.hpp +17 -11
  73. data/ext/libsass/src/inspect.cpp +186 -148
  74. data/ext/libsass/src/inspect.hpp +31 -29
  75. data/ext/libsass/src/lexer.cpp +20 -82
  76. data/ext/libsass/src/lexer.hpp +5 -16
  77. data/ext/libsass/src/listize.cpp +23 -37
  78. data/ext/libsass/src/listize.hpp +8 -9
  79. data/ext/libsass/src/mapping.hpp +1 -0
  80. data/ext/libsass/src/memory.hpp +12 -0
  81. data/ext/libsass/src/memory/allocator.cpp +48 -0
  82. data/ext/libsass/src/memory/allocator.hpp +138 -0
  83. data/ext/libsass/src/memory/config.hpp +20 -0
  84. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  85. data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
  86. data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +55 -9
  87. data/ext/libsass/src/operation.hpp +71 -61
  88. data/ext/libsass/src/operators.cpp +19 -18
  89. data/ext/libsass/src/operators.hpp +11 -11
  90. data/ext/libsass/src/ordered_map.hpp +112 -0
  91. data/ext/libsass/src/output.cpp +45 -64
  92. data/ext/libsass/src/output.hpp +6 -6
  93. data/ext/libsass/src/parser.cpp +512 -700
  94. data/ext/libsass/src/parser.hpp +89 -97
  95. data/ext/libsass/src/parser_selectors.cpp +189 -0
  96. data/ext/libsass/src/permutate.hpp +164 -0
  97. data/ext/libsass/src/plugins.cpp +7 -7
  98. data/ext/libsass/src/plugins.hpp +8 -8
  99. data/ext/libsass/src/position.cpp +7 -26
  100. data/ext/libsass/src/position.hpp +44 -21
  101. data/ext/libsass/src/prelexer.cpp +6 -6
  102. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  103. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  104. data/ext/libsass/src/sass.cpp +16 -15
  105. data/ext/libsass/src/sass.hpp +10 -5
  106. data/ext/libsass/src/sass2scss.cpp +4 -4
  107. data/ext/libsass/src/sass_context.cpp +91 -122
  108. data/ext/libsass/src/sass_context.hpp +2 -2
  109. data/ext/libsass/src/sass_functions.cpp +1 -1
  110. data/ext/libsass/src/sass_values.cpp +8 -11
  111. data/ext/libsass/src/settings.hpp +19 -0
  112. data/ext/libsass/src/source.cpp +69 -0
  113. data/ext/libsass/src/source.hpp +95 -0
  114. data/ext/libsass/src/source_data.hpp +32 -0
  115. data/ext/libsass/src/source_map.cpp +22 -18
  116. data/ext/libsass/src/source_map.hpp +12 -9
  117. data/ext/libsass/src/stylesheet.cpp +22 -0
  118. data/ext/libsass/src/stylesheet.hpp +57 -0
  119. data/ext/libsass/src/to_value.cpp +2 -2
  120. data/ext/libsass/src/to_value.hpp +1 -1
  121. data/ext/libsass/src/units.cpp +24 -22
  122. data/ext/libsass/src/units.hpp +8 -8
  123. data/ext/libsass/src/utf8_string.cpp +9 -10
  124. data/ext/libsass/src/utf8_string.hpp +7 -6
  125. data/ext/libsass/src/util.cpp +48 -50
  126. data/ext/libsass/src/util.hpp +20 -21
  127. data/ext/libsass/src/util_string.cpp +111 -61
  128. data/ext/libsass/src/util_string.hpp +62 -8
  129. data/ext/libsass/src/values.cpp +12 -12
  130. data/lib/sassc/engine.rb +5 -3
  131. data/lib/sassc/functions_handler.rb +11 -13
  132. data/lib/sassc/native.rb +9 -7
  133. data/lib/sassc/script.rb +4 -6
  134. data/lib/sassc/version.rb +1 -1
  135. data/test/functions_test.rb +38 -1
  136. data/test/native_test.rb +4 -4
  137. metadata +31 -18
  138. data/ext/libsass/src/extend.cpp +0 -2132
  139. data/ext/libsass/src/extend.hpp +0 -86
  140. data/ext/libsass/src/node.cpp +0 -322
  141. data/ext/libsass/src/node.hpp +0 -118
  142. data/ext/libsass/src/paths.hpp +0 -71
  143. data/ext/libsass/src/sass_util.cpp +0 -152
  144. data/ext/libsass/src/sass_util.hpp +0 -256
  145. data/ext/libsass/src/subset_map.cpp +0 -58
  146. data/ext/libsass/src/subset_map.hpp +0 -76
  147. data/lib/sassc/native/lib_c.rb +0 -21
@@ -0,0 +1,292 @@
1
+ #ifndef SASS_AST_HELPERS_H
2
+ #define SASS_AST_HELPERS_H
3
+
4
+ // sass.hpp must go before all system headers to get the
5
+ // __EXTENSIONS__ fix on Solaris.
6
+ #include "sass.hpp"
7
+ #include <algorithm>
8
+ #include <functional>
9
+ #include "util_string.hpp"
10
+
11
+ namespace Sass {
12
+
13
+ // ###########################################################################
14
+ // ###########################################################################
15
+
16
+ // easier to search with name
17
+ const bool DELAYED = true;
18
+
19
+ // ToDo: should this really be hardcoded
20
+ // Note: most methods follow precision option
21
+ const double NUMBER_EPSILON = 1e-12;
22
+
23
+ // macro to test if numbers are equal within a small error margin
24
+ #define NEAR_EQUAL(lhs, rhs) std::fabs(lhs - rhs) < NUMBER_EPSILON
25
+
26
+ // ###########################################################################
27
+ // We define various functions and functors here.
28
+ // Functions satisfy the BinaryPredicate requirement
29
+ // Functors are structs used for e.g. unordered_map
30
+ // ###########################################################################
31
+
32
+ // ###########################################################################
33
+ // Implement compare and hashing operations for raw pointers
34
+ // ###########################################################################
35
+
36
+ template <class T>
37
+ size_t PtrHashFn(const T* ptr) {
38
+ return std::hash<std::size_t>()((size_t)ptr);
39
+ }
40
+
41
+ struct PtrHash {
42
+ template <class T>
43
+ size_t operator() (const T* ptr) const {
44
+ return PtrHashFn(ptr);
45
+ }
46
+ };
47
+
48
+ template <class T>
49
+ bool PtrEqualityFn(const T* lhs, const T* rhs) {
50
+ return lhs == rhs; // compare raw pointers
51
+ }
52
+
53
+ struct PtrEquality {
54
+ template <class T>
55
+ bool operator() (const T* lhs, const T* rhs) const {
56
+ return PtrEqualityFn<T>(lhs, rhs);
57
+ }
58
+ };
59
+
60
+ // ###########################################################################
61
+ // Implement compare and hashing operations for AST Nodes
62
+ // ###########################################################################
63
+
64
+ // TODO: get rid of funtions and use ObjEquality<T>
65
+
66
+ template <class T>
67
+ // Hash the raw pointer instead of object
68
+ size_t ObjPtrHashFn(const T& obj) {
69
+ return PtrHashFn(obj.ptr());
70
+ }
71
+
72
+ struct ObjPtrHash {
73
+ template <class T>
74
+ // Hash the raw pointer instead of object
75
+ size_t operator() (const T& obj) const {
76
+ return ObjPtrHashFn(obj);
77
+ }
78
+ };
79
+
80
+ template <class T>
81
+ // Hash the object and its content
82
+ size_t ObjHashFn(const T& obj) {
83
+ return obj ? obj->hash() : 0;
84
+ }
85
+
86
+ struct ObjHash {
87
+ template <class T>
88
+ // Hash the object and its content
89
+ size_t operator() (const T& obj) const {
90
+ return ObjHashFn(obj);
91
+ }
92
+ };
93
+
94
+ template <class T>
95
+ // Hash the object behind pointer
96
+ size_t PtrObjHashFn(const T* obj) {
97
+ return obj ? obj->hash() : 0;
98
+ }
99
+
100
+ struct PtrObjHash {
101
+ template <class T>
102
+ // Hash the object behind pointer
103
+ size_t operator() (const T* obj) const {
104
+ return PtrObjHashFn(obj);
105
+ }
106
+ };
107
+
108
+ template <class T>
109
+ // Compare raw pointers to the object
110
+ bool ObjPtrEqualityFn(const T& lhs, const T& rhs) {
111
+ return PtrEqualityFn(lhs.ptr(), rhs.ptr());
112
+ }
113
+
114
+ struct ObjPtrEquality {
115
+ template <class T>
116
+ // Compare raw pointers to the object
117
+ bool operator() (const T& lhs, const T& rhs) const {
118
+ return ObjPtrEqualityFn<T>(lhs, rhs);
119
+ }
120
+ };
121
+
122
+ template <class T>
123
+ // Compare the objects behind the pointers
124
+ bool PtrObjEqualityFn(const T* lhs, const T* rhs) {
125
+ if (lhs == nullptr) return rhs == nullptr;
126
+ else if (rhs == nullptr) return false;
127
+ else return *lhs == *rhs;
128
+ }
129
+
130
+ struct PtrObjEquality {
131
+ template <class T>
132
+ // Compare the objects behind the pointers
133
+ bool operator() (const T* lhs, const T* rhs) const {
134
+ return PtrObjEqualityFn<T>(lhs, rhs);
135
+ }
136
+ };
137
+
138
+ template <class T>
139
+ // Compare the objects and its contents
140
+ bool ObjEqualityFn(const T& lhs, const T& rhs) {
141
+ return PtrObjEqualityFn(lhs.ptr(), rhs.ptr());
142
+ }
143
+
144
+ struct ObjEquality {
145
+ template <class T>
146
+ // Compare the objects and its contents
147
+ bool operator() (const T& lhs, const T& rhs) const {
148
+ return ObjEqualityFn<T>(lhs, rhs);
149
+ }
150
+ };
151
+
152
+ // ###########################################################################
153
+ // Implement ordering operations for AST Nodes
154
+ // ###########################################################################
155
+
156
+ template <class T>
157
+ // Compare the objects behind pointers
158
+ bool PtrObjLessThanFn(const T* lhs, const T* rhs) {
159
+ if (lhs == nullptr) return rhs != nullptr;
160
+ else if (rhs == nullptr) return false;
161
+ else return *lhs < *rhs;
162
+ }
163
+
164
+ struct PtrObjLessThan {
165
+ template <class T>
166
+ // Compare the objects behind pointers
167
+ bool operator() (const T* lhs, const T* rhs) const {
168
+ return PtrObjLessThanFn<T>(lhs, rhs);
169
+ }
170
+ };
171
+
172
+ template <class T>
173
+ // Compare the objects and its content
174
+ bool ObjLessThanFn(const T& lhs, const T& rhs) {
175
+ return PtrObjLessThanFn(lhs.ptr(), rhs.ptr());
176
+ };
177
+
178
+ struct ObjLessThan {
179
+ template <class T>
180
+ // Compare the objects and its content
181
+ bool operator() (const T& lhs, const T& rhs) const {
182
+ return ObjLessThanFn<T>(lhs, rhs);
183
+ }
184
+ };
185
+
186
+ // ###########################################################################
187
+ // Some STL helper functions
188
+ // ###########################################################################
189
+
190
+ // Check if all elements are equal
191
+ template <class X, class Y,
192
+ typename XT = typename X::value_type,
193
+ typename YT = typename Y::value_type>
194
+ bool ListEquality(const X& lhs, const Y& rhs,
195
+ bool(*cmp)(const XT*, const YT*))
196
+ {
197
+ return lhs.size() == rhs.size() &&
198
+ std::equal(lhs.begin(), lhs.end(),
199
+ rhs.begin(), cmp);
200
+ }
201
+
202
+ // Return if Vector is empty
203
+ template <class T>
204
+ bool listIsEmpty(T* cnt) {
205
+ return cnt && cnt->empty();
206
+ }
207
+
208
+ // Erase items from vector that match predicate
209
+ template<class T, class UnaryPredicate>
210
+ void listEraseItemIf(T& vec, UnaryPredicate* predicate)
211
+ {
212
+ vec.erase(std::remove_if(vec.begin(), vec.end(), predicate), vec.end());
213
+ }
214
+
215
+ // Check that every item in `lhs` is also in `rhs`
216
+ // Note: this works by comparing the raw pointers
217
+ template <typename T>
218
+ bool listIsSubsetOrEqual(const T& lhs, const T& rhs) {
219
+ for (const auto& item : lhs) {
220
+ if (std::find(rhs.begin(), rhs.end(), item) == rhs.end())
221
+ return false;
222
+ }
223
+ return true;
224
+ }
225
+
226
+ // ##########################################################################
227
+ // Returns whether [name] is the name of a pseudo-element
228
+ // that can be written with pseudo-class syntax (CSS2 vs CSS3):
229
+ // `:before`, `:after`, `:first-line`, or `:first-letter`
230
+ // ##########################################################################
231
+ inline bool isFakePseudoElement(const sass::string& name)
232
+ {
233
+ return Util::equalsLiteral("after", name)
234
+ || Util::equalsLiteral("before", name)
235
+ || Util::equalsLiteral("first-line", name)
236
+ || Util::equalsLiteral("first-letter", name);
237
+ }
238
+
239
+ // ##########################################################################
240
+ // Names of pseudo selectors that take selectors as arguments,
241
+ // and that are subselectors of their arguments.
242
+ // For example, `.foo` is a superselector of `:matches(.foo)`.
243
+ // ##########################################################################
244
+ inline bool isSubselectorPseudo(const sass::string& norm)
245
+ {
246
+ return Util::equalsLiteral("any", norm)
247
+ || Util::equalsLiteral("matches", norm)
248
+ || Util::equalsLiteral("nth-child", norm)
249
+ || Util::equalsLiteral("nth-last-child", norm);
250
+ }
251
+ // EO isSubselectorPseudo
252
+
253
+ // ###########################################################################
254
+ // Pseudo-class selectors that take unadorned selectors as arguments.
255
+ // ###########################################################################
256
+ inline bool isSelectorPseudoClass(const sass::string& test)
257
+ {
258
+ return Util::equalsLiteral("not", test)
259
+ || Util::equalsLiteral("matches", test)
260
+ || Util::equalsLiteral("current", test)
261
+ || Util::equalsLiteral("any", test)
262
+ || Util::equalsLiteral("has", test)
263
+ || Util::equalsLiteral("host", test)
264
+ || Util::equalsLiteral("host-context", test);
265
+ }
266
+ // EO isSelectorPseudoClass
267
+
268
+ // ###########################################################################
269
+ // Pseudo-element selectors that take unadorned selectors as arguments.
270
+ // ###########################################################################
271
+ inline bool isSelectorPseudoElement(const sass::string& test)
272
+ {
273
+ return Util::equalsLiteral("slotted", test);
274
+ }
275
+ // EO isSelectorPseudoElement
276
+
277
+ // ###########################################################################
278
+ // Pseudo-element selectors that has binominals
279
+ // ###########################################################################
280
+ inline bool isSelectorPseudoBinominal(const sass::string& test)
281
+ {
282
+ return Util::equalsLiteral("nth-child", test)
283
+ || Util::equalsLiteral("nth-last-child", test);
284
+ }
285
+ // isSelectorPseudoBinominal
286
+
287
+ // ###########################################################################
288
+ // ###########################################################################
289
+
290
+ }
291
+
292
+ #endif
@@ -2,51 +2,17 @@
2
2
  // __EXTENSIONS__ fix on Solaris.
3
3
  #include "sass.hpp"
4
4
 
5
- #include "ast.hpp"
6
- #include "context.hpp"
7
- #include "node.hpp"
8
- #include "eval.hpp"
9
- #include "extend.hpp"
10
- #include "emitter.hpp"
11
- #include "color_maps.hpp"
12
- #include "ast_fwd_decl.hpp"
13
- #include <set>
14
- #include <iomanip>
15
- #include <iostream>
16
- #include <algorithm>
17
- #include <functional>
18
- #include <cctype>
19
- #include <locale>
20
-
21
5
  #include "ast_selectors.hpp"
22
6
 
23
7
  namespace Sass {
24
8
 
25
9
  /*#########################################################################*/
10
+ // Compare against base class on right hand side
11
+ // try to find the most specialized implementation
26
12
  /*#########################################################################*/
27
13
 
28
- bool Selector_List::operator== (const Selector& rhs) const
29
- {
30
- if (auto sl = Cast<Selector_List>(&rhs)) { return *this == *sl; }
31
- else if (auto ss = Cast<Simple_Selector>(&rhs)) { return *this == *ss; }
32
- else if (auto cpx = Cast<Complex_Selector>(&rhs)) { return *this == *cpx; }
33
- else if (auto cpd = Cast<Compound_Selector>(&rhs)) { return *this == *cpd; }
34
- else if (auto ls = Cast<List>(&rhs)) { return *this == *ls; }
35
- throw std::runtime_error("invalid selector base classes to compare");
36
- }
37
-
38
- bool Selector_List::operator< (const Selector& rhs) const
39
- {
40
- if (auto sl = Cast<Selector_List>(&rhs)) { return *this < *sl; }
41
- else if (auto ss = Cast<Simple_Selector>(&rhs)) { return *this < *ss; }
42
- else if (auto cpx = Cast<Complex_Selector>(&rhs)) { return *this < *cpx; }
43
- else if (auto cpd = Cast<Compound_Selector>(&rhs)) { return *this < *cpd; }
44
- else if (auto ls = Cast<List>(&rhs)) { return *this < *ls; }
45
- throw std::runtime_error("invalid selector base classes to compare");
46
- }
47
-
48
14
  // Selector lists can be compared to comma lists
49
- bool Selector_List::operator== (const Expression& rhs) const
15
+ bool SelectorList::operator== (const Expression& rhs) const
50
16
  {
51
17
  if (auto l = Cast<List>(&rhs)) { return *this == *l; }
52
18
  if (auto s = Cast<Selector>(&rhs)) { return *this == *s; }
@@ -55,852 +21,373 @@ namespace Sass {
55
21
  }
56
22
 
57
23
  // Selector lists can be compared to comma lists
58
- bool Selector_List::operator< (const Expression& rhs) const
59
- {
60
- if (auto l = Cast<List>(&rhs)) { return *this < *l; }
61
- if (auto s = Cast<Selector>(&rhs)) { return *this < *s; }
62
- if (Cast<String>(&rhs) || Cast<Null>(&rhs)) { return true; }
63
- throw std::runtime_error("invalid selector base classes to compare");
64
- }
65
-
66
- bool Complex_Selector::operator== (const Selector& rhs) const
67
- {
68
- if (auto sl = Cast<Selector_List>(&rhs)) return *this == *sl;
69
- if (auto ss = Cast<Simple_Selector>(&rhs)) return *this == *ss;
70
- if (auto cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
71
- if (auto ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
72
- throw std::runtime_error("invalid selector base classes to compare");
73
- }
74
-
75
- bool Complex_Selector::operator< (const Selector& rhs) const
76
- {
77
- if (auto sl = Cast<Selector_List>(&rhs)) return *this < *sl;
78
- if (auto ss = Cast<Simple_Selector>(&rhs)) return *this < *ss;
79
- if (auto cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
80
- if (auto ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
81
- throw std::runtime_error("invalid selector base classes to compare");
82
- }
83
-
84
- bool Compound_Selector::operator== (const Selector& rhs) const
24
+ bool SelectorList::operator== (const Selector& rhs) const
85
25
  {
86
- if (auto sl = Cast<Selector_List>(&rhs)) return *this == *sl;
87
- if (auto ss = Cast<Simple_Selector>(&rhs)) return *this == *ss;
88
- if (auto cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
89
- if (auto ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
26
+ if (auto sel = Cast<SelectorList>(&rhs)) { return *this == *sel; }
27
+ if (auto sel = Cast<ComplexSelector>(&rhs)) { return *this == *sel; }
28
+ if (auto sel = Cast<CompoundSelector>(&rhs)) { return *this == *sel; }
29
+ if (auto sel = Cast<SimpleSelector>(&rhs)) { return *this == *sel; }
30
+ if (auto list = Cast<List>(&rhs)) { return *this == *list; }
90
31
  throw std::runtime_error("invalid selector base classes to compare");
91
32
  }
92
33
 
93
- bool Compound_Selector::operator< (const Selector& rhs) const
34
+ bool ComplexSelector::operator== (const Selector& rhs) const
94
35
  {
95
- if (auto sl = Cast<Selector_List>(&rhs)) return *this < *sl;
96
- if (auto ss = Cast<Simple_Selector>(&rhs)) return *this < *ss;
97
- if (auto cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
98
- if (auto ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
36
+ if (auto sel = Cast<SelectorList>(&rhs)) { return *this == *sel; }
37
+ if (auto sel = Cast<ComplexSelector>(&rhs)) { return *sel == *this; }
38
+ if (auto sel = Cast<CompoundSelector>(&rhs)) { return *this == *sel; }
39
+ if (auto sel = Cast<SimpleSelector>(&rhs)) { return *this == *sel; }
99
40
  throw std::runtime_error("invalid selector base classes to compare");
100
41
  }
101
42
 
102
- bool Selector_Schema::operator== (const Selector& rhs) const
43
+ bool SelectorCombinator::operator== (const Selector& rhs) const
103
44
  {
104
- if (auto sl = Cast<Selector_List>(&rhs)) return *this == *sl;
105
- if (auto ss = Cast<Simple_Selector>(&rhs)) return *this == *ss;
106
- if (auto cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
107
- if (auto ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
108
- throw std::runtime_error("invalid selector base classes to compare");
109
- }
110
-
111
- bool Selector_Schema::operator< (const Selector& rhs) const
112
- {
113
- if (auto sl = Cast<Selector_List>(&rhs)) return *this < *sl;
114
- if (auto ss = Cast<Simple_Selector>(&rhs)) return *this < *ss;
115
- if (auto cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
116
- if (auto ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
117
- throw std::runtime_error("invalid selector base classes to compare");
45
+ if (auto cpx = Cast<SelectorCombinator>(&rhs)) { return *this == *cpx; }
46
+ return false;
118
47
  }
119
48
 
120
- bool Simple_Selector::operator== (const Selector& rhs) const
49
+ bool CompoundSelector::operator== (const Selector& rhs) const
121
50
  {
122
- if (auto sl = Cast<Selector_List>(&rhs)) return *this == *sl;
123
- if (auto ss = Cast<Simple_Selector>(&rhs)) return *this == *ss;
124
- if (auto cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
125
- if (auto ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
51
+ if (auto sel = Cast<SimpleSelector>(&rhs)) { return *this == *sel; }
52
+ if (auto sel = Cast<SelectorList>(&rhs)) { return *this == *sel; }
53
+ if (auto sel = Cast<ComplexSelector>(&rhs)) { return *this == *sel; }
54
+ if (auto sel = Cast<CompoundSelector>(&rhs)) { return *this == *sel; }
126
55
  throw std::runtime_error("invalid selector base classes to compare");
127
56
  }
128
57
 
129
- bool Simple_Selector::operator< (const Selector& rhs) const
58
+ bool SimpleSelector::operator== (const Selector& rhs) const
130
59
  {
131
- if (auto sl = Cast<Selector_List>(&rhs)) return *this < *sl;
132
- if (auto ss = Cast<Simple_Selector>(&rhs)) return *this < *ss;
133
- if (auto cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
134
- if (auto ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
60
+ if (auto sel = Cast<SelectorList>(&rhs)) { return *this == *sel; }
61
+ if (auto sel = Cast<ComplexSelector>(&rhs)) { return *this == *sel; }
62
+ if (auto sel = Cast<CompoundSelector>(&rhs)) { return *this == *sel; }
63
+ if (auto sel = Cast<SimpleSelector>(&rhs)) return *this == *sel;
135
64
  throw std::runtime_error("invalid selector base classes to compare");
136
65
  }
137
66
 
138
67
  /*#########################################################################*/
139
68
  /*#########################################################################*/
140
69
 
141
- bool Selector_List::operator< (const Selector_List& rhs) const
142
- {
143
- size_t l = rhs.length();
144
- if (length() < l) l = length();
145
- for (size_t i = 0; i < l; i ++) {
146
- if (*at(i) < *rhs.at(i)) return true;
147
- if (*at(i) != *rhs.at(i)) return false;
148
- }
149
- return false;
150
- }
151
-
152
- bool Selector_List::operator== (const Selector_List& rhs) const
70
+ bool SelectorList::operator== (const SelectorList& rhs) const
153
71
  {
154
72
  if (&rhs == this) return true;
155
73
  if (rhs.length() != length()) return false;
156
- std::unordered_set<const Complex_Selector *, HashPtr, ComparePtrs> lhs_set;
74
+ std::unordered_set<const ComplexSelector*, PtrObjHash, PtrObjEquality> lhs_set;
157
75
  lhs_set.reserve(length());
158
- for (const Complex_Selector_Obj &element : elements()) {
76
+ for (const ComplexSelectorObj& element : elements()) {
159
77
  lhs_set.insert(element.ptr());
160
78
  }
161
- for (const Complex_Selector_Obj &element : rhs.elements()) {
162
- if (lhs_set.find(element.ptr()) == lhs_set.end()) return false;
163
- }
164
- return true;
165
- }
166
-
167
- bool Compound_Selector::operator< (const Compound_Selector& rhs) const
168
- {
169
- size_t L = std::min(length(), rhs.length());
170
- for (size_t i = 0; i < L; ++i)
171
- {
172
- Simple_Selector* l = (*this)[i];
173
- Simple_Selector* r = rhs[i];
174
- if (!l && !r) return false;
175
- else if (!r) return false;
176
- else if (!l) return true;
177
- else if (*l != *r)
178
- { return *l < *r; }
179
- }
180
- // just compare the length now
181
- return length() < rhs.length();
182
- }
183
-
184
- bool Compound_Selector::operator== (const Compound_Selector& rhs) const
185
- {
186
- if (&rhs == this) return true;
187
- if (rhs.length() != length()) return false;
188
- std::unordered_set<const Simple_Selector *, HashPtr, ComparePtrs> lhs_set;
189
- lhs_set.reserve(length());
190
- for (const Simple_Selector_Obj &element : elements()) {
191
- lhs_set.insert(element.ptr());
192
- }
193
- // there is no break?!
194
- for (const Simple_Selector_Obj &element : rhs.elements()) {
79
+ for (const ComplexSelectorObj& element : rhs.elements()) {
195
80
  if (lhs_set.find(element.ptr()) == lhs_set.end()) return false;
196
81
  }
197
82
  return true;
198
83
  }
199
84
 
200
- bool Complex_Selector::operator< (const Complex_Selector& rhs) const
201
- {
202
- // const iterators for tails
203
- const Complex_Selector* l = this;
204
- const Complex_Selector* r = &rhs;
205
- Compound_Selector* l_h = NULL;
206
- Compound_Selector* r_h = NULL;
207
- if (l) l_h = l->head();
208
- if (r) r_h = r->head();
209
- // process all tails
210
- while (true)
211
- {
212
- #ifdef DEBUG
213
- // skip empty ancestor first
214
- if (l && l->is_empty_ancestor())
215
- {
216
- l_h = NULL;
217
- l = l->tail();
218
- if(l) l_h = l->head();
219
- continue;
220
- }
221
- // skip empty ancestor first
222
- if (r && r->is_empty_ancestor())
223
- {
224
- r_h = NULL;
225
- r = r->tail();
226
- if (r) r_h = r->head();
227
- continue;
228
- }
229
- #endif
230
- // check for valid selectors
231
- if (!l) return !!r;
232
- if (!r) return false;
233
- // both are null
234
- else if (!l_h && !r_h)
235
- {
236
- // check combinator after heads
237
- if (l->combinator() != r->combinator())
238
- { return l->combinator() < r->combinator(); }
239
- // advance to next tails
240
- l = l->tail();
241
- r = r->tail();
242
- // fetch the next headers
243
- l_h = NULL; r_h = NULL;
244
- if (l) l_h = l->head();
245
- if (r) r_h = r->head();
246
- }
247
- // one side is null
248
- else if (!r_h) return true;
249
- else if (!l_h) return false;
250
- // heads ok and equal
251
- else if (*l_h == *r_h)
252
- {
253
- // check combinator after heads
254
- if (l->combinator() != r->combinator())
255
- { return l->combinator() < r->combinator(); }
256
- // advance to next tails
257
- l = l->tail();
258
- r = r->tail();
259
- // fetch the next headers
260
- l_h = NULL; r_h = NULL;
261
- if (l) l_h = l->head();
262
- if (r) r_h = r->head();
263
- }
264
- // heads are not equal
265
- else return *l_h < *r_h;
266
- }
267
- }
268
85
 
269
- bool Complex_Selector::operator== (const Complex_Selector& rhs) const
270
- {
271
- // const iterators for tails
272
- const Complex_Selector* l = this;
273
- const Complex_Selector* r = &rhs;
274
- Compound_Selector* l_h = NULL;
275
- Compound_Selector* r_h = NULL;
276
- if (l) l_h = l->head();
277
- if (r) r_h = r->head();
278
- // process all tails
279
- while (true)
280
- {
281
- // check the pointers
282
- if (!r) return !l;
283
- if (!l) return !r;
284
- // both are null
285
- if (!l_h && !r_h)
286
- {
287
- // check combinator after heads
288
- if (l->combinator() != r->combinator())
289
- { return l->combinator() < r->combinator(); }
290
- // advance to next tails
291
- l = l->tail();
292
- r = r->tail();
293
- // fetch the next heads
294
- l_h = NULL; r_h = NULL;
295
- if (l) l_h = l->head();
296
- if (r) r_h = r->head();
297
- }
298
- // equals if other head is empty
299
- else if ((!l_h && !r_h) ||
300
- (!l_h && r_h->empty()) ||
301
- (!r_h && l_h->empty()) ||
302
- (l_h && r_h && *l_h == *r_h))
303
- {
304
- // check combinator after heads
305
- if (l->combinator() != r->combinator())
306
- { return l->combinator() == r->combinator(); }
307
- // advance to next tails
308
- l = l->tail();
309
- r = r->tail();
310
- // fetch the next heads
311
- l_h = NULL; r_h = NULL;
312
- if (l) l_h = l->head();
313
- if (r) r_h = r->head();
314
- }
315
- // abort
316
- else break;
317
- }
318
- // unreachable
319
- return false;
320
- }
321
86
 
322
87
  /*#########################################################################*/
88
+ // Compare SelectorList against all other selector types
323
89
  /*#########################################################################*/
324
90
 
325
- bool Selector_List::operator== (const Complex_Selector& rhs) const
326
- {
327
- size_t len = length();
328
- if (len > 1) return false;
329
- if (len == 0) return rhs.empty();
330
- return *at(0) == rhs;
331
- }
332
-
333
- bool Selector_List::operator< (const Complex_Selector& rhs) const
91
+ bool SelectorList::operator== (const ComplexSelector& rhs) const
334
92
  {
335
- size_t len = length();
336
- if (len > 1) return false;
337
- if (len == 0) return !rhs.empty();
338
- return *at(0) < rhs;
93
+ // If both are empty they are equal
94
+ if (empty() && rhs.empty()) return true;
95
+ // Must have exactly one item
96
+ if (length() != 1) return false;
97
+ // Compare simple selectors
98
+ return *get(0) == rhs;
339
99
  }
340
100
 
341
- bool Selector_List::operator== (const Compound_Selector& rhs) const
101
+ bool SelectorList::operator== (const CompoundSelector& rhs) const
342
102
  {
343
- size_t len = length();
344
- if (len > 1) return false;
345
- if (len == 0) return rhs.empty();
346
- return *at(0) == rhs;
103
+ // If both are empty they are equal
104
+ if (empty() && rhs.empty()) return true;
105
+ // Must have exactly one item
106
+ if (length() != 1) return false;
107
+ // Compare simple selectors
108
+ return *get(0) == rhs;
347
109
  }
348
110
 
349
- bool Selector_List::operator< (const Compound_Selector& rhs) const
111
+ bool SelectorList::operator== (const SimpleSelector& rhs) const
350
112
  {
351
- size_t len = length();
352
- if (len > 1) return false;
353
- if (len == 0) return !rhs.empty();
354
- return *at(0) < rhs;
113
+ // If both are empty they are equal
114
+ if (empty() && rhs.empty()) return true;
115
+ // Must have exactly one item
116
+ if (length() != 1) return false;
117
+ // Compare simple selectors
118
+ return *get(0) == rhs;
355
119
  }
356
120
 
357
- bool Selector_List::operator== (const Simple_Selector& rhs) const
358
- {
359
- size_t len = length();
360
- if (len > 1) return false;
361
- if (len == 0) return rhs.empty();
362
- return *at(0) == rhs;
363
- }
121
+ /*#########################################################################*/
122
+ // Compare ComplexSelector against itself
123
+ /*#########################################################################*/
364
124
 
365
- bool Selector_List::operator< (const Simple_Selector& rhs) const
125
+ bool ComplexSelector::operator== (const ComplexSelector& rhs) const
366
126
  {
367
127
  size_t len = length();
368
- if (len > 1) return false;
369
- if (len == 0) return !rhs.empty();
370
- return *at(0) < rhs;
371
- }
372
-
373
- /***************************************************************************/
374
- /***************************************************************************/
375
-
376
- bool Complex_Selector::operator== (const Selector_List& rhs) const
377
- {
378
- size_t len = rhs.length();
379
- if (len > 1) return false;
380
- if (len == 0) return empty();
381
- return *this == *rhs.at(0);
382
- }
383
-
384
- bool Complex_Selector::operator< (const Selector_List& rhs) const
385
- {
386
- size_t len = rhs.length();
387
- if (len > 1) return true;
388
- if (len == 0) return false;
389
- return *this < *rhs.at(0);
128
+ size_t rlen = rhs.length();
129
+ if (len != rlen) return false;
130
+ for (size_t i = 0; i < len; i += 1) {
131
+ if (*get(i) != *rhs.get(i)) return false;
132
+ }
133
+ return true;
390
134
  }
391
135
 
392
- bool Complex_Selector::operator== (const Compound_Selector& rhs) const
393
- {
394
- if (tail()) return false;
395
- if (!head()) return rhs.empty();
396
- return *head() == rhs;
397
- }
136
+ /*#########################################################################*/
137
+ // Compare ComplexSelector against all other selector types
138
+ /*#########################################################################*/
398
139
 
399
- bool Complex_Selector::operator< (const Compound_Selector& rhs) const
140
+ bool ComplexSelector::operator== (const SelectorList& rhs) const
400
141
  {
401
- if (tail()) return false;
402
- if (!head()) return !rhs.empty();
403
- return *head() < rhs;
142
+ // If both are empty they are equal
143
+ if (empty() && rhs.empty()) return true;
144
+ // Must have exactly one item
145
+ if (rhs.length() != 1) return false;
146
+ // Compare complex selector
147
+ return *this == *rhs.get(0);
404
148
  }
405
149
 
406
- bool Complex_Selector::operator== (const Simple_Selector& rhs) const
150
+ bool ComplexSelector::operator== (const CompoundSelector& rhs) const
407
151
  {
408
- if (tail()) return false;
409
- if (!head()) return rhs.empty();
410
- return *head() == rhs;
152
+ // If both are empty they are equal
153
+ if (empty() && rhs.empty()) return true;
154
+ // Must have exactly one item
155
+ if (length() != 1) return false;
156
+ // Compare compound selector
157
+ return *get(0) == rhs;
411
158
  }
412
159
 
413
- bool Complex_Selector::operator< (const Simple_Selector& rhs) const
160
+ bool ComplexSelector::operator== (const SimpleSelector& rhs) const
414
161
  {
415
- if (tail()) return false;
416
- if (!head()) return !rhs.empty();
417
- return *head() < rhs;
162
+ // If both are empty they are equal
163
+ if (empty() && rhs.empty()) return true;
164
+ // Must have exactly one item
165
+ if (length() != 1) return false;
166
+ // Compare simple selectors
167
+ return *get(0) == rhs;
418
168
  }
419
169
 
420
- /***************************************************************************/
421
- /***************************************************************************/
170
+ /*#########################################################################*/
171
+ // Compare SelectorCombinator against itself
172
+ /*#########################################################################*/
422
173
 
423
- bool Compound_Selector::operator== (const Selector_List& rhs) const
174
+ bool SelectorCombinator::operator==(const SelectorCombinator& rhs) const
424
175
  {
425
- size_t len = rhs.length();
426
- if (len > 1) return false;
427
- if (len == 0) return empty();
428
- return *this == *rhs.at(0);
176
+ return combinator() == rhs.combinator();
429
177
  }
430
178
 
431
- bool Compound_Selector::operator< (const Selector_List& rhs) const
432
- {
433
- size_t len = rhs.length();
434
- if (len > 1) return true;
435
- if (len == 0) return false;
436
- return *this < *rhs.at(0);
437
- }
179
+ /*#########################################################################*/
180
+ // Compare SelectorCombinator against SelectorComponent
181
+ /*#########################################################################*/
438
182
 
439
- bool Compound_Selector::operator== (const Complex_Selector& rhs) const
183
+ bool SelectorCombinator::operator==(const SelectorComponent& rhs) const
440
184
  {
441
- if (rhs.tail()) return false;
442
- if (!rhs.head()) return empty();
443
- return *this == *rhs.head();
185
+ if (const SelectorCombinator * sel = rhs.getCombinator()) {
186
+ return *this == *sel;
187
+ }
188
+ return false;
444
189
  }
445
190
 
446
- bool Compound_Selector::operator< (const Complex_Selector& rhs) const
191
+ bool CompoundSelector::operator==(const SelectorComponent& rhs) const
447
192
  {
448
- if (rhs.tail()) return true;
449
- if (!rhs.head()) return false;
450
- return *this < *rhs.head();
193
+ if (const CompoundSelector * sel = rhs.getCompound()) {
194
+ return *this == *sel;
195
+ }
196
+ return false;
451
197
  }
452
198
 
453
- bool Compound_Selector::operator< (const Simple_Selector& rhs) const
454
- {
455
- size_t len = length();
456
- if (len > 1) return false;
457
- if (len == 0) return rhs.empty();
458
- return *at(0) == rhs;
459
- }
199
+ /*#########################################################################*/
200
+ // Compare CompoundSelector against itself
201
+ /*#########################################################################*/
202
+ // ToDo: Verifiy implementation
203
+ /*#########################################################################*/
460
204
 
461
- bool Compound_Selector::operator== (const Simple_Selector& rhs) const
205
+ bool CompoundSelector::operator== (const CompoundSelector& rhs) const
462
206
  {
463
- size_t len = length();
464
- if (len > 1) return false;
465
- if (len == 0) return !rhs.empty();
466
- return *at(0) < rhs;
207
+ // std::cerr << "comp vs comp\n";
208
+ if (&rhs == this) return true;
209
+ if (rhs.length() != length()) return false;
210
+ std::unordered_set<const SimpleSelector*, PtrObjHash, PtrObjEquality> lhs_set;
211
+ lhs_set.reserve(length());
212
+ for (const SimpleSelectorObj& element : elements()) {
213
+ lhs_set.insert(element.ptr());
214
+ }
215
+ // there is no break?!
216
+ for (const SimpleSelectorObj& element : rhs.elements()) {
217
+ if (lhs_set.find(element.ptr()) == lhs_set.end()) return false;
218
+ }
219
+ return true;
467
220
  }
468
221
 
469
- /***************************************************************************/
470
- /***************************************************************************/
471
222
 
472
- bool Simple_Selector::operator== (const Selector_List& rhs) const
473
- {
474
- return rhs.length() == 1 && *this == *rhs.at(0);
475
- }
223
+ /*#########################################################################*/
224
+ // Compare CompoundSelector against all other selector types
225
+ /*#########################################################################*/
476
226
 
477
- bool Simple_Selector::operator< (const Selector_List& rhs) const
227
+ bool CompoundSelector::operator== (const SelectorList& rhs) const
478
228
  {
479
- size_t len = rhs.length();
480
- if (len > 1) return true;
481
- if (len == 0) return false;
482
- return *this < *rhs.at(0);
229
+ // If both are empty they are equal
230
+ if (empty() && rhs.empty()) return true;
231
+ // Must have exactly one item
232
+ if (rhs.length() != 1) return false;
233
+ // Compare complex selector
234
+ return *this == *rhs.get(0);
483
235
  }
484
236
 
485
- bool Simple_Selector::operator== (const Complex_Selector& rhs) const
237
+ bool CompoundSelector::operator== (const ComplexSelector& rhs) const
486
238
  {
487
- return !rhs.tail() && rhs.head() &&
488
- rhs.combinator() == Complex_Selector::ANCESTOR_OF &&
489
- *this == *rhs.head();
239
+ // If both are empty they are equal
240
+ if (empty() && rhs.empty()) return true;
241
+ // Must have exactly one item
242
+ if (rhs.length() != 1) return false;
243
+ // Compare compound selector
244
+ return *this == *rhs.get(0);
490
245
  }
491
246
 
492
- bool Simple_Selector::operator< (const Complex_Selector& rhs) const
247
+ bool CompoundSelector::operator== (const SimpleSelector& rhs) const
493
248
  {
494
- if (rhs.tail()) return true;
495
- if (!rhs.head()) return false;
496
- return *this < *rhs.head();
249
+ // If both are empty they are equal
250
+ if (empty() && rhs.empty()) return false;
251
+ // Must have exactly one item
252
+ size_t rlen = length();
253
+ if (rlen > 1) return false;
254
+ if (rlen == 0) return true;
255
+ // Compare simple selectors
256
+ return *get(0) < rhs;
497
257
  }
498
258
 
499
- bool Simple_Selector::operator== (const Compound_Selector& rhs) const
500
- {
501
- return rhs.length() == 1 && *this == *rhs.at(0);
502
- }
259
+ /*#########################################################################*/
260
+ // Compare SimpleSelector against itself (upcast from abstract base)
261
+ /*#########################################################################*/
503
262
 
504
- bool Simple_Selector::operator< (const Compound_Selector& rhs) const
505
- {
506
- size_t len = rhs.length();
507
- if (len > 1) return true;
508
- if (len == 0) return false;
509
- return *this < *rhs.at(0);
510
- }
263
+ // DOES NOT EXIST FOR ABSTRACT BASE CLASS
511
264
 
512
265
  /*#########################################################################*/
266
+ // Compare SimpleSelector against all other selector types
513
267
  /*#########################################################################*/
514
268
 
515
- bool Simple_Selector::operator== (const Simple_Selector& rhs) const
516
- {
517
- switch (simple_type()) {
518
- case ID_SEL: return (const Id_Selector&) *this == rhs; break;
519
- case TYPE_SEL: return (const Type_Selector&) *this == rhs; break;
520
- case CLASS_SEL: return (const Class_Selector&) *this == rhs; break;
521
- case PARENT_SEL: return (const Parent_Selector&) *this == rhs; break;
522
- case PSEUDO_SEL: return (const Pseudo_Selector&) *this == rhs; break;
523
- case WRAPPED_SEL: return (const Wrapped_Selector&) *this == rhs; break;
524
- case ATTRIBUTE_SEL: return (const Attribute_Selector&) *this == rhs; break;
525
- case PLACEHOLDER_SEL: return (const Placeholder_Selector&) *this == rhs; break;
526
- }
527
- return false;
269
+ bool SimpleSelector::operator== (const SelectorList& rhs) const
270
+ {
271
+ // If both are empty they are equal
272
+ if (empty() && rhs.empty()) return true;
273
+ // Must have exactly one item
274
+ if (rhs.length() != 1) return false;
275
+ // Compare complex selector
276
+ return *this == *rhs.get(0);
528
277
  }
529
278
 
530
- /***************************************************************************/
531
- /***************************************************************************/
532
-
533
- bool Id_Selector::operator== (const Simple_Selector& rhs) const
279
+ bool SimpleSelector::operator== (const ComplexSelector& rhs) const
534
280
  {
535
- auto sel = Cast<Id_Selector>(&rhs);
536
- return sel ? *this == *sel : false;
281
+ // If both are empty they are equal
282
+ if (empty() && rhs.empty()) return true;
283
+ // Must have exactly one item
284
+ if (rhs.length() != 1) return false;
285
+ // Compare compound selector
286
+ return *this == *rhs.get(0);
537
287
  }
538
288
 
539
- bool Type_Selector::operator== (const Simple_Selector& rhs) const
289
+ bool SimpleSelector::operator== (const CompoundSelector& rhs) const
540
290
  {
541
- auto sel = Cast<Type_Selector>(&rhs);
542
- return sel ? *this == *sel : false;
291
+ // If both are empty they are equal
292
+ if (empty() && rhs.empty()) return false;
293
+ // Must have exactly one item
294
+ if (rhs.length() != 1) return false;
295
+ // Compare simple selector
296
+ return *this == *rhs.get(0);
543
297
  }
544
298
 
545
- bool Class_Selector::operator== (const Simple_Selector& rhs) const
299
+ /*#########################################################################*/
300
+ /*#########################################################################*/
301
+
302
+ bool IDSelector::operator== (const SimpleSelector& rhs) const
546
303
  {
547
- auto sel = Cast<Class_Selector>(&rhs);
304
+ auto sel = Cast<IDSelector>(&rhs);
548
305
  return sel ? *this == *sel : false;
549
306
  }
550
307
 
551
- bool Parent_Selector::operator== (const Simple_Selector& rhs) const
308
+ bool TypeSelector::operator== (const SimpleSelector& rhs) const
552
309
  {
553
- auto sel = Cast<Parent_Selector>(&rhs);
310
+ auto sel = Cast<TypeSelector>(&rhs);
554
311
  return sel ? *this == *sel : false;
555
312
  }
556
313
 
557
- bool Pseudo_Selector::operator== (const Simple_Selector& rhs) const
314
+ bool ClassSelector::operator== (const SimpleSelector& rhs) const
558
315
  {
559
- auto sel = Cast<Pseudo_Selector>(&rhs);
316
+ auto sel = Cast<ClassSelector>(&rhs);
560
317
  return sel ? *this == *sel : false;
561
318
  }
562
319
 
563
- bool Wrapped_Selector::operator== (const Simple_Selector& rhs) const
320
+ bool PseudoSelector::operator== (const SimpleSelector& rhs) const
564
321
  {
565
- auto sel = Cast<Wrapped_Selector>(&rhs);
322
+ auto sel = Cast<PseudoSelector>(&rhs);
566
323
  return sel ? *this == *sel : false;
567
324
  }
568
325
 
569
- bool Attribute_Selector::operator== (const Simple_Selector& rhs) const
326
+ bool AttributeSelector::operator== (const SimpleSelector& rhs) const
570
327
  {
571
- auto sel = Cast<Attribute_Selector>(&rhs);
328
+ auto sel = Cast<AttributeSelector>(&rhs);
572
329
  return sel ? *this == *sel : false;
573
330
  }
574
331
 
575
- bool Placeholder_Selector::operator== (const Simple_Selector& rhs) const
332
+ bool PlaceholderSelector::operator== (const SimpleSelector& rhs) const
576
333
  {
577
- auto sel = Cast<Placeholder_Selector>(&rhs);
334
+ auto sel = Cast<PlaceholderSelector>(&rhs);
578
335
  return sel ? *this == *sel : false;
579
336
  }
580
337
 
581
- /***************************************************************************/
582
- /***************************************************************************/
338
+ /*#########################################################################*/
339
+ /*#########################################################################*/
583
340
 
584
- bool Id_Selector::operator== (const Id_Selector& rhs) const
341
+ bool IDSelector::operator== (const IDSelector& rhs) const
585
342
  {
586
343
  // ID has no namespacing
587
344
  return name() == rhs.name();
588
345
  }
589
346
 
590
- bool Type_Selector::operator== (const Type_Selector& rhs) const
347
+ bool TypeSelector::operator== (const TypeSelector& rhs) const
591
348
  {
592
349
  return is_ns_eq(rhs) && name() == rhs.name();
593
350
  }
594
351
 
595
- bool Class_Selector::operator== (const Class_Selector& rhs) const
352
+ bool ClassSelector::operator== (const ClassSelector& rhs) const
596
353
  {
597
354
  // Class has no namespacing
598
355
  return name() == rhs.name();
599
356
  }
600
357
 
601
- bool Parent_Selector::operator== (const Parent_Selector& rhs) const
602
- {
603
- // Parent has no namespacing
604
- return name() == rhs.name();
605
- }
606
-
607
- bool Pseudo_Selector::operator== (const Pseudo_Selector& rhs) const
608
- {
609
- std::string lname = name();
610
- std::string rname = rhs.name();
611
- if (is_pseudo_class_element(lname)) {
612
- if (rname[0] == ':' && rname[1] == ':') {
613
- lname = lname.substr(1, std::string::npos);
614
- }
615
- }
616
- // right hand is special pseudo (single colon)
617
- if (is_pseudo_class_element(rname)) {
618
- if (lname[0] == ':' && lname[1] == ':') {
619
- lname = lname.substr(1, std::string::npos);
620
- }
621
- }
622
- // Pseudo has no namespacing
623
- if (lname != rname) return false;
624
- String_Obj lhs_ex = expression();
625
- String_Obj rhs_ex = rhs.expression();
626
- if (rhs_ex && lhs_ex) return *lhs_ex == *rhs_ex;
627
- else return lhs_ex.ptr() == rhs_ex.ptr();
628
- }
629
-
630
- bool Wrapped_Selector::operator== (const Wrapped_Selector& rhs) const
631
- {
632
- // Wrapped has no namespacing
633
- if (name() != rhs.name()) return false;
634
- return *(selector()) == *(rhs.selector());
635
- }
636
-
637
- bool Attribute_Selector::operator== (const Attribute_Selector& rhs) const
638
- {
639
- // get optional value state
640
- bool no_lhs_val = value().isNull();
641
- bool no_rhs_val = rhs.value().isNull();
642
- // both are null, therefore equal
643
- if (no_lhs_val && no_rhs_val) {
644
- return (name() == rhs.name())
645
- && (matcher() == rhs.matcher())
646
- && (is_ns_eq(rhs));
647
- }
648
- // both are defined, evaluate
649
- if (no_lhs_val == no_rhs_val) {
650
- return (name() == rhs.name())
651
- && (matcher() == rhs.matcher())
652
- && (is_ns_eq(rhs))
653
- && (*value() == *rhs.value());
654
- }
655
- // not equal
656
- return false;
657
- }
658
-
659
- bool Placeholder_Selector::operator== (const Placeholder_Selector& rhs) const
358
+ bool PlaceholderSelector::operator== (const PlaceholderSelector& rhs) const
660
359
  {
661
360
  // Placeholder has no namespacing
662
361
  return name() == rhs.name();
663
362
  }
664
363
 
665
- /*#########################################################################*/
666
- /*#########################################################################*/
667
-
668
- bool Simple_Selector::operator< (const Simple_Selector& rhs) const
669
- {
670
- switch (simple_type()) {
671
- case ID_SEL: return (const Id_Selector&) *this < rhs; break;
672
- case TYPE_SEL: return (const Type_Selector&) *this < rhs; break;
673
- case CLASS_SEL: return (const Class_Selector&) *this < rhs; break;
674
- case PARENT_SEL: return (const Parent_Selector&) *this < rhs; break;
675
- case PSEUDO_SEL: return (const Pseudo_Selector&) *this < rhs; break;
676
- case WRAPPED_SEL: return (const Wrapped_Selector&) *this < rhs; break;
677
- case ATTRIBUTE_SEL: return (const Attribute_Selector&) *this < rhs; break;
678
- case PLACEHOLDER_SEL: return (const Placeholder_Selector&) *this < rhs; break;
679
- }
680
- return false;
681
- }
682
-
683
- /***************************************************************************/
684
- /***************************************************************************/
685
-
686
- bool Id_Selector::operator< (const Simple_Selector& rhs) const
687
- {
688
- switch (rhs.simple_type()) {
689
- case TYPE_SEL: return '#' < 's'; break;
690
- case CLASS_SEL: return '#' < '.'; break;
691
- case PARENT_SEL: return '#' < '&'; break;
692
- case PSEUDO_SEL: return '#' < ':'; break;
693
- case WRAPPED_SEL: return '#' < '('; break;
694
- case ATTRIBUTE_SEL: return '#' < '['; break;
695
- case PLACEHOLDER_SEL: return '#' < '%'; break;
696
- case ID_SEL: /* let if fall through */ break;
697
- }
698
- const Id_Selector& sel =
699
- (const Id_Selector&) rhs;
700
- return *this < sel;
701
- }
702
-
703
- bool Type_Selector::operator< (const Simple_Selector& rhs) const
704
- {
705
- switch (rhs.simple_type()) {
706
- case ID_SEL: return 'e' < '#'; break;
707
- case CLASS_SEL: return 'e' < '.'; break;
708
- case PARENT_SEL: return 'e' < '&'; break;
709
- case PSEUDO_SEL: return 'e' < ':'; break;
710
- case WRAPPED_SEL: return 'e' < '('; break;
711
- case ATTRIBUTE_SEL: return 'e' < '['; break;
712
- case PLACEHOLDER_SEL: return 'e' < '%'; break;
713
- case TYPE_SEL: /* let if fall through */ break;
714
- }
715
- const Type_Selector& sel =
716
- (const Type_Selector&) rhs;
717
- return *this < sel;
718
- }
719
-
720
- bool Class_Selector::operator< (const Simple_Selector& rhs) const
721
- {
722
- switch (rhs.simple_type()) {
723
- case ID_SEL: return '.' < '#'; break;
724
- case TYPE_SEL: return '.' < 's'; break;
725
- case PARENT_SEL: return '.' < '&'; break;
726
- case PSEUDO_SEL: return '.' < ':'; break;
727
- case WRAPPED_SEL: return '.' < '('; break;
728
- case ATTRIBUTE_SEL: return '.' < '['; break;
729
- case PLACEHOLDER_SEL: return '.' < '%'; break;
730
- case CLASS_SEL: /* let if fall through */ break;
731
- }
732
- const Class_Selector& sel =
733
- (const Class_Selector&) rhs;
734
- return *this < sel;
735
- }
736
-
737
- bool Pseudo_Selector::operator< (const Simple_Selector& rhs) const
738
- {
739
- switch (rhs.simple_type()) {
740
- case ID_SEL: return ':' < '#'; break;
741
- case TYPE_SEL: return ':' < 's'; break;
742
- case CLASS_SEL: return ':' < '.'; break;
743
- case PARENT_SEL: return ':' < '&'; break;
744
- case WRAPPED_SEL: return ':' < '('; break;
745
- case ATTRIBUTE_SEL: return ':' < '['; break;
746
- case PLACEHOLDER_SEL: return ':' < '%'; break;
747
- case PSEUDO_SEL: /* let if fall through */ break;
748
- }
749
- const Pseudo_Selector& sel =
750
- (const Pseudo_Selector&) rhs;
751
- return *this < sel;
752
- }
753
-
754
- bool Wrapped_Selector::operator< (const Simple_Selector& rhs) const
755
- {
756
- switch (rhs.simple_type()) {
757
- case ID_SEL: return '(' < '#'; break;
758
- case TYPE_SEL: return '(' < 's'; break;
759
- case CLASS_SEL: return '(' < '.'; break;
760
- case PARENT_SEL: return '(' < '&'; break;
761
- case PSEUDO_SEL: return '(' < ':'; break;
762
- case ATTRIBUTE_SEL: return '(' < '['; break;
763
- case PLACEHOLDER_SEL: return '(' < '%'; break;
764
- case WRAPPED_SEL: /* let if fall through */ break;
765
- }
766
- const Wrapped_Selector& sel =
767
- (const Wrapped_Selector&) rhs;
768
- return *this < sel;
769
- }
770
-
771
- bool Parent_Selector::operator< (const Simple_Selector& rhs) const
772
- {
773
- switch (rhs.simple_type()) {
774
- case ID_SEL: return '&' < '#'; break;
775
- case TYPE_SEL: return '&' < 's'; break;
776
- case CLASS_SEL: return '&' < '.'; break;
777
- case PSEUDO_SEL: return '&' < ':'; break;
778
- case WRAPPED_SEL: return '&' < '('; break;
779
- case ATTRIBUTE_SEL: return '&' < '['; break;
780
- case PLACEHOLDER_SEL: return '&' < '%'; break;
781
- case PARENT_SEL: /* let if fall through */ break;
782
- }
783
- const Parent_Selector& sel =
784
- (const Parent_Selector&) rhs;
785
- return *this < sel;
786
- }
787
-
788
- bool Attribute_Selector::operator< (const Simple_Selector& rhs) const
789
- {
790
- switch (rhs.simple_type()) {
791
- case ID_SEL: return '[' < '#'; break;
792
- case TYPE_SEL: return '[' < 'e'; break;
793
- case CLASS_SEL: return '[' < '.'; break;
794
- case PARENT_SEL: return '[' < '&'; break;
795
- case PSEUDO_SEL: return '[' < ':'; break;
796
- case WRAPPED_SEL: return '[' < '('; break;
797
- case PLACEHOLDER_SEL: return '[' < '%'; break;
798
- case ATTRIBUTE_SEL: /* let if fall through */ break;
799
- }
800
- const Attribute_Selector& sel =
801
- (const Attribute_Selector&) rhs;
802
- return *this < sel;
803
- }
804
-
805
- bool Placeholder_Selector::operator< (const Simple_Selector& rhs) const
806
- {
807
- switch (rhs.simple_type()) {
808
- case ID_SEL: return '%' < '#'; break;
809
- case TYPE_SEL: return '%' < 's'; break;
810
- case CLASS_SEL: return '%' < '.'; break;
811
- case PARENT_SEL: return '%' < '&'; break;
812
- case PSEUDO_SEL: return '%' < ':'; break;
813
- case WRAPPED_SEL: return '%' < '('; break;
814
- case ATTRIBUTE_SEL: return '%' < '['; break;
815
- case PLACEHOLDER_SEL: /* let if fall through */ break;
816
- }
817
- const Placeholder_Selector& sel =
818
- (const Placeholder_Selector&) rhs;
819
- return *this < sel;
820
- }
821
-
822
- /***************************************************************************/
823
- /***************************************************************************/
824
-
825
- bool Id_Selector::operator< (const Id_Selector& rhs) const
826
- {
827
- // ID has no namespacing
828
- return name() < rhs.name();
829
- }
830
-
831
- bool Type_Selector::operator< (const Type_Selector& rhs) const
832
- {
833
- return has_ns_ == rhs.has_ns_
834
- ? (ns_ == rhs.ns_
835
- ? name_ < rhs.name_
836
- : ns_ < rhs.ns_)
837
- : has_ns_ < rhs.has_ns_;
838
- }
839
-
840
- bool Class_Selector::operator< (const Class_Selector& rhs) const
364
+ bool AttributeSelector::operator== (const AttributeSelector& rhs) const
841
365
  {
842
- // Class has no namespacing
843
- return name() < rhs.name();
844
- }
845
-
846
- bool Parent_Selector::operator< (const Parent_Selector& rhs) const
847
- {
848
- // Parent has no namespacing
849
- return name() < rhs.name();
850
- }
851
-
852
- bool Pseudo_Selector::operator< (const Pseudo_Selector& rhs) const
853
- {
854
- std::string lname = name();
855
- std::string rname = rhs.name();
856
- if (is_pseudo_class_element(lname)) {
857
- if (rname[0] == ':' && rname[1] == ':') {
858
- lname = lname.substr(1, std::string::npos);
859
- }
860
- }
861
- // right hand is special pseudo (single colon)
862
- if (is_pseudo_class_element(rname)) {
863
- if (lname[0] == ':' && lname[1] == ':') {
864
- lname = lname.substr(1, std::string::npos);
865
- }
366
+ // smaller return, equal go on, bigger abort
367
+ if (is_ns_eq(rhs)) {
368
+ if (name() != rhs.name()) return false;
369
+ if (matcher() != rhs.matcher()) return false;
370
+ if (modifier() != rhs.modifier()) return false;
371
+ const String* lhs_val = value();
372
+ const String* rhs_val = rhs.value();
373
+ return PtrObjEquality()(lhs_val, rhs_val);
866
374
  }
867
- // Peudo has no namespacing
868
- if (lname != rname)
869
- { return lname < rname; }
870
- String_Obj lhs_ex = expression();
871
- String_Obj rhs_ex = rhs.expression();
872
- if (rhs_ex && lhs_ex) return *lhs_ex < *rhs_ex;
873
- else return lhs_ex.ptr() < rhs_ex.ptr();
874
- }
875
-
876
- bool Wrapped_Selector::operator< (const Wrapped_Selector& rhs) const
877
- {
878
- // Wrapped has no namespacing
879
- if (name() != rhs.name())
880
- { return name() < rhs.name(); }
881
- return *(selector()) < *(rhs.selector());
375
+ else { return false; }
882
376
  }
883
377
 
884
- bool Attribute_Selector::operator< (const Attribute_Selector& rhs) const
378
+ bool PseudoSelector::operator== (const PseudoSelector& rhs) const
885
379
  {
886
380
  if (is_ns_eq(rhs)) {
887
- if (name() != rhs.name())
888
- { return name() < rhs.name(); }
889
- if (matcher() != rhs.matcher())
890
- { return matcher() < rhs.matcher(); }
891
- bool no_lhs_val = value().isNull();
892
- bool no_rhs_val = rhs.value().isNull();
893
- if (no_lhs_val && no_rhs_val) return false; // equal
894
- else if (no_lhs_val) return true; // lhs is null
895
- else if (no_rhs_val) return false; // rhs is null
896
- return *value() < *rhs.value(); // both are given
897
- } else { return ns() < rhs.ns(); }
898
- }
899
-
900
- bool Placeholder_Selector::operator< (const Placeholder_Selector& rhs) const
901
- {
902
- // Placeholder has no namespacing
903
- return name() < rhs.name();
381
+ if (name() != rhs.name()) return false;
382
+ if (isElement() != rhs.isElement()) return false;
383
+ const String* lhs_arg = argument();
384
+ const String* rhs_arg = rhs.argument();
385
+ if (!PtrObjEquality()(lhs_arg, rhs_arg)) return false;
386
+ const SelectorList* lhs_sel = selector();
387
+ const SelectorList* rhs_sel = rhs.selector();
388
+ return PtrObjEquality()(lhs_sel, rhs_sel);
389
+ }
390
+ else { return false; }
904
391
  }
905
392
 
906
393
  /*#########################################################################*/