1 | // sass.hpp must go before all system headers to get the |
2 | // __EXTENSIONS__ fix on Solaris. |
3 | #include "sass.hpp" |
4 | |
5 | #include "sass.h" |
6 | #include "values.hpp" |
7 | |
8 | #include <stdint.h> |
9 | |
10 | namespace Sass { |
11 | |
12 | // convert value from C++ side to C-API |
13 | union Sass_Value* ast_node_to_sass_value (const Expression* val) |
14 | { |
15 | if (val->concrete_type() == Expression::NUMBER) |
16 | { |
17 | const Number* res = Cast<Number>(ptr: val); |
18 | return sass_make_number(val: res->value(), unit: res->unit().c_str()); |
19 | } |
20 | else if (val->concrete_type() == Expression::COLOR) |
21 | { |
22 | if (const Color_RGBA* rgba = Cast<Color_RGBA>(ptr: val)) { |
23 | return sass_make_color(r: rgba->r(), g: rgba->g(), b: rgba->b(), a: rgba->a()); |
24 | } else { |
25 | // ToDo: allow to also use HSLA colors!! |
26 | Color_RGBA_Obj col = Cast<Color>(ptr: val)->copyAsRGBA(); |
27 | return sass_make_color(r: col->r(), g: col->g(), b: col->b(), a: col->a()); |
28 | } |
29 | } |
30 | else if (val->concrete_type() == Expression::LIST) |
31 | { |
32 | const List* l = Cast<List>(ptr: val); |
33 | union Sass_Value* list = sass_make_list(len: l->size(), sep: l->separator(), is_bracketed: l->is_bracketed()); |
34 | for (size_t i = 0, L = l->length(); i < L; ++i) { |
35 | ExpressionObj obj = l->at(i); |
36 | auto val = ast_node_to_sass_value(val: obj); |
37 | sass_list_set_value(v: list, i, value: val); |
38 | } |
39 | return list; |
40 | } |
41 | else if (val->concrete_type() == Expression::MAP) |
42 | { |
43 | const Map* m = Cast<Map>(ptr: val); |
44 | union Sass_Value* map = sass_make_map(len: m->length()); |
45 | size_t i = 0; for (ExpressionObj key : m->keys()) { |
46 | sass_map_set_key(v: map, i, ast_node_to_sass_value(val: key)); |
47 | sass_map_set_value(v: map, i, ast_node_to_sass_value(val: m->at(k: key))); |
48 | ++ i; |
49 | } |
50 | return map; |
51 | } |
52 | else if (val->concrete_type() == Expression::NULL_VAL) |
53 | { |
54 | return sass_make_null(); |
55 | } |
56 | else if (val->concrete_type() == Expression::BOOLEAN) |
57 | { |
58 | const Boolean* res = Cast<Boolean>(ptr: val); |
59 | return sass_make_boolean(val: res->value()); |
60 | } |
61 | else if (val->concrete_type() == Expression::STRING) |
62 | { |
63 | if (const String_Quoted* qstr = Cast<String_Quoted>(ptr: val)) |
64 | { |
65 | return sass_make_qstring(val: qstr->value().c_str()); |
66 | } |
67 | else if (const String_Constant* cstr = Cast<String_Constant>(ptr: val)) |
68 | { |
69 | return sass_make_string(val: cstr->value().c_str()); |
70 | } |
71 | } |
72 | return sass_make_error(msg: "unknown sass value type" ); |
73 | } |
74 | |
75 | // convert value from C-API to C++ side |
76 | Value* sass_value_to_ast_node (const union Sass_Value* val) |
77 | { |
78 | switch (sass_value_get_tag(v: val)) { |
79 | case SASS_NUMBER: |
80 | return SASS_MEMORY_NEW(Number, |
81 | SourceSpan("[C-VALUE]" ), |
82 | sass_number_get_value(val), |
83 | sass_number_get_unit(val)); |
84 | case SASS_BOOLEAN: |
85 | return SASS_MEMORY_NEW(Boolean, |
86 | SourceSpan("[C-VALUE]" ), |
87 | sass_boolean_get_value(val)); |
88 | case SASS_COLOR: |
89 | // ToDo: allow to also use HSLA colors!! |
90 | return SASS_MEMORY_NEW(Color_RGBA, |
91 | SourceSpan("[C-VALUE]" ), |
92 | sass_color_get_r(val), |
93 | sass_color_get_g(val), |
94 | sass_color_get_b(val), |
95 | sass_color_get_a(val)); |
96 | case SASS_STRING: |
97 | if (sass_string_is_quoted(v: val)) { |
98 | return SASS_MEMORY_NEW(String_Quoted, |
99 | SourceSpan("[C-VALUE]" ), |
100 | sass_string_get_value(val)); |
101 | } |
102 | return SASS_MEMORY_NEW(String_Constant, |
103 | SourceSpan("[C-VALUE]" ), |
104 | sass_string_get_value(val)); |
105 | case SASS_LIST: { |
106 | List* l = SASS_MEMORY_NEW(List, |
107 | SourceSpan("[C-VALUE]" ), |
108 | sass_list_get_length(val), |
109 | sass_list_get_separator(val)); |
110 | for (size_t i = 0, L = sass_list_get_length(v: val); i < L; ++i) { |
111 | l->append(element: sass_value_to_ast_node(val: sass_list_get_value(v: val, i))); |
112 | } |
113 | l->is_bracketed(is_bracketed__: sass_list_get_is_bracketed(v: val)); |
114 | return l; |
115 | } |
116 | case SASS_MAP: { |
117 | Map* m = SASS_MEMORY_NEW(Map, SourceSpan("[C-VALUE]" )); |
118 | for (size_t i = 0, L = sass_map_get_length(v: val); i < L; ++i) { |
119 | *m << std::make_pair( |
120 | x: sass_value_to_ast_node(val: sass_map_get_key(v: val, i)), |
121 | y: sass_value_to_ast_node(val: sass_map_get_value(v: val, i))); |
122 | } |
123 | return m; |
124 | } |
125 | case SASS_NULL: |
126 | return SASS_MEMORY_NEW(Null, SourceSpan("[C-VALUE]" )); |
127 | case SASS_ERROR: |
128 | return SASS_MEMORY_NEW(Custom_Error, |
129 | SourceSpan("[C-VALUE]" ), |
130 | sass_error_get_message(val)); |
131 | case SASS_WARNING: |
132 | return SASS_MEMORY_NEW(Custom_Warning, |
133 | SourceSpan("[C-VALUE]" ), |
134 | sass_warning_get_message(val)); |
135 | default: break; |
136 | } |
137 | return 0; |
138 | } |
139 | |
140 | } |
141 | |