sassc 2.2.1 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +13 -0
- data/Rakefile +1 -3
- data/ext/extconf.rb +13 -5
- data/ext/libsass/VERSION +1 -1
- data/ext/libsass/include/sass/base.h +2 -1
- data/ext/libsass/include/sass/context.h +1 -0
- data/ext/libsass/src/ast.cpp +49 -59
- data/ext/libsass/src/ast.hpp +263 -102
- data/ext/libsass/src/ast_def_macros.hpp +8 -0
- data/ext/libsass/src/ast_fwd_decl.cpp +2 -1
- data/ext/libsass/src/ast_fwd_decl.hpp +40 -116
- data/ext/libsass/src/ast_helpers.hpp +292 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +209 -722
- data/ext/libsass/src/ast_sel_super.cpp +539 -0
- data/ext/libsass/src/ast_sel_unify.cpp +207 -212
- data/ext/libsass/src/ast_sel_weave.cpp +616 -0
- data/ext/libsass/src/ast_selectors.cpp +559 -1001
- data/ext/libsass/src/ast_selectors.hpp +311 -367
- data/ext/libsass/src/ast_supports.cpp +1 -17
- data/ext/libsass/src/ast_values.cpp +216 -29
- data/ext/libsass/src/ast_values.hpp +42 -33
- data/ext/libsass/src/bind.cpp +1 -1
- data/ext/libsass/src/cencode.c +4 -6
- data/ext/libsass/src/check_nesting.cpp +5 -6
- data/ext/libsass/src/check_nesting.hpp +4 -0
- data/ext/libsass/src/color_maps.cpp +11 -10
- data/ext/libsass/src/color_maps.hpp +0 -8
- data/ext/libsass/src/constants.cpp +5 -0
- data/ext/libsass/src/constants.hpp +6 -0
- data/ext/libsass/src/context.cpp +30 -60
- data/ext/libsass/src/context.hpp +8 -20
- data/ext/libsass/src/cssize.cpp +36 -120
- data/ext/libsass/src/cssize.hpp +4 -10
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debugger.hpp +364 -207
- data/ext/libsass/src/emitter.cpp +3 -4
- data/ext/libsass/src/emitter.hpp +0 -2
- data/ext/libsass/src/environment.hpp +5 -0
- data/ext/libsass/src/error_handling.cpp +21 -0
- data/ext/libsass/src/error_handling.hpp +25 -3
- data/ext/libsass/src/eval.cpp +33 -153
- data/ext/libsass/src/eval.hpp +11 -13
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +214 -167
- data/ext/libsass/src/expand.hpp +26 -6
- data/ext/libsass/src/extender.cpp +1186 -0
- data/ext/libsass/src/extender.hpp +399 -0
- data/ext/libsass/src/extension.cpp +43 -0
- data/ext/libsass/src/extension.hpp +89 -0
- data/ext/libsass/src/file.cpp +15 -14
- data/ext/libsass/src/file.hpp +5 -12
- data/ext/libsass/src/fn_colors.cpp +12 -10
- data/ext/libsass/src/fn_lists.cpp +12 -11
- data/ext/libsass/src/fn_miscs.cpp +22 -34
- data/ext/libsass/src/fn_numbers.cpp +13 -6
- data/ext/libsass/src/fn_selectors.cpp +94 -124
- data/ext/libsass/src/fn_strings.cpp +16 -14
- data/ext/libsass/src/fn_utils.cpp +5 -6
- data/ext/libsass/src/fn_utils.hpp +9 -3
- data/ext/libsass/src/inspect.cpp +154 -117
- data/ext/libsass/src/inspect.hpp +10 -8
- data/ext/libsass/src/lexer.cpp +17 -81
- data/ext/libsass/src/lexer.hpp +5 -16
- data/ext/libsass/src/listize.cpp +22 -36
- data/ext/libsass/src/listize.hpp +8 -9
- data/ext/libsass/src/memory/SharedPtr.hpp +39 -5
- data/ext/libsass/src/operation.hpp +27 -17
- data/ext/libsass/src/operators.cpp +1 -0
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +30 -49
- data/ext/libsass/src/output.hpp +1 -1
- data/ext/libsass/src/parser.cpp +211 -381
- data/ext/libsass/src/parser.hpp +17 -15
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +140 -0
- data/ext/libsass/src/position.hpp +1 -1
- data/ext/libsass/src/prelexer.cpp +6 -6
- data/ext/libsass/src/remove_placeholders.cpp +55 -56
- data/ext/libsass/src/remove_placeholders.hpp +21 -18
- data/ext/libsass/src/sass.hpp +1 -0
- data/ext/libsass/src/sass2scss.cpp +4 -4
- data/ext/libsass/src/sass_context.cpp +42 -91
- data/ext/libsass/src/sass_context.hpp +2 -2
- data/ext/libsass/src/sass_functions.cpp +1 -1
- data/ext/libsass/src/sass_values.cpp +0 -1
- data/ext/libsass/src/stylesheet.cpp +22 -0
- data/ext/libsass/src/stylesheet.hpp +57 -0
- data/ext/libsass/src/to_value.cpp +2 -2
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.cpp +5 -3
- data/ext/libsass/src/util.cpp +10 -12
- data/ext/libsass/src/util.hpp +2 -3
- data/ext/libsass/src/util_string.cpp +111 -61
- data/ext/libsass/src/util_string.hpp +61 -8
- data/lib/sassc/engine.rb +5 -3
- data/lib/sassc/functions_handler.rb +8 -8
- data/lib/sassc/native.rb +1 -1
- data/lib/sassc/script.rb +4 -4
- data/lib/sassc/version.rb +1 -1
- data/test/functions_test.rb +18 -1
- data/test/native_test.rb +1 -1
- metadata +17 -12
- data/ext/libsass/src/extend.cpp +0 -2132
- data/ext/libsass/src/extend.hpp +0 -86
- data/ext/libsass/src/node.cpp +0 -322
- data/ext/libsass/src/node.hpp +0 -118
- data/ext/libsass/src/paths.hpp +0 -71
- data/ext/libsass/src/sass_util.cpp +0 -152
- data/ext/libsass/src/sass_util.hpp +0 -256
- data/ext/libsass/src/subset_map.cpp +0 -58
- data/ext/libsass/src/subset_map.hpp +0 -76
data/ext/libsass/src/inspect.hpp
CHANGED
@@ -23,7 +23,6 @@ namespace Sass {
|
|
23
23
|
virtual void operator()(Ruleset*);
|
24
24
|
virtual void operator()(Bubble*);
|
25
25
|
virtual void operator()(Supports_Block*);
|
26
|
-
virtual void operator()(Media_Block*);
|
27
26
|
virtual void operator()(At_Root_Block*);
|
28
27
|
virtual void operator()(Directive*);
|
29
28
|
virtual void operator()(Keyframe_Rule*);
|
@@ -40,7 +39,7 @@ namespace Sass {
|
|
40
39
|
virtual void operator()(Each*);
|
41
40
|
virtual void operator()(While*);
|
42
41
|
virtual void operator()(Return*);
|
43
|
-
virtual void operator()(
|
42
|
+
virtual void operator()(ExtendRule*);
|
44
43
|
virtual void operator()(Definition*);
|
45
44
|
virtual void operator()(Mixin_Call*);
|
46
45
|
virtual void operator()(Content*);
|
@@ -67,11 +66,14 @@ namespace Sass {
|
|
67
66
|
virtual void operator()(Supports_Negation*);
|
68
67
|
virtual void operator()(Supports_Declaration*);
|
69
68
|
virtual void operator()(Supports_Interpolation*);
|
69
|
+
virtual void operator()(MediaRule*);
|
70
|
+
virtual void operator()(CssMediaRule*);
|
71
|
+
virtual void operator()(CssMediaQuery*);
|
70
72
|
virtual void operator()(Media_Query*);
|
71
73
|
virtual void operator()(Media_Query_Expression*);
|
72
74
|
virtual void operator()(At_Root_Query*);
|
73
75
|
virtual void operator()(Null*);
|
74
|
-
virtual void operator()(
|
76
|
+
virtual void operator()(Parent_Reference* p);
|
75
77
|
// parameters and arguments
|
76
78
|
virtual void operator()(Parameter*);
|
77
79
|
virtual void operator()(Parameters*);
|
@@ -85,11 +87,11 @@ namespace Sass {
|
|
85
87
|
virtual void operator()(Id_Selector*);
|
86
88
|
virtual void operator()(Attribute_Selector*);
|
87
89
|
virtual void operator()(Pseudo_Selector*);
|
88
|
-
virtual void operator()(
|
89
|
-
virtual void operator()(
|
90
|
-
virtual void operator()(
|
91
|
-
virtual void operator()(
|
92
|
-
|
90
|
+
virtual void operator()(SelectorComponent*);
|
91
|
+
virtual void operator()(SelectorCombinator*);
|
92
|
+
virtual void operator()(CompoundSelector*);
|
93
|
+
virtual void operator()(ComplexSelector*);
|
94
|
+
virtual void operator()(SelectorList*);
|
93
95
|
virtual std::string lbracket(List*);
|
94
96
|
virtual std::string rbracket(List*);
|
95
97
|
|
data/ext/libsass/src/lexer.cpp
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
// __EXTENSIONS__ fix on Solaris.
|
3
3
|
#include "sass.hpp"
|
4
4
|
|
5
|
-
#include <cctype>
|
6
5
|
#include <iostream>
|
7
6
|
#include <iomanip>
|
8
7
|
#include "lexer.hpp"
|
9
8
|
#include "constants.hpp"
|
9
|
+
#include "util_string.hpp"
|
10
10
|
|
11
11
|
|
12
12
|
namespace Sass {
|
@@ -28,77 +28,14 @@ namespace Sass {
|
|
28
28
|
const char* kwd_minus(const char* src) { return exactly<'-'>(src); };
|
29
29
|
const char* kwd_slash(const char* src) { return exactly<'/'>(src); };
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
// this even seems to improve performance by quite a bit
|
35
|
-
//####################################
|
36
|
-
|
37
|
-
bool is_alpha(const char& chr)
|
38
|
-
{
|
39
|
-
return unsigned(chr - 'A') <= 'Z' - 'A' ||
|
40
|
-
unsigned(chr - 'a') <= 'z' - 'a';
|
41
|
-
}
|
42
|
-
|
43
|
-
bool is_space(const char& chr)
|
44
|
-
{
|
45
|
-
// adapted the technique from is_alpha
|
46
|
-
return chr == ' ' || unsigned(chr - '\t') <= '\r' - '\t';
|
47
|
-
}
|
48
|
-
|
49
|
-
bool is_digit(const char& chr)
|
50
|
-
{
|
51
|
-
// adapted the technique from is_alpha
|
52
|
-
return unsigned(chr - '0') <= '9' - '0';
|
53
|
-
}
|
54
|
-
|
55
|
-
bool is_number(const char& chr)
|
56
|
-
{
|
57
|
-
// adapted the technique from is_alpha
|
58
|
-
return is_digit(chr) || chr == '-' || chr == '+';
|
59
|
-
}
|
60
|
-
|
61
|
-
bool is_xdigit(const char& chr)
|
62
|
-
{
|
63
|
-
// adapted the technique from is_alpha
|
64
|
-
return unsigned(chr - '0') <= '9' - '0' ||
|
65
|
-
unsigned(chr - 'a') <= 'f' - 'a' ||
|
66
|
-
unsigned(chr - 'A') <= 'F' - 'A';
|
67
|
-
}
|
68
|
-
|
69
|
-
bool is_punct(const char& chr)
|
70
|
-
{
|
71
|
-
// locale independent
|
72
|
-
return chr == '.';
|
73
|
-
}
|
74
|
-
|
75
|
-
bool is_alnum(const char& chr)
|
76
|
-
{
|
77
|
-
return is_alpha(chr) || is_digit(chr);
|
78
|
-
}
|
79
|
-
|
80
|
-
// check if char is outside ascii range
|
81
|
-
bool is_unicode(const char& chr)
|
82
|
-
{
|
83
|
-
// check for unicode range
|
84
|
-
return unsigned(chr) > 127;
|
85
|
-
}
|
86
|
-
|
87
|
-
// check if char is outside ascii range
|
88
|
-
// but with specific ranges (copied from Ruby Sass)
|
89
|
-
bool is_nonascii(const char& chr)
|
90
|
-
{
|
91
|
-
unsigned int cmp = unsigned(chr);
|
92
|
-
return (
|
93
|
-
(cmp >= 128 && cmp <= 15572911) ||
|
94
|
-
(cmp >= 15630464 && cmp <= 15712189) ||
|
95
|
-
(cmp >= 4036001920)
|
96
|
-
);
|
31
|
+
bool is_number(char chr) {
|
32
|
+
return Util::ascii_isdigit(static_cast<unsigned char>(chr)) ||
|
33
|
+
chr == '-' || chr == '+';
|
97
34
|
}
|
98
35
|
|
99
36
|
// check if char is within a reduced ascii range
|
100
37
|
// valid in a uri (copied from Ruby Sass)
|
101
|
-
bool is_uri_character(
|
38
|
+
bool is_uri_character(char chr)
|
102
39
|
{
|
103
40
|
unsigned int cmp = unsigned(chr);
|
104
41
|
return (cmp > 41 && cmp < 127) ||
|
@@ -107,17 +44,19 @@ namespace Sass {
|
|
107
44
|
|
108
45
|
// check if char is within a reduced ascii range
|
109
46
|
// valid for escaping (copied from Ruby Sass)
|
110
|
-
bool is_escapable_character(
|
47
|
+
bool is_escapable_character(char chr)
|
111
48
|
{
|
112
49
|
unsigned int cmp = unsigned(chr);
|
113
50
|
return cmp > 31 && cmp < 127;
|
114
51
|
}
|
115
52
|
|
116
53
|
// Match word character (look ahead)
|
117
|
-
bool is_character(
|
54
|
+
bool is_character(char chr)
|
118
55
|
{
|
119
56
|
// valid alpha, numeric or unicode char (plus hyphen)
|
120
|
-
return
|
57
|
+
return Util::ascii_isalnum(static_cast<unsigned char>(chr)) ||
|
58
|
+
!Util::ascii_isascii(static_cast<unsigned char>(chr)) ||
|
59
|
+
chr == '-';
|
121
60
|
}
|
122
61
|
|
123
62
|
//####################################
|
@@ -125,16 +64,13 @@ namespace Sass {
|
|
125
64
|
//####################################
|
126
65
|
|
127
66
|
// create matchers that advance the position
|
128
|
-
const char* space(const char* src) { return
|
129
|
-
const char* alpha(const char* src) { return
|
130
|
-
const char*
|
131
|
-
const char*
|
132
|
-
const char*
|
133
|
-
const char*
|
134
|
-
const char*
|
135
|
-
const char* punct(const char* src) { return is_punct(*src) ? src + 1 : 0; }
|
136
|
-
const char* hyphen(const char* src) { return *src && *src == '-' ? src + 1 : 0; }
|
137
|
-
const char* character(const char* src) { return is_character(*src) ? src + 1 : 0; }
|
67
|
+
const char* space(const char* src) { return Util::ascii_isspace(static_cast<unsigned char>(*src)) ? src + 1 : nullptr; }
|
68
|
+
const char* alpha(const char* src) { return Util::ascii_isalpha(static_cast<unsigned char>(*src)) ? src + 1 : nullptr; }
|
69
|
+
const char* nonascii(const char* src) { return Util::ascii_isascii(static_cast<unsigned char>(*src)) ? nullptr : src + 1; }
|
70
|
+
const char* digit(const char* src) { return Util::ascii_isdigit(static_cast<unsigned char>(*src)) ? src + 1 : nullptr; }
|
71
|
+
const char* xdigit(const char* src) { return Util::ascii_isxdigit(static_cast<unsigned char>(*src)) ? src + 1 : nullptr; }
|
72
|
+
const char* alnum(const char* src) { return Util::ascii_isalnum(static_cast<unsigned char>(*src)) ? src + 1 : nullptr; }
|
73
|
+
const char* hyphen(const char* src) { return *src == '-' ? src + 1 : 0; }
|
138
74
|
const char* uri_character(const char* src) { return is_uri_character(*src) ? src + 1 : 0; }
|
139
75
|
const char* escapable_character(const char* src) { return is_escapable_character(*src) ? src + 1 : 0; }
|
140
76
|
|
data/ext/libsass/src/lexer.hpp
CHANGED
@@ -24,19 +24,11 @@ namespace Sass {
|
|
24
24
|
// BASIC CLASS MATCHERS
|
25
25
|
//####################################
|
26
26
|
|
27
|
-
//
|
28
|
-
bool
|
29
|
-
|
30
|
-
bool
|
31
|
-
bool
|
32
|
-
bool is_number(const char& src);
|
33
|
-
bool is_alnum(const char& src);
|
34
|
-
bool is_xdigit(const char& src);
|
35
|
-
bool is_unicode(const char& src);
|
36
|
-
bool is_nonascii(const char& src);
|
37
|
-
bool is_character(const char& src);
|
38
|
-
bool is_uri_character(const char& src);
|
39
|
-
bool escapable_character(const char& src);
|
27
|
+
// Matches ASCII digits, +, and -.
|
28
|
+
bool is_number(char src);
|
29
|
+
|
30
|
+
bool is_uri_character(char src);
|
31
|
+
bool escapable_character(char src);
|
40
32
|
|
41
33
|
// Match a single ctype predicate.
|
42
34
|
const char* space(const char* src);
|
@@ -44,11 +36,8 @@ namespace Sass {
|
|
44
36
|
const char* digit(const char* src);
|
45
37
|
const char* xdigit(const char* src);
|
46
38
|
const char* alnum(const char* src);
|
47
|
-
const char* punct(const char* src);
|
48
39
|
const char* hyphen(const char* src);
|
49
|
-
const char* unicode(const char* src);
|
50
40
|
const char* nonascii(const char* src);
|
51
|
-
const char* character(const char* src);
|
52
41
|
const char* uri_character(const char* src);
|
53
42
|
const char* escapable_character(const char* src);
|
54
43
|
|
data/ext/libsass/src/listize.cpp
CHANGED
@@ -16,7 +16,13 @@ namespace Sass {
|
|
16
16
|
Listize::Listize()
|
17
17
|
{ }
|
18
18
|
|
19
|
-
Expression* Listize::
|
19
|
+
Expression* Listize::perform(AST_Node* node)
|
20
|
+
{
|
21
|
+
Listize listize;
|
22
|
+
return node->perform(&listize);
|
23
|
+
}
|
24
|
+
|
25
|
+
Expression* Listize::operator()(SelectorList* sel)
|
20
26
|
{
|
21
27
|
List_Obj l = SASS_MEMORY_NEW(List, sel->pstate(), sel->length(), SASS_COMMA);
|
22
28
|
l->from_selector(true);
|
@@ -28,7 +34,7 @@ namespace Sass {
|
|
28
34
|
return SASS_MEMORY_NEW(Null, l->pstate());
|
29
35
|
}
|
30
36
|
|
31
|
-
Expression* Listize::operator()(
|
37
|
+
Expression* Listize::operator()(CompoundSelector* sel)
|
32
38
|
{
|
33
39
|
std::string str;
|
34
40
|
for (size_t i = 0, L = sel->length(); i < L; ++i) {
|
@@ -38,45 +44,25 @@ namespace Sass {
|
|
38
44
|
return SASS_MEMORY_NEW(String_Quoted, sel->pstate(), str);
|
39
45
|
}
|
40
46
|
|
41
|
-
Expression* Listize::operator()(
|
47
|
+
Expression* Listize::operator()(ComplexSelector* sel)
|
42
48
|
{
|
43
|
-
List_Obj l = SASS_MEMORY_NEW(List, sel->pstate()
|
49
|
+
List_Obj l = SASS_MEMORY_NEW(List, sel->pstate());
|
50
|
+
// ToDo: investigate what this does
|
51
|
+
// Note: seems reated to parent ref
|
44
52
|
l->from_selector(true);
|
45
|
-
Compound_Selector_Obj head = sel->head();
|
46
|
-
if (head && !head->is_empty_reference())
|
47
|
-
{
|
48
|
-
Expression* hh = head->perform(this);
|
49
|
-
if (hh) l->append(hh);
|
50
|
-
}
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
l->append(SASS_MEMORY_NEW(String_Quoted,
|
61
|
-
|
62
|
-
case Complex_Selector::REFERENCE:
|
63
|
-
l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), "/" + reference + "/"));
|
64
|
-
break;
|
65
|
-
case Complex_Selector::PRECEDES:
|
66
|
-
l->append(SASS_MEMORY_NEW(String_Quoted, sel->pstate(), "~"));
|
67
|
-
break;
|
68
|
-
case Complex_Selector::ANCESTOR_OF:
|
69
|
-
break;
|
70
|
-
default: break;
|
54
|
+
for (auto component : sel->elements()) {
|
55
|
+
if (CompoundSelectorObj compound = Cast<CompoundSelector>(component)) {
|
56
|
+
if (!compound->empty()) {
|
57
|
+
Expression_Obj hh = compound->perform(this);
|
58
|
+
if (hh) l->append(hh);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
else if (component) {
|
62
|
+
l->append(SASS_MEMORY_NEW(String_Quoted, component->pstate(), component->to_string()));
|
63
|
+
}
|
71
64
|
}
|
72
65
|
|
73
|
-
Complex_Selector_Obj tail = sel->tail();
|
74
|
-
if (tail)
|
75
|
-
{
|
76
|
-
Expression_Obj tt = tail->perform(this);
|
77
|
-
if (List* ls = Cast<List>(tt))
|
78
|
-
{ l->concat(ls); }
|
79
|
-
}
|
80
66
|
if (l->length() == 0) return 0;
|
81
67
|
return l.detach();
|
82
68
|
}
|
data/ext/libsass/src/listize.hpp
CHANGED
@@ -5,13 +5,8 @@
|
|
5
5
|
// __EXTENSIONS__ fix on Solaris.
|
6
6
|
#include "sass.hpp"
|
7
7
|
|
8
|
-
#include
|
9
|
-
#include <iostream>
|
10
|
-
|
11
|
-
#include "ast.hpp"
|
12
|
-
#include "context.hpp"
|
8
|
+
#include "ast_fwd_decl.hpp"
|
13
9
|
#include "operation.hpp"
|
14
|
-
#include "environment.hpp"
|
15
10
|
|
16
11
|
namespace Sass {
|
17
12
|
|
@@ -19,13 +14,17 @@ namespace Sass {
|
|
19
14
|
|
20
15
|
class Listize : public Operation_CRTP<Expression*, Listize> {
|
21
16
|
|
17
|
+
public:
|
18
|
+
|
19
|
+
static Expression* perform(AST_Node* node);
|
20
|
+
|
22
21
|
public:
|
23
22
|
Listize();
|
24
23
|
~Listize() { }
|
25
24
|
|
26
|
-
Expression* operator()(
|
27
|
-
Expression* operator()(
|
28
|
-
Expression* operator()(
|
25
|
+
Expression* operator()(SelectorList*);
|
26
|
+
Expression* operator()(ComplexSelector*);
|
27
|
+
Expression* operator()(CompoundSelector*);
|
29
28
|
|
30
29
|
// generic fallback
|
31
30
|
template <typename U>
|
@@ -9,6 +9,10 @@
|
|
9
9
|
#include <type_traits>
|
10
10
|
#include <vector>
|
11
11
|
|
12
|
+
// https://lokiastari.com/blog/2014/12/30/c-plus-plus-by-example-smart-pointer/index.html
|
13
|
+
// https://lokiastari.com/blog/2015/01/15/c-plus-plus-by-example-smart-pointer-part-ii/index.html
|
14
|
+
// https://lokiastari.com/blog/2015/01/23/c-plus-plus-by-example-smart-pointer-part-iii/index.html
|
15
|
+
|
12
16
|
namespace Sass {
|
13
17
|
|
14
18
|
class SharedPtr;
|
@@ -42,6 +46,16 @@ namespace Sass {
|
|
42
46
|
|
43
47
|
#endif
|
44
48
|
|
49
|
+
// SharedObj is the base class for all objects that can be stored as a shared object
|
50
|
+
// It adds the reference counter and other values directly to the objects
|
51
|
+
// This gives a slight overhead when directly used as a stack object, but has some
|
52
|
+
// advantages for our code. It is safe to create two shared pointers from the same
|
53
|
+
// objects, as the "control block" is directly attached to it. This would lead
|
54
|
+
// to undefined behavior with std::shared_ptr. This also avoids the need to
|
55
|
+
// allocate additional control blocks and/or the need to dereference two
|
56
|
+
// pointers on each operation. This can be optimized in `std::shared_ptr`
|
57
|
+
// too by using `std::make_shared` (where the control block and the actual
|
58
|
+
// object are allocated in one continuous memory block via one single call).
|
45
59
|
class SharedObj {
|
46
60
|
public:
|
47
61
|
SharedObj() : refcount(0), detached(false) {
|
@@ -51,7 +65,12 @@ namespace Sass {
|
|
51
65
|
}
|
52
66
|
virtual ~SharedObj() {
|
53
67
|
#ifdef DEBUG_SHARED_PTR
|
54
|
-
all.
|
68
|
+
for (size_t i = 0; i < all.size(); i++) {
|
69
|
+
if (all[i] == this) {
|
70
|
+
all.erase(all.begin() + i);
|
71
|
+
break;
|
72
|
+
}
|
73
|
+
}
|
55
74
|
#endif
|
56
75
|
}
|
57
76
|
|
@@ -70,7 +89,7 @@ namespace Sass {
|
|
70
89
|
|
71
90
|
static void setTaint(bool val) { taint = val; }
|
72
91
|
|
73
|
-
virtual
|
92
|
+
virtual std::string to_string() const = 0;
|
74
93
|
protected:
|
75
94
|
friend class SharedPtr;
|
76
95
|
friend class Memory_Manager;
|
@@ -85,6 +104,9 @@ namespace Sass {
|
|
85
104
|
#endif
|
86
105
|
};
|
87
106
|
|
107
|
+
// SharedPtr is a intermediate (template-less) base class for SharedImpl.
|
108
|
+
// ToDo: there should be a way to include this in SharedImpl and to get
|
109
|
+
// ToDo: rid of all the static_cast that are now needed in SharedImpl.
|
88
110
|
class SharedPtr {
|
89
111
|
public:
|
90
112
|
SharedPtr() : node(nullptr) {}
|
@@ -114,6 +136,11 @@ namespace Sass {
|
|
114
136
|
// Prevents all SharedPtrs from freeing this node until it is assigned to another SharedPtr.
|
115
137
|
SharedObj* detach() {
|
116
138
|
if (node != nullptr) node->detached = true;
|
139
|
+
#ifdef DEBUG_SHARED_PTR
|
140
|
+
if (node->dbg) {
|
141
|
+
std::cerr << "DETACHING NODE\n";
|
142
|
+
}
|
143
|
+
#endif
|
117
144
|
return node;
|
118
145
|
}
|
119
146
|
|
@@ -136,6 +163,11 @@ namespace Sass {
|
|
136
163
|
#endif
|
137
164
|
delete node;
|
138
165
|
}
|
166
|
+
else if (node->refcount == 0) {
|
167
|
+
#ifdef DEBUG_SHARED_PTR
|
168
|
+
if (node->dbg) std::cerr << "NODE EVAEDED DELETE " << node << "\n";
|
169
|
+
#endif
|
170
|
+
}
|
139
171
|
}
|
140
172
|
void incRefCount() {
|
141
173
|
if (node == nullptr) return;
|
@@ -149,7 +181,8 @@ namespace Sass {
|
|
149
181
|
|
150
182
|
template <class T>
|
151
183
|
class SharedImpl : private SharedPtr {
|
152
|
-
|
184
|
+
|
185
|
+
public:
|
153
186
|
SharedImpl() : SharedPtr(nullptr) {}
|
154
187
|
|
155
188
|
template <class U>
|
@@ -172,9 +205,9 @@ namespace Sass {
|
|
172
205
|
SharedPtr::operator=(static_cast<const SharedImpl<T>&>(rhs)));
|
173
206
|
}
|
174
207
|
|
175
|
-
operator
|
208
|
+
operator std::string() const {
|
176
209
|
if (node) return node->to_string();
|
177
|
-
return "
|
210
|
+
return "null";
|
178
211
|
}
|
179
212
|
|
180
213
|
using SharedPtr::isNull;
|
@@ -185,6 +218,7 @@ namespace Sass {
|
|
185
218
|
T* operator-> () const { return static_cast<T*>(this->obj()); };
|
186
219
|
T* ptr () const { return static_cast<T*>(this->obj()); };
|
187
220
|
T* detach() { return static_cast<T*>(SharedPtr::detach()); }
|
221
|
+
|
188
222
|
};
|
189
223
|
|
190
224
|
// Comparison operators, based on:
|